feat: implement security agent service with webhook integration and error handling

This commit is contained in:
bryancito1090 2026-09-16 16:54:44 -05:00
parent 3676637de3
commit 4b14eaf21b
5 changed files with 86 additions and 0 deletions

View File

@ -0,0 +1,6 @@
import { InjectionToken } from '@angular/core';
export const SECURITY_AGENT_WEBHOOK_URL = new InjectionToken<string>('SECURITY_AGENT_WEBHOOK_URL', {
providedIn: 'root',
factory: () => 'https://n8n.bryan-bano.com/webhook/security-agent'
});

View File

@ -0,0 +1,38 @@
export type SimulationMode = 'PURPLE_TEAM' | 'EASM' | 'SOAR';
export type SecurityVerdict = 'SAFE' | 'ATTENTION_REQUIRED' | 'CRITICAL_THREAT';
export interface SecurityAgentParameters {
readonly auto_isolate?: boolean;
readonly scan_depth?: 'quick' | 'full';
}
export interface SecurityAgentRequest {
readonly mode: SimulationMode;
readonly target: string;
readonly requested_by: string;
readonly parameters?: SecurityAgentParameters;
}
export interface SecurityExecutionSummary {
readonly risk_score: number;
readonly verdict: SecurityVerdict;
readonly mitre_techniques: string[];
readonly containment_executed: boolean;
readonly mitigation_time_ms: number;
}
export interface SecurityEvidence {
readonly sha256_hash: string;
readonly report_url: string;
}
export interface SecurityAgentResponse {
readonly success: boolean;
readonly execution_id: string;
readonly simulation_id: string;
readonly timestamp: string;
readonly mode: SimulationMode;
readonly target: string;
readonly summary: SecurityExecutionSummary;
readonly evidence: SecurityEvidence;
}

View File

@ -0,0 +1,6 @@
import { Observable } from 'rxjs';
import { SecurityAgentRequest, SecurityAgentResponse } from '../models/security.model';
export abstract class SecurityAgentPort {
abstract triggerSimulation(payload: SecurityAgentRequest): Observable<SecurityAgentResponse>;
}

View File

@ -0,0 +1 @@
export * from '../domain/models/security.model';

View File

@ -0,0 +1,35 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { SecurityAgentRequest, SecurityAgentResponse } from '../domain/models/security.model';
import { SecurityAgentPort } from '../domain/ports/security-agent.port';
import { SECURITY_AGENT_WEBHOOK_URL } from '../core/tokens/security-agent-config.token';
@Injectable({
providedIn: 'root'
})
export class SecurityAgentService implements SecurityAgentPort {
private readonly http = inject(HttpClient);
private readonly webhookUrl = inject(SECURITY_AGENT_WEBHOOK_URL);
triggerSimulation(payload: SecurityAgentRequest): Observable<SecurityAgentResponse> {
return this.http.post<SecurityAgentResponse>(this.webhookUrl, payload).pipe(
catchError((error: HttpErrorResponse) => this.handleError(error))
);
}
private handleError(error: HttpErrorResponse): Observable<never> {
let errorMessage = 'Ocurrió un error inesperado al conectar con el orquestador n8n.';
if (error.status === 429) {
errorMessage = 'Límite de tasa excedido (Rate Limit: máx 10 peticiones cada 5 min).';
} else if (error.status === 400) {
errorMessage = error.error?.message || 'Payload o parámetros inválidos.';
} else if (error.status === 0) {
errorMessage = 'Error de red o conexión rechazada con el servidor n8n.';
} else if (error.status >= 500) {
errorMessage = error.error?.message || `Error interno del orquestador n8n (HTTP ${error.status}).`;
}
return throwError(() => new Error(errorMessage));
}
}