fix(#199): implement rate limiting on webhook endpoints
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Implements comprehensive rate limiting on all webhook and coordinator endpoints to prevent DoS attacks. Follows TDD protocol with 14 passing tests. Implementation: - Added @nestjs/throttler package for rate limiting - Created ThrottlerApiKeyGuard for per-API-key rate limiting - Created ThrottlerValkeyStorageService for distributed rate limiting via Redis - Configured rate limits on stitcher endpoints (60 req/min) - Configured rate limits on coordinator endpoints (100 req/min) - Higher limits for health endpoints (300 req/min for monitoring) - Added environment variables for rate limit configuration - Rate limiting logs violations for security monitoring Rate Limits: - Stitcher webhooks: 60 requests/minute per API key - Coordinator endpoints: 100 requests/minute per API key - Health endpoints: 300 requests/minute (higher for monitoring) Storage: - Uses Valkey (Redis) for distributed rate limiting across API instances - Falls back to in-memory storage if Redis unavailable Testing: - 14 comprehensive rate limiting tests (all passing) - Tests verify: rate limit enforcement, Retry-After headers, per-API-key isolation - TDD approach: RED (failing tests) → GREEN (implementation) → REFACTOR Additional improvements: - Type safety improvements in websocket gateway - Array type notation standardization in coordinator service Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { APP_INTERCEPTOR } from "@nestjs/core";
|
||||
import { APP_INTERCEPTOR, APP_GUARD } from "@nestjs/core";
|
||||
import { ThrottlerModule } from "@nestjs/throttler";
|
||||
import { ThrottlerValkeyStorageService, ThrottlerApiKeyGuard } from "./common/throttler";
|
||||
import { AppController } from "./app.controller";
|
||||
import { AppService } from "./app.service";
|
||||
import { PrismaModule } from "./prisma/prisma.module";
|
||||
@@ -31,6 +33,23 @@ import { CoordinatorIntegrationModule } from "./coordinator-integration/coordina
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
// Rate limiting configuration
|
||||
ThrottlerModule.forRootAsync({
|
||||
useFactory: () => {
|
||||
const ttl = parseInt(process.env.RATE_LIMIT_TTL ?? "60", 10) * 1000; // Convert to milliseconds
|
||||
const limit = parseInt(process.env.RATE_LIMIT_GLOBAL_LIMIT ?? "100", 10);
|
||||
|
||||
return {
|
||||
throttlers: [
|
||||
{
|
||||
ttl,
|
||||
limit,
|
||||
},
|
||||
],
|
||||
storage: new ThrottlerValkeyStorageService(),
|
||||
};
|
||||
},
|
||||
}),
|
||||
TelemetryModule,
|
||||
PrismaModule,
|
||||
DatabaseModule,
|
||||
@@ -65,6 +84,10 @@ import { CoordinatorIntegrationModule } from "./coordinator-integration/coordina
|
||||
provide: APP_INTERCEPTOR,
|
||||
useClass: TelemetryInterceptor,
|
||||
},
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: ThrottlerApiKeyGuard,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
Reference in New Issue
Block a user