mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-31 00:16:47 +01:00
feat: make all internal rate limits configurable (#5095)
### What This PR makes the rate limit for user creation and simple login (our password based login) configurable in the same way you can do metricsRateLimiting. ### Worth noting In addition this PR adds a `rate_limit{endpoint, method}` prometheus gauge, which gets the data from the UnleashConfig.
This commit is contained in:
parent
6fe4740e67
commit
1bba76413f
@ -145,6 +145,10 @@ exports[`should create default config 1`] = `
|
||||
"preRouterHook": undefined,
|
||||
"prometheusApi": undefined,
|
||||
"publicFolder": undefined,
|
||||
"rateLimiting": {
|
||||
"createUserMaxPerMinute": 20,
|
||||
"simpleLoginMaxPerMinute": 10,
|
||||
},
|
||||
"secureHeaders": false,
|
||||
"segmentValuesLimit": 1000,
|
||||
"server": {
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
ICspDomainOptions,
|
||||
IClientCachingOption,
|
||||
IMetricsRateLimiting,
|
||||
IRateLimiting,
|
||||
} from './types/option';
|
||||
import { getDefaultLogProvider, LogLevel, validateLogProvider } from './logger';
|
||||
import { defaultCustomAuthDenyAll } from './default-custom-auth-deny-all';
|
||||
@ -132,6 +133,23 @@ function loadMetricsRateLimitingConfig(
|
||||
]);
|
||||
}
|
||||
|
||||
function loadRateLimitingConfig(options: IUnleashOptions): IRateLimiting {
|
||||
const createUserMaxPerMinute = parseEnvVarNumber(
|
||||
process.env.CREATE_USER_RATE_LIMIT_PER_MINUTE,
|
||||
20,
|
||||
);
|
||||
const simpleLoginMaxPerMinute = parseEnvVarNumber(
|
||||
process.env.SIMPLE_LOGIN_LIMIT_PER_MINUTE,
|
||||
10,
|
||||
);
|
||||
|
||||
const defaultRateLimitOptions: IRateLimiting = {
|
||||
createUserMaxPerMinute,
|
||||
simpleLoginMaxPerMinute,
|
||||
};
|
||||
return mergeAll([defaultRateLimitOptions, options.rateLimiting || {}]);
|
||||
}
|
||||
|
||||
function loadUI(options: IUnleashOptions): IUIConfig {
|
||||
const uiO = options.ui || {};
|
||||
const ui: IUIConfig = {
|
||||
@ -525,6 +543,8 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
|
||||
|
||||
const metricsRateLimiting = loadMetricsRateLimitingConfig(options);
|
||||
|
||||
const rateLimiting = loadRateLimitingConfig(options);
|
||||
|
||||
return {
|
||||
db,
|
||||
session,
|
||||
@ -559,6 +579,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
|
||||
disableScheduler: options.disableScheduler,
|
||||
isEnterprise: isEnterprise,
|
||||
metricsRateLimiting,
|
||||
rateLimiting,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,12 @@ export default class MetricsMonitor {
|
||||
labelNames: ['environment'],
|
||||
});
|
||||
|
||||
const rateLimits = new client.Gauge({
|
||||
name: 'rate_limits',
|
||||
help: 'Rate limits (per minute) for METHOD/ENDPOINT pairs',
|
||||
labelNames: ['endpoint', 'method'],
|
||||
});
|
||||
|
||||
async function collectStaticCounters() {
|
||||
try {
|
||||
const stats = await instanceStatsService.getStats();
|
||||
@ -259,6 +265,42 @@ export default class MetricsMonitor {
|
||||
.labels({ range: clientStat.range })
|
||||
.set(clientStat.count),
|
||||
);
|
||||
|
||||
rateLimits.reset();
|
||||
rateLimits
|
||||
.labels({ endpoint: '/api/client/metrics', method: 'POST' })
|
||||
.set(config.metricsRateLimiting.clientMetricsMaxPerMinute);
|
||||
rateLimits
|
||||
.labels({
|
||||
endpoint: '/api/client/register',
|
||||
method: 'POST',
|
||||
})
|
||||
.set(config.metricsRateLimiting.clientRegisterMaxPerMinute);
|
||||
rateLimits
|
||||
.labels({
|
||||
endpoint: '/api/frontend/metrics',
|
||||
method: 'POST',
|
||||
})
|
||||
.set(
|
||||
config.metricsRateLimiting.frontendMetricsMaxPerMinute,
|
||||
);
|
||||
rateLimits
|
||||
.labels({
|
||||
endpoint: '/api/frontend/register',
|
||||
method: 'POST',
|
||||
})
|
||||
.set(
|
||||
config.metricsRateLimiting.frontendRegisterMaxPerMinute,
|
||||
);
|
||||
rateLimits
|
||||
.labels({
|
||||
endpoint: '/api/admin/user-admin',
|
||||
method: 'POST',
|
||||
})
|
||||
.set(config.rateLimiting.createUserMaxPerMinute);
|
||||
rateLimits
|
||||
.labels({ endpoint: '/auth/simple', method: 'POST' })
|
||||
.set(config.rateLimiting.simpleLoginMaxPerMinute);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ export default class UserAdminController extends Controller {
|
||||
}),
|
||||
rateLimit({
|
||||
windowMs: minutesToMilliseconds(1),
|
||||
max: 20,
|
||||
max: config.rateLimiting.createUserMaxPerMinute,
|
||||
validate: false,
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
|
@ -31,7 +31,7 @@ class IndexRouter extends Controller {
|
||||
new SimplePasswordProvider(config, services).router,
|
||||
rateLimit({
|
||||
windowMs: minutesToMilliseconds(1),
|
||||
max: 10,
|
||||
max: config.rateLimiting.simpleLoginMaxPerMinute,
|
||||
validate: false,
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
|
@ -124,6 +124,7 @@ export interface IUnleashOptions {
|
||||
publicFolder?: string;
|
||||
disableScheduler?: boolean;
|
||||
metricsRateLimiting?: Partial<IMetricsRateLimiting>;
|
||||
rateLimiting?: Partial<IRateLimiting>;
|
||||
}
|
||||
|
||||
export interface IEmailOption {
|
||||
@ -193,6 +194,11 @@ export interface IMetricsRateLimiting {
|
||||
frontendRegisterMaxPerMinute: number;
|
||||
}
|
||||
|
||||
export interface IRateLimiting {
|
||||
createUserMaxPerMinute: number;
|
||||
simpleLoginMaxPerMinute: number;
|
||||
}
|
||||
|
||||
export interface IUnleashConfig {
|
||||
db: IDBOption;
|
||||
session: ISessionOption;
|
||||
@ -227,4 +233,5 @@ export interface IUnleashConfig {
|
||||
publicFolder?: string;
|
||||
disableScheduler?: boolean;
|
||||
isEnterprise: boolean;
|
||||
rateLimiting: IRateLimiting;
|
||||
}
|
||||
|
@ -140,10 +140,13 @@ unleash.start(unleashOptions);
|
||||
- **keepAliveTimeout** - Use this to tweak connection keepalive timeout in seconds. Useful for hosted situations where you need to make sure your connections are closed before terminating the instance. Defaults to `15`. Overridable with the `SERVER_KEEPALIVE_TIMEOUT` environment variable.
|
||||
You can also set the environment variable `ENABLED_ENVIRONMENTS` to a comma delimited string of environment names to override environments.
|
||||
- **metricsRateLimiting** - Use the following to tweak the rate limits for `/api/client/register`, `/api/client/metrics`, `/api/frontend/register` and `/api/frontend/metrics` POST endpoints
|
||||
- `clientMetricsMaxPerMinute` - How many requests per minute is allowed against POST `/api/client/metrics` before returning 429. Set to 6000 by default (100rps) - Overridable with `REGISTER_CLIENT_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `clientRegisterMaxPerMinute` - How many requests per minute is allowed against POST `/api/client/register` before returning 429. Set to 6000 by default (100rps) - Overridable with `CLIENT_METRICS_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `frontendMetricsMaxPerMinute` - How many requests per minute is allowed against POST `/api/frontend/metrics` before returning 429. Set to 6000 by default (100rps) - Overridable with `FRONTEND_METRICS_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `frontendRegisterMaxPerMinute` - How many requests per minute is allowed against POST `/api/frontend/register` before returning 429. Set to 6000 by default (100rps) - Overridable with `REGISTER_FRONTEND_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `clientMetricsMaxPerMinute` - How many requests per minute per IP is allowed against POST `/api/client/metrics` before returning 429. Set to 6000 by default (100rps) - Overridable with `REGISTER_CLIENT_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `clientRegisterMaxPerMinute` - How many requests per minute per IP is allowed against POST `/api/client/register` before returning 429. Set to 6000 by default (100rps) - Overridable with `CLIENT_METRICS_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `frontendMetricsMaxPerMinute` - How many requests per minute per IP is allowed against POST `/api/frontend/metrics` before returning 429. Set to 6000 by default (100rps) - Overridable with `FRONTEND_METRICS_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- `frontendRegisterMaxPerMinute` - How many requests per minute per IP is allowed against POST `/api/frontend/register` before returning 429. Set to 6000 by default (100rps) - Overridable with `REGISTER_FRONTEND_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
- **rateLimiting** - Use the following to tweak the rate limits for `POST /auth/simple` (Password-based login) and `POST /api/admin/user-admin` (Creating users)
|
||||
- `simpleLoginMaxPerMinute` - How many requests per minute per IP is allowed against POST `/auth/simple` before returning 429. Set to 10 by default - Overridable with `SIMPLE_LOGIN_LIMIT_PER_MINUTE` environment variable
|
||||
- `createUserMaxPerMinute` - How many requests per minute per IP is allowed against POST `/api/admin/user-admin` before returning 429. Set to 20 by default - Overridable with `CREATE_USER_RATE_LIMIT_PER_MINUTE` environment variable
|
||||
### Disabling Auto-Start {#disabling-auto-start}
|
||||
|
||||
If you're using Unleash as part of a larger express app, you can disable the automatic server start by calling `server.create`. It takes the same options as `server.start`, but will not begin listening for connections.
|
||||
|
Loading…
Reference in New Issue
Block a user