From ad2232969f243cecd8ff43c6c123e39989ed4c29 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 8 Feb 2025 09:30:41 +0100 Subject: [PATCH] change: security with ENV --- .env.example | 11 +++++++++-- src/env.defaults.ts | 22 ++++++++++++++++++++-- src/routes/index.ts | 29 +++++++++++++++++++++++------ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 6520381..bda00c7 100644 --- a/.env.example +++ b/.env.example @@ -34,5 +34,12 @@ CLUB_NAME = clubname #default FF Admin CLUB_WEBSITE = https://my-club-website-url #optional, muss aber mit http:// oder https:// beginnen BACKUP_INTERVAL = number of days (min 1) # default 1 -BACKUP_COPIES = number of parallel copies #default 7 -BACKUP_AUTO_RESTORE = (true|false) # default false \ No newline at end of file +BACKUP_COPIES = number of parallel copies # default 7 +BACKUP_AUTO_RESTORE = (true|false) # default ist true + +USE_SECURITY_STRICT_LIMIT = (true|false) # default ist true +SECURITY_STRICT_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 15 +SECURITY_STRICT_LIMIT_REQUEST_COUNT = strict_request_count # default ist 15 +USE_SECURITY_LIMIT = (true|false) # default ist true +SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m +SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500 \ No newline at end of file diff --git a/src/env.defaults.ts b/src/env.defaults.ts index 19024c2..4c8362d 100644 --- a/src/env.defaults.ts +++ b/src/env.defaults.ts @@ -28,6 +28,13 @@ export const BACKUP_INTERVAL = Number(process.env.BACKUP_INTERVAL ?? "1"); export const BACKUP_COPIES = Number(process.env.BACKUP_COPIES ?? "7"); export const BACKUP_AUTO_RESTORE = process.env.BACKUP_AUTO_RESTORE ?? "true"; +export const USE_SECURITY_STRICT_LIMIT = process.env.USE_SECURITY_STRICT_LIMIT ?? "true"; +export const SECURITY_STRICT_LIMIT_WINDOW = process.env.SECURITY_STRICT_LIMIT_WINDOW ?? "15m"; +export const SECURITY_STRICT_LIMIT_REQUEST_COUNT = Number(process.env.SECURITY_STRICT_LIMIT_REQUEST_COUNT ?? "15"); +export const USE_SECURITY_LIMIT = process.env.USE_SECURITY_LIMIT ?? "true"; +export const SECURITY_LIMIT_WINDOW = process.env.SECURITY_LIMIT_WINDOW ?? "1m"; +export const SECURITY_LIMIT_REQUEST_COUNT = Number(process.env.SECURITY_LIMIT_REQUEST_COUNT ?? "500"); + export function configCheck() { if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres") throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)"); @@ -62,15 +69,26 @@ export function configCheck() { throw new Error("set 'true' or 'false' to BACKUP_AUTO_RESTORE"); if (BACKUP_INTERVAL < 1) throw new Error("BACKUP_INTERVAL has to be at least 1"); if (BACKUP_COPIES < 1) throw new Error("BACKUP_COPIES has to be at least 1"); + + if (USE_SECURITY_STRICT_LIMIT != "true" && USE_SECURITY_STRICT_LIMIT != "false") + throw new Error("set 'true' or 'false' to USE_SECURITY_STRICT_LIMIT"); + checkMS(SECURITY_STRICT_LIMIT_WINDOW, "SECURITY_STRICT_LIMIT_WINDOW"); + if (typeof SECURITY_STRICT_LIMIT_REQUEST_COUNT != "number") + throw new Error("set valid numeric value to SECURITY_STRICT_LIMIT_REQUEST_COUNT"); + if (USE_SECURITY_LIMIT != "true" && USE_SECURITY_LIMIT != "false") + throw new Error("set 'true' or 'false' to USE_SECURITY_LIMIT"); + checkMS(SECURITY_LIMIT_WINDOW, "SECURITY_LIMIT_WINDOW"); + if (typeof SECURITY_LIMIT_REQUEST_COUNT != "number") + throw new Error("set valid numeric value to SECURITY_LIMIT_REQUEST_COUNT"); } function checkMS(input: string, origin: string) { try { const result = ms(input); if (result === undefined) { - throw new Error(`set valid ms value to ${origin}`); + throw new Error(`set valid ms value to ${origin} -> [0-9]*(y|d|h|m|s)`); } } catch (e) { - throw new Error(`set valid ms value to ${origin}`); + throw new Error(`set valid ms value to ${origin} -> [0-9]*(y|d|h|m|s)`); } } diff --git a/src/routes/index.ts b/src/routes/index.ts index 75b25d7..ed95543 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -22,17 +22,34 @@ import authenticateAPI from "../middleware/authenticateAPI"; import server from "./server"; import PermissionHelper from "../helpers/permissionHelper"; import preventWebapiAccess from "../middleware/preventWebApiAccess"; +import ms from "ms"; +import { + SECURITY_LIMIT_REQUEST_COUNT, + SECURITY_LIMIT_WINDOW, + SECURITY_STRICT_LIMIT_REQUEST_COUNT, + SECURITY_STRICT_LIMIT_WINDOW, + USE_SECURITY_LIMIT, + USE_SECURITY_STRICT_LIMIT, +} from "../env.defaults"; const strictLimiter = rateLimit({ - windowMs: 15 * 60 * 1000, - max: 10, - message: "Zu viele Anmeldeversuche innerhalb von 15 Minuten. Bitte warten.", + windowMs: ms(SECURITY_STRICT_LIMIT_WINDOW), + max: SECURITY_STRICT_LIMIT_REQUEST_COUNT, + message: `Zu viele Anmeldeversuche innerhalb von ${SECURITY_STRICT_LIMIT_WINDOW}. Bitte warten.`, + skipSuccessfulRequests: true, + skip: () => { + return USE_SECURITY_STRICT_LIMIT == "false"; + }, }); const generalLimiter = rateLimit({ - windowMs: 60 * 1000, - max: 500, - message: "Zu viele Anfragen innerhalb von 1 Minute. Bitte warten.", + windowMs: ms(SECURITY_LIMIT_WINDOW), + max: SECURITY_LIMIT_REQUEST_COUNT, + message: `Zu viele Anfragen innerhalb von ${SECURITY_LIMIT_WINDOW}. Bitte warten.`, + skipSuccessfulRequests: true, + skip: () => { + return USE_SECURITY_LIMIT == "false"; + }, }); function excludePaths(middleware: RequestHandler, excludedPaths: Array) {