orquestador/specs/SECURITY.md

114 lines
6.7 KiB
Markdown

# Seguridad T07
Para la POC sin Keycloak, el perfil explícito `demo-token` permite un secreto fijo
según [POC_AUTH.md](POC_AUTH.md) y ADR-023. La validación JWT de esta guía describe
el modo normal, activo cuando no se selecciona ese perfil.
El servicio valida tokens RS256 mediante JWKS, emisor exacto, audiencia configurada,
expiración obligatoria y sujeto no vacío. También valida nbf cuando está presente;
el validador temporal de Spring admite 60 segundos de desfase. Las pruebas usan
tokens RSA realmente firmados y un servidor JWKS local. No acreditan todavía una
emisión real de Keycloak controlms: faltan un token de prueba y su configuración
de audiencia/claims, sin necesidad de entregar contraseñas al repositorio.
`JWT_AUDIENCE` identifica la audiencia y el cliente cuyos roles se aceptan desde
`resource_access`. También se aceptan `realm_access.roles`. Roles de otros clientes
y el claim OAuth `scope` no conceden permisos técnicos. `JWT_BUSINESS_SCOPE_CLAIM`
selecciona el claim de negocio (por defecto `business_scope`); debe ser un string
no vacío. Identidad, roles y ámbito proceden exclusivamente del JWT verificado.
## Administración
`FLOW_ADMIN_ENABLED=false` mantiene deshabilitados los controladores administrativos.
Para habilitarlos se necesita un usuario DB de ejecución restringido, credenciales
de migración separadas, catálogo confiable y `ADMIN_BUSINESS_SCOPES` con ámbitos
permitidos separados por comas. Una lista vacía deniega todas las operaciones.
Los flujos y tipos son un catálogo global: pertenecer a uno de esos ámbitos autoriza
administrarlo según el rol; no implica aislamiento de flujos por tenant.
| Operación implementada | Rol requerido |
|---|---|
| POST /api/v1/admin/flows; PUT /api/v1/admin/flows/{id} | FLOW_EDITOR |
| POST /api/v1/admin/flows/{id}/validate | FLOW_EDITOR o FLOW_PUBLISHER |
| POST /api/v1/admin/flows/{id}/publish | FLOW_PUBLISHER |
| POST /api/v1/admin/flows/{id}/retire | FLOW_ADMIN |
| PUT /api/v1/admin/request-types/{key}/active-flow | FLOW_ADMIN |
Edición, publicación, retiro y activación requieren un ETag fuerte `If-Match`.
Ausente: 428; sintaxis inválida: 400; revisión obsoleta: 412. Editar un flujo publicado
retorna 409. JSON inválido/duplicado: 400; definición fuera de schema: 422;
cuerpo superior a 1 MiB: 413. Respuestas de error no exponen SQL ni tokens y llevan
un correlationId generado por el servidor. Sesiones y caché de peticiones deshabilitadas.
`config/publication-catalog.json` es configuración de despliegue de solo lectura en
Docker. No puede reemplazarse desde HTTP. El ejemplo registra ANALISTA y ningún
handler, integración ni documento; no simula proveedores ni permite publicar
acciones no registradas. Reiniciar aplica una nueva configuración. Simulación y
resolución siguen pendientes de sus tareas funcionales; la matriz de roles no
constituye una implementación de esas rutas.
## Recursos de negocio
`ResourceAccess` exige propietario (`sub`) **y** ámbito coincidentes para solicitud,
ejecución, documento y auditoría. El adapter resuelve los tres últimos contra su
solicitud padre en PostgreSQL. Recurso inexistente o ajeno retorna el mismo 404;
FLOW_ADMIN no permite eludir esta política. La conciliación tiene una autorización
separada: EXECUTION_OPERATOR y mismo ámbito, aunque el propietario sea otro.
T08 integra esta puerta en la consulta de solicitudes y filtra también propietario/ámbito
en el SELECT que devuelve los datos. PersistenceAccessConfiguration comparte codec,
FlowStore, ResourceAccess y la verificación DB cuando administración o solicitudes
estén habilitadas; REQUEST_API_ENABLED es independiente del interruptor administrativo.
T09/T12/T13/T15 deben reutilizar la puerta antes de devolver datos o ejecutar comandos.
Las pruebas T07 de ejecución/documento/auditoría usan un controlador exclusivo de test,
fuera del paquete escaneado y ausente del JAR; sus endpoints funcionales siguen pendientes.
T08 prueba POST/GET reales de solicitudes (REQUESTS.md). No se acepta identidad en cuerpos.
## PostgreSQL externo
Configurar `DB_USERNAME`/`DB_PASSWORD` para un rol LOGIN sin privilegios elevados,
sin propiedad ni CREATE en el schema orchestrator, sin pertenencia a roles elevados.
Configurar `DB_MIGRATION_USERNAME`/`DB_MIGRATION_PASSWORD` para el propietario que
aplica Flyway. El DBA provisiona ambos; la aplicación no crea roles automáticamente.
Después de las migraciones, el propietario concede los permisos de V2 mediante:
```sql
SELECT orchestrator.grant_runtime_access('orchestrator_app'::name);
```
El nombre es ilustrativo: el rol debe existir previamente. `RuntimeRoleVerifier`
rechaza al iniciar administración un runtime elevado, propietario, con DDL en el
schema, capaz de modificar historiales append-only o acceder a flyway_schema_history.
Esta comprobación no configura permisos de otras bases/schemas: el DBA controla
también los permisos heredados de PUBLIC, particularmente en PostgreSQL 9.6.
No cambiar permisos globales del servidor para ejecutar las pruebas.
Prueba reproducible: `mvnw.cmd clean verify -Pmigration-tests-external`, con
MIGRATION_TEST_DB_URL/USER/PASSWORD en entorno de proceso. Solo admite la base
orquestador_test. T07 crea schema t07_<UUID> y rol LOGIN t07_runtime_<UUID>, contraseña
aleatoria y concesiones limitadas; los elimina en AfterAll. Las pruebas se conectan
con ese rol real, no con SET ROLE ni una simulación de permisos. Sin perfil externo,
verify requiere Docker y usa PostgreSQL de Testcontainers.
T09 integra ResourceAccess en aceptación de eventos y vuelve a filtrar propietario/
ámbito bajo SELECT FOR UPDATE. allowedRoles del flujo se comprueba para eventos
nuevos. El replay requiere acceso actual y sujeto original, pero no vuelve a evaluar
roles/guardias: solo consulta una aceptación anterior. actor_snapshot guarda atributos
mínimos verificados; nunca JWT. Ver EVENTS.md.
T10: GET de ejecución usa ResourceAccess y repite owner/scope en la consulta SQL;
no devuelve inputs, identidad snapshot, leases ni respuestas crudas. WORKER_ENABLED
habilita infraestructura común y RuntimeRoleVerifier incluso con ambas APIs apagadas.
El worker usa identidad mínima persistida al aceptar, no reutiliza JWT vencidos.
## T15: historial y métricas
El historial de solicitudes exige propietario y businessScope iguales al JWT;
FLOW_ADMIN/EXECUTION_OPERATOR no obtienen acceso a historial ajeno. La proyección
no entrega evidencia de conciliación ni resultados completos de proveedores.
/actuator/metrics y descendientes requieren EXECUTION_OPERATOR y ámbito autorizado
en ADMIN_BUSINESS_SCOPES, incluso con FLOW_ADMIN_ENABLED=false. Las tres rutas
health/liveness/readiness permanecen públicas sin detalles. Resto de /actuator/**
se deniega. Ver OBSERVABILITY.md para etiquetas permitidas, cursor y logs.