1432 lines
56 KiB
Markdown
1432 lines
56 KiB
Markdown
# Aegis v2 — Plan de Tareas: Sistema de Tests de Validación Red Team / Blue Team
|
|
|
|
> **Instrucciones de uso**: Cada tarea (T-XXX) es una unidad de trabajo independiente que debe
|
|
> resultar en un commit. Están ordenadas secuencialmente — cada tarea puede depender de las
|
|
> anteriores pero nunca de las posteriores. Cada tarea incluye una sección de validación:
|
|
> no hagas commit hasta que todos los checks pasen.
|
|
>
|
|
> **Contexto**: Este plan extiende el MVP de Aegis (36 tareas completadas) para implementar
|
|
> un sistema completo de validación de tests de seguridad inspirado en [Validato](https://validato.io/).
|
|
> La idea central: cada TTP de MITRE ATT&CK tiene tests que son ejecutados por el Red Team
|
|
> y validados/detectados por el Blue Team. Cada test tiene pestañas separadas para evidencias
|
|
> de ataque (Red Team) y detección (Blue Team), con un flujo de validación por managers de
|
|
> ambos equipos que actualiza progresivamente el estado del test y de la TTP.
|
|
|
|
---
|
|
|
|
## Visión General del Flujo de Validación
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ CICLO DE VIDA DE UN TEST │
|
|
│ │
|
|
│ ┌──────┐ ┌──────────────┐ ┌─────────────────┐ ┌───────────┐ │
|
|
│ │ DRAFT│───▶│RED_EXECUTING │───▶│ BLUE_EVALUATING │───▶│ IN_REVIEW │ │
|
|
│ └──────┘ └──────────────┘ └─────────────────┘ └───────────┘ │
|
|
│ │ │
|
|
│ ┌────────────────────┤ │
|
|
│ ▼ ▼ │
|
|
│ ┌──────────┐ ┌──────────┐ │
|
|
│ │ REJECTED │ │VALIDATED │ │
|
|
│ └──────────┘ └──────────┘ │
|
|
│ │ │
|
|
│ └──────▶ Vuelve a DRAFT │
|
|
└─────────────────────────────────────────────────────────────────────────┘
|
|
|
|
Estados del Test:
|
|
- draft: Creado, pendiente de ejecución por Red Team
|
|
- red_executing: Red Team documenta ataque y sube evidencias
|
|
- blue_evaluating: Blue Team documenta detección y sube evidencias
|
|
- in_review: Ambos managers revisan evidencias
|
|
- validated: Aprobado por ambos managers
|
|
- rejected: Rechazado — vuelve a draft para rehacer
|
|
|
|
Roles involucrados:
|
|
- red_tech: Crea tests, documenta ataques, sube evidencias de ataque
|
|
- blue_tech: Documenta detección, sube evidencias de detección
|
|
- red_lead: Valida/rechaza la parte de Red Team
|
|
- blue_lead: Valida/rechaza la parte de Blue Team
|
|
- admin: Acceso total
|
|
```
|
|
|
|
---
|
|
|
|
## Catálogo de Tests Básicos por TTP
|
|
|
|
Los tests básicos se obtienen de varias fuentes:
|
|
1. **Atomic Red Team** (Red Canary): repositorio open-source con tests atómicos mapeados a MITRE ATT&CK
|
|
2. **MITRE ATT&CK procedures**: procedimientos documentados en la propia base de datos de MITRE
|
|
3. **Tests personalizados**: creados manualmente por los equipos según su entorno
|
|
|
|
---
|
|
|
|
## FASE 10 — Evolución del Modelo de Datos para Red/Blue Team
|
|
|
|
### T-100: Ampliar estados del Test (TestState)
|
|
|
|
**Objetivo:** Añadir los nuevos estados al ciclo de vida del test que permitan diferenciar las fases de Red Team ejecutando, Blue Team evaluando, y revisión por managers.
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `backend/app/models/enums.py`
|
|
|
|
**Cambios en `TestState`:**
|
|
|
|
```python
|
|
class TestState(str, enum.Enum):
|
|
draft = "draft"
|
|
red_executing = "red_executing" # NUEVO: Red Team documentando ataque
|
|
blue_evaluating = "blue_evaluating" # NUEVO: Blue Team evaluando detección
|
|
in_review = "in_review"
|
|
validated = "validated"
|
|
rejected = "rejected"
|
|
```
|
|
|
|
**Generar migración Alembic** para actualizar el enum en PostgreSQL.
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `alembic upgrade head` aplica la migración sin errores
|
|
- [ ] Los tests existentes con estados antiguos siguen funcionando
|
|
- [ ] Se pueden crear tests con los nuevos estados vía SQL directo
|
|
- [ ] `alembic downgrade -1` revierte sin errores
|
|
|
|
---
|
|
|
|
### T-101: Modelo EvidenceTeam — separar evidencias Red/Blue
|
|
|
|
**Objetivo:** Añadir un campo `team` a las evidencias para distinguir si pertenecen al Red Team (evidencia de ataque) o al Blue Team (evidencia de detección).
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `backend/app/models/enums.py` — añadir enum `TeamSide`
|
|
- `backend/app/models/evidence.py` — añadir campo `team`
|
|
|
|
**Nuevo enum:**
|
|
|
|
```python
|
|
class TeamSide(str, enum.Enum):
|
|
red = "red"
|
|
blue = "blue"
|
|
```
|
|
|
|
**Nuevo campo en Evidence:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|-----------|-------------------|----------------------------------|
|
|
| team | Enum(TeamSide) | not null, default "red" |
|
|
| notes | Text | nullable (notas sobre la evidencia) |
|
|
|
|
**Generar migración.** El default `red` asegura que las evidencias existentes se asignen correctamente.
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `alembic upgrade head` añade la columna `team` y `notes` a la tabla `evidences`
|
|
- [ ] Las evidencias existentes tienen `team = 'red'` por defecto
|
|
- [ ] Se puede insertar una evidencia con `team = 'blue'`
|
|
- [ ] La columna `notes` acepta texto largo
|
|
|
|
---
|
|
|
|
### T-102: Campos de validación dual en Test (red_lead + blue_lead)
|
|
|
|
**Objetivo:** Extender el modelo Test para soportar validación independiente por Red Lead y Blue Lead, de manera que un test solo pase a `validated` cuando ambos managers lo aprueban.
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `backend/app/models/test.py`
|
|
|
|
**Nuevos campos:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|----------------------|----------|----------------------------------------|
|
|
| red_validated_by | UUID | FK → users.id, nullable |
|
|
| red_validated_at | DateTime | nullable |
|
|
| red_validation_status| String | nullable (pending/approved/rejected) |
|
|
| red_validation_notes | Text | nullable |
|
|
| blue_validated_by | UUID | FK → users.id, nullable |
|
|
| blue_validated_at | DateTime | nullable |
|
|
| blue_validation_status| String | nullable (pending/approved/rejected) |
|
|
| blue_validation_notes| Text | nullable |
|
|
| red_summary | Text | nullable (resumen del ataque por red) |
|
|
| blue_summary | Text | nullable (resumen de detección por blue)|
|
|
| detection_result | Enum(TestResult) | nullable (resultado de detección blue) |
|
|
| attack_success | Boolean | nullable (si el ataque tuvo éxito) |
|
|
|
|
**Relaciones nuevas:**
|
|
|
|
```python
|
|
red_validator = relationship("User", foreign_keys=[red_validated_by])
|
|
blue_validator = relationship("User", foreign_keys=[blue_validated_by])
|
|
```
|
|
|
|
**Generar migración.**
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `alembic upgrade head` crea las nuevas columnas sin errores
|
|
- [ ] Los tests existentes tienen los nuevos campos como `null`
|
|
- [ ] Se puede actualizar `red_validation_status` y `blue_validation_status` independientemente
|
|
- [ ] Las FKs a `users.id` funcionan correctamente
|
|
|
|
---
|
|
|
|
### T-103: Modelo TestTemplate — catálogo de tests predefinidos
|
|
|
|
**Objetivo:** Crear un modelo para almacenar plantillas de tests predefinidos (basados en Atomic Red Team, MITRE procedures, etc.) que los usuarios pueden instanciar como tests reales.
|
|
|
|
**Archivo a crear:** `backend/app/models/test_template.py`
|
|
|
|
**Campos:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|--------------------|----------|--------------------------------------------|
|
|
| id | UUID | PK, default uuid4 |
|
|
| mitre_technique_id | String | not null (ej: "T1059.001") |
|
|
| name | String | not null |
|
|
| description | Text | nullable |
|
|
| source | String | not null (ej: "atomic_red_team", "mitre", "custom") |
|
|
| source_url | String | nullable (URL al test original) |
|
|
| attack_procedure | Text | nullable (procedimiento de ataque sugerido)|
|
|
| expected_detection | Text | nullable (qué debería detectar blue team) |
|
|
| platform | String | nullable (windows, linux, macos) |
|
|
| tool_suggested | String | nullable (herramienta sugerida) |
|
|
| severity | String | nullable (low, medium, high, critical) |
|
|
| atomic_test_id | String | nullable (ID del test en Atomic Red Team) |
|
|
| is_active | Boolean | default True |
|
|
| created_at | DateTime | default utcnow |
|
|
|
|
**Actualizar** `models/__init__.py` para importar TestTemplate.
|
|
|
|
**Generar migración.**
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `alembic upgrade head` crea la tabla `test_templates`
|
|
- [ ] Se puede insertar un template con todos los campos
|
|
- [ ] El campo `source` acepta los valores esperados
|
|
- [ ] La tabla soporta múltiples templates para la misma técnica MITRE
|
|
|
|
---
|
|
|
|
### T-104: Schemas Pydantic para los nuevos modelos
|
|
|
|
**Objetivo:** Crear schemas de request/response para los modelos modificados y nuevos.
|
|
|
|
**Archivos a crear/modificar:**
|
|
|
|
- `backend/app/schemas/test.py` — actualizar con nuevos campos
|
|
- `backend/app/schemas/evidence.py` — añadir `team` y `notes`
|
|
- `backend/app/schemas/test_template.py` — nuevo
|
|
|
|
**Schemas de Test actualizados:**
|
|
|
|
- `TestOut`: añadir campos de validación dual (`red_validated_by`, `blue_validated_by`, `red_validation_status`, `blue_validation_status`, `red_summary`, `blue_summary`, etc.)
|
|
- `TestRedUpdate`: name, description, procedure_text, tool_used, attack_success, red_summary (campos que rellena Red Team)
|
|
- `TestBlueUpdate`: detection_result, blue_summary (campos que rellena Blue Team)
|
|
- `TestRedValidate`: red_validation_status (approved/rejected), red_validation_notes
|
|
- `TestBlueValidate`: blue_validation_status (approved/rejected), blue_validation_notes
|
|
|
|
**Schemas de Evidence actualizados:**
|
|
|
|
- `EvidenceOut`: añadir `team` y `notes`
|
|
- `EvidenceUpload`: añadir `team` (requerido) y `notes` (opcional)
|
|
|
|
**Schemas de TestTemplate:**
|
|
|
|
- `TestTemplateOut`: todos los campos
|
|
- `TestTemplateCreate`: para crear templates personalizados
|
|
- `TestTemplateSummary`: id, mitre_technique_id, name, source, platform, severity (para listados)
|
|
- `TestTemplateInstantiate`: template_id, technique_id (para crear un test real desde un template)
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Todos los schemas se importan sin errores
|
|
- [ ] `TestOut` incluye los campos de validación dual
|
|
- [ ] `TestTemplateCreate` valida correctamente los campos requeridos
|
|
- [ ] `EvidenceOut` incluye `team` y `notes`
|
|
|
|
---
|
|
|
|
## FASE 11 — Lógica de Negocio del Flujo Red/Blue
|
|
|
|
### T-105: Servicio de transiciones de estado del Test
|
|
|
|
**Objetivo:** Crear un servicio que controle las transiciones de estado válidas del test y garantice que solo se puedan hacer los cambios permitidos.
|
|
|
|
**Archivo a crear:** `backend/app/services/test_workflow_service.py`
|
|
|
|
**Transiciones válidas:**
|
|
|
|
```python
|
|
VALID_TRANSITIONS = {
|
|
TestState.draft: [TestState.red_executing],
|
|
TestState.red_executing: [TestState.blue_evaluating],
|
|
TestState.blue_evaluating: [TestState.in_review],
|
|
TestState.in_review: [TestState.validated, TestState.rejected],
|
|
TestState.rejected: [TestState.draft],
|
|
TestState.validated: [], # estado final (o puede reabrirse)
|
|
}
|
|
```
|
|
|
|
**Funciones a implementar:**
|
|
|
|
- `can_transition(test: Test, target_state: TestState) -> bool`
|
|
- `transition_state(db, test, target_state, user) -> Test` — valida transición, cambia estado, log de auditoría
|
|
- `submit_red_evidence(db, test, user) -> Test` — marca como `blue_evaluating` cuando Red Team termina
|
|
- `submit_blue_evidence(db, test, user) -> Test` — marca como `in_review` cuando Blue Team termina
|
|
- `validate_as_red_lead(db, test, user, status, notes) -> Test` — valida parte Red
|
|
- `validate_as_blue_lead(db, test, user, status, notes) -> Test` — valida parte Blue
|
|
- `check_dual_validation(db, test) -> Test` — si ambos aprobaron, pasa a validated; si alguno rechazó, pasa a rejected
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Transición draft → red_executing funciona
|
|
- [ ] Transición draft → validated falla (no permitida)
|
|
- [ ] Transición red_executing → blue_evaluating funciona
|
|
- [ ] `check_dual_validation` pasa a validated solo si ambos managers aprobaron
|
|
- [ ] `check_dual_validation` pasa a rejected si algún manager rechazó
|
|
- [ ] Cada transición genera un log de auditoría
|
|
|
|
---
|
|
|
|
### T-106: Actualizar servicio de recalculación de status
|
|
|
|
**Objetivo:** Mejorar `status_service.py` para tener en cuenta los nuevos estados y la validación dual.
|
|
|
|
**Archivo a modificar:** `backend/app/services/status_service.py`
|
|
|
|
**Nueva lógica:**
|
|
|
|
```python
|
|
def recalculate_technique_status(db, technique):
|
|
tests = technique.tests
|
|
if not tests:
|
|
technique.status_global = TechniqueStatus.not_evaluated
|
|
elif all(t.state == TestState.validated for t in tests):
|
|
# Todos validados — revisar resultados de detección
|
|
results = [t.detection_result for t in tests if t.detection_result]
|
|
if all(r == "detected" for r in results):
|
|
technique.status_global = TechniqueStatus.validated
|
|
elif any(r == "partially_detected" for r in results):
|
|
technique.status_global = TechniqueStatus.partial
|
|
else:
|
|
technique.status_global = TechniqueStatus.not_covered
|
|
elif any(t.state == TestState.validated for t in tests):
|
|
technique.status_global = TechniqueStatus.partial
|
|
else:
|
|
technique.status_global = TechniqueStatus.in_progress
|
|
db.commit()
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Sin tests → `not_evaluated`
|
|
- [ ] Todos validated con detection=detected → `validated`
|
|
- [ ] Algunos validated, otros en progreso → `partial`
|
|
- [ ] Todos en estados intermedios → `in_progress`
|
|
- [ ] Todos validated con detection=not_detected → `not_covered`
|
|
|
|
---
|
|
|
|
### T-107: Servicio de importación de Atomic Red Team
|
|
|
|
**Objetivo:** Crear un servicio que importe tests predefinidos desde el repositorio de Atomic Red Team de Red Canary y los almacene como TestTemplates.
|
|
|
|
**Archivo a crear:** `backend/app/services/atomic_import_service.py`
|
|
|
|
**Lógica:**
|
|
|
|
1. Descargar/parsear el índice de Atomic Red Team desde GitHub (`https://github.com/redcanaryco/atomic-red-team`)
|
|
2. El repositorio contiene ficheros YAML organizados por técnica MITRE (`atomics/T1059.001/T1059.001.yaml`)
|
|
3. Para cada test atómico:
|
|
- Extraer `name`, `description`, `supported_platforms`, `executor` (tipo y command)
|
|
- Mapear a la técnica MITRE correspondiente
|
|
- Crear un `TestTemplate` con `source = "atomic_red_team"`
|
|
4. No duplicar templates que ya existen (comparar por `atomic_test_id`)
|
|
5. Log de auditoría con resumen
|
|
|
|
**Nota:** En el MVP, se puede hacer una importación simplificada usando la API de GitHub para obtener los YAML directamente, o descargar un JSON resumen pre-generado.
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Ejecutar la importación crea TestTemplates en la BD
|
|
- [ ] Cada template tiene `source = "atomic_red_team"` y datos válidos
|
|
- [ ] Ejecutar dos veces no duplica templates
|
|
- [ ] Los templates se mapean correctamente a técnicas MITRE existentes
|
|
- [ ] Se importan al menos 50+ templates
|
|
|
|
---
|
|
|
|
## FASE 12 — Endpoints API Red/Blue
|
|
|
|
### T-108: Endpoints actualizados de Tests con flujo Red/Blue
|
|
|
|
**Objetivo:** Modificar y añadir endpoints al router de tests para soportar el nuevo flujo de trabajo.
|
|
|
|
**Archivo a modificar:** `backend/app/routers/tests.py`
|
|
|
|
**Endpoints nuevos/modificados:**
|
|
|
|
| Método | Ruta | Auth | Descripción |
|
|
|--------|-----------------------------------|----------------------|------------------------------------------------|
|
|
| GET | /tests | autenticado | Listar tests con filtros (state, technique_id) |
|
|
| POST | /tests | red_tech, admin | Crear test (nuevo o desde template) |
|
|
| POST | /tests/from-template | red_tech, admin | Crear test instanciando un template |
|
|
| GET | /tests/{id} | autenticado | Detalle con evidencias separadas red/blue |
|
|
| PATCH | /tests/{id}/red | red_tech, admin | Red Team actualiza su parte (procedure, tool, etc.) |
|
|
| PATCH | /tests/{id}/blue | blue_tech, admin | Blue Team actualiza su parte (detection, summary) |
|
|
| POST | /tests/{id}/submit-red | red_tech, admin | Red Team finaliza → pasa a blue_evaluating |
|
|
| POST | /tests/{id}/submit-blue | blue_tech, admin | Blue Team finaliza → pasa a in_review |
|
|
| POST | /tests/{id}/validate-red | red_lead, admin | Red Lead valida/rechaza parte red |
|
|
| POST | /tests/{id}/validate-blue | blue_lead, admin | Blue Lead valida/rechaza parte blue |
|
|
| POST | /tests/{id}/reopen | red_lead, blue_lead, admin | Reabrir test rechazado → draft |
|
|
| GET | /tests/{id}/timeline | autenticado | Timeline de cambios de estado del test |
|
|
|
|
**Detalle del endpoint GET /tests/{id}:**
|
|
|
|
La respuesta debe incluir:
|
|
```json
|
|
{
|
|
"id": "...",
|
|
"name": "...",
|
|
"state": "blue_evaluating",
|
|
"red_evidences": [...], // evidencias con team=red
|
|
"blue_evidences": [...], // evidencias con team=blue
|
|
"red_summary": "...",
|
|
"blue_summary": "...",
|
|
"attack_success": true,
|
|
"detection_result": "detected",
|
|
"red_validation_status": "approved",
|
|
"blue_validation_status": "pending",
|
|
"timeline": [...] // historial de cambios
|
|
}
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `POST /tests` crea un test en estado `draft`
|
|
- [ ] `POST /tests/from-template` crea un test con datos pre-rellenados del template
|
|
- [ ] `PATCH /tests/{id}/red` solo funciona si el test está en `red_executing`
|
|
- [ ] `PATCH /tests/{id}/blue` solo funciona si el test está en `blue_evaluating`
|
|
- [ ] `POST /tests/{id}/submit-red` cambia estado a `blue_evaluating`
|
|
- [ ] `POST /tests/{id}/submit-blue` cambia estado a `in_review`
|
|
- [ ] `POST /tests/{id}/validate-red` solo accesible por red_lead
|
|
- [ ] `POST /tests/{id}/validate-blue` solo accesible por blue_lead
|
|
- [ ] Cuando ambos validan como approved → test pasa a `validated`
|
|
- [ ] Cuando alguno rechaza → test pasa a `rejected`
|
|
- [ ] `POST /tests/{id}/reopen` solo funciona en tests `rejected`
|
|
- [ ] `GET /tests/{id}/timeline` retorna el historial ordenado cronológicamente
|
|
- [ ] Cada operación genera audit log
|
|
|
|
---
|
|
|
|
### T-109: Endpoints de Evidence con separación Red/Blue
|
|
|
|
**Objetivo:** Modificar el router de evidencias para soportar la separación por equipo.
|
|
|
|
**Archivo a modificar:** `backend/app/routers/evidence.py`
|
|
|
|
**Endpoints modificados:**
|
|
|
|
| Método | Ruta | Auth | Descripción |
|
|
|--------|-----------------------------------|-----------------|----------------------------------------------|
|
|
| POST | /tests/{test_id}/evidence | autenticado | Subir evidencia indicando team (red/blue) |
|
|
| GET | /tests/{test_id}/evidence | autenticado | Listar evidencias del test, filtrable por team |
|
|
| GET | /evidence/{id} | autenticado | Obtener URL pre-firmada |
|
|
| DELETE | /evidence/{id} | creador o admin | Eliminar evidencia (solo en estados editables)|
|
|
|
|
**Lógica de control:**
|
|
|
|
- Red Team solo puede subir evidencias `team=red` cuando el test está en `red_executing`
|
|
- Blue Team solo puede subir evidencias `team=blue` cuando el test está en `blue_evaluating`
|
|
- Admin puede subir en cualquier momento
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Un `red_tech` puede subir evidencia con `team=red` en estado `red_executing`
|
|
- [ ] Un `red_tech` NO puede subir evidencia con `team=blue`
|
|
- [ ] Un `blue_tech` puede subir evidencia con `team=blue` en estado `blue_evaluating`
|
|
- [ ] Un `blue_tech` NO puede subir evidencia con `team=red`
|
|
- [ ] `GET /tests/{id}/evidence?team=red` filtra correctamente
|
|
- [ ] `DELETE /evidence/{id}` solo permite borrar en estados editables
|
|
- [ ] Admin puede subir cualquier tipo de evidencia en cualquier momento
|
|
|
|
---
|
|
|
|
### T-110: Endpoints CRUD de TestTemplates
|
|
|
|
**Objetivo:** Crear endpoints para gestionar el catálogo de templates de tests.
|
|
|
|
**Archivo a crear:** `backend/app/routers/test_templates.py`
|
|
|
|
**Endpoints:**
|
|
|
|
| Método | Ruta | Auth | Descripción |
|
|
|--------|-----------------------------------|-----------------|----------------------------------------------|
|
|
| GET | /test-templates | autenticado | Listar templates con filtros |
|
|
| GET | /test-templates/{id} | autenticado | Detalle de un template |
|
|
| POST | /test-templates | admin | Crear template personalizado |
|
|
| PATCH | /test-templates/{id} | admin | Actualizar template |
|
|
| DELETE | /test-templates/{id} | admin | Desactivar template (soft delete) |
|
|
| GET | /test-templates/by-technique/{mitre_id} | autenticado | Templates para una técnica MITRE específica |
|
|
|
|
**Filtros del GET /test-templates:**
|
|
- `source`: atomic_red_team, mitre, custom
|
|
- `platform`: windows, linux, macos
|
|
- `severity`: low, medium, high, critical
|
|
- `mitre_technique_id`: filtrar por técnica
|
|
- `search`: búsqueda por nombre/descripción
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `GET /test-templates` retorna lista paginada
|
|
- [ ] `GET /test-templates?source=atomic_red_team` filtra por fuente
|
|
- [ ] `GET /test-templates?platform=windows` filtra por plataforma
|
|
- [ ] `GET /test-templates/by-technique/T1059.001` retorna templates para esa técnica
|
|
- [ ] `POST /test-templates` solo accesible por admin
|
|
- [ ] `DELETE /test-templates/{id}` hace soft delete (is_active=False)
|
|
- [ ] El filtro `search` busca en name y description
|
|
|
|
---
|
|
|
|
### T-111: Endpoint de importación de Atomic Red Team
|
|
|
|
**Objetivo:** Exponer la importación de Atomic Red Team como endpoint del sistema.
|
|
|
|
**Archivo a modificar:** `backend/app/routers/system.py`
|
|
|
|
**Endpoint:**
|
|
|
|
```
|
|
POST /api/v1/system/import-atomic-tests
|
|
Auth: admin only
|
|
Response: {"message": "Import completed", "imported": X, "skipped": Y, "errors": Z}
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `POST /system/import-atomic-tests` ejecuta la importación y retorna estadísticas
|
|
- [ ] Solo admin puede ejecutar
|
|
- [ ] Audit log registra la importación
|
|
- [ ] Ejecutar dos veces no duplica — incrementa `skipped`
|
|
|
|
---
|
|
|
|
## FASE 13 — Frontend: Tipos y API Clients
|
|
|
|
### T-112: Actualizar tipos TypeScript
|
|
|
|
**Objetivo:** Actualizar los tipos del frontend para reflejar los cambios del backend.
|
|
|
|
**Archivo a modificar:** `frontend/src/types/models.ts`
|
|
|
|
**Tipos a añadir/modificar:**
|
|
|
|
```typescript
|
|
// Actualizar TestState
|
|
export type TestState =
|
|
| "draft"
|
|
| "red_executing"
|
|
| "blue_evaluating"
|
|
| "in_review"
|
|
| "validated"
|
|
| "rejected";
|
|
|
|
// Nuevo tipo TeamSide
|
|
export type TeamSide = "red" | "blue";
|
|
|
|
// Actualizar Evidence
|
|
export interface Evidence {
|
|
id: string;
|
|
test_id: string;
|
|
file_name: string;
|
|
file_path: string;
|
|
sha256_hash: string;
|
|
uploaded_by: string | null;
|
|
uploaded_at: string;
|
|
team: TeamSide;
|
|
notes: string | null;
|
|
}
|
|
|
|
// Actualizar Test con campos duales
|
|
export interface Test {
|
|
// ... campos existentes ...
|
|
red_summary: string | null;
|
|
blue_summary: string | null;
|
|
attack_success: boolean | null;
|
|
detection_result: TestResult | null;
|
|
red_validation_status: ValidationStatus | null;
|
|
blue_validation_status: ValidationStatus | null;
|
|
red_validation_notes: string | null;
|
|
blue_validation_notes: string | null;
|
|
red_validated_by: string | null;
|
|
blue_validated_by: string | null;
|
|
red_evidences: Evidence[];
|
|
blue_evidences: Evidence[];
|
|
}
|
|
|
|
export type ValidationStatus = "pending" | "approved" | "rejected";
|
|
|
|
// Nuevo tipo TestTemplate
|
|
export interface TestTemplate {
|
|
id: string;
|
|
mitre_technique_id: string;
|
|
name: string;
|
|
description: string | null;
|
|
source: string;
|
|
source_url: string | null;
|
|
attack_procedure: string | null;
|
|
expected_detection: string | null;
|
|
platform: string | null;
|
|
tool_suggested: string | null;
|
|
severity: string | null;
|
|
atomic_test_id: string | null;
|
|
is_active: boolean;
|
|
created_at: string;
|
|
}
|
|
|
|
// Timeline
|
|
export interface TestTimelineEntry {
|
|
id: string;
|
|
action: string;
|
|
user: string;
|
|
timestamp: string;
|
|
details: Record<string, unknown>;
|
|
}
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] TypeScript compila sin errores
|
|
- [ ] Todos los tipos nuevos están exportados
|
|
- [ ] Los tipos coinciden con los schemas del backend
|
|
|
|
---
|
|
|
|
### T-113: Nuevos API clients
|
|
|
|
**Objetivo:** Crear/actualizar los clientes API del frontend para los nuevos endpoints.
|
|
|
|
**Archivos a crear/modificar:**
|
|
|
|
- `frontend/src/api/tests.ts` — actualizar con nuevos endpoints
|
|
- `frontend/src/api/evidence.ts` — actualizar con parámetro `team`
|
|
- `frontend/src/api/test-templates.ts` — nuevo
|
|
|
|
**Funciones nuevas en tests.ts:**
|
|
|
|
```typescript
|
|
export const createTestFromTemplate = (templateId: string, techniqueId: string) => ...
|
|
export const updateTestRed = (testId: string, data: RedUpdateData) => ...
|
|
export const updateTestBlue = (testId: string, data: BlueUpdateData) => ...
|
|
export const submitRedEvidence = (testId: string) => ...
|
|
export const submitBlueEvidence = (testId: string) => ...
|
|
export const validateAsRedLead = (testId: string, data: RedValidation) => ...
|
|
export const validateAsBlueLead = (testId: string, data: BlueValidation) => ...
|
|
export const reopenTest = (testId: string) => ...
|
|
export const getTestTimeline = (testId: string) => ...
|
|
```
|
|
|
|
**Funciones nuevas en evidence.ts:**
|
|
|
|
```typescript
|
|
export const uploadEvidence = (testId: string, file: File, team: TeamSide, notes?: string) => ...
|
|
export const getTestEvidences = (testId: string, team?: TeamSide) => ...
|
|
export const deleteEvidence = (evidenceId: string) => ...
|
|
```
|
|
|
|
**Funciones en test-templates.ts:**
|
|
|
|
```typescript
|
|
export const getTemplates = (filters?: TemplateFilters) => ...
|
|
export const getTemplateById = (id: string) => ...
|
|
export const getTemplatesByTechnique = (mitreId: string) => ...
|
|
export const createTemplate = (data: CreateTemplate) => ...
|
|
export const importAtomicTests = () => ...
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Todos los imports funcionan sin errores TypeScript
|
|
- [ ] Cada función envía la petición al endpoint correcto
|
|
- [ ] `uploadEvidence` incluye el campo `team` en FormData
|
|
- [ ] `getTestEvidences` envía el query param `team` correctamente
|
|
|
|
---
|
|
|
|
## FASE 14 — Frontend: Página de Test Rediseñada con Pestañas Red/Blue
|
|
|
|
### T-114: Componente TestDetailHeader
|
|
|
|
**Objetivo:** Crear el header del detalle del test con información del estado, progreso y acciones contextuales.
|
|
|
|
**Archivo a crear:** `frontend/src/components/test-detail/TestDetailHeader.tsx`
|
|
|
|
**Contenido:**
|
|
|
|
- Nombre del test y badge de estado con color
|
|
- Barra de progreso visual (5 pasos: draft → red → blue → review → validated)
|
|
- Nombre de la técnica asociada (link)
|
|
- Botones de acción contextuales según rol y estado:
|
|
- Red Tech en `red_executing`: botón "Submit to Blue Team"
|
|
- Blue Tech en `blue_evaluating`: botón "Submit for Review"
|
|
- Red Lead en `in_review`: botón "Approve/Reject Red"
|
|
- Blue Lead en `in_review`: botón "Approve/Reject Blue"
|
|
- Indicadores de validación dual (checkmarks para red_lead y blue_lead)
|
|
|
|
**Validación:**
|
|
|
|
- [ ] El header muestra toda la información correcta
|
|
- [ ] La barra de progreso refleja el estado actual
|
|
- [ ] Los botones aparecen solo cuando el rol y estado lo permiten
|
|
- [ ] Los indicadores de validación dual se actualizan correctamente
|
|
|
|
---
|
|
|
|
### T-115: Componente de pestañas Red Team / Blue Team
|
|
|
|
**Objetivo:** Crear el sistema de pestañas que separa las evidencias y el contenido entre Red Team y Blue Team.
|
|
|
|
**Archivo a crear:** `frontend/src/components/test-detail/TeamTabs.tsx`
|
|
|
|
**Estructura de pestañas:**
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ [🔴 Red Team] [🔵 Blue Team] [📋 Summary] [📜 Timeline] │
|
|
├──────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Contenido de la pestaña seleccionada │
|
|
│ │
|
|
└──────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Pestaña Red Team:**
|
|
- Procedimiento de ataque (editable en `red_executing`)
|
|
- Herramienta utilizada
|
|
- Indicador de éxito del ataque (switch: sí/no)
|
|
- Resumen del Red Team (textarea)
|
|
- Lista de evidencias Red con upload (solo en `red_executing` para red_tech)
|
|
- Estado de validación del Red Lead (si aplica)
|
|
|
|
**Pestaña Blue Team:**
|
|
- Resultado de detección (detected/not_detected/partially_detected)
|
|
- Resumen del Blue Team (textarea)
|
|
- Lista de evidencias Blue con upload (solo en `blue_evaluating` para blue_tech)
|
|
- Estado de validación del Blue Lead (si aplica)
|
|
|
|
**Pestaña Summary:**
|
|
- Vista resumen con ambos lados lado a lado
|
|
- Comparativa visual: ataque vs detección
|
|
- Resultado final
|
|
|
|
**Pestaña Timeline:**
|
|
- Historial cronológico de todos los cambios del test
|
|
- Cada entrada con usuario, acción, fecha y detalles
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Las pestañas se renderizan correctamente
|
|
- [ ] Cambiar de pestaña muestra el contenido correcto
|
|
- [ ] Los campos son editables solo en el estado y rol apropiados
|
|
- [ ] Upload de evidencias funciona dentro de cada pestaña
|
|
- [ ] La pestaña Summary muestra comparativa correcta
|
|
|
|
---
|
|
|
|
### T-116: Página TestDetailPage rediseñada
|
|
|
|
**Objetivo:** Integrar los nuevos componentes en la página de detalle del test, reemplazando el diseño actual.
|
|
|
|
**Archivo a modificar:** `frontend/src/pages/TestDetailPage.tsx`
|
|
|
|
**Estructura:**
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ TestDetailHeader (estado, progreso, acciones) │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ TeamTabs │
|
|
│ ┌─────────────────────────────────────────────────────┐│
|
|
│ │ Pestaña seleccionada (Red/Blue/Summary/Timeline) ││
|
|
│ └─────────────────────────────────────────────────────┘│
|
|
│ │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ Sidebar: Metadata del test │
|
|
│ - Técnica asociada │
|
|
│ - Plataforma │
|
|
│ - Creador │
|
|
│ - Fechas │
|
|
│ - Template origen (si aplica) │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Interacciones:**
|
|
- Toda acción usa mutations de react-query con invalidación
|
|
- Modales de confirmación para validar/rechazar
|
|
- Toast notifications para feedback
|
|
- Loading states en todas las operaciones
|
|
|
|
**Validación:**
|
|
|
|
- [ ] La página carga y muestra todos los datos del test
|
|
- [ ] Las pestañas Red/Blue/Summary/Timeline funcionan
|
|
- [ ] Las acciones de validación dual funcionan correctamente
|
|
- [ ] La transición de estado se refleja en tiempo real tras cada acción
|
|
- [ ] Los permisos de edición se respetan según rol y estado
|
|
- [ ] La subida de evidencias funciona dentro de las pestañas
|
|
|
|
---
|
|
|
|
### T-117: Modal de Validación Dual
|
|
|
|
**Objetivo:** Crear un modal de validación que permita a los managers aprobar o rechazar su parte del test, con notas obligatorias en caso de rechazo.
|
|
|
|
**Archivo a crear:** `frontend/src/components/test-detail/ValidationModal.tsx`
|
|
|
|
**Contenido:**
|
|
|
|
- Título: "Validate as Red Lead" / "Validate as Blue Lead"
|
|
- Resumen de evidencias del equipo correspondiente
|
|
- Opciones: Approve / Reject
|
|
- Textarea para notas (obligatorio en rechazo)
|
|
- Indicador visual del estado de la otra validación
|
|
- Botón de confirmar con loading state
|
|
|
|
**Validación:**
|
|
|
|
- [ ] El modal aparece al hacer click en Validate
|
|
- [ ] Se puede seleccionar Approve o Reject
|
|
- [ ] Reject requiere notas obligatorias — botón deshabilitado sin notas
|
|
- [ ] Approve envía la petición y cierra el modal
|
|
- [ ] Se muestra el estado de la validación del otro manager
|
|
- [ ] Loading state funciona durante la petición
|
|
|
|
---
|
|
|
|
## FASE 15 — Frontend: Catálogo de Tests y Creación desde Templates
|
|
|
|
### T-118: Página de catálogo de TestTemplates
|
|
|
|
**Objetivo:** Crear una página donde los usuarios puedan explorar el catálogo de tests disponibles, filtrar por técnica, plataforma y fuente, y ver el detalle de cada template.
|
|
|
|
**Archivo a crear:** `frontend/src/pages/TestCatalogPage.tsx`
|
|
|
|
**Componentes necesarios:**
|
|
|
|
- Barra de búsqueda y filtros (source, platform, severity, technique)
|
|
- Grid/lista de templates con cards
|
|
- Cada card muestra: nombre, técnica MITRE, plataforma, severidad, fuente (badge), botón "Use Template"
|
|
- Paginación
|
|
|
|
**Ruta:** `/test-catalog` — añadir al router y al sidebar.
|
|
|
|
**Validación:**
|
|
|
|
- [ ] La página carga y muestra templates del backend
|
|
- [ ] Los filtros funcionan (source, platform, severity, search)
|
|
- [ ] Cada card muestra la información correcta
|
|
- [ ] El botón "Use Template" navega o abre modal de instanciación
|
|
- [ ] Responsive en móvil y desktop
|
|
|
|
---
|
|
|
|
### T-119: Modal/Página de instanciación de Template
|
|
|
|
**Objetivo:** Permitir crear un test real a partir de un template, pre-rellenando los campos y permitiendo modificaciones.
|
|
|
|
**Archivo a crear:** `frontend/src/components/TestFromTemplateForm.tsx`
|
|
|
|
**Flujo:**
|
|
|
|
1. El usuario selecciona un template (desde el catálogo o desde la vista de técnica)
|
|
2. Se abre un formulario pre-rellenado con los datos del template
|
|
3. El usuario puede modificar los campos
|
|
4. Al guardar, se crea un test real con `state=draft`
|
|
|
|
**Campos del formulario:**
|
|
- Nombre (pre-rellenado)
|
|
- Descripción (pre-rellenado)
|
|
- Técnica asociada (pre-rellenado si se viene de una técnica)
|
|
- Plataforma (pre-rellenado)
|
|
- Procedimiento de ataque sugerido (pre-rellenado, editable)
|
|
- Herramienta sugerida (pre-rellenado, editable)
|
|
- Detección esperada (pre-rellenado, readonly — referencia para blue team)
|
|
|
|
**Validación:**
|
|
|
|
- [ ] El formulario se pre-rellena con datos del template
|
|
- [ ] Se puede modificar cualquier campo editable
|
|
- [ ] Submit crea el test y redirige al detalle
|
|
- [ ] El test creado tiene referencia al template origen
|
|
- [ ] Campos requeridos se validan antes de submit
|
|
|
|
---
|
|
|
|
### T-120: Integrar catálogo en vista de Técnica
|
|
|
|
**Objetivo:** Desde la página de detalle de una técnica, permitir ver los templates disponibles y crear tests directamente.
|
|
|
|
**Archivo a modificar:** `frontend/src/pages/TechniqueDetailPage.tsx`
|
|
|
|
**Cambios:**
|
|
|
|
- Añadir sección "Available Test Templates" debajo de los tests existentes
|
|
- Mostrar cards resumidas de templates disponibles para esa técnica
|
|
- Botón "Run This Test" en cada template que abre el formulario de instanciación
|
|
- Si no hay templates, mostrar mensaje y link al catálogo general
|
|
|
|
**Validación:**
|
|
|
|
- [ ] La sección de templates aparece en la página de técnica
|
|
- [ ] Se muestran solo los templates para esa técnica MITRE
|
|
- [ ] "Run This Test" pre-rellena correctamente el formulario
|
|
- [ ] Si no hay templates se muestra mensaje apropiado
|
|
- [ ] La creación del test actualiza la lista de tests de la técnica
|
|
|
|
---
|
|
|
|
## FASE 16 — Frontend: Vistas de Gestión y Dashboard Mejorado
|
|
|
|
### T-121: Vista de Tests mejorada con filtros por estado y equipo
|
|
|
|
**Objetivo:** Mejorar la página de listado de tests con filtros avanzados y vistas específicas por equipo.
|
|
|
|
**Archivo a modificar:** `frontend/src/pages/TestsPage.tsx`
|
|
|
|
**Mejoras:**
|
|
|
|
- Filtros: por estado (todos los nuevos estados), por equipo asignado, por técnica, por plataforma
|
|
- Vista de "Mis tareas pendientes" según rol:
|
|
- Red Tech: tests en `draft` o `red_executing` creados por mí
|
|
- Blue Tech: tests en `blue_evaluating`
|
|
- Red Lead: tests en `in_review` pendientes de validación red
|
|
- Blue Lead: tests en `in_review` pendientes de validación blue
|
|
- Estadísticas rápidas: contadores por estado (cards superiores)
|
|
- Tabla con columnas: nombre, técnica, estado, equipo actual, última actualización, acciones
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Los filtros por estado funcionan con los nuevos estados
|
|
- [ ] "Mis tareas pendientes" filtra correctamente según el rol del usuario
|
|
- [ ] Los contadores por estado son correctos
|
|
- [ ] La tabla muestra toda la información necesaria
|
|
- [ ] Click en un test navega al detalle
|
|
|
|
---
|
|
|
|
### T-122: Dashboard mejorado con métricas Red/Blue
|
|
|
|
**Objetivo:** Añadir al dashboard métricas específicas del flujo de validación Red/Blue.
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `backend/app/routers/metrics.py` — añadir nuevos endpoints
|
|
- `backend/app/schemas/metrics.py` — añadir nuevos schemas
|
|
- `frontend/src/pages/DashboardPage.tsx` — añadir nuevas secciones
|
|
|
|
**Nuevos endpoints de métricas:**
|
|
|
|
```
|
|
GET /metrics/test-pipeline → contadores por estado del pipeline
|
|
GET /metrics/team-activity → actividad por equipo (tests completados, pendientes)
|
|
GET /metrics/validation-rate → tasa de aprobación/rechazo por manager
|
|
```
|
|
|
|
**Nuevas secciones del dashboard:**
|
|
|
|
1. **Pipeline de Tests**: gráfico de funnel mostrando cuántos tests hay en cada estado
|
|
2. **Actividad por equipo**: Red Team vs Blue Team — tests completados, tiempo medio
|
|
3. **Tasa de validación**: porcentaje de aprobación por Red Lead y Blue Lead
|
|
4. **Tests recientes**: tabla con los últimos 10 tests actualizados
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Los nuevos endpoints retornan datos correctos
|
|
- [ ] El dashboard muestra las nuevas secciones
|
|
- [ ] El pipeline de tests refleja los estados reales
|
|
- [ ] Las métricas de equipo se calculan correctamente
|
|
- [ ] La sección de tests recientes se actualiza
|
|
|
|
---
|
|
|
|
### T-123: Panel de administración de Templates
|
|
|
|
**Objetivo:** Añadir al panel de sistema la gestión de templates: importar Atomic Red Team, crear templates personalizados, ver estadísticas del catálogo.
|
|
|
|
**Archivo a modificar:** `frontend/src/pages/SystemPage.tsx`
|
|
|
|
**Nuevas secciones:**
|
|
|
|
1. **Importar Atomic Red Team**: botón para ejecutar importación, con progreso y resultado
|
|
2. **Estadísticas del catálogo**: total templates, por fuente, por plataforma
|
|
3. **Crear template personalizado**: formulario inline o modal
|
|
4. **Gestionar templates**: tabla con opción de activar/desactivar
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Botón de importación ejecuta y muestra resultados
|
|
- [ ] Las estadísticas del catálogo se muestran correctamente
|
|
- [ ] Se puede crear un template personalizado
|
|
- [ ] Se puede desactivar un template
|
|
- [ ] Solo admin puede acceder a estas funciones
|
|
|
|
---
|
|
|
|
## FASE 17 — Backend Tests Automatizados
|
|
|
|
### T-124: Tests del flujo de trabajo Red/Blue
|
|
|
|
**Objetivo:** Crear tests automatizados que verifiquen todo el ciclo de vida de un test de seguridad.
|
|
|
|
**Archivo a crear:** `backend/tests/test_workflow.py`
|
|
|
|
**Tests a implementar:**
|
|
|
|
```python
|
|
class TestWorkflow:
|
|
def test_full_happy_path():
|
|
"""draft → red_executing → blue_evaluating → in_review → validated"""
|
|
|
|
def test_rejection_and_reopen():
|
|
"""in_review → rejected → draft → red_executing → ..."""
|
|
|
|
def test_invalid_transitions():
|
|
"""Verificar que transiciones no válidas fallan"""
|
|
|
|
def test_red_tech_cannot_access_blue_phase():
|
|
"""Red tech no puede editar en blue_evaluating"""
|
|
|
|
def test_blue_tech_cannot_access_red_phase():
|
|
"""Blue tech no puede editar en red_executing"""
|
|
|
|
def test_dual_validation_both_approve():
|
|
"""Ambos managers aprueban → validated"""
|
|
|
|
def test_dual_validation_one_rejects():
|
|
"""Un manager rechaza → rejected"""
|
|
|
|
def test_evidence_team_separation():
|
|
"""Evidencias red y blue se separan correctamente"""
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `pytest tests/test_workflow.py` ejecuta todos los tests
|
|
- [ ] Todos los tests pasan (verde)
|
|
- [ ] Cobertura del flujo completo
|
|
|
|
---
|
|
|
|
### T-125: Tests de TestTemplates
|
|
|
|
**Objetivo:** Tests automatizados para el CRUD de templates y la instanciación.
|
|
|
|
**Archivo a crear:** `backend/tests/test_templates.py`
|
|
|
|
**Tests:**
|
|
|
|
```python
|
|
class TestTemplates:
|
|
def test_create_template():
|
|
"""Admin puede crear un template"""
|
|
|
|
def test_list_templates_with_filters():
|
|
"""Filtros de source, platform, severity funcionan"""
|
|
|
|
def test_get_templates_by_technique():
|
|
"""Filtrar templates por técnica MITRE"""
|
|
|
|
def test_instantiate_template():
|
|
"""Crear test desde template pre-rellena campos"""
|
|
|
|
def test_soft_delete_template():
|
|
"""Desactivar template no lo borra físicamente"""
|
|
|
|
def test_non_admin_cannot_create_template():
|
|
"""Solo admin puede crear templates"""
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `pytest tests/test_templates.py` pasa todos los tests
|
|
- [ ] Cobertura de CRUD y filtros
|
|
- [ ] Cobertura de permisos
|
|
|
|
---
|
|
|
|
### T-126: Tests de métricas actualizadas
|
|
|
|
**Objetivo:** Tests automatizados para los nuevos endpoints de métricas.
|
|
|
|
**Archivo a crear:** `backend/tests/test_metrics_v2.py`
|
|
|
|
**Tests:**
|
|
|
|
```python
|
|
class TestMetricsV2:
|
|
def test_pipeline_metrics():
|
|
"""Contadores por estado del pipeline correctos"""
|
|
|
|
def test_team_activity_metrics():
|
|
"""Actividad por equipo calculada correctamente"""
|
|
|
|
def test_technique_status_recalculation_with_new_states():
|
|
"""Recalculación funciona con los nuevos estados"""
|
|
|
|
def test_coverage_with_dual_validation():
|
|
"""Cobertura correcta tras validación dual"""
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `pytest tests/test_metrics_v2.py` pasa todos los tests
|
|
- [ ] Las métricas coinciden con los datos de prueba
|
|
|
|
---
|
|
|
|
## FASE 18 — Notificaciones y Sidebar de Actividad
|
|
|
|
### T-127: Modelo de notificaciones
|
|
|
|
**Objetivo:** Crear un sistema básico de notificaciones in-app para alertar a los usuarios cuando necesitan actuar.
|
|
|
|
**Archivo a crear:** `backend/app/models/notification.py`
|
|
|
|
**Campos:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|-----------|----------|------------------------------------|
|
|
| id | UUID | PK, default uuid4 |
|
|
| user_id | UUID | FK → users.id, not null |
|
|
| type | String | not null (test_assigned, validation_needed, test_rejected, etc.) |
|
|
| title | String | not null |
|
|
| message | Text | nullable |
|
|
| entity_type | String | nullable (test, technique) |
|
|
| entity_id | UUID | nullable |
|
|
| read | Boolean | default False |
|
|
| created_at| DateTime | default utcnow |
|
|
|
|
**Generar migración.**
|
|
|
|
**Servicio** `backend/app/services/notification_service.py`:
|
|
|
|
```python
|
|
def create_notification(db, user_id, type, title, message, entity_type, entity_id)
|
|
def mark_as_read(db, notification_id, user_id)
|
|
def mark_all_as_read(db, user_id)
|
|
def get_unread_count(db, user_id) -> int
|
|
```
|
|
|
|
**Disparar notificaciones automáticamente:**
|
|
- Cuando un test pasa a `blue_evaluating` → notificar a todos los `blue_tech`
|
|
- Cuando un test pasa a `in_review` → notificar a `red_lead` y `blue_lead`
|
|
- Cuando un test es rechazado → notificar al creador
|
|
- Cuando un test es validado → notificar al creador
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Se crea una notificación cuando un test cambia a `blue_evaluating`
|
|
- [ ] Se crea una notificación para managers cuando un test llega a `in_review`
|
|
- [ ] Se crea una notificación al creador cuando un test es rechazado
|
|
- [ ] Se crea una notificación al creador cuando un test es validado
|
|
- [ ] `get_unread_count` retorna el número correcto
|
|
|
|
---
|
|
|
|
### T-128: Endpoints y frontend de notificaciones
|
|
|
|
**Objetivo:** Endpoints API y UI de notificaciones.
|
|
|
|
**Archivos a crear:**
|
|
|
|
- `backend/app/routers/notifications.py`
|
|
- `frontend/src/api/notifications.ts`
|
|
- `frontend/src/components/NotificationBell.tsx`
|
|
- `frontend/src/components/NotificationDropdown.tsx`
|
|
|
|
**Endpoints:**
|
|
|
|
| Método | Ruta | Auth | Descripción |
|
|
|--------|-----------------------------|-------------|-------------------------------|
|
|
| GET | /notifications | autenticado | Listar notificaciones del user|
|
|
| GET | /notifications/unread-count | autenticado | Contador de no leídas |
|
|
| PATCH | /notifications/{id}/read | autenticado | Marcar como leída |
|
|
| POST | /notifications/read-all | autenticado | Marcar todas como leídas |
|
|
|
|
**Frontend:**
|
|
|
|
- `NotificationBell`: icono de campana en el header con badge de conteo
|
|
- `NotificationDropdown`: dropdown con lista de notificaciones
|
|
- Click en notificación navega a la entidad correspondiente y marca como leída
|
|
- Polling cada 30 segundos para actualizar conteo (o usar react-query con refetchInterval)
|
|
|
|
**Validación:**
|
|
|
|
- [ ] La campana muestra el conteo correcto de no leídas
|
|
- [ ] El dropdown lista las notificaciones ordenadas por fecha
|
|
- [ ] Click en una notificación navega correctamente y marca como leída
|
|
- [ ] "Mark all as read" limpia el conteo
|
|
- [ ] Las notificaciones se generan automáticamente con los cambios de estado
|
|
|
|
---
|
|
|
|
## FASE 19 — Mejoras de Remediación y Reportes (inspirado en Validato)
|
|
|
|
### T-129: Campo de remediación en tests y templates
|
|
|
|
**Objetivo:** Añadir campos de remediación y recomendaciones, inspirados en el enfoque de Validato de "step-by-step remediation".
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `backend/app/models/test.py` — nuevos campos
|
|
- `backend/app/models/test_template.py` — nuevo campo
|
|
- Schemas correspondientes
|
|
|
|
**Nuevos campos en Test:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|----------------------|--------|---------------|
|
|
| remediation_steps | Text | nullable |
|
|
| remediation_status | String | nullable (pending, in_progress, completed, not_applicable) |
|
|
| remediation_assignee | UUID | FK → users.id, nullable |
|
|
|
|
**Nuevo campo en TestTemplate:**
|
|
|
|
| Campo | Tipo | Restricciones |
|
|
|---------------------------|--------|---------------|
|
|
| suggested_remediation | Text | nullable |
|
|
|
|
**Generar migración.**
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Los nuevos campos se crean en la BD
|
|
- [ ] Se pueden asignar pasos de remediación a un test
|
|
- [ ] Se puede asignar un responsable de remediación
|
|
- [ ] El template puede sugerir remediación al instanciar
|
|
|
|
---
|
|
|
|
### T-130: Endpoint y UI de reportes
|
|
|
|
**Objetivo:** Crear un sistema básico de reportes que permita exportar el estado de cobertura en diferentes formatos.
|
|
|
|
**Archivos a crear:**
|
|
|
|
- `backend/app/routers/reports.py`
|
|
- `frontend/src/pages/ReportsPage.tsx`
|
|
|
|
**Endpoints:**
|
|
|
|
| Método | Ruta | Auth | Descripción |
|
|
|--------|--------------------------------|-------------|-----------------------------------|
|
|
| GET | /reports/coverage-summary | autenticado | Reporte JSON completo |
|
|
| GET | /reports/coverage-csv | autenticado | Export CSV de cobertura |
|
|
| GET | /reports/test-results | autenticado | Reporte de resultados de tests |
|
|
| GET | /reports/remediation-status | autenticado | Reporte de estado de remediación |
|
|
|
|
**Página de reportes:**
|
|
|
|
- Selector de tipo de reporte
|
|
- Filtros (rango de fechas, tácticas, plataformas)
|
|
- Preview del reporte
|
|
- Botones de descarga (CSV, JSON)
|
|
- Resumen visual con métricas clave
|
|
|
|
**Ruta:** `/reports` — añadir al router y sidebar.
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Cada endpoint retorna datos correctos
|
|
- [ ] El CSV se descarga y abre correctamente en Excel
|
|
- [ ] Los filtros funcionan en el frontend
|
|
- [ ] La preview del reporte se muestra correctamente
|
|
- [ ] Solo usuarios autenticados pueden acceder
|
|
|
|
---
|
|
|
|
## FASE 20 — Pulido Final y Documentación
|
|
|
|
### T-131: Actualizar navegación y routing
|
|
|
|
**Objetivo:** Integrar todas las nuevas páginas en la navegación de la aplicación.
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `frontend/src/App.tsx` — nuevas rutas
|
|
- `frontend/src/components/Sidebar.tsx` — nuevos items
|
|
|
|
**Nuevas rutas:**
|
|
|
|
```
|
|
/test-catalog → TestCatalogPage
|
|
/tests/:testId → TestDetailPage (rediseñada)
|
|
/reports → ReportsPage
|
|
```
|
|
|
|
**Items del sidebar:**
|
|
|
|
- Dashboard
|
|
- ATT&CK Matrix (Techniques)
|
|
- Tests (con submenu)
|
|
- All Tests
|
|
- My Pending Tasks
|
|
- Test Catalog
|
|
- Reports
|
|
- System (admin)
|
|
- MITRE Sync
|
|
- Intel Scan
|
|
- Templates Management
|
|
- Users
|
|
- Audit Log
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Todas las rutas nuevas funcionan
|
|
- [ ] El sidebar muestra los items correctos según el rol
|
|
- [ ] La navegación entre páginas es fluida
|
|
- [ ] No hay rutas rotas o 404
|
|
|
|
---
|
|
|
|
### T-132: Error handling y edge cases
|
|
|
|
**Objetivo:** Asegurar que todos los nuevos flujos manejan errores correctamente.
|
|
|
|
**Verificaciones:**
|
|
|
|
**Backend:**
|
|
- Todos los endpoints nuevos tienen manejo de 404, 400, 403
|
|
- Las transiciones de estado inválidas retornan errores descriptivos
|
|
- Los permisos de equipo se validan en cada endpoint
|
|
|
|
**Frontend:**
|
|
- Loading states en todas las operaciones nuevas
|
|
- Error messages descriptivos en validaciones y transiciones
|
|
- Confirmación antes de acciones destructivas (rechazar, reabrir)
|
|
- Feedback visual tras cada acción exitosa (toast)
|
|
|
|
**Validación:**
|
|
|
|
- [ ] Intentar transición inválida muestra error descriptivo
|
|
- [ ] Permisos incorrectos muestran 403 con mensaje claro
|
|
- [ ] Loading states aparecen en todas las operaciones
|
|
- [ ] Toast de éxito tras cada acción exitosa
|
|
- [ ] Modal de confirmación antes de rechazar un test
|
|
|
|
---
|
|
|
|
### T-133: Backend tests finales de integración
|
|
|
|
**Objetivo:** Suite final de tests que verifica el sistema completo end-to-end.
|
|
|
|
**Archivo a crear:** `backend/tests/test_integration.py`
|
|
|
|
**Tests:**
|
|
|
|
```python
|
|
class TestIntegration:
|
|
def test_full_e2e_flow():
|
|
"""
|
|
1. Admin importa Atomic Red Team templates
|
|
2. Red Tech crea test desde template
|
|
3. Red Tech sube evidencias y submite
|
|
4. Blue Tech evalúa y sube evidencias
|
|
5. Blue Tech submite para review
|
|
6. Red Lead y Blue Lead validan
|
|
7. Verificar que la técnica cambia de estado
|
|
"""
|
|
|
|
def test_rejection_recovery_flow():
|
|
"""Flujo completo con rechazo y recuperación"""
|
|
|
|
def test_notification_flow():
|
|
"""Verificar que las notificaciones se generan correctamente"""
|
|
|
|
def test_metrics_accuracy():
|
|
"""Verificar que las métricas son correctas tras operaciones"""
|
|
|
|
def test_report_generation():
|
|
"""Verificar generación de reportes"""
|
|
```
|
|
|
|
**Validación:**
|
|
|
|
- [ ] `pytest tests/test_integration.py` pasa todos los tests
|
|
- [ ] El flujo E2E completo funciona sin errores
|
|
- [ ] Las métricas son consistentes tras todas las operaciones
|
|
|
|
---
|
|
|
|
### T-134: Actualizar documentación
|
|
|
|
**Objetivo:** Actualizar README y documentación API para reflejar todos los cambios.
|
|
|
|
**Archivos a modificar:**
|
|
|
|
- `README.md` — actualizar con nuevas funcionalidades
|
|
- `docs/API.md` — documentar nuevos endpoints
|
|
|
|
**Secciones nuevas en README:**
|
|
|
|
- Descripción del flujo Red Team / Blue Team
|
|
- Descripción de los roles y permisos
|
|
- Cómo importar tests de Atomic Red Team
|
|
- Cómo usar el catálogo de templates
|
|
- Explicación del ciclo de vida de un test
|
|
- Diagrama del flujo de validación dual
|
|
|
|
**Documentación API:**
|
|
|
|
- Nuevos endpoints de tests (flujo Red/Blue)
|
|
- Endpoints de templates
|
|
- Endpoints de notificaciones
|
|
- Endpoints de reportes
|
|
- Nuevos endpoints de métricas
|
|
|
|
**Validación:**
|
|
|
|
- [ ] El README refleja todas las funcionalidades nuevas
|
|
- [ ] La documentación API cubre todos los endpoints nuevos
|
|
- [ ] Swagger UI en /docs muestra todos los endpoints correctamente
|
|
- [ ] Siguiendo el README, un nuevo desarrollador puede entender el flujo completo
|
|
|
|
---
|
|
|
|
## Resumen de Fases
|
|
|
|
| Fase | Tareas | Descripción |
|
|
|------|------------------|-------------------------------------------------------|
|
|
| 10 | T-100 a T-104 | Evolución del modelo de datos para Red/Blue Team |
|
|
| 11 | T-105 a T-107 | Lógica de negocio del flujo Red/Blue |
|
|
| 12 | T-108 a T-111 | Endpoints API Red/Blue |
|
|
| 13 | T-112 a T-113 | Frontend: tipos y API clients |
|
|
| 14 | T-114 a T-117 | Frontend: página de test con pestañas Red/Blue |
|
|
| 15 | T-118 a T-120 | Frontend: catálogo de tests y templates |
|
|
| 16 | T-121 a T-123 | Frontend: vistas de gestión y dashboard mejorado |
|
|
| 17 | T-124 a T-126 | Backend tests automatizados |
|
|
| 18 | T-127 a T-128 | Notificaciones in-app |
|
|
| 19 | T-129 a T-130 | Remediación y reportes |
|
|
| 20 | T-131 a T-134 | Pulido final y documentación |
|
|
|
|
> **Total: 35 tareas = 35 commits mínimo**
|
|
> Cada tarea es autocontenida y verificable antes de hacer commit.
|
|
|
|
---
|
|
|
|
## Inspiración de Validato
|
|
|
|
Las siguientes ideas están inspiradas en la plataforma [Validato](https://validato.io/) y adaptadas al contexto de Aegis:
|
|
|
|
1. **Tests mapeados a MITRE ATT&CK**: Cada test está directamente vinculado a una técnica, igual que Validato mapea simulaciones a TTPs.
|
|
2. **Catálogo de tests predefinidos**: Similar a cómo Validato ofrece escenarios de validación pre-configurados, Aegis usa Atomic Red Team como fuente de tests base.
|
|
3. **Validación de Protection + Detection**: Validato evalúa si los controles protegen Y detectan. En Aegis, Red Team valida la ejecución del ataque y Blue Team valida la detección.
|
|
4. **Resultados mapeados a frameworks**: Los resultados se mapean de vuelta a MITRE ATT&CK para actualizar la cobertura.
|
|
5. **Remediación paso a paso**: Inspirado en cómo Validato proporciona remediation steps, cada test puede incluir pasos de remediación sugeridos.
|
|
6. **Validación continua**: El pipeline draft → red → blue → review → validated permite re-ejecutar tests continuamente para medir mejoras.
|
|
7. **Reportes de cobertura**: Exportación de reportes para demostrar compliance (similar a los reportes de Validato para DORA, NIS2, GLBA).
|
|
8. **Priorización por severidad**: Los templates incluyen severidad para priorizar qué tests ejecutar primero.
|