f87959369b
Red and Blue could not see each other's real field data until both reviews passed, showing a placeholder message instead. This kept detection testing blind to what Red actually did; both sides now see the full, live test data at all times.
120 lines
4.3 KiB
Python
120 lines
4.3 KiB
Python
"""Regression: Red and Blue must see each other's fields at every stage.
|
|
|
|
Blind visibility (hiding the other team's fields until both reviews pass)
|
|
was a deliberate design in an earlier phase, but the org decided both teams
|
|
should see each other's work throughout — detection testing isn't meant to
|
|
be blind here. This confirms neither the frontend nor backend hides
|
|
anything based on role/state anymore.
|
|
"""
|
|
|
|
import uuid
|
|
|
|
import pytest
|
|
|
|
from app.models.evidence import Evidence
|
|
from app.models.enums import TeamSide
|
|
|
|
_RED_FIELDS = [
|
|
"procedure_text", "tool_used", "attack_success",
|
|
"execution_start_time", "execution_end_time", "red_summary",
|
|
]
|
|
_BLUE_FIELDS = [
|
|
"detection_result", "containment_result", "detection_time",
|
|
"containment_time", "blue_summary", "system_gaps",
|
|
]
|
|
|
|
|
|
def _add_evidence(db, test_id, team: TeamSide):
|
|
ev = Evidence(
|
|
test_id=uuid.UUID(test_id),
|
|
file_name="proof.txt",
|
|
file_path="s3://bucket/proof.txt",
|
|
sha256_hash="a" * 64,
|
|
team=team,
|
|
)
|
|
db.add(ev)
|
|
db.commit()
|
|
|
|
|
|
@pytest.fixture
|
|
def technique(api, auth_headers):
|
|
resp = api(
|
|
"post", "/api/v1/techniques", auth_headers,
|
|
json={"mitre_id": "T1059.100", "name": "Command Line"},
|
|
)
|
|
assert resp.status_code == 201, resp.text
|
|
return resp.json()["id"]
|
|
|
|
|
|
@pytest.fixture
|
|
def in_progress_test(client, db, api, red_lead_headers, red_lead_user, red_tech_headers, technique):
|
|
"""A test in red_executing with red-side content already filled in."""
|
|
resp = api(
|
|
"post", "/api/v1/tests", red_lead_headers,
|
|
json={"technique_id": technique, "name": "Visibility test"},
|
|
)
|
|
test_id = resp.json()["id"]
|
|
|
|
api("post", f"/api/v1/tests/{test_id}/start-execution", red_tech_headers)
|
|
api(
|
|
"patch", f"/api/v1/tests/{test_id}/red", red_tech_headers,
|
|
json={"procedure_text": "run mimikatz", "tool_used": "mimikatz", "red_summary": "dumped creds"},
|
|
)
|
|
return test_id
|
|
|
|
|
|
def test_blue_viewer_sees_red_fields_during_red_executing(
|
|
client, db, api, in_progress_test, blue_tech_headers
|
|
):
|
|
resp = api("get", f"/api/v1/tests/{in_progress_test}", blue_tech_headers)
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert body["procedure_text"] == "run mimikatz"
|
|
assert body["tool_used"] == "mimikatz"
|
|
assert body["red_summary"] == "dumped creds"
|
|
|
|
|
|
def test_red_viewer_sees_own_fields_during_red_executing(
|
|
client, db, api, in_progress_test, red_tech_headers
|
|
):
|
|
resp = api("get", f"/api/v1/tests/{in_progress_test}", red_tech_headers)
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert body["procedure_text"] == "run mimikatz"
|
|
|
|
|
|
def test_both_sides_see_everything_once_in_review(
|
|
client, db, api, auth_headers, red_tech_headers, red_lead_headers,
|
|
blue_tech_headers, blue_lead_headers, red_lead_user, blue_lead_user, in_progress_test,
|
|
):
|
|
test_id = in_progress_test
|
|
_add_evidence(db, test_id, TeamSide.red)
|
|
submit_red = api("post", f"/api/v1/tests/{test_id}/submit-red", red_tech_headers)
|
|
assert submit_red.status_code == 200, submit_red.text
|
|
|
|
approve_red = api("post", f"/api/v1/tests/{test_id}/review-red", red_lead_headers, json={"decision": "approve"})
|
|
assert approve_red.status_code == 200, approve_red.text
|
|
|
|
api("post", f"/api/v1/tests/{test_id}/start-blue-work", blue_tech_headers)
|
|
api(
|
|
"patch", f"/api/v1/tests/{test_id}/blue", blue_tech_headers,
|
|
json={"detection_result": "detected", "blue_summary": "caught it"},
|
|
)
|
|
_add_evidence(db, test_id, TeamSide.blue)
|
|
submit_blue = api("post", f"/api/v1/tests/{test_id}/submit-blue", blue_tech_headers)
|
|
assert submit_blue.status_code == 200, submit_blue.text
|
|
|
|
approve_blue = api("post", f"/api/v1/tests/{test_id}/review-blue", blue_lead_headers, json={"decision": "approve"})
|
|
assert approve_blue.status_code == 200, approve_blue.text
|
|
assert approve_blue.json()["state"] == "in_review"
|
|
|
|
resp_as_red = api("get", f"/api/v1/tests/{test_id}", red_tech_headers)
|
|
body_red = resp_as_red.json()
|
|
assert body_red["detection_result"] == "detected"
|
|
assert body_red["blue_summary"] == "caught it"
|
|
|
|
resp_as_blue = api("get", f"/api/v1/tests/{test_id}", blue_tech_headers)
|
|
body_blue = resp_as_blue.json()
|
|
assert body_blue["procedure_text"] == "run mimikatz"
|
|
assert body_blue["red_summary"] == "dumped creds"
|