fix(jira): correct Data Sensitivity field ID and replicate Jira's real classification scheme
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

The auto-create-ticket call was sending customfield_11233 (a field that
doesn't exist in the project) instead of the real Data Sensitivity field
customfield_11814, which made Jira reject the WHOLE issue and silently
block ticket creation for every new test.

Also replaces Aegis's invented 4-tier data_classification scheme
(public_release/general_use/confidential/restricted) with the 6 values
Jira's Data Sensitivity field actually uses (public/general_use/
internal_use_only/trusted_people/customer_content/pii), since that is
the classification the organization actually applies. Includes a data
migration remapping existing rows and a defensive retry if Jira ever
rejects an unscreened custom field again.
This commit is contained in:
kitos
2026-07-09 16:33:41 +02:00
parent 512b682cc5
commit d726e3adfe
12 changed files with 229 additions and 47 deletions
+17 -17
View File
@@ -34,7 +34,7 @@ def _seed_technique(db, tactic="execution") -> Technique:
return technique
def test_new_test_defaults_to_confidential_via_db_default(db, red_lead_user):
def test_new_test_defaults_to_internal_use_only_via_db_default(db, red_lead_user):
"""A Test() constructed without going through the create_test service
still gets a safe classification via the column's server_default."""
technique = _seed_technique(db)
@@ -46,7 +46,7 @@ def test_new_test_defaults_to_confidential_via_db_default(db, red_lead_user):
db.add(test)
db.commit()
db.refresh(test)
assert test.data_classification == "confidential"
assert test.data_classification == "internal_use_only"
def test_create_test_endpoint_uses_tactic_heuristic(client, db, api, auth_headers, technique):
@@ -57,8 +57,8 @@ def test_create_test_endpoint_uses_tactic_heuristic(client, db, api, auth_header
)
assert resp.status_code == 201, resp.text
# The shared `technique` fixture (see conftest/test_tests.py) doesn't set
# a restricted-tier tactic, so this should land on the baseline.
assert resp.json()["data_classification"] == "confidential"
# a pii-tier tactic, so this should land on the baseline.
assert resp.json()["data_classification"] == "internal_use_only"
def test_admin_can_update_classification(client, db, admin_user, admin_token, red_lead_user):
@@ -74,14 +74,14 @@ def test_admin_can_update_classification(client, db, admin_user, admin_token, re
response = client.patch(
f"/api/v1/tests/{test.id}/classification",
json={"data_classification": "restricted"},
json={"data_classification": "pii"},
headers={"Authorization": f"Bearer {admin_token}"},
)
assert response.status_code == 200
assert response.json()["data_classification"] == "restricted"
assert response.json()["data_classification"] == "pii"
db.refresh(test)
assert test.data_classification == "restricted"
assert test.data_classification == "pii"
def test_operator_can_update_classification(client, db, admin_user, red_lead_token, red_lead_user):
@@ -130,7 +130,7 @@ def test_viewer_cannot_update_classification(client, db, admin_user, red_lead_us
response = client.patch(
f"/api/v1/tests/{test.id}/classification",
json={"data_classification": "restricted"},
json={"data_classification": "pii"},
headers={"Authorization": f"Bearer {viewer_token}"},
)
assert response.status_code == 403
@@ -142,15 +142,15 @@ def _technique_stub(tactic):
return t
def test_determine_initial_classification_defaults_to_confidential():
assert determine_initial_classification(_technique_stub("execution")) == "confidential"
assert determine_initial_classification(_technique_stub(None)) == "confidential"
assert determine_initial_classification(None) == "confidential"
def test_determine_initial_classification_defaults_to_internal_use_only():
assert determine_initial_classification(_technique_stub("execution")) == "internal_use_only"
assert determine_initial_classification(_technique_stub(None)) == "internal_use_only"
assert determine_initial_classification(None) == "internal_use_only"
def test_determine_initial_classification_escalates_for_sensitive_tactics():
assert determine_initial_classification(_technique_stub("exfiltration")) == "restricted"
assert determine_initial_classification(_technique_stub("collection")) == "restricted"
assert determine_initial_classification(_technique_stub("credential-access")) == "restricted"
assert determine_initial_classification(_technique_stub("impact")) == "restricted"
assert determine_initial_classification(_technique_stub("Exfiltration")) == "restricted"
assert determine_initial_classification(_technique_stub("exfiltration")) == "pii"
assert determine_initial_classification(_technique_stub("collection")) == "pii"
assert determine_initial_classification(_technique_stub("credential-access")) == "pii"
assert determine_initial_classification(_technique_stub("impact")) == "pii"
assert determine_initial_classification(_technique_stub("Exfiltration")) == "pii"