fix(#338): Add rate limiting to orchestrator API
- Add @nestjs/throttler for rate limiting support - Configure multiple throttle profiles: default (100/min), strict (10/min for spawn/kill), status (200/min for polling) - Apply strict rate limits to spawn and kill endpoints to prevent DoS - Apply higher rate limits to status/health endpoints for monitoring - Add OrchestratorThrottlerGuard with X-Forwarded-For support for proxy setups - Add unit tests for throttler guard Refs #338 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,21 +12,28 @@ import {
|
||||
HttpCode,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { Throttle } from "@nestjs/throttler";
|
||||
import { QueueService } from "../../queue/queue.service";
|
||||
import { AgentSpawnerService } from "../../spawner/agent-spawner.service";
|
||||
import { AgentLifecycleService } from "../../spawner/agent-lifecycle.service";
|
||||
import { KillswitchService } from "../../killswitch/killswitch.service";
|
||||
import { SpawnAgentDto, SpawnAgentResponseDto } from "./dto/spawn-agent.dto";
|
||||
import { OrchestratorApiKeyGuard } from "../../common/guards/api-key.guard";
|
||||
import { OrchestratorThrottlerGuard } from "../../common/guards/throttler.guard";
|
||||
|
||||
/**
|
||||
* Controller for agent management endpoints
|
||||
*
|
||||
* All endpoints require API key authentication via X-API-Key header.
|
||||
* Set ORCHESTRATOR_API_KEY environment variable to configure the expected key.
|
||||
*
|
||||
* Rate limits:
|
||||
* - Status endpoints: 200 requests/minute
|
||||
* - Spawn/kill endpoints: 10 requests/minute (strict)
|
||||
* - Default: 100 requests/minute
|
||||
*/
|
||||
@Controller("agents")
|
||||
@UseGuards(OrchestratorApiKeyGuard)
|
||||
@UseGuards(OrchestratorApiKeyGuard, OrchestratorThrottlerGuard)
|
||||
export class AgentsController {
|
||||
private readonly logger = new Logger(AgentsController.name);
|
||||
|
||||
@@ -43,6 +50,7 @@ export class AgentsController {
|
||||
* @returns Agent spawn response with agentId and status
|
||||
*/
|
||||
@Post("spawn")
|
||||
@Throttle({ strict: { limit: 10, ttl: 60000 } })
|
||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
|
||||
async spawn(@Body() dto: SpawnAgentDto): Promise<SpawnAgentResponseDto> {
|
||||
this.logger.log(`Received spawn request for task: ${dto.taskId}`);
|
||||
@@ -81,6 +89,7 @@ export class AgentsController {
|
||||
* @returns Array of all agent sessions with their status
|
||||
*/
|
||||
@Get()
|
||||
@Throttle({ status: { limit: 200, ttl: 60000 } })
|
||||
listAgents(): {
|
||||
agentId: string;
|
||||
taskId: string;
|
||||
@@ -123,6 +132,7 @@ export class AgentsController {
|
||||
* @returns Agent status details
|
||||
*/
|
||||
@Get(":agentId/status")
|
||||
@Throttle({ status: { limit: 200, ttl: 60000 } })
|
||||
async getAgentStatus(@Param("agentId") agentId: string): Promise<{
|
||||
agentId: string;
|
||||
taskId: string;
|
||||
@@ -181,6 +191,7 @@ export class AgentsController {
|
||||
* @returns Success message
|
||||
*/
|
||||
@Post(":agentId/kill")
|
||||
@Throttle({ strict: { limit: 10, ttl: 60000 } })
|
||||
@HttpCode(200)
|
||||
async killAgent(@Param("agentId") agentId: string): Promise<{ message: string }> {
|
||||
this.logger.warn(`Received kill request for agent: ${agentId}`);
|
||||
@@ -204,6 +215,7 @@ export class AgentsController {
|
||||
* @returns Summary of kill operation
|
||||
*/
|
||||
@Post("kill-all")
|
||||
@Throttle({ strict: { limit: 10, ttl: 60000 } })
|
||||
@HttpCode(200)
|
||||
async killAllAgents(): Promise<{
|
||||
message: string;
|
||||
|
||||
Reference in New Issue
Block a user