diff --git a/.changeset/late-dodos-swim.md b/.changeset/late-dodos-swim.md new file mode 100644 index 00000000..6229535d --- /dev/null +++ b/.changeset/late-dodos-swim.md @@ -0,0 +1,5 @@ +--- +'guard-service': minor +--- + +Add rate limit to all apis diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index bb43dc55..44048fa6 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -31,7 +31,7 @@ jobs: uses: rosen-bridge/operation@V0.1 with: type: ${{ vars.RELEASE_NAME }} - tag: ${{ vars.RELEASE_TAG }} + tag: ${{ vars.RELEASE_TAG }} - name: Move the Files run: | diff --git a/config/default.yaml b/config/default.yaml index d352832d..630b8340 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -7,6 +7,7 @@ api: apiKeyHash: '' # blake2b hash of Api-Key jsonBodyLimit: 50 isManualTxRequestActive: false + maxRequestsPerMinute: 100_000 cardano: networkType: 'mainnet' # Cardano network type [testnet, mainnet] diff --git a/package-lock.json b/package-lock.json index 573a3be5..22d7b4d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "guard-service", - "version": "1.3.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "guard-service", - "version": "1.3.0", + "version": "2.0.0", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -15,6 +15,7 @@ "@chainsafe/libp2p-noise": "^10.2.0", "@emurgo/cardano-serialization-lib-nodejs": "^11.1.0", "@fastify/cors": "^8.3.0", + "@fastify/rate-limit": "^9.1.0", "@fastify/swagger": "^8.8.0", "@fastify/swagger-ui": "^1.9.3", "@fastify/type-provider-typebox": "^3.4.0", @@ -1872,6 +1873,16 @@ "fast-json-stringify": "^5.7.0" } }, + "node_modules/@fastify/rate-limit": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@fastify/rate-limit/-/rate-limit-9.1.0.tgz", + "integrity": "sha512-h5dZWCkuZXN0PxwqaFQLxeln8/LNwQwH9popywmDCFdKfgpi4b/HoMH1lluy6P+30CG9yzzpSpwTCIPNB9T1JA==", + "dependencies": { + "@lukeed/ms": "^2.0.1", + "fastify-plugin": "^4.0.0", + "toad-cache": "^3.3.1" + } + }, "node_modules/@fastify/send": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz", @@ -14430,6 +14441,14 @@ "node": ">=8.0" } }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "engines": { + "node": ">=12" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/package.json b/package.json index bb47cbc0..3c6137e8 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@chainsafe/libp2p-noise": "^10.2.0", "@emurgo/cardano-serialization-lib-nodejs": "^11.1.0", "@fastify/cors": "^8.3.0", + "@fastify/rate-limit": "^9.1.0", "@fastify/swagger": "^8.8.0", "@fastify/swagger-ui": "^1.9.3", "@fastify/type-provider-typebox": "^3.4.0", diff --git a/src/configs/Configs.ts b/src/configs/Configs.ts index 4652b810..8f90c124 100644 --- a/src/configs/Configs.ts +++ b/src/configs/Configs.ts @@ -70,6 +70,10 @@ class Configs { static apiKeyHash = config.get('api.apiKeyHash'); static apiBodyLimit = getConfigIntKeyOrDefault('api.jsonBodyLimit', 50) * 1024 * 1024; // value in MB + static apiMaxRequestsPerMinute = getConfigIntKeyOrDefault( + 'api.maxRequestsPerMinute', + 100_000 + ); static isManualTxRequestActive = getOptionalConfig( 'api.isManualTxRequestActive', false @@ -165,7 +169,10 @@ class Configs { const logTypeValidation = ['console', 'file', 'loki'].includes(log.type); let loggerChecks = true; if (log.type === 'loki') { - const overrideLokiBasicAuth = getOptionalConfig('overrideLokiBasicAuth', ''); + const overrideLokiBasicAuth = getOptionalConfig( + 'overrideLokiBasicAuth', + '' + ); if (overrideLokiBasicAuth !== '') log.basicAuth = overrideLokiBasicAuth; loggerChecks = log.host != undefined && diff --git a/src/jobs/apiServer.ts b/src/jobs/apiServer.ts index 2b915e0f..b4a090bc 100644 --- a/src/jobs/apiServer.ts +++ b/src/jobs/apiServer.ts @@ -14,6 +14,7 @@ import { healthRoutes } from '../api/healthCheck'; import { tssRoute } from '../api/tss'; import WinstonLogger from '@rosen-bridge/winston-logger'; import { signRoute } from '../api/signTx'; +import rateLimit from '@fastify/rate-limit'; const logger = WinstonLogger.getInstance().getLogger(import.meta.url); @@ -66,6 +67,11 @@ const initApiServer = async () => { transformSpecificationClone: true, }); + await apiServer.register(rateLimit, { + max: Configs.apiMaxRequestsPerMinute, + timeWindow: '1 minute', + }); + await apiServer.register(p2pRoutes); if (Configs.keygen.isActive) { await apiServer.register(keygenRoute);