Add wiki page: Test-Lifecycle
@@ -0,0 +1,251 @@
|
|||||||
|
# Test Lifecycle
|
||||||
|
|
||||||
|
Every test in Aegis follows a structured state machine from creation to final validation.
|
||||||
|
This page documents every state, transition, actor, and field update rule.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## State Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────┐
|
||||||
|
│ draft │◄──────────────────────────┐
|
||||||
|
└────┬────┘ │
|
||||||
|
│ POST /start-execution │
|
||||||
|
│ (red_tech, red_lead, admin) │ POST /reopen
|
||||||
|
▼ │ (leads, admin)
|
||||||
|
┌─────────────────┐ │
|
||||||
|
│ red_executing │ │
|
||||||
|
└────────┬────────┘ │
|
||||||
|
│ POST /submit-red │
|
||||||
|
│ (red_tech, red_lead, admin) │
|
||||||
|
▼ │
|
||||||
|
┌─────────────────────┐ │
|
||||||
|
│ blue_evaluating │ │
|
||||||
|
└────────┬────────────┘ │
|
||||||
|
│ POST /submit-blue │
|
||||||
|
│ (blue_tech, blue_lead, admin) │
|
||||||
|
▼ │
|
||||||
|
┌───────────┐ │
|
||||||
|
│ in_review │ │
|
||||||
|
└─────┬─────┘ │
|
||||||
|
│ Both validate (approved) │
|
||||||
|
│ │
|
||||||
|
┌──────────┴──────────┐ │
|
||||||
|
│ Either rejects │ │
|
||||||
|
▼ ▼ │
|
||||||
|
┌──────────┐ ┌───────────┐ │
|
||||||
|
│ rejected │─────────┤ validated │ │
|
||||||
|
└──────────┘ └───────────┘ │
|
||||||
|
│ │
|
||||||
|
└───────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## States Reference
|
||||||
|
|
||||||
|
### draft
|
||||||
|
|
||||||
|
- **Description**: Initial state. Test has been defined but not yet executed.
|
||||||
|
- **Who creates**: red_lead, blue_lead, admin (POST /api/v1/tests)
|
||||||
|
- **Who can edit general fields**: red_lead, blue_lead, admin (PATCH /api/v1/tests/{id})
|
||||||
|
- **Available actions**:
|
||||||
|
- Edit test metadata (title, description, technique_id, objective, target_environment, etc.)
|
||||||
|
- Add to campaigns
|
||||||
|
- Attach red evidence (even before execution, for pre-work files)
|
||||||
|
- **Cannot do**: upload blue evidence, start timer
|
||||||
|
|
||||||
|
**Create payload example:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "T1059.001 PowerShell cradle download",
|
||||||
|
"technique_id": "T1059.001",
|
||||||
|
"objective": "Verify AMSI bypass detection",
|
||||||
|
"target_environment": "Windows 10 workstation",
|
||||||
|
"severity": "high",
|
||||||
|
"campaign_id": "optional-uuid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### red_executing
|
||||||
|
|
||||||
|
- **Description**: Red team is actively executing the attack.
|
||||||
|
- **Trigger**: POST /api/v1/tests/{id}/start-execution
|
||||||
|
- **Who can trigger**: red_tech, red_lead, admin
|
||||||
|
- **Timer starts** automatically when entering this state.
|
||||||
|
- **Who updates red fields**: red_tech, red_lead, admin (PATCH /api/v1/tests/{id}/red)
|
||||||
|
|
||||||
|
**Red fields (PATCH /tests/{id}/red):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tool_used": "Cobalt Strike 4.8",
|
||||||
|
"command_executed": "powershell -nop -w hidden -enc ...",
|
||||||
|
"output_observed": "Beacon established on 10.0.0.5",
|
||||||
|
"red_notes": "Used staged payload to bypass AV",
|
||||||
|
"attacker_ip": "10.10.10.100",
|
||||||
|
"target_ip": "10.0.0.5",
|
||||||
|
"start_time": "2024-03-15T10:00:00Z",
|
||||||
|
"end_time": "2024-03-15T10:15:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Evidence upload (team=red):**
|
||||||
|
```http
|
||||||
|
POST /api/v1/tests/{id}/evidence
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
|
||||||
|
file=<binary>
|
||||||
|
team=red
|
||||||
|
description=PowerShell execution screenshot
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### blue_evaluating
|
||||||
|
|
||||||
|
- **Description**: Blue team is evaluating what they detected (or didn't).
|
||||||
|
- **Trigger**: POST /api/v1/tests/{id}/submit-red
|
||||||
|
- **Who can trigger**: red_tech, red_lead, admin
|
||||||
|
- **Who updates blue fields**: blue_tech, blue_lead, admin (PATCH /api/v1/tests/{id}/blue)
|
||||||
|
|
||||||
|
**Blue fields (PATCH /tests/{id}/blue):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"detection_result": "detected",
|
||||||
|
"detection_notes": "Windows Defender ATP alert fired: Suspicious PowerShell",
|
||||||
|
"alert_fired": true,
|
||||||
|
"alert_name": "ASR rule: Block Office apps from creating child processes",
|
||||||
|
"response_action": "Endpoint isolated automatically",
|
||||||
|
"time_to_detect_seconds": 47,
|
||||||
|
"blue_notes": "AMSI telemetry captured full script content"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`detection_result` values:
|
||||||
|
- `detected` — blue team observed the attack in time
|
||||||
|
- `not_detected` — attack was not detected
|
||||||
|
- `partial` — partial detection (some indicators observed but not full alert)
|
||||||
|
|
||||||
|
**Evidence upload (team=blue):**
|
||||||
|
```http
|
||||||
|
POST /api/v1/tests/{id}/evidence
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
|
||||||
|
file=<binary>
|
||||||
|
team=blue
|
||||||
|
description=SIEM alert screenshot
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### in_review
|
||||||
|
|
||||||
|
- **Description**: Both leads must independently validate their side.
|
||||||
|
- **Trigger**: POST /api/v1/tests/{id}/submit-blue
|
||||||
|
- **Who can trigger**: blue_tech, blue_lead, admin
|
||||||
|
- **No field updates allowed** while in review.
|
||||||
|
- **Evidence is locked** — no new evidence uploads.
|
||||||
|
|
||||||
|
**Red validation (red_lead, admin):**
|
||||||
|
```http
|
||||||
|
POST /api/v1/tests/{id}/validate-red
|
||||||
|
{"red_validation_status": "approved", "red_validation_notes": "Execution was clean"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Blue validation (blue_lead, admin):**
|
||||||
|
```http
|
||||||
|
POST /api/v1/tests/{id}/validate-blue
|
||||||
|
{"blue_validation_status": "approved", "blue_validation_notes": "Detection confirmed"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Both validations can be `approved` or `rejected`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### validated
|
||||||
|
|
||||||
|
- **Description**: Both leads approved. Test is complete and results are official.
|
||||||
|
- **Trigger**: Both red_validation_status and blue_validation_status = `approved`
|
||||||
|
- **Effects**:
|
||||||
|
- Technique coverage status is recalculated
|
||||||
|
- Webhook events fired (if configured): `test.validated`
|
||||||
|
- Score may be updated
|
||||||
|
- Snapshot data refreshed
|
||||||
|
- **After validation**: Leads and admin can still edit the `remediation` fields:
|
||||||
|
```http
|
||||||
|
PATCH /api/v1/tests/{id}/remediation
|
||||||
|
{
|
||||||
|
"remediation_status": "in_progress",
|
||||||
|
"remediation_notes": "SIEM rule deployed to block this technique",
|
||||||
|
"remediation_owner": "blue-lead-user-uuid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### rejected
|
||||||
|
|
||||||
|
- **Description**: At least one lead rejected their side.
|
||||||
|
- **Trigger**: Either validate-red or validate-blue returns `rejected`
|
||||||
|
- **Recovery**: POST /api/v1/tests/{id}/reopen (leads, admin) sends back to `draft`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Evidence Rules Summary
|
||||||
|
|
||||||
|
| State | Red evidence | Blue evidence |
|
||||||
|
|-------|-------------|---------------|
|
||||||
|
| draft | Upload allowed | Not allowed |
|
||||||
|
| red_executing | Upload allowed | Not allowed |
|
||||||
|
| blue_evaluating | Not allowed | Upload allowed |
|
||||||
|
| in_review | **Locked** | **Locked** |
|
||||||
|
| validated | **Locked** | **Locked** |
|
||||||
|
| rejected | **Locked** | **Locked** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Timer
|
||||||
|
|
||||||
|
The test timer measures elapsed execution time.
|
||||||
|
|
||||||
|
| Action | Endpoint | Allowed roles |
|
||||||
|
|--------|----------|---------------|
|
||||||
|
| Pause timer | POST /tests/{id}/pause-timer | All except viewer |
|
||||||
|
| Resume timer | POST /tests/{id}/resume-timer | All except viewer |
|
||||||
|
|
||||||
|
The timer automatically starts when entering `red_executing`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Timeline and Audit Trail
|
||||||
|
|
||||||
|
Every state change is recorded in the timeline:
|
||||||
|
```http
|
||||||
|
GET /api/v1/tests/{id}/timeline
|
||||||
|
```
|
||||||
|
|
||||||
|
Response includes entries for:
|
||||||
|
- State transitions (from_state, to_state, actor, timestamp)
|
||||||
|
- Validation actions (approved/rejected, actor, timestamp)
|
||||||
|
- Evidence uploads (team, filename, actor, timestamp)
|
||||||
|
- Timer pauses/resumes
|
||||||
|
- Worklog entries
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Retest Chain
|
||||||
|
|
||||||
|
When a test is a retest of a previous (failed) test, it is linked via `retest_of`:
|
||||||
|
```json
|
||||||
|
{"retest_of": "previous-test-uuid"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Navigate the full chain:
|
||||||
|
```http
|
||||||
|
GET /api/v1/tests/{id}/retest-chain
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns an ordered list of all tests in the chain, oldest first.
|
||||||
|
|||||||
Reference in New Issue
Block a user