fix: D3FEND expandable cards, System page cleanup, and multi-source improvements
- Make D3FEND defense cards clickable with expandable details and external link - Fix D3FEND URLs to use PascalCase technique names matching the ontology - Remove duplicate Import Atomic Red Team from System page (use Data Sources) - Add bulk Activate All / Deactivate All buttons with confirmation modal - Fix template admin list to show both active and inactive templates - Add PATCH /test-templates/bulk-activate backend endpoint - Auto-seed data sources on container startup via entrypoint.sh - Fix SigmaHQ, CALDERA, GTFOBins import issues - Register D3FEND sync handler in data sources router - Add CIS Controls v8 compliance framework import - Expand Test Catalog source filters (CALDERA, LOLBAS, GTFOBins) - Campaign Generate from Threat Actor now opens actor selector modal - Add coverage snapshot creation button to Comparison page - Update README with accurate data source and feature documentation
This commit is contained in:
@@ -329,6 +329,159 @@ def _import_sample_nist_mappings(db: Session, framework: ComplianceFramework) ->
|
||||
}
|
||||
|
||||
|
||||
def import_cis_controls_v8_mappings(db: Session) -> dict:
|
||||
"""Import CIS Controls v8 with ATT&CK technique mappings.
|
||||
|
||||
Uses a curated set of CIS Controls mapped to MITRE ATT&CK techniques
|
||||
based on the CIS Controls Navigator and official documentation.
|
||||
|
||||
Returns a summary dict with counts.
|
||||
"""
|
||||
# ── 1. Create or get framework ────────────────────────────────
|
||||
framework = (
|
||||
db.query(ComplianceFramework)
|
||||
.filter(ComplianceFramework.name == "CIS Controls v8")
|
||||
.first()
|
||||
)
|
||||
|
||||
if not framework:
|
||||
framework = ComplianceFramework(
|
||||
name="CIS Controls v8",
|
||||
version="8",
|
||||
description="Center for Internet Security Critical Security Controls Version 8 — "
|
||||
"a prioritized set of 18 security safeguards organized by Implementation Groups (IG1, IG2, IG3).",
|
||||
url="https://www.cisecurity.org/controls/v8",
|
||||
is_active=True,
|
||||
)
|
||||
db.add(framework)
|
||||
db.flush()
|
||||
logger.info("Created CIS Controls v8 framework")
|
||||
else:
|
||||
logger.info("CIS Controls v8 framework already exists")
|
||||
|
||||
# ── 2. Control definitions with ATT&CK mappings ───────────────
|
||||
CIS_CONTROLS = [
|
||||
{"control_id": "CIS-1", "title": "Inventory and Control of Enterprise Assets",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1595", "T1590", "T1018", "T1082"]},
|
||||
{"control_id": "CIS-2", "title": "Inventory and Control of Software Assets",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1518", "T1072", "T1195"]},
|
||||
{"control_id": "CIS-3", "title": "Data Protection",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1005", "T1114", "T1560", "T1048", "T1041"]},
|
||||
{"control_id": "CIS-4", "title": "Secure Configuration of Enterprise Assets and Software",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1574", "T1546", "T1112", "T1543"]},
|
||||
{"control_id": "CIS-5", "title": "Account Management",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1078", "T1136", "T1098", "T1087"]},
|
||||
{"control_id": "CIS-6", "title": "Access Control Management",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1078", "T1548", "T1134", "T1021"]},
|
||||
{"control_id": "CIS-7", "title": "Continuous Vulnerability Management",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1190", "T1203", "T1068", "T1210"]},
|
||||
{"control_id": "CIS-8", "title": "Audit Log Management",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1562", "T1070", "T1059"]},
|
||||
{"control_id": "CIS-9", "title": "Email and Web Browser Protections",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1566", "T1204", "T1189", "T1598"]},
|
||||
{"control_id": "CIS-10", "title": "Malware Defenses",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1059", "T1204", "T1027", "T1140", "T1497"]},
|
||||
{"control_id": "CIS-11", "title": "Data Recovery",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1486", "T1490", "T1561"]},
|
||||
{"control_id": "CIS-12", "title": "Network Infrastructure Management",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1557", "T1071", "T1572", "T1571"]},
|
||||
{"control_id": "CIS-13", "title": "Network Monitoring and Defense",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1071", "T1048", "T1041", "T1105", "T1572"]},
|
||||
{"control_id": "CIS-14", "title": "Security Awareness and Skills Training",
|
||||
"category": "IG1 — Basic",
|
||||
"techniques": ["T1566", "T1204", "T1598"]},
|
||||
{"control_id": "CIS-15", "title": "Service Provider Management",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1199", "T1195"]},
|
||||
{"control_id": "CIS-16", "title": "Application Software Security",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1190", "T1059", "T1203"]},
|
||||
{"control_id": "CIS-17", "title": "Incident Response Management",
|
||||
"category": "IG2 — Foundational",
|
||||
"techniques": ["T1059", "T1547", "T1053"]},
|
||||
{"control_id": "CIS-18", "title": "Penetration Testing",
|
||||
"category": "IG3 — Organizational",
|
||||
"techniques": ["T1595", "T1046", "T1190", "T1059"]},
|
||||
]
|
||||
|
||||
# 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 CIS_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"CIS Controls v8 import complete: {summary}")
|
||||
return summary
|
||||
|
||||
|
||||
def _get_nist_category(family_code: str) -> str:
|
||||
"""Map NIST 800-53 family code to category name."""
|
||||
categories = {
|
||||
|
||||
Reference in New Issue
Block a user