mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 07:30:20 +00:00
misc: addressed review comments
This commit is contained in:
@@ -6,7 +6,7 @@ import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.RateLimit))) {
|
||||
await knex.schema.createTable(TableName.RateLimit, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("id", { primaryKey: true }).defaultTo("00000000-0000-0000-0000-000000000000");
|
||||
t.integer("readRateLimit").defaultTo(600).notNullable();
|
||||
t.integer("writeRateLimit").defaultTo(200).notNullable();
|
||||
t.integer("secretsRateLimit").defaultTo(60).notNullable();
|
||||
|
||||
@@ -17,6 +17,8 @@ import { Logger } from "pino";
|
||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { TQueueServiceFactory } from "@app/queue";
|
||||
import { rateLimitDALFactory } from "@app/services/rate-limit/rate-limit-dal";
|
||||
import { rateLimitServiceFactory } from "@app/services/rate-limit/rate-limit-service";
|
||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||
|
||||
import { globalRateLimiterCfg } from "./config/rateLimiter";
|
||||
@@ -69,8 +71,11 @@ export const main = async ({ db, smtp, logger, queue, keyStore }: TMain) => {
|
||||
|
||||
// Rate limiters and security headers
|
||||
if (appCfg.isProductionMode) {
|
||||
await server.register<FastifyRateLimitOptions>(ratelimiter, await globalRateLimiterCfg(db));
|
||||
const rateLimitDAL = rateLimitDALFactory(db);
|
||||
const rateLimits = await rateLimitServiceFactory({ rateLimitDAL }).getRateLimits();
|
||||
await server.register<FastifyRateLimitOptions>(ratelimiter, globalRateLimiterCfg(rateLimits));
|
||||
}
|
||||
|
||||
await server.register(helmet, { contentSecurityPolicy: false });
|
||||
|
||||
await server.register(maintenanceMode);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
||||
import { Redis } from "ioredis";
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TRateLimit } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { rateLimitDALFactory } from "@app/services/rate-limit/rate-limit-dal";
|
||||
import { rateLimitServiceFactory } from "@app/services/rate-limit/rate-limit-service";
|
||||
|
||||
// GET endpoints
|
||||
export const readLimit: RateLimitOptions = {
|
||||
@@ -63,31 +61,20 @@ export const publicEndpointLimit: RateLimitOptions = {
|
||||
keyGenerator: (req) => req.realIp
|
||||
};
|
||||
|
||||
async function fetchRateLimitsFromDb(db: Knex) {
|
||||
try {
|
||||
const rateLimitDAL = rateLimitDALFactory(db);
|
||||
const rateLimits = await rateLimitServiceFactory({ rateLimitDAL }).getRateLimits();
|
||||
|
||||
readLimit.max = rateLimits.readRateLimit;
|
||||
publicEndpointLimit.max = rateLimits.publicEndpointLimit;
|
||||
writeLimit.max = rateLimits.writeRateLimit;
|
||||
secretsLimit.max = rateLimits.secretsRateLimit;
|
||||
authRateLimit.max = rateLimits.authRateLimit;
|
||||
inviteUserRateLimit.max = rateLimits.inviteUserRateLimit;
|
||||
mfaRateLimit.max = rateLimits.mfaRateLimit;
|
||||
creationLimit.max = rateLimits.creationLimit;
|
||||
} catch (error) {
|
||||
console.error("Error fetching rate limits:", error);
|
||||
}
|
||||
}
|
||||
|
||||
export const globalRateLimiterCfg = async (db: Knex): Promise<RateLimitPluginOptions> => {
|
||||
export const globalRateLimiterCfg = async (rateLimits: TRateLimit): Promise<RateLimitPluginOptions> => {
|
||||
const appCfg = getConfig();
|
||||
const redis = appCfg.isRedisConfigured
|
||||
? new Redis(appCfg.REDIS_URL, { connectTimeout: 500, maxRetriesPerRequest: 1 })
|
||||
: null;
|
||||
|
||||
await fetchRateLimitsFromDb(db);
|
||||
readLimit.max = rateLimits.readRateLimit;
|
||||
publicEndpointLimit.max = rateLimits.publicEndpointLimit;
|
||||
writeLimit.max = rateLimits.writeRateLimit;
|
||||
secretsLimit.max = rateLimits.secretsRateLimit;
|
||||
authRateLimit.max = rateLimits.authRateLimit;
|
||||
inviteUserRateLimit.max = rateLimits.inviteUserRateLimit;
|
||||
mfaRateLimit.max = rateLimits.mfaRateLimit;
|
||||
creationLimit.max = rateLimits.creationLimit;
|
||||
|
||||
return {
|
||||
timeWindow: 60 * 1000,
|
||||
|
||||
@@ -39,10 +39,15 @@ export const registerRateLimitRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
|
||||
schema: {
|
||||
body: RateLimitSchema.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true
|
||||
body: z.object({
|
||||
readRateLimit: z.number().optional(),
|
||||
writeRateLimit: z.number().optional(),
|
||||
secretsRateLimit: z.number().optional(),
|
||||
authRateLimit: z.number().optional(),
|
||||
inviteUserRateLimit: z.number().optional(),
|
||||
mfaRateLimit: z.number().optional(),
|
||||
creationLimit: z.number().optional(),
|
||||
publicEndpointLimit: z.number().optional()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -10,34 +10,23 @@ type TRateLimitServiceFactoryDep = {
|
||||
export type TRateLimitServiceFactory = ReturnType<typeof rateLimitServiceFactory>;
|
||||
|
||||
export const rateLimitServiceFactory = ({ rateLimitDAL }: TRateLimitServiceFactoryDep) => {
|
||||
const initRateLimits = async (): Promise<TRateLimit> => {
|
||||
const rateLimit = await rateLimitDAL.create({});
|
||||
return rateLimit;
|
||||
};
|
||||
|
||||
const getRateLimits = async (): Promise<TRateLimit> => {
|
||||
let rateLimit = (await rateLimitDAL.find({}))[0];
|
||||
if (!rateLimit) {
|
||||
rateLimit = await initRateLimits();
|
||||
}
|
||||
return rateLimit;
|
||||
return rateLimitDAL.findOne({ id: "00000000-0000-0000-0000-000000000000" });
|
||||
};
|
||||
|
||||
const updateRateLimit = async (updates: TRateLimitUpdateDTO): Promise<TRateLimit> => {
|
||||
const rateLimit = await rateLimitDAL.findOne({});
|
||||
if (!rateLimit) throw new BadRequestError({ name: "Rate Limit Update", message: "Rate Limit does not exist yet" });
|
||||
const rateLimit = await rateLimitDAL.findOne({
|
||||
id: "00000000-0000-0000-0000-000000000000"
|
||||
});
|
||||
|
||||
const updateData: Record<string, number> = {};
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
updateData[key] = value;
|
||||
if (!rateLimit) {
|
||||
throw new BadRequestError({ name: "Rate Limit Update", message: "Rate Limit does not exist yet" });
|
||||
}
|
||||
|
||||
const updatedRateLimit = await rateLimitDAL.updateById(rateLimit.id, updateData);
|
||||
return updatedRateLimit;
|
||||
return rateLimitDAL.updateById(rateLimit.id, updates);
|
||||
};
|
||||
|
||||
return {
|
||||
initRateLimits,
|
||||
getRateLimits,
|
||||
updateRateLimit
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user