misc: moved to plan-based rate limit

This commit is contained in:
Sheen Capadngan
2024-08-02 21:37:48 +08:00
parent a0490d0fde
commit 55a6740714
8 changed files with 82 additions and 12 deletions
+16 -9
View File
@@ -1,7 +1,6 @@
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
import { Redis } from "ioredis";
import { getRateLimiterConfig } from "@app/ee/services/rate-limit/rate-limit-service";
import { getConfig } from "@app/lib/config/env";
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
@@ -22,14 +21,16 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
// GET endpoints
export const readLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().readLimit,
hook: "preValidation",
max: (req) => req.rateLimits.readLimit,
keyGenerator: (req) => req.realIp
};
// POST, PATCH, PUT, DELETE endpoints
export const writeLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().writeLimit,
hook: "preValidation",
max: (req) => req.rateLimits.writeLimit,
keyGenerator: (req) => req.realIp
};
@@ -37,25 +38,29 @@ export const writeLimit: RateLimitOptions = {
export const secretsLimit: RateLimitOptions = {
// secrets, folders, secret imports
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().secretsLimit,
hook: "preValidation",
max: (req) => req.rateLimits.secretsLimit,
keyGenerator: (req) => req.realIp
};
export const authRateLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().authRateLimit,
hook: "preValidation",
max: (req) => req.rateLimits.authRateLimit,
keyGenerator: (req) => req.realIp
};
export const inviteUserRateLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().inviteUserRateLimit,
hook: "preValidation",
max: (req) => req.rateLimits.inviteUserRateLimit,
keyGenerator: (req) => req.realIp
};
export const mfaRateLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().mfaRateLimit,
hook: "preValidation",
max: (req) => req.rateLimits.mfaRateLimit,
keyGenerator: (req) => {
return req.headers.authorization?.split(" ")[1] || req.realIp;
}
@@ -64,7 +69,8 @@ export const mfaRateLimit: RateLimitOptions = {
export const creationLimit: RateLimitOptions = {
// identity, project, org
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().creationLimit,
hook: "preValidation",
max: (req) => req.rateLimits.creationLimit,
keyGenerator: (req) => req.realIp
};
@@ -72,7 +78,8 @@ export const creationLimit: RateLimitOptions = {
export const publicEndpointLimit: RateLimitOptions = {
// Read Shared Secrets
timeWindow: 60 * 1000,
max: () => getRateLimiterConfig().publicEndpointLimit,
hook: "preValidation",
max: (req) => req.rateLimits.publicEndpointLimit,
keyGenerator: (req) => req.realIp
};
@@ -0,0 +1,35 @@
import fp from "fastify-plugin";
import { getRateLimiterConfig } from "@app/ee/services/rate-limit/rate-limit-service";
export const injectRateLimits = fp(async (server) => {
server.decorateRequest("rateLimits", null);
server.addHook("onRequest", async (req) => {
const defaultRateLimiterConfig = getRateLimiterConfig();
if (!req.auth) {
// for public endpoints
req.rateLimits = defaultRateLimiterConfig;
return;
}
const plan = await server.services.license.getPlan(req.auth.orgId);
const { rateLimits } = plan;
if (plan.customRateLimits) {
req.rateLimits = defaultRateLimiterConfig;
return;
}
// we're using the null coalescing operator in order to handle outdated licenses
req.rateLimits = {
readLimit: rateLimits?.readLimit ?? defaultRateLimiterConfig.readLimit,
publicEndpointLimit: rateLimits?.publicEndpointLimit ?? defaultRateLimiterConfig.publicEndpointLimit,
writeLimit: rateLimits?.writeLimit ?? defaultRateLimiterConfig.writeLimit,
secretsLimit: rateLimits?.secretsLimit ?? defaultRateLimiterConfig.secretsLimit,
authRateLimit: rateLimits?.authRateLimit ?? defaultRateLimiterConfig.authRateLimit,
inviteUserRateLimit: rateLimits?.inviteUserRateLimit ?? defaultRateLimiterConfig.inviteUserRateLimit,
mfaRateLimit: rateLimits?.mfaRateLimit ?? defaultRateLimiterConfig.mfaRateLimit,
creationLimit: rateLimits?.creationLimit ?? defaultRateLimiterConfig.creationLimit
};
});
});
+2
View File
@@ -183,6 +183,7 @@ import { webhookServiceFactory } from "@app/services/webhook/webhook-service";
import { injectAuditLogInfo } from "../plugins/audit-log";
import { injectIdentity } from "../plugins/auth/inject-identity";
import { injectPermission } from "../plugins/auth/inject-permission";
import { injectRateLimits } from "../plugins/inject-rate-limits";
import { registerSecretScannerGhApp } from "../plugins/secret-scanner";
import { registerV1Routes } from "./v1";
import { registerV2Routes } from "./v2";
@@ -1130,6 +1131,7 @@ export const registerRoutes = async (
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
await server.register(injectPermission);
await server.register(injectRateLimits);
await server.register(injectAuditLogInfo);
server.route({