Integre sistemas externos con EVA
API de integración: PAT, extract report_core, alta de proyecto/escenario, ingest de hallazgos y jobs de retest. El runner on-prem se opera con una imagen publicada y un PAT. Esta guía describe solo esas operaciones.
Tres superficies, tres credenciales
No mezcle JWT de sesión, PAT de reportería y PAT de runner. Cada uno autentica un conjunto distinto de rutas.
| Superficie | Quién | Credencial | Para qué |
|---|---|---|---|
| UI humana | Persona en el navegador | JWT de sesión (cookies BFF) | Crear, listar y revocar tokens; cola de retest; estados |
| API extract / ingest | Cliente de reportería o escáner | PAT con extract y/o ingest | Índice, snapshot report_core (GET o batch) e ingest de hallazgos/aspectos |
| API retest | Runner Nuclei/Nmap | PAT con retest_read + retest_write | Jobs opacos de retest automático |
El JWT de sesión no autentica extract, ingest ni retest. El PAT no autentica el CRUD de tokens. Un PAT solo-extract no autentica ingest ni retest. El tenant del runner sale del PAT; la imagen no envía X-Tenant-Id.
Contratos congelados
eva.integration.report.v1
Índice + GET de un escenario o batch de hasta 10. Sin binarios, sin emails, sin SQL.
eva.integration.projects.v1
Un POST idempotente. Crea proyecto y enlaza escenario si faltan. Acepta client_emails; sella origin=integration.
eva.integration.ingest.v1
Cuatro métodos. Hallazgos siempre en draft. Identidad por nombre + código.
eva.integration.retest.v1
Pending, claim, heartbeat y result. El runner nunca cierra el hallazgo.
Imagen Nuclei / Nmap
Registro privado, tag versionado, linux/amd64. Health local /health y /ready. El cliente no construye.
Métodos de ingest (v1)
| # | Ruta | Body | Éxito |
|---|---|---|---|
| 1 | POST /api/v1/integrations/ingest/vulnerabilities | JSON de un hallazgo | 201 |
| 2 | POST /api/v1/integrations/ingest/vulnerabilities.csv | multipart file | 200 (parcial) |
| 3 | POST /api/v1/integrations/ingest/positive-aspects | JSON de un aspecto | 201 |
| 4 | POST /api/v1/integrations/ingest/positive-aspects.csv | multipart file | 200 |
Además (scope ingest): POST /api/v1/integrations/projects (ensure, 200 / 201). Scope extract: GET /api/v1/integrations/reports/index (200), GET /api/v1/integrations/reports/extract (200 / 304) y POST /api/v1/integrations/reports/extract-batch (200 parcial). Y las cuatro rutas de retest (scopes retest_read / retest_write).
Base URL
Extract, ingest y retest van directo al backend Flask. No hay BFF de Next para estas rutas. Sustituya el host por el de su entorno:
https://api.ejemplo.com/api/v1/integrations/…
Laboratorio local típico: http://localhost:8002.
Camino recomendado
- Cree un PAT en Cuenta → Configuración → Integración con los alcances que necesita.
- Guarde el secreto una sola vez. EVA no lo vuelve a mostrar.
- Pruebe extract, ensure o ingest con curl. Compare con los JSON de examples/.
- Si opera un runner: PAT
retest_read+retest_write, luegodocker pullde la imagen publicada. No compile. - Revogue el token de prueba. El mismo curl debe devolver 401.
Patrón HTTP
- Lectura: 200.
- Alta JSON unitaria: 201.
- CSV por lotes: 200 aunque fallen todas las filas (éxito parcial en el cuerpo).
- No hay 202 en v1.
- Validación: 422, no 400.
- Envelope de error:
{ "code", "message", "details" }. - Extract/ingest: allowlist CIDR del PAT (vacío = cualquier IP) y cupo 60/min → 403
INTEGRATION_IP_DENIED/ 429INTEGRATION_RATE_LIMITED. Retest y el runner no usan esas barreras.