diff --git a/backend/app/routers/compliance.py b/backend/app/routers/compliance.py index cd642ae..e225f09 100644 --- a/backend/app/routers/compliance.py +++ b/backend/app/routers/compliance.py @@ -22,6 +22,7 @@ from app.services.compliance_service import ( from app.services.compliance_import_service import ( import_nist_800_53_mappings, import_cis_controls_v8_mappings, + import_dora_mappings, ) router = APIRouter(prefix="/compliance", tags=["compliance"]) @@ -119,3 +120,13 @@ def import_cis( """Import CIS Controls v8 mappings (admin only).""" result = import_cis_controls_v8_mappings(db) return result + + +@router.post("/import/dora") +def import_dora( + db: Session = Depends(get_db), + current_user: User = Depends(require_role("admin")), +): + """Import DORA (EU 2022/2554) compliance mappings (admin only).""" + result = import_dora_mappings(db) + return result diff --git a/backend/app/services/compliance_import_service.py b/backend/app/services/compliance_import_service.py index 7dd0b41..fcfe56e 100644 --- a/backend/app/services/compliance_import_service.py +++ b/backend/app/services/compliance_import_service.py @@ -482,6 +482,252 @@ def import_cis_controls_v8_mappings(db: Session) -> dict: return summary +def import_dora_mappings(db: Session) -> dict: + """Import DORA (Digital Operational Resilience Act) with ATT&CK technique mappings. + + DORA (EU 2022/2554) applies to financial entities and ICT third-party providers. + Controls map the key cybersecurity articles (Chapters II–VI) to MITRE ATT&CK + techniques based on ENISA guidance and TIBER-EU threat-led testing framework. + + Returns a summary dict with counts. + """ + # ── 1. Create or get framework ──────────────────────────────── + framework = ( + db.query(ComplianceFramework) + .filter(ComplianceFramework.name == "DORA") + .first() + ) + + if not framework: + framework = ComplianceFramework( + name="DORA", + version="2022/2554", + description=( + "Digital Operational Resilience Act (Regulation EU 2022/2554) — " + "EU regulation establishing ICT risk management, incident reporting, " + "digital operational resilience testing, and ICT third-party risk " + "management requirements for financial entities." + ), + url="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022R2554", + is_active=True, + ) + db.add(framework) + db.flush() + logger.info("Created DORA framework") + else: + logger.info("DORA framework already exists") + + # ── 2. Control definitions with ATT&CK mappings ─────────────── + # Based on ENISA DORA guidelines and TIBER-EU threat intelligence framework. + # Each control maps to a DORA article and the ATT&CK techniques it addresses. + DORA_CONTROLS = [ + # ─── Chapter II — ICT Risk Management ──────────────────────────── + { + "control_id": "DORA-Art.5", + "title": "Governance and Organisation", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1078", "T1136", "T1098", "T1087"], + }, + { + "control_id": "DORA-Art.6", + "title": "ICT Risk Management Framework", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1595", "T1590", "T1589", "T1046", "T1018", "T1082"], + }, + { + "control_id": "DORA-Art.7", + "title": "ICT Systems, Protocols and Tools", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1574", "T1543", "T1112", "T1546", "T1195", "T1133"], + }, + { + "control_id": "DORA-Art.8", + "title": "Identification", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1018", "T1082", "T1083", "T1087", "T1590", "T1592"], + }, + { + "control_id": "DORA-Art.9", + "title": "Protection and Prevention", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1078", "T1548", "T1134", "T1190", "T1574", "T1543", "T1021"], + }, + { + "control_id": "DORA-Art.10", + "title": "Detection", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1562", "T1070", "T1059", "T1053", "T1547", "T1037"], + }, + { + "control_id": "DORA-Art.11", + "title": "Response and Recovery", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1486", "T1490", "T1561", "T1485", "T1048", "T1041"], + }, + { + "control_id": "DORA-Art.12", + "title": "Backup Policies and Recovery Methods", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1486", "T1490", "T1561", "T1485"], + }, + { + "control_id": "DORA-Art.13", + "title": "Learning and Evolving", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1566", "T1589", "T1590", "T1595", "T1598"], + }, + { + "control_id": "DORA-Art.14", + "title": "Communication", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1114", "T1566", "T1102", "T1071"], + }, + { + "control_id": "DORA-Art.15", + "title": "Further Harmonisation of ICT Risk Management Tools", + "category": "Chapter II — ICT Risk Management", + "techniques": ["T1078", "T1190", "T1133", "T1021", "T1199"], + }, + # ─── Chapter III — ICT-related Incident Management ──────────────── + { + "control_id": "DORA-Art.17", + "title": "ICT-related Incidents Classification", + "category": "Chapter III — Incident Management", + "techniques": ["T1499", "T1498", "T1486", "T1041", "T1048", "T1565"], + }, + { + "control_id": "DORA-Art.18", + "title": "Major ICT-Related Incidents Reporting", + "category": "Chapter III — Incident Management", + "techniques": ["T1486", "T1041", "T1048", "T1499", "T1498"], + }, + { + "control_id": "DORA-Art.19", + "title": "Harmonisation of Reporting Content and Formats", + "category": "Chapter III — Incident Management", + "techniques": ["T1566", "T1190", "T1203", "T1059"], + }, + # ─── Chapter IV — Digital Operational Resilience Testing ────────── + { + "control_id": "DORA-Art.24", + "title": "General Digital Operational Resilience Testing", + "category": "Chapter IV — Resilience Testing", + "techniques": ["T1059", "T1190", "T1046", "T1595", "T1078"], + }, + { + "control_id": "DORA-Art.25", + "title": "Testing of ICT Tools and Systems", + "category": "Chapter IV — Resilience Testing", + "techniques": ["T1059", "T1190", "T1046", "T1595", "T1078", "T1068", "T1210"], + }, + { + "control_id": "DORA-Art.26", + "title": "Advanced Testing — Threat-Led Penetration Testing (TLPT)", + "category": "Chapter IV — Resilience Testing", + "techniques": [ + "T1566", "T1204", "T1055", "T1059", "T1021", "T1078", + "T1190", "T1046", "T1548", "T1134", "T1027", + ], + }, + { + "control_id": "DORA-Art.27", + "title": "Requirements for Testers Carrying Out TLPT", + "category": "Chapter IV — Resilience Testing", + "techniques": ["T1595", "T1046", "T1190", "T1059", "T1078"], + }, + # ─── Chapter V — ICT Third-Party Risk Management ────────────────── + { + "control_id": "DORA-Art.28", + "title": "General Principles of ICT Third-Party Risk Management", + "category": "Chapter V — Third-Party Risk", + "techniques": ["T1199", "T1195", "T1078", "T1133"], + }, + { + "control_id": "DORA-Art.30", + "title": "Key Contractual Provisions for ICT Services", + "category": "Chapter V — Third-Party Risk", + "techniques": ["T1199", "T1195", "T1078"], + }, + { + "control_id": "DORA-Art.42", + "title": "Oversight of Critical ICT Third-Party Providers", + "category": "Chapter V — Third-Party Risk", + "techniques": ["T1199", "T1195", "T1133", "T1078", "T1190"], + }, + # ─── Chapter VI — Information Sharing ──────────────────────────── + { + "control_id": "DORA-Art.45", + "title": "Arrangements for Information Sharing on Cyber Threats", + "category": "Chapter VI — Information Sharing", + "techniques": ["T1566", "T1589", "T1590", "T1595", "T1598"], + }, + ] + + # Build technique lookup + all_techniques = {t.mitre_id: t for t in db.query(Technique).all()} + + existing_controls = { + c.control_id: c + for c in db.query(ComplianceControl) + .filter(ComplianceControl.framework_id == framework.id) + .all() + } + + existing_mappings = set() + for m in ( + db.query(ComplianceControlMapping) + .join(ComplianceControl) + .filter(ComplianceControl.framework_id == framework.id) + .all() + ): + existing_mappings.add((str(m.compliance_control_id), str(m.technique_id))) + + controls_created = 0 + mappings_created = 0 + + for item in DORA_CONTROLS: + if item["control_id"] in existing_controls: + control = existing_controls[item["control_id"]] + else: + control = ComplianceControl( + framework_id=framework.id, + control_id=item["control_id"], + title=item["title"], + category=item["category"], + ) + db.add(control) + db.flush() + existing_controls[item["control_id"]] = control + controls_created += 1 + + for mitre_id in item["techniques"]: + technique = all_techniques.get(mitre_id) + if not technique: + continue + key = (str(control.id), str(technique.id)) + if key in existing_mappings: + continue + mapping = ComplianceControlMapping( + compliance_control_id=control.id, + technique_id=technique.id, + ) + db.add(mapping) + existing_mappings.add(key) + mappings_created += 1 + + db.commit() + + summary = { + "framework": framework.name, + "controls_created": controls_created, + "controls_existing": len(existing_controls) - controls_created, + "mappings_created": mappings_created, + "total_controls": len(existing_controls), + } + logger.info(f"DORA import complete: {summary}") + return summary + + def _get_nist_category(family_code: str) -> str: """Map NIST 800-53 family code to category name.""" categories = { diff --git a/frontend/src/api/compliance.ts b/frontend/src/api/compliance.ts index b6e16ef..f13e545 100644 --- a/frontend/src/api/compliance.ts +++ b/frontend/src/api/compliance.ts @@ -120,3 +120,9 @@ export async function importCisMappings(): Promise> { const { data } = await client.post("/compliance/import/cis-controls-v8"); return data; } + +/** Import DORA (EU 2022/2554) compliance mappings (admin). */ +export async function importDoraMappings(): Promise> { + const { data } = await client.post("/compliance/import/dora"); + return data; +} diff --git a/frontend/src/pages/CompliancePage.tsx b/frontend/src/pages/CompliancePage.tsx index 14e9ff5..3d528d9 100644 --- a/frontend/src/pages/CompliancePage.tsx +++ b/frontend/src/pages/CompliancePage.tsx @@ -7,6 +7,7 @@ import { downloadComplianceCSV, importNistMappings, importCisMappings, + importDoraMappings, type ComplianceFrameworkSummary, } from "../api/compliance"; import { useAuth } from "../context/AuthContext"; @@ -81,7 +82,15 @@ export default function CompliancePage() { }, }); - const isImporting = importNist.isPending || importCis.isPending; + const importDora = useMutation({ + mutationFn: importDoraMappings, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["compliance-frameworks"] }); + queryClient.invalidateQueries({ queryKey: ["compliance-status"] }); + }, + }); + + const isImporting = importNist.isPending || importCis.isPending || importDora.isPending; if (isLoading && !frameworkStatus) { return ( @@ -215,10 +224,18 @@ export default function CompliancePage() { {importCis.isPending ? : } CIS Controls v8 - {(importNist.isSuccess || importCis.isSuccess) && ( + + {(importNist.isSuccess || importCis.isSuccess || importDora.isSuccess) && ( Import complete )} - {(importNist.isError || importCis.isError) && ( + {(importNist.isError || importCis.isError || importDora.isError) && ( Import failed )}