feat(jira): label standalone tests, include round data in submission comments
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

- Tests created without a campaign parent ticket now get a "standalone-test"
  label, so they're identifiable in Jira without cross-referencing Aegis.
- The comment posted on every red/blue submission was a generic one-liner
  with no data — only a reopened round got a full data dump (via
  push_round_archived), so a round that was approved outright left no
  record in Jira of what was actually done. Now every submission comment
  includes the round number, procedure/tool/attack success (red) or
  detection/containment result (blue), and summary.
This commit is contained in:
kitos
2026-07-14 08:37:40 +02:00
parent 6d6f87b968
commit 814cfa9671
2 changed files with 129 additions and 5 deletions
+109 -1
View File
@@ -59,6 +59,8 @@ def _make_test(**overrides):
t.containment_time = None
t.red_round_number = 1
t.blue_round_number = 1
t.procedure_text = None
t.tool_used = None
# _build_state_comment() appends these raw (not via an f-string) when
# truthy, so an un-nulled MagicMock attribute breaks "\n".join(lines).
t.red_summary = None
@@ -230,6 +232,58 @@ def test_push_test_event_maps_every_state_to_jira_status(
mock_jira.set_issue_status.assert_called_once_with(link.jira_issue_key, expected_status)
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_admin_jira_client")
def test_push_test_event_red_review_comment_includes_round_data(mock_get_client, mock_configured, db):
"""Every submission — not just ones that later get reopened — must leave
a data-bearing comment in Jira. Previously this comment was a generic
one-liner with no procedure/tool/result, so a round that got approved
(never archived via reopen) left no record of what was actually done."""
mock_jira = MagicMock()
mock_get_client.return_value = mock_jira
test = _make_test(
red_round_number=2,
procedure_text="ran mimikatz again", tool_used="mimikatz",
attack_success=MagicMock(value="successful"), red_summary="Got a shell this time.",
)
link = _make_link(test.id)
db.add(link)
db.commit()
jira_service.push_test_event(db, test, MagicMock(username="alice", jira_account_id=None), "red_review")
comment = mock_jira.issue_add_comment.call_args[0][1]
assert "Round 2" in comment
assert "ran mimikatz again" in comment
assert "mimikatz" in comment
assert "successful" in comment
assert "Got a shell this time." in comment
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_admin_jira_client")
def test_push_test_event_blue_review_comment_includes_round_data(mock_get_client, mock_configured, db):
mock_jira = MagicMock()
mock_get_client.return_value = mock_jira
test = _make_test(
blue_round_number=1,
detection_result=MagicMock(value="detected"),
containment_result=MagicMock(value="contained"),
blue_summary="Caught it via EDR.",
)
link = _make_link(test.id)
db.add(link)
db.commit()
jira_service.push_test_event(db, test, MagicMock(username="alice", jira_account_id=None), "blue_review")
comment = mock_jira.issue_add_comment.call_args[0][1]
assert "Round 1" in comment
assert "detected" in comment
assert "contained" in comment
assert "Caught it via EDR." in comment
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_admin_jira_client")
def test_push_test_event_clears_assignee_on_in_review(mock_get_client, mock_configured, db):
@@ -658,7 +712,61 @@ def test_auto_create_test_issue_adds_platform_label(
if expected_label:
assert expected_label in labels
else:
assert len(labels) == 2
# Just "aegis", the technique ID, and "standalone-test" (no
# parent_ticket_override passed here, same as any non-campaign test).
assert len(labels) == 3
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_jira_project_key", return_value="SEC")
@patch("app.services.jira_service.get_jira_parent_ticket_standalone", return_value=None)
@patch("app.services.jira_service.get_admin_jira_client")
def test_auto_create_test_issue_labels_standalone_tests(
mock_get_client, mock_parent, mock_project_key, mock_configured, db,
):
"""A test created with no campaign parent ticket is standalone — tag it
so standalone tests are identifiable in Jira without cross-referencing
Aegis."""
mock_jira = MagicMock()
mock_jira.issue_create.return_value = {"key": "SEC-1", "id": "1"}
mock_get_client.return_value = mock_jira
from app.models.user import User
test = _make_test_for_issue()
technique = _make_technique()
actor = User(username="gerardo-ruiz", email="gerardo.ruiz@kaseya.com", hashed_password="x")
db.add(actor)
db.commit()
jira_service.auto_create_test_issue(db, test, actor, technique=technique)
labels = mock_jira.issue_create.call_args.kwargs["fields"]["labels"]
assert "standalone-test" in labels
@patch("app.services.jira_service.has_admin_jira_configured", return_value=True)
@patch("app.services.jira_service.get_jira_project_key", return_value="SEC")
@patch("app.services.jira_service.get_admin_jira_client")
def test_auto_create_test_issue_does_not_label_campaign_tests_as_standalone(
mock_get_client, mock_project_key, mock_configured, db,
):
"""A campaign test passes parent_ticket_override — it must NOT get
"standalone-test", since it's nested under the campaign's ticket."""
mock_jira = MagicMock()
mock_jira.issue_create.return_value = {"key": "SEC-1", "id": "1"}
mock_get_client.return_value = mock_jira
from app.models.user import User
test = _make_test_for_issue()
technique = _make_technique()
actor = User(username="gerardo-ruiz", email="gerardo.ruiz@kaseya.com", hashed_password="x")
db.add(actor)
db.commit()
jira_service.auto_create_test_issue(
db, test, actor, technique=technique, parent_ticket_override="CAMP-1",
)
labels = mock_jira.issue_create.call_args.kwargs["fields"]["labels"]
assert "standalone-test" not in labels
def _make_user(**overrides):