Merge pull request #4764 from Budibase/feature/rate-limiting

Public API IP rate limiting
This commit is contained in:
Michael Drury 2022-03-03 14:26:29 +00:00 committed by GitHub
commit 3bcd1fdad1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1281 additions and 27 deletions

View File

@ -108,6 +108,7 @@
"koa-send": "5.0.0", "koa-send": "5.0.0",
"koa-session": "5.12.0", "koa-session": "5.12.0",
"koa-static": "5.0.0", "koa-static": "5.0.0",
"koa2-ratelimit": "^1.1.0",
"lodash": "4.17.21", "lodash": "4.17.21",
"memorystream": "^0.3.1", "memorystream": "^0.3.1",
"mongodb": "3.6.3", "mongodb": "3.6.3",
@ -123,6 +124,7 @@
"pouchdb-all-dbs": "1.0.2", "pouchdb-all-dbs": "1.0.2",
"pouchdb-find": "^7.2.2", "pouchdb-find": "^7.2.2",
"pouchdb-replication-stream": "1.2.9", "pouchdb-replication-stream": "1.2.9",
"redis": "4",
"server-destroy": "1.0.1", "server-destroy": "1.0.1",
"svelte": "^3.38.2", "svelte": "^3.38.2",
"swagger-parser": "^10.0.3", "swagger-parser": "^10.0.3",
@ -148,6 +150,7 @@
"@types/koa-router": "^7.4.2", "@types/koa-router": "^7.4.2",
"@types/node": "^15.12.4", "@types/node": "^15.12.4",
"@types/oracledb": "^5.2.1", "@types/oracledb": "^5.2.1",
"@types/redis": "^4.0.11",
"@typescript-eslint/parser": "4.28.0", "@typescript-eslint/parser": "4.28.0",
"apidoc": "^0.50.2", "apidoc": "^0.50.2",
"babel-jest": "^27.0.2", "babel-jest": "^27.0.2",

View File

@ -58,7 +58,7 @@ module External {
) { ) {
const primary = table.primary const primary = table.primary
// if passed in array need to copy for shifting etc // if passed in array need to copy for shifting etc
let idCopy = cloneDeep(id) let idCopy: undefined | string | any[] = cloneDeep(id)
if (filters) { if (filters) {
// need to map over the filters and make sure the _id field isn't present // need to map over the filters and make sure the _id field isn't present
for (let filter of Object.values(filters)) { for (let filter of Object.values(filters)) {

View File

@ -8,18 +8,54 @@ import authorized from "../../../middleware/authorized"
import { paramResource, paramSubResource } from "../../../middleware/resourceId" import { paramResource, paramSubResource } from "../../../middleware/resourceId"
import { CtxFn } from "./utils/Endpoint" import { CtxFn } from "./utils/Endpoint"
import mapperMiddleware from "./middleware/mapper" import mapperMiddleware from "./middleware/mapper"
import env from "../../../environment"
// below imports don't have declaration files
const Router = require("@koa/router") const Router = require("@koa/router")
const { RateLimit, Stores } = require("koa2-ratelimit")
const { const {
PermissionLevels, PermissionLevels,
PermissionTypes, PermissionTypes,
} = require("@budibase/backend-core/permissions") } = require("@budibase/backend-core/permissions")
const { getRedisOptions } = require("@budibase/backend-core/redis").utils
const PREFIX = "/api/public/v1" const PREFIX = "/api/public/v1"
// allow a lot more requests when in test
const DEFAULT_API_REQ_LIMIT_PER_SEC = env.isTest() ? 100 : 10
function getApiLimitPerSecond(): number {
if (!env.API_REQ_LIMIT_PER_SEC) {
return DEFAULT_API_REQ_LIMIT_PER_SEC
}
return parseInt(env.API_REQ_LIMIT_PER_SEC)
}
if (!env.isTest()) {
const REDIS_OPTS = getRedisOptions()
RateLimit.defaultOptions({
store: new Stores.Redis({
// @ts-ignore
socket: {
host: REDIS_OPTS.host,
port: REDIS_OPTS.port,
},
password: REDIS_OPTS.opts.password,
database: 1,
}),
})
}
// rate limiting, allows for 2 requests per second
const limiter = RateLimit.middleware({
interval: { sec: 1 },
// per ip, per interval
max: getApiLimitPerSecond(),
})
const publicRouter = new Router({ const publicRouter = new Router({
prefix: PREFIX, prefix: PREFIX,
}) })
publicRouter.use(limiter)
function addMiddleware( function addMiddleware(
endpoints: any, endpoints: any,
middleware: CtxFn, middleware: CtxFn,

View File

@ -45,6 +45,7 @@ module.exports = {
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
MULTI_TENANCY: process.env.MULTI_TENANCY, MULTI_TENANCY: process.env.MULTI_TENANCY,
HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS, HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC,
// environment // environment
NODE_ENV: process.env.NODE_ENV, NODE_ENV: process.env.NODE_ENV,
JEST_WORKER_ID: process.env.JEST_WORKER_ID, JEST_WORKER_ID: process.env.JEST_WORKER_ID,

File diff suppressed because it is too large Load Diff