Skip to content

Commit

Permalink
Merge branch '355-api_key' into 'dev'
Browse files Browse the repository at this point in the history
add api_key middleware for sign route

Closes #355

See merge request ergo/rosen-bridge/guard-service!312
  • Loading branch information
vorujack committed Feb 13, 2024
2 parents f358aae + dc3c0c7 commit c9e0471
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 1 deletion.
1 change: 1 addition & 0 deletions config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
api:
port: 8080 # service deployment port
host: 'localhost' # service listening host
apiKeyHash: '' # blake2b hash of API_KEY
jsonBodyLimit: 50
isManualTxRequestActive: false

Expand Down
1 change: 1 addition & 0 deletions config/test.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
api:
isManualTxRequestActive: true
apiKeyHash: '324dcf027dd4a30a932c441f365a25e86b173defa4b8e58948253471b81b72cf'
cardano:
networkType: 'testnet'
chainNetwork: 'koios'
Expand Down
4 changes: 4 additions & 0 deletions src/api/signTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import DatabaseHandler from '../db/DatabaseHandler';
import WinstonLogger from '@rosen-bridge/winston-logger';
import { DuplicateTransaction } from '../utils/errors';
import GuardPkHandler from '../handlers/GuardPkHandler';
import { authenticateKey } from '../utils/authentication';

const logger = WinstonLogger.getInstance().getLogger(import.meta.url);

Expand All @@ -25,8 +26,11 @@ const signTxRoute = (server: FastifySeverInstance) => {
response: {
200: MessageResponseSchema,
400: MessageResponseSchema,
403: MessageResponseSchema,
},
security: [{ apiKey: [] }],
},
preHandler: [authenticateKey],
},
async (request, reply) => {
const { chain, txJson, requiredSign, overwrite } = request.body;
Expand Down
1 change: 1 addition & 0 deletions src/configs/Configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Configs {
// express config
static apiPort = getConfigIntKeyOrDefault('api.port', 8080);
static apiHost = getOptionalConfig<string>('api.host', 'localhost');
static apiKeyHash = config.get<string>('api.apiKeyHash');
static apiBodyLimit =
getConfigIntKeyOrDefault('api.jsonBodyLimit', 50) * 1024 * 1024; // value in MB
static isManualTxRequestActive = getOptionalConfig<boolean>(
Expand Down
14 changes: 13 additions & 1 deletion src/jobs/apiServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,19 @@ const initApiServer = async () => {
bodyLimit: Configs.apiBodyLimit,
}).withTypeProvider<TypeBoxTypeProvider>();

await apiServer.register(swagger);
await apiServer.register(swagger, {
openapi: {
components: {
securitySchemes: {
apiKey: {
type: 'apiKey',
name: 'api_key',
in: 'header',
},
},
},
},
});
await apiServer.register(fastifyCors, {});

await apiServer.register(swaggerUi, {
Expand Down
24 changes: 24 additions & 0 deletions src/utils/authentication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { blake2b } from 'blakejs';
import { Buffer } from 'buffer';
import Configs from '../configs/Configs';
import { FastifyReply, FastifyRequest } from 'fastify';
import { HookHandlerDoneFunction } from 'fastify/types/hooks';

const authenticateKey = <T extends FastifyRequest, U extends FastifyReply>(
req: T,
res: U,
next: HookHandlerDoneFunction
) => {
const api_key: string = req.headers.api_key as string;
if (
api_key &&
Buffer.from(blake2b(api_key, undefined, 32)).toString('hex') ==
Configs.apiKeyHash
) {
next();
} else {
res.status(403).send({ message: "API_KEY doesn't exist or it's wrong" });
}
};

export { authenticateKey };
66 changes: 66 additions & 0 deletions tests/api/signTx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ describe('signTx', () => {
txJson: 'txJson',
requiredSign: requiredSign,
},
headers: {
API_KEY: 'hello',
},
});

// check the result
Expand Down Expand Up @@ -123,6 +126,9 @@ describe('signTx', () => {
txJson: 'txJson',
requiredSign: requiredSign,
},
headers: {
API_KEY: 'hello',
},
});

// check the result
Expand Down Expand Up @@ -185,6 +191,9 @@ describe('signTx', () => {
txJson: 'txJson',
requiredSign: requiredSign,
},
headers: {
API_KEY: 'hello',
},
});

// check the result
Expand Down Expand Up @@ -248,6 +257,9 @@ describe('signTx', () => {
requiredSign: newRequiredSign,
overwrite: true,
},
headers: {
API_KEY: 'hello',
},
});

// check the result
Expand Down Expand Up @@ -302,10 +314,64 @@ describe('signTx', () => {
txJson: 'txJson',
requiredSign: GuardPkHandler.getInstance().guardsLen + 1,
},
headers: {
API_KEY: 'hello',
},
});

// check the result
expect(result.statusCode).toEqual(400);
});

/**
* @target fastifyServer[POST /sign] should return 403 when api_key did not set in header
* @dependencies
* @scenario
* - send a request to the server
* - check the result
* @expected
* - it should return status code 403
*/
it('should return 403 when api_key did not set in header', async () => {
// send a request to the server
const result = await mockedServer.inject({
method: 'POST',
url: '/sign',
body: {
chain: CARDANO_CHAIN,
txJson: 'txJson',
requiredSign: GuardPkHandler.getInstance().guardsLen,
},
});
// check the result
expect(result.statusCode).toEqual(403);
});

/**
* @target fastifyServer[POST /sign] should return 403 when api_key is wrong
* @dependencies
* @scenario
* - send a request to the server
* - check the result
* @expected
* - it should return status code 403
*/
it('should return 403 when api_key is wrong', async () => {
// send a request to the server
const result = await mockedServer.inject({
method: 'POST',
url: '/sign',
body: {
chain: CARDANO_CHAIN,
txJson: 'txJson',
requiredSign: GuardPkHandler.getInstance().guardsLen,
},
headers: {
API_KEY: 'wrong',
},
});
// check the result
expect(result.statusCode).toEqual(403);
});
});
});

0 comments on commit c9e0471

Please sign in to comment.