Files
Aegis/backend/tests/test_tests.py
T
kitos a3f86c7b31
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
fix(permissions): admin can no longer operate tests — start/submit/edit/create, view only
Admin still bypassed require_any_role (non-strict) on the pure
operator actions: start-execution, submit-red, start-blue-work,
submit-blue, pause/resume-timer, and the red/blue field-edit + general
test create/update/remediation/import-rt/template endpoints all used
the loose dependency even where admin wasn't in the role tuple.
Switched every one of these to require_any_role_strict, matching the
review/validate/dispute/hold/assign endpoints already fixed earlier.

Frontend: removed every remaining role === "admin" disjunct gating
Start Execution, Submit to Blue Team, blue evaluating actions, timer
control, red/blue field editing, test creation, and template creation.
Team-blindness visibility (isBlind) deliberately keeps the admin
bypass — admin still sees both sides unmasked for oversight, since
that's visibility, not operating.

Updated ~20 tests whose fixtures used the admin account as a
convenience shortcut to create/drive tests through the workflow —
switched them to a red_lead account, fixing an incidental
fixture-resolution-order cookie bug along the way (client's cookie
jar prefers the last-logged-in role's cookie over any Bearer header
explicitly passed to a later request).
2026-07-13 09:27:43 +02:00

126 lines
4.0 KiB
Python

"""Tests for security test endpoints (V2 API).
Covers the test CRUD and basic workflow via the REST API.
For full workflow logic tests see ``test_workflow.py`` and
``test_integration_v2.py``.
"""
import pytest
@pytest.fixture
def technique(client, auth_headers):
"""Create a technique for test association."""
response = client.post(
"/api/v1/techniques",
json={"mitre_id": "T1059", "name": "Test Technique"},
headers=auth_headers,
)
return response.json()
def test_create_test_requires_auth(client):
"""POST /tests without token returns 401 or 403."""
response = client.post(
"/api/v1/tests",
json={
"technique_id": "00000000-0000-0000-0000-000000000000",
"name": "Test Name",
},
)
assert response.status_code in (401, 403)
def test_create_test_success(client, red_lead_headers, red_lead_user, technique):
"""Lead can create a test via POST /tests (admin administers the site, not test content)."""
# The `technique` fixture logs in as admin (its own auth_headers
# dependency), leaving a cookie that would otherwise outrank the
# red_lead Bearer header below — get_current_user prefers the cookie.
client.cookies.clear()
response = client.post(
"/api/v1/tests",
json={
"technique_id": technique["id"],
"name": "My Security Test",
"description": "Test description",
"platform": "windows",
},
headers=red_lead_headers,
)
assert response.status_code == 201
data = response.json()
assert data["name"] == "My Security Test"
assert data["state"] == "draft"
assert data["technique_id"] == technique["id"]
def test_create_test_nonexistent_technique(client, red_lead_headers, red_lead_user):
"""Creating a test with non-existent technique fails."""
response = client.post(
"/api/v1/tests",
json={
"technique_id": "00000000-0000-0000-0000-000000000000",
"name": "Test",
},
headers=red_lead_headers,
)
assert response.status_code == 404
def test_get_test_by_id(client, auth_headers, technique, red_lead_headers, red_lead_user):
"""GET /tests/{id} returns the test. Admin can still view (just not create)."""
client.cookies.clear()
create_response = client.post(
"/api/v1/tests",
json={"technique_id": technique["id"], "name": "Test"},
headers=red_lead_headers,
)
test_id = create_response.json()["id"]
client.cookies.clear()
response = client.get(f"/api/v1/tests/{test_id}", headers=auth_headers)
assert response.status_code == 200
assert response.json()["id"] == test_id
def test_start_execution_twice_returns_invalid_transition(
client, red_lead_headers, red_lead_user, technique, red_tech_user
):
"""Invalid workflow transition surfaces domain error JSON (FASE 0.4).
HttpOnly login cookies take precedence over the Authorization header.
Clear cookies before each phase so Bearer tokens match the intended user.
"""
client.cookies.clear()
create_response = client.post(
"/api/v1/tests",
json={"technique_id": technique["id"], "name": "Workflow dup start"},
headers=red_lead_headers,
)
assert create_response.status_code == 201
test_id = create_response.json()["id"]
rl = client.post(
"/api/v1/auth/login",
data={"username": "redtech", "password": "redtech123"},
)
assert rl.status_code == 200
red_headers = {"Authorization": f"Bearer {rl.json()['access_token']}"}
client.cookies.clear()
first = client.post(
f"/api/v1/tests/{test_id}/start-execution",
headers=red_headers,
)
assert first.status_code == 200
client.cookies.clear()
second = client.post(
f"/api/v1/tests/{test_id}/start-execution",
headers=red_headers,
)
assert second.status_code == 400
body = second.json()
assert body.get("code") == "INVALID_TRANSITION"
assert "detail" in body