Resumen
Endpoint privado que recibe alertas desde el Agent local. Los agentes (dev-observatory, dev-auto-provision, etc.) lo invocan para reportar estado de targets (dispositivos monitoreados, racks, etc.).
Endpoint: POST /api/agent/alert
Módulo: terminal.api.sentinel (función receive_agent_alert)
Autenticación: JWT de Agent (Bearer token). El token codifica agent_id, tenant_id, email.
Requisitos de seguridad (s104) — Tenant isolation fix
Problema histórico: El endpoint confiaba en el tenant_id del body JSON en vez del JWT firmado. Esto permitía a un Agent con token de tenant A escribir alertas sobre targets de tenant B (bypass de RLS).
Fix (s104, 2026-06-02):
- Añadir validación explícita:
if agent_data["tenant_id"] != payload.tenant_id: return 401, {"error": "Tenant ID mismatch"}. - Usar
agent_data["tenant_id"](del JWT) para filtrar elMonitoringTarget, no el del body.
Flujo
- Cliente (Agent) invoca POST con Bearer token + JSON body.
- Parsear JWT → extraer
agent_data = {agent_id, tenant_id, email}. - Parsear body → extraer
AgentAlertSchema = {agent_id, tenant_id, target_id, alert_type, message, timestamp}. - Validar
agent_data["agent_id"] == payload.agent_id→ 401 si falla. - NUEVO s104: Validar
agent_data["tenant_id"] == payload.tenant_id→ 401 si falla. - Buscar target:
MonitoringTarget.objects.filter(id=payload.target_id, organization_id=agent_data["tenant_id"])(usar JWT tenant, no body). - Si existe, crear
MonitoringAlert(nota: hay un bug preexistente aquí, ver abajo). - Response 200 o error.
Campos del schema
class AgentAlertSchema(BaseModel):
agent_id: str
tenant_id: int # Ahora se valida contra el JWT
target_id: int
alert_type: str # "warning", "critical", "info", etc.
message: str
timestamp: str # ISO 8601
Bug preexistente (fuera de alcance s104)
La creación de MonitoringAlert en el happy path pasa kwargs inexistentes (alert_type, message). El modelo no los acepta → error 500. El endpoint nunca ha creado una alerta correctamente. Anotado para backlog.
Tests
tests/api/test_sentinel.py::test_alert_rejects_body_tenant_spoofing— Tenant mismatch → 401, sin alerta creada.tests/api/test_sentinel.py::test_alert_matching_tenant_passes_guard— Tenant match → pasa el guard (luego 404 por target no existe, que demuestra que no fue rechazado antes).
Véase también
- [[entity—terminal—model—agent-instance]]
- [[entity—monitoring—model—monitoring-alert]]
- [[entity—monitoring—model—monitoring-target]]
- [[entity—terminal—service—generate-agent-token]]
- [[feature—security—s104-auditoria-suprema-fixes-core]]
- [[concept—saas—multi-tenancy]]
Referenciado desde
- Decision · Auditoría Suprema: 4 hallazgos ALTA confirmados en core
- Feature s104 · Auditoría Suprema — 4 arreglos de seguridad en el núcleo
- Incident · Auditoría Suprema (s104): Mini-tanda de arreglos de seguridad core
- Mega-auditoría B-16 (27-09-2026): un Agente secundario recibía las credenciales SNMP de todos los equipos