diff --git a/backend/app/routers/compliance.py b/backend/app/routers/compliance.py index e225f09..9183f29 100644 --- a/backend/app/routers/compliance.py +++ b/backend/app/routers/compliance.py @@ -23,6 +23,8 @@ from app.services.compliance_import_service import ( import_nist_800_53_mappings, import_cis_controls_v8_mappings, import_dora_mappings, + import_iso_27001_mappings, + import_iso_42001_mappings, ) router = APIRouter(prefix="/compliance", tags=["compliance"]) @@ -130,3 +132,23 @@ def import_dora( """Import DORA (EU 2022/2554) compliance mappings (admin only).""" result = import_dora_mappings(db) return result + + +@router.post("/import/iso-27001") +def import_iso27001( + db: Session = Depends(get_db), + current_user: User = Depends(require_role("admin")), +): + """Import ISO/IEC 27001:2022 Annex A compliance mappings (admin only).""" + result = import_iso_27001_mappings(db) + return result + + +@router.post("/import/iso-42001") +def import_iso42001( + db: Session = Depends(get_db), + current_user: User = Depends(require_role("admin")), +): + """Import ISO/IEC 42001:2023 AI Management System compliance mappings (admin only).""" + result = import_iso_42001_mappings(db) + return result diff --git a/backend/app/services/compliance_import_service.py b/backend/app/services/compliance_import_service.py index fcfe56e..24f59cb 100644 --- a/backend/app/services/compliance_import_service.py +++ b/backend/app/services/compliance_import_service.py @@ -728,6 +728,568 @@ def import_dora_mappings(db: Session) -> dict: return summary +def import_iso_27001_mappings(db: Session) -> dict: + """Import ISO/IEC 27001:2022 Annex A controls with ATT&CK technique mappings. + + ISO/IEC 27001:2022 has 93 controls in Annex A organised into 4 themes: + - 5. Organizational controls (37) + - 6. People controls (8) + - 7. Physical controls (14) + - 8. Technological controls (34) + + Mappings follow MITRE ATT&CK Enterprise v14 and published ISO/IEC 27002:2022 + guidance on threat mitigations. + + Returns a summary dict with counts. + """ + framework = ( + db.query(ComplianceFramework) + .filter(ComplianceFramework.name == "ISO/IEC 27001:2022") + .first() + ) + + if not framework: + framework = ComplianceFramework( + name="ISO/IEC 27001:2022", + version="2022", + description=( + "ISO/IEC 27001:2022 — International standard for Information Security " + "Management Systems (ISMS). Annex A contains 93 controls across 4 themes: " + "Organizational, People, Physical, and Technological." + ), + url="https://www.iso.org/standard/27001", + is_active=True, + ) + db.add(framework) + db.flush() + logger.info("Created ISO/IEC 27001:2022 framework") + else: + logger.info("ISO/IEC 27001:2022 framework already exists") + + ISO_27001_CONTROLS = [ + # ── 5. Organizational Controls ────────────────────────────────────── + { + "control_id": "5.2", + "title": "Information Security Roles and Responsibilities", + "category": "5 — Organizational Controls", + "techniques": ["T1078", "T1087", "T1069"], + }, + { + "control_id": "5.7", + "title": "Threat Intelligence", + "category": "5 — Organizational Controls", + "techniques": ["T1566", "T1589", "T1590", "T1595", "T1598"], + }, + { + "control_id": "5.9", + "title": "Inventory of Information and Other Assets", + "category": "5 — Organizational Controls", + "techniques": ["T1082", "T1083", "T1018", "T1592"], + }, + { + "control_id": "5.14", + "title": "Information Transfer", + "category": "5 — Organizational Controls", + "techniques": ["T1048", "T1041", "T1567", "T1071"], + }, + { + "control_id": "5.16", + "title": "Identity Management", + "category": "5 — Organizational Controls", + "techniques": ["T1078", "T1136", "T1098", "T1087"], + }, + { + "control_id": "5.17", + "title": "Authentication Information", + "category": "5 — Organizational Controls", + "techniques": ["T1110", "T1003", "T1078", "T1552"], + }, + { + "control_id": "5.20", + "title": "Addressing Information Security in Supplier Agreements", + "category": "5 — Organizational Controls", + "techniques": ["T1199", "T1195"], + }, + { + "control_id": "5.23", + "title": "Information Security for Use of Cloud Services", + "category": "5 — Organizational Controls", + "techniques": ["T1530", "T1537", "T1078", "T1190"], + }, + { + "control_id": "5.24", + "title": "Information Security Incident Management Planning", + "category": "5 — Organizational Controls", + "techniques": ["T1059", "T1547", "T1486"], + }, + { + "control_id": "5.26", + "title": "Response to Information Security Incidents", + "category": "5 — Organizational Controls", + "techniques": ["T1059", "T1547", "T1070", "T1562"], + }, + { + "control_id": "5.28", + "title": "Collection of Evidence", + "category": "5 — Organizational Controls", + "techniques": ["T1562", "T1070"], + }, + { + "control_id": "5.29", + "title": "Information Security During Disruption", + "category": "5 — Organizational Controls", + "techniques": ["T1486", "T1490", "T1561"], + }, + { + "control_id": "5.30", + "title": "ICT Readiness for Business Continuity", + "category": "5 — Organizational Controls", + "techniques": ["T1486", "T1490", "T1499", "T1498"], + }, + # ── 6. People Controls ─────────────────────────────────────────────── + { + "control_id": "6.1", + "title": "Screening", + "category": "6 — People Controls", + "techniques": ["T1078", "T1134"], + }, + { + "control_id": "6.3", + "title": "Information Security Awareness, Education and Training", + "category": "6 — People Controls", + "techniques": ["T1566", "T1204", "T1598"], + }, + { + "control_id": "6.4", + "title": "Disciplinary Process", + "category": "6 — People Controls", + "techniques": ["T1078", "T1098"], + }, + # ── 7. Physical Controls ───────────────────────────────────────────── + { + "control_id": "7.1", + "title": "Physical Security Perimeters", + "category": "7 — Physical Controls", + "techniques": ["T1200"], + }, + { + "control_id": "7.4", + "title": "Physical Security Monitoring", + "category": "7 — Physical Controls", + "techniques": ["T1200", "T1556"], + }, + # ── 8. Technological Controls ──────────────────────────────────────── + { + "control_id": "8.2", + "title": "Privileged Access Rights", + "category": "8 — Technological Controls", + "techniques": ["T1078", "T1548", "T1134"], + }, + { + "control_id": "8.3", + "title": "Information Access Restriction", + "category": "8 — Technological Controls", + "techniques": ["T1078", "T1021", "T1548", "T1550"], + }, + { + "control_id": "8.5", + "title": "Secure Authentication", + "category": "8 — Technological Controls", + "techniques": ["T1078", "T1110", "T1003", "T1558"], + }, + { + "control_id": "8.7", + "title": "Protection Against Malware", + "category": "8 — Technological Controls", + "techniques": ["T1059", "T1204", "T1027", "T1566", "T1140"], + }, + { + "control_id": "8.8", + "title": "Management of Technical Vulnerabilities", + "category": "8 — Technological Controls", + "techniques": ["T1190", "T1203", "T1068", "T1210"], + }, + { + "control_id": "8.9", + "title": "Configuration Management", + "category": "8 — Technological Controls", + "techniques": ["T1574", "T1546", "T1112", "T1543"], + }, + { + "control_id": "8.12", + "title": "Data Leakage Prevention", + "category": "8 — Technological Controls", + "techniques": ["T1048", "T1041", "T1567", "T1071"], + }, + { + "control_id": "8.13", + "title": "Information Backup", + "category": "8 — Technological Controls", + "techniques": ["T1486", "T1490", "T1561"], + }, + { + "control_id": "8.15", + "title": "Logging", + "category": "8 — Technological Controls", + "techniques": ["T1562", "T1070"], + }, + { + "control_id": "8.16", + "title": "Monitoring Activities", + "category": "8 — Technological Controls", + "techniques": ["T1059", "T1053", "T1547", "T1562"], + }, + { + "control_id": "8.18", + "title": "Use of Privileged Utility Programs", + "category": "8 — Technological Controls", + "techniques": ["T1059", "T1548", "T1134", "T1569"], + }, + { + "control_id": "8.19", + "title": "Installation of Software on Operational Systems", + "category": "8 — Technological Controls", + "techniques": ["T1195", "T1072", "T1546"], + }, + { + "control_id": "8.20", + "title": "Networks Security", + "category": "8 — Technological Controls", + "techniques": ["T1571", "T1572", "T1090", "T1021"], + }, + { + "control_id": "8.22", + "title": "Segregation of Networks", + "category": "8 — Technological Controls", + "techniques": ["T1021", "T1550", "T1558"], + }, + { + "control_id": "8.23", + "title": "Web Filtering", + "category": "8 — Technological Controls", + "techniques": ["T1566", "T1204", "T1189"], + }, + { + "control_id": "8.24", + "title": "Use of Cryptography", + "category": "8 — Technological Controls", + "techniques": ["T1573", "T1022", "T1027"], + }, + { + "control_id": "8.26", + "title": "Application Security Requirements", + "category": "8 — Technological Controls", + "techniques": ["T1190", "T1059", "T1203"], + }, + { + "control_id": "8.28", + "title": "Secure Coding", + "category": "8 — Technological Controls", + "techniques": ["T1059", "T1190", "T1203"], + }, + { + "control_id": "8.32", + "title": "Change Management", + "category": "8 — Technological Controls", + "techniques": ["T1574", "T1546", "T1112"], + }, + { + "control_id": "8.34", + "title": "Protection of Information Systems During Audit Testing", + "category": "8 — Technological Controls", + "techniques": ["T1562", "T1059"], + }, + ] + + return _import_curated_framework(db, framework, ISO_27001_CONTROLS) + + +def import_iso_42001_mappings(db: Session) -> dict: + """Import ISO/IEC 42001:2023 Annex A controls with ATT&CK technique mappings. + + ISO/IEC 42001:2023 is the international standard for Artificial Intelligence + Management Systems (AIMS). Annex A contains controls specific to the governance, + operation, and security of AI systems. + + ATT&CK mappings focus on threats to AI system infrastructure: + - Supply chain attacks on ML frameworks and model artefacts + - Data pipeline compromise (training data poisoning / exfiltration) + - AI model serving exploitation + - Adversarial access to AI APIs and datasets + + Returns a summary dict with counts. + """ + framework = ( + db.query(ComplianceFramework) + .filter(ComplianceFramework.name == "ISO/IEC 42001:2023") + .first() + ) + + if not framework: + framework = ComplianceFramework( + name="ISO/IEC 42001:2023", + version="2023", + description=( + "ISO/IEC 42001:2023 — International standard for Artificial Intelligence " + "Management Systems (AIMS). Establishes requirements and guidance for " + "organisations developing or using AI systems responsibly, covering governance, " + "risk, transparency, and security of AI pipelines and models." + ), + url="https://www.iso.org/standard/81230.html", + is_active=True, + ) + db.add(framework) + db.flush() + logger.info("Created ISO/IEC 42001:2023 framework") + else: + logger.info("ISO/IEC 42001:2023 framework already exists") + + ISO_42001_CONTROLS = [ + # ── A.2 Organization's Policies Related to AI ──────────────────────── + { + "control_id": "A.2.2", + "title": "Process to Determine AI Impacts on Individuals", + "category": "A.2 — AI Policy", + "techniques": ["T1082", "T1592", "T1590"], + }, + { + "control_id": "A.2.6", + "title": "Responsible Development and Use of AI", + "category": "A.2 — AI Policy", + "techniques": ["T1195", "T1059"], + }, + # ── A.3 Internal Organization ───────────────────────────────────────── + { + "control_id": "A.3.2", + "title": "Roles and Responsibilities for AI Systems", + "category": "A.3 — Internal Organization", + "techniques": ["T1078", "T1087", "T1069"], + }, + { + "control_id": "A.3.3", + "title": "Reporting on AI Performance", + "category": "A.3 — Internal Organization", + "techniques": ["T1562", "T1070"], + }, + # ── A.4 Resources for AI Systems ───────────────────────────────────── + { + "control_id": "A.4.1", + "title": "Resource Management for AI Systems", + "category": "A.4 — AI Resources", + "techniques": ["T1499", "T1498"], + }, + { + "control_id": "A.4.2", + "title": "AI System Supply Chain Management", + "category": "A.4 — AI Resources", + "techniques": ["T1195", "T1199", "T1072"], + }, + # ── A.5 Assessing Impacts of AI Systems ────────────────────────────── + { + "control_id": "A.5.2", + "title": "AI System Impact Assessment", + "category": "A.5 — AI Impact Assessment", + "techniques": ["T1082", "T1592", "T1589"], + }, + { + "control_id": "A.5.4", + "title": "AI Risk Treatment", + "category": "A.5 — AI Impact Assessment", + "techniques": ["T1190", "T1068", "T1203"], + }, + # ── A.6 AI System Life Cycle ────────────────────────────────────────── + { + "control_id": "A.6.1", + "title": "AI System Life Cycle Management", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1195", "T1574", "T1543"], + }, + { + "control_id": "A.6.2", + "title": "AI Objectives and Requirements", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1190", "T1059"], + }, + { + "control_id": "A.6.3", + "title": "AI System Design and Implementation", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1195", "T1059", "T1190", "T1027"], + }, + { + "control_id": "A.6.4", + "title": "AI System Verification and Validation", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1565", "T1195"], + }, + { + "control_id": "A.6.5", + "title": "AI System Documentation", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1083", "T1005"], + }, + { + "control_id": "A.6.6", + "title": "AI System Monitoring", + "category": "A.6 — AI Life Cycle", + "techniques": ["T1562", "T1070", "T1059"], + }, + # ── A.7 Data for AI Systems ─────────────────────────────────────────── + { + "control_id": "A.7.2", + "title": "Data Acquisition", + "category": "A.7 — AI Data", + "techniques": ["T1005", "T1074", "T1114"], + }, + { + "control_id": "A.7.3", + "title": "Data Preparation", + "category": "A.7 — AI Data", + "techniques": ["T1565", "T1059"], + }, + { + "control_id": "A.7.4", + "title": "Data Quality", + "category": "A.7 — AI Data", + "techniques": ["T1565", "T1485"], + }, + { + "control_id": "A.7.5", + "title": "Data Provenance", + "category": "A.7 — AI Data", + "techniques": ["T1195", "T1565"], + }, + { + "control_id": "A.7.6", + "title": "Data Privacy", + "category": "A.7 — AI Data", + "techniques": ["T1005", "T1114", "T1048", "T1041"], + }, + # ── A.8 Information About Use of AI Systems ─────────────────────────── + { + "control_id": "A.8.1", + "title": "Transparency and Explainability of AI Systems", + "category": "A.8 — AI Information", + "techniques": ["T1082", "T1592", "T1590"], + }, + { + "control_id": "A.8.2", + "title": "Security of AI Systems", + "category": "A.8 — AI Information", + "techniques": ["T1190", "T1059", "T1203", "T1078", "T1110"], + }, + # ── A.9 Use of AI Systems by Affected Parties ───────────────────────── + { + "control_id": "A.9.1", + "title": "Intended Use of AI Systems", + "category": "A.9 — AI Use", + "techniques": ["T1566", "T1204", "T1598"], + }, + { + "control_id": "A.9.3", + "title": "Human Oversight of AI Systems", + "category": "A.9 — AI Use", + "techniques": ["T1078", "T1134", "T1562"], + }, + # ── A.10 Third-Party and Customer Relationships ─────────────────────── + { + "control_id": "A.10.1", + "title": "Third-Party AI System Governance", + "category": "A.10 — Third-Party Relationships", + "techniques": ["T1199", "T1195", "T1078", "T1133"], + }, + { + "control_id": "A.10.2", + "title": "Customer Relationships for AI Systems", + "category": "A.10 — Third-Party Relationships", + "techniques": ["T1566", "T1598", "T1078"], + }, + ] + + return _import_curated_framework(db, framework, ISO_42001_CONTROLS) + + +def _import_curated_framework( + db: Session, + framework: ComplianceFramework, + controls: list[dict], +) -> dict: + """Shared helper to import a curated list of controls and technique mappings. + + ``controls`` is a list of dicts with keys: + - control_id (str) + - title (str) + - category (str) + - techniques (list[str] — MITRE ATT&CK IDs) + + Returns a summary dict. + """ + 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[tuple[str, str]] = 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 controls: + cid = item["control_id"] + if cid in existing_controls: + control = existing_controls[cid] + else: + control = ComplianceControl( + framework_id=framework.id, + control_id=cid, + title=item["title"], + category=item.get("category"), + description=item.get("description"), + ) + db.add(control) + db.flush() + existing_controls[cid] = control + controls_created += 1 + + for mitre_id in item.get("techniques", []): + technique = all_techniques.get(mitre_id) + if not technique: + continue + key = (str(control.id), str(technique.id)) + if key in existing_mappings: + continue + db.add(ComplianceControlMapping( + compliance_control_id=control.id, + technique_id=technique.id, + )) + 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, + "mappings_skipped": 0, + "total_controls": len(existing_controls), + } + logger.info(f"{framework.name} 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 f13e545..aac5fbc 100644 --- a/frontend/src/api/compliance.ts +++ b/frontend/src/api/compliance.ts @@ -126,3 +126,15 @@ export async function importDoraMappings(): Promise> { const { data } = await client.post("/compliance/import/dora"); return data; } + +/** Import ISO/IEC 27001:2022 Annex A compliance mappings (admin). */ +export async function importIso27001Mappings(): Promise> { + const { data } = await client.post("/compliance/import/iso-27001"); + return data; +} + +/** Import ISO/IEC 42001:2023 AI Management System compliance mappings (admin). */ +export async function importIso42001Mappings(): Promise> { + const { data } = await client.post("/compliance/import/iso-42001"); + return data; +} diff --git a/frontend/src/pages/CompliancePage.tsx b/frontend/src/pages/CompliancePage.tsx index 3d528d9..7247a70 100644 --- a/frontend/src/pages/CompliancePage.tsx +++ b/frontend/src/pages/CompliancePage.tsx @@ -8,6 +8,8 @@ import { importNistMappings, importCisMappings, importDoraMappings, + importIso27001Mappings, + importIso42001Mappings, type ComplianceFrameworkSummary, } from "../api/compliance"; import { useAuth } from "../context/AuthContext"; @@ -90,7 +92,28 @@ export default function CompliancePage() { }, }); - const isImporting = importNist.isPending || importCis.isPending || importDora.isPending; + const importIso27001 = useMutation({ + mutationFn: importIso27001Mappings, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["compliance-frameworks"] }); + queryClient.invalidateQueries({ queryKey: ["compliance-status"] }); + }, + }); + + const importIso42001 = useMutation({ + mutationFn: importIso42001Mappings, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["compliance-frameworks"] }); + queryClient.invalidateQueries({ queryKey: ["compliance-status"] }); + }, + }); + + const isImporting = + importNist.isPending || + importCis.isPending || + importDora.isPending || + importIso27001.isPending || + importIso42001.isPending; if (isLoading && !frameworkStatus) { return ( @@ -232,10 +255,28 @@ export default function CompliancePage() { {importDora.isPending ? : } DORA - {(importNist.isSuccess || importCis.isSuccess || importDora.isSuccess) && ( + + + {(importNist.isSuccess || importCis.isSuccess || importDora.isSuccess || + importIso27001.isSuccess || importIso42001.isSuccess) && ( Import complete )} - {(importNist.isError || importCis.isError || importDora.isError) && ( + {(importNist.isError || importCis.isError || importDora.isError || + importIso27001.isError || importIso42001.isError) && ( Import failed )}