feat(phase-9): implement MVP polishing and closure

T-032: User management admin panel - backend users router with CRUD, frontend UsersPage with modals

T-033: Audit log viewer - backend audit router with filters/pagination, frontend AuditLogPage

T-034: Global error handling - ErrorBoundary, LoadingSpinner, ErrorMessage, Toast components

T-035: Backend tests - pytest setup with SQLite, tests for health/auth/techniques/tests

T-036: Documentation - Updated README with testing section, created docs/API.md
This commit is contained in:
2026-02-06 16:30:35 +01:00
parent cb447f3803
commit 174919da4e
27 changed files with 2539 additions and 17 deletions

385
docs/API.md Normal file
View File

@@ -0,0 +1,385 @@
# Aegis API Documentation
This document provides an overview of the Aegis REST API. For interactive documentation with request/response examples, visit:
- **Swagger UI**: http://localhost:8000/docs
- **ReDoc**: http://localhost:8000/redoc
## Base URL
All API endpoints are prefixed with `/api/v1`.
## Authentication
The API uses JWT (JSON Web Token) for authentication. Include the token in the `Authorization` header:
```
Authorization: Bearer <your-token>
```
### Obtaining a Token
```bash
curl -X POST http://localhost:8000/api/v1/auth/login \
-d "username=admin&password=admin123"
```
Response:
```json
{
"access_token": "eyJ...",
"token_type": "bearer"
}
```
## Endpoints
### Authentication
#### POST /auth/login
Authenticate and receive a JWT token.
**Request** (form data):
- `username`: string
- `password`: string
**Response** (200):
```json
{
"access_token": "string",
"token_type": "bearer"
}
```
#### GET /auth/me
Get current authenticated user.
**Headers**: `Authorization: Bearer <token>`
**Response** (200):
```json
{
"id": "uuid",
"username": "string",
"email": "string|null",
"role": "string",
"is_active": true
}
```
---
### Techniques
#### GET /techniques
List all techniques with optional filters.
**Query Parameters**:
- `tactic` (optional): Filter by tactic name
- `status` (optional): Filter by status (`not_evaluated`, `in_progress`, `validated`, `partial`, `not_covered`)
- `review_required` (optional): Filter by review flag (`true`/`false`)
**Response** (200):
```json
[
{
"id": "uuid",
"mitre_id": "T1059",
"name": "Command and Scripting Interpreter",
"tactic": "execution",
"status_global": "validated"
}
]
```
#### GET /techniques/{mitre_id}
Get a single technique with associated tests.
**Response** (200):
```json
{
"id": "uuid",
"mitre_id": "T1059",
"name": "Command and Scripting Interpreter",
"description": "...",
"tactic": "execution",
"platforms": ["windows", "linux"],
"status_global": "validated",
"review_required": false,
"tests": [...]
}
```
#### POST /techniques
Create a new technique. **Admin only.**
**Request**:
```json
{
"mitre_id": "T1059",
"name": "Command and Scripting Interpreter",
"description": "...",
"tactic": "execution",
"platforms": ["windows", "linux"]
}
```
#### PATCH /techniques/{mitre_id}
Update a technique. **Admin only.**
**Request**:
```json
{
"name": "Updated Name",
"status_global": "validated"
}
```
#### PATCH /techniques/{mitre_id}/review
Mark a technique as reviewed. **Leads/Admin only.**
---
### Tests
#### POST /tests
Create a new test. **Red Tech/Admin only.**
**Request**:
```json
{
"technique_id": "uuid",
"name": "My Test",
"description": "Test description",
"platform": "windows",
"procedure_text": "Step by step...",
"tool_used": "Atomic Red Team"
}
```
#### GET /tests/{id}
Get a test with associated evidences.
#### PATCH /tests/{id}
Update a test. **Creator/Admin only.** Only allowed when state is `draft` or `rejected`.
#### POST /tests/{id}/validate
Validate a test. **Leads/Admin only.**
**Request**:
```json
{
"result": "detected",
"comments": "Optional comment"
}
```
Valid results: `detected`, `not_detected`, `partially_detected`
#### POST /tests/{id}/reject
Reject a test. **Leads/Admin only.**
---
### Evidence
#### POST /tests/{test_id}/evidence
Upload an evidence file.
**Request**: `multipart/form-data` with `file` field.
**Response** (201):
```json
{
"id": "uuid",
"test_id": "uuid",
"file_name": "screenshot.png",
"sha256_hash": "abc123...",
"uploaded_at": "2024-01-01T00:00:00Z",
"download_url": "https://..."
}
```
#### GET /evidence/{id}
Get evidence metadata with presigned download URL.
---
### Metrics
#### GET /metrics/summary
Get global coverage summary.
**Response** (200):
```json
{
"total_techniques": 200,
"validated": 50,
"partial": 20,
"not_covered": 30,
"in_progress": 10,
"not_evaluated": 90,
"coverage_percentage": 35.0
}
```
#### GET /metrics/by-tactic
Get coverage breakdown by tactic.
**Response** (200):
```json
[
{
"tactic": "execution",
"total": 15,
"validated": 5,
"partial": 2,
"not_covered": 3,
"not_evaluated": 5,
"in_progress": 0
}
]
```
---
### Users (Admin Only)
#### GET /users
List all users.
#### POST /users
Create a new user.
**Request**:
```json
{
"username": "newuser",
"email": "user@example.com",
"password": "securepassword",
"role": "red_tech"
}
```
Valid roles: `admin`, `red_tech`, `blue_tech`, `red_lead`, `blue_lead`, `viewer`
#### PATCH /users/{id}
Update a user.
**Request**:
```json
{
"email": "new@email.com",
"role": "blue_tech",
"is_active": false,
"password": "newpassword"
}
```
---
### Audit Logs (Admin Only)
#### GET /audit-logs
List audit logs with pagination and filters.
**Query Parameters**:
- `user_id` (optional): Filter by user UUID
- `action` (optional): Filter by action type
- `entity_type` (optional): Filter by entity type
- `start_date` (optional): Filter from date (ISO format)
- `end_date` (optional): Filter to date (ISO format)
- `offset` (optional): Pagination offset (default: 0)
- `limit` (optional): Page size (default: 50, max: 100)
**Response** (200):
```json
{
"items": [
{
"id": "uuid",
"user_id": "uuid",
"username": "admin",
"action": "create_technique",
"entity_type": "technique",
"entity_id": "uuid",
"timestamp": "2024-01-01T00:00:00Z",
"details": {"mitre_id": "T1059"}
}
],
"total": 100,
"offset": 0,
"limit": 50
}
```
#### GET /audit-logs/actions
List distinct action types.
#### GET /audit-logs/entity-types
List distinct entity types.
---
### System (Admin Only)
#### POST /system/sync-mitre
Trigger MITRE ATT&CK synchronization.
**Response** (200):
```json
{
"message": "MITRE sync completed",
"new": 5,
"updated": 10
}
```
#### POST /system/run-intel-scan
Trigger threat intelligence scan.
**Response** (200):
```json
{
"message": "Intel scan completed",
"new_items": 3
}
```
#### GET /system/scheduler-status
Get background scheduler status.
**Response** (200):
```json
{
"running": true,
"jobs": [
{
"id": "mitre_sync",
"name": "MITRE ATT&CK Sync",
"next_run_time": "2024-01-02T00:00:00Z"
}
]
}
```
---
## Error Responses
All errors follow a consistent format:
```json
{
"detail": "Error message",
"code": "ERROR_CODE"
}
```
Common HTTP status codes:
- `400` - Bad Request (validation error, invalid input)
- `401` - Unauthorized (missing or invalid token)
- `403` - Forbidden (insufficient permissions)
- `404` - Not Found (resource doesn't exist)
- `409` - Conflict (duplicate resource)
- `500` - Internal Server Error