Some checks failed
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / tests (push) Successful in 1m41s
CD Pipeline / build-and-deploy (push) Successful in 4m34s
CD Pipeline / post-deploy-checks (push) Successful in 1m43s
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled
657 lines
28 KiB
Python
657 lines
28 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
IwoooS SOC / SIEM / Kali 112 / Wazuh 整合控制矩陣產生器。
|
||
|
||
本工具只產生 repo 內 snapshot,將 Wazuh、Kali 112、Prometheus /
|
||
Alertmanager、SigNoz、Sentry、host / gateway / K8s / supply-chain 訊號,
|
||
收斂成一份可審核的 SOC 整合控制面。
|
||
|
||
它不連線 Wazuh、不呼叫 Kali、不 SSH、不讀 live log、不送 Telegram、
|
||
不 reload Alertmanager / Prometheus、不啟用 active response、不執行 scan、
|
||
不建立 case、不修改 firewall / Nginx / K8s / workflow / secret。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
from datetime import datetime, timedelta, timezone
|
||
from pathlib import Path
|
||
from typing import Any
|
||
|
||
|
||
TAIPEI = timezone(timedelta(hours=8))
|
||
|
||
STANDARD_FRAMEWORKS = [
|
||
{
|
||
"framework_id": "nist_csf_2_0",
|
||
"label": "NIST CSF 2.0",
|
||
"source_url": "https://www.nist.gov/cyberframework",
|
||
"mapped_functions": ["Govern", "Identify", "Protect", "Detect", "Respond", "Recover"],
|
||
"integration_intent": "將資安監控與回應放進治理、辨識、防護、偵測、回應與復原閉環。",
|
||
},
|
||
{
|
||
"framework_id": "nist_sp_800_61_r3",
|
||
"label": "NIST SP 800-61 Rev. 3",
|
||
"source_url": "https://csrc.nist.gov/pubs/sp/800/61/r3/final",
|
||
"mapped_functions": ["Prepare", "Detect", "Analyze", "Respond", "Recover", "Improve"],
|
||
"integration_intent": "將事件處理生命週期轉成 IwoooS case gate、postcheck 與 lesson learned 回寫。",
|
||
},
|
||
{
|
||
"framework_id": "cis_controls_v8_1",
|
||
"label": "CIS Controls v8.1",
|
||
"source_url": "https://www.cisecurity.org/controls/v8",
|
||
"mapped_functions": ["Inventory", "Vulnerability", "Audit Log", "Malware", "Recovery", "Access"],
|
||
"integration_intent": "把資產、弱點、稽核日誌、惡意程式防護、復原與權限審查納入 IwoooS。",
|
||
},
|
||
{
|
||
"framework_id": "cisa_zero_trust_maturity_model",
|
||
"label": "CISA Zero Trust Maturity Model",
|
||
"source_url": "https://www.cisa.gov/resources-tools/resources/zero-trust-maturity-model",
|
||
"mapped_functions": ["Identity", "Devices", "Networks", "Applications", "Data", "Visibility"],
|
||
"integration_intent": "以 identity、device、network、application、data 與 visibility / automation 作為零信任成熟度對照。",
|
||
},
|
||
{
|
||
"framework_id": "cisa_kev_prioritization",
|
||
"label": "CISA KEV 優先化",
|
||
"source_url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog",
|
||
"mapped_functions": ["Known exploited vulnerability", "Patch priority", "Owner SLA"],
|
||
"integration_intent": "以已知遭利用漏洞作為漏洞修補與維護窗口排序依據。",
|
||
},
|
||
{
|
||
"framework_id": "mitre_attack_d3fend",
|
||
"label": "MITRE ATT&CK / D3FEND",
|
||
"source_url": "https://attack.mitre.org/",
|
||
"mapped_functions": ["Tactic", "Technique", "Data source", "Detection", "Mitigation", "Countermeasure"],
|
||
"integration_intent": "以 ATT&CK 描述攻擊行為與資料源,再用 D3FEND 對應防禦與驗證缺口。",
|
||
},
|
||
{
|
||
"framework_id": "owasp_asvs_samm",
|
||
"label": "OWASP ASVS / SAMM",
|
||
"source_url": "https://owasp.org/www-project-application-security-verification-standard/",
|
||
"mapped_functions": ["Security requirement", "Verification", "Secure SDLC", "Logging", "Access control"],
|
||
"integration_intent": "把應用層安全驗證、secure SDLC 與 API / auth / logging 控制納入 IwoooS。",
|
||
},
|
||
{
|
||
"framework_id": "wazuh_xdr_siem",
|
||
"label": "Wazuh XDR / SIEM",
|
||
"source_url": "https://documentation.wazuh.com/current/index.html",
|
||
"mapped_functions": ["Agent telemetry", "FIM", "Rule", "Decoder", "Alert", "Active response dry-run"],
|
||
"integration_intent": "將 endpoint / host 訊號、檔案完整性、事件規則與 response 邊界納入 IwoooS。",
|
||
},
|
||
{
|
||
"framework_id": "wazuh_active_response_model",
|
||
"label": "Wazuh Active Response",
|
||
"source_url": "https://documentation.wazuh.com/current/user-manual/capabilities/active-response/index.html",
|
||
"mapped_functions": ["Trigger", "Command", "Scope", "Timeout", "Rollback", "Dry-run gate"],
|
||
"integration_intent": "只採用 active response 的能力模型;IwoooS 目前只做 dry-run 與 rollback gate,不啟用 response。",
|
||
},
|
||
{
|
||
"framework_id": "prometheus_alertmanager",
|
||
"label": "Prometheus Alertmanager",
|
||
"source_url": "https://prometheus.io/docs/alerting/latest/alertmanager/",
|
||
"mapped_functions": ["Grouping", "Deduplication", "Routing", "Silencing", "Inhibition", "Receipt"],
|
||
"integration_intent": "把告警分組、去重、路由、抑制與 receipt 驗收納入 no-false-green 告警鏈。",
|
||
},
|
||
{
|
||
"framework_id": "opentelemetry_observability",
|
||
"label": "OpenTelemetry observability",
|
||
"source_url": "https://opentelemetry.io/docs/what-is-opentelemetry/",
|
||
"mapped_functions": ["Trace", "Metric", "Log", "Resource", "Correlation", "Semantic convention"],
|
||
"integration_intent": "以 vendor-neutral telemetry 口徑把 traces、metrics、logs 與 resource 關聯到事件證據。",
|
||
},
|
||
{
|
||
"framework_id": "slsa_sigstore_sbom",
|
||
"label": "SLSA / Sigstore / SBOM",
|
||
"source_url": "https://slsa.dev/",
|
||
"mapped_functions": ["Provenance", "Build integrity", "Artifact signing", "SBOM", "Verification"],
|
||
"integration_intent": "把 build provenance、artifact integrity、SBOM 與簽章驗證轉成供應鏈 evidence lane。",
|
||
},
|
||
{
|
||
"framework_id": "ndr_ids_suricata_zeek",
|
||
"label": "Suricata / Zeek NDR",
|
||
"source_url": "https://suricata.io/",
|
||
"mapped_functions": ["Network detection", "Passive telemetry", "Rule hit", "Flow", "Future IPS gate"],
|
||
"integration_intent": "將網路偵測與封包層線索納入未來 NDR lane;IPS 仍需獨立批准。",
|
||
},
|
||
{
|
||
"framework_id": "kali_assessment_tooling",
|
||
"label": "Kali assessment tooling",
|
||
"source_url": "https://www.kali.org/docs/",
|
||
"mapped_functions": ["Health", "Scope", "Safe crawl", "Tool version", "Finding normalization"],
|
||
"integration_intent": "Kali 112 作為安全驗證與工具節點,先接只讀 health / scope / finding contract。",
|
||
},
|
||
]
|
||
|
||
OPERATING_ROLES = [
|
||
("iwooos_control_owner", "IwoooS 控制負責人", "維護控制域、例外、進度口徑與 LOGBOOK;不能直接開 runtime。"),
|
||
("soc_reviewer", "SOC 審查人", "審查 Wazuh / Kali / alert / forensic refs 是否脫敏、可交叉驗證。"),
|
||
("incident_commander", "事故指揮", "在 incident case 中確認 severity、scope、containment 候選與升級路線。"),
|
||
("platform_owner", "平台負責人", "負責 Nginx、K8s、Docker、systemd、runner 與 release impact 判讀。"),
|
||
("service_owner", "服務負責人", "負責產品 / API / website / webhook 的影響範圍、驗證與回復責任。"),
|
||
("evidence_custodian", "證據保管人", "維護 redacted evidence refs、chain of custody、retention 與 raw absence 證明。"),
|
||
("change_manager", "變更管理人", "確認維護窗口、rollback owner、postcheck 與跨專案同步。"),
|
||
("ai_security_reviewer", "AI 安全審查人", "審核 AI agent tool 權限、prompt redaction、過度代理與成本邊界。"),
|
||
("executive_risk_owner", "風險負責人", "接受風險、例外期限、治理報告與資源優先序。"),
|
||
]
|
||
|
||
INCIDENT_LIFECYCLE_STAGES = [
|
||
("prepare_govern", "準備與治理", "資產、owner、控制域、例外、權限與證據模板先就緒。"),
|
||
("detect_normalize", "偵測與正規化", "Wazuh、Alertmanager、SigNoz、Sentry、Nginx、K8s、Gitea 訊號統一成脫敏事件。"),
|
||
("triage_prioritize", "分流與排序", "用 severity、confidence、KEV、ATT&CK、asset criticality 與 noise budget 排序。"),
|
||
("investigate_correlate", "調查與關聯", "串 Wazuh event、Kali scope、host forensic、gateway diff、supply-chain 與 timeline refs。"),
|
||
("containment_decision", "圍堵決策", "只產生 containment 候選;無 owner、rollback、maintenance window 不得執行。"),
|
||
("eradicate_recover", "清除與復原", "清除、修補、還原與服務恢復都必須有 postcheck 與 no-false-green 證據。"),
|
||
("post_incident_learning", "事後學習", "回寫 detection gap、false positive、playbook、owner SLA、LOGBOOK 與風險例外。"),
|
||
("continuous_improvement", "持續改善", "用 KPI、演練、tabletop、purple-team 與 evidence aging 收斂下一輪優先序。"),
|
||
]
|
||
|
||
MATURITY_STAGES = [
|
||
("L0", "分散觀測", "工具與文件分散,不能宣稱 SOC 形成。"),
|
||
("L1", "只讀證據", "repo / snapshot / guard / frontstage marker 可重跑,runtime 維持 0。"),
|
||
("L2", "Owner Packet", "owner、scope、evidence refs、rollback、postcheck 與 redaction 證明可驗收。"),
|
||
("L3", "Live Metadata 只讀", "在獨立批准後接只讀 live metadata,仍不執行 response。"),
|
||
("L4", "Dry-run Automation", "SOAR / active response / scan 只跑 dry-run、blast radius 與 rollback 演練。"),
|
||
("L5", "Human-approved Response", "人工批准、維護窗口與 postcheck 完成後,才允許可回滾 response。"),
|
||
("L6", "Governed Low-risk Autonomy", "僅低風險、可回滾、已演練、有 receipt 的動作可逐步自動化。"),
|
||
]
|
||
|
||
VALIDATION_GATES = [
|
||
"asset_owner_mapping_verified",
|
||
"source_to_live_diff_available",
|
||
"redacted_evidence_refs_present",
|
||
"raw_payload_absence_attested",
|
||
"secret_value_absence_attested",
|
||
"wazuh_manager_registry_truth_received",
|
||
"kali_scope_and_finding_envelope_accepted",
|
||
"alert_route_receipt_available",
|
||
"incident_case_id_present",
|
||
"severity_confidence_mapping_reviewed",
|
||
"forensic_time_window_present",
|
||
"chain_of_custody_present",
|
||
"kev_or_cve_prioritization_done",
|
||
"rollback_owner_present",
|
||
"maintenance_window_present",
|
||
"postcheck_metrics_present",
|
||
"cross_project_sync_recorded",
|
||
"production_desktop_mobile_smoke_passed",
|
||
]
|
||
|
||
CONTROL_DOMAINS = [
|
||
("asset_inventory_owner", "資產 / owner / attack surface inventory", "C0"),
|
||
("endpoint_log_collection", "Endpoint / host / auth / process log collection", "C0"),
|
||
("fim_persistence_detection", "FIM / persistence / malware signal", "C0"),
|
||
("vulnerability_kev_prioritization", "CVE / KEV / package / image prioritization", "C0"),
|
||
("network_detection_response", "NDR / IDS / firewall / WireGuard / NodePort evidence", "C0"),
|
||
("wazuh_siem_correlation", "Wazuh SIEM correlation / rule / decoder readback", "C0"),
|
||
("kali_assessment_orchestration", "Kali 112 scanner health / scope / finding normalization", "C0"),
|
||
("alert_routing_noise_budget", "Alert routing / dedup / inhibit / noise budget", "C0"),
|
||
("incident_case_management", "Incident / case / owner response / escalation", "C0"),
|
||
("forensic_evidence_retention", "Forensic evidence retention / redaction / chain of custody", "C0"),
|
||
("config_drift_control", "Nginx / host / K8s / runner / workflow config drift", "C0"),
|
||
("supply_chain_ci_cd", "Gitea / runner / workflow / Harbor / SBOM / image evidence", "C0"),
|
||
("identity_secret_access", "IAM / SSH / sudo / secret / token exposure control", "C1"),
|
||
("web_api_appsec_logging", "Web / API appsec logging / auth / rate-limit / headers", "C1"),
|
||
("backup_recovery_dr", "Backup / restore / escrow / DR recovery proof", "C1"),
|
||
("executive_reporting_metrics", "Dashboard / KPI / LOGBOOK / no-false-green reporting", "C1"),
|
||
]
|
||
|
||
SIGNAL_SOURCES = [
|
||
("wazuh_endpoint_alerts", "Wazuh endpoint / agent / FIM alerts"),
|
||
("kali_112_health_findings", "Kali 112 health / scope / normalized findings"),
|
||
("prometheus_alertmanager", "Prometheus / Alertmanager rules and delivery chain"),
|
||
("signoz_apm_traces", "SigNoz traces / metrics / errors"),
|
||
("sentry_application_errors", "Sentry application and frontend errors"),
|
||
("nginx_gateway_tls", "Nginx / gateway / TLS / ACME / upstream evidence"),
|
||
("host_auth_process_network", "Host auth / process / network / package evidence"),
|
||
("docker_systemd_runtime", "Docker / systemd / process / port binding evidence"),
|
||
("k8s_argocd_gitops", "K8s / ArgoCD / RBAC / NetworkPolicy evidence"),
|
||
("gitea_runner_workflow", "Gitea / runner / workflow / deploy key evidence"),
|
||
("harbor_container_sbom", "Harbor / registry / container image / SBOM evidence"),
|
||
("backup_restore_dr", "Backup / restore / offsite / escrow / cold-start evidence"),
|
||
]
|
||
|
||
CONTROL_CANDIDATES = [
|
||
("SOC-P0-01", "資產與 owner 對應表先完整", "C0", "P0"),
|
||
("SOC-P0-02", "Wazuh agent / manager / indexer / dashboard health ref 收件", "C0", "P0"),
|
||
("SOC-P0-03", "Host auth / process / network / FIM 訊號正規化", "C0", "P0"),
|
||
("SOC-P0-04", "Kali 112 health / tool version / scope approval 串接", "C0", "P0"),
|
||
("SOC-P0-05", "Kali finding 只接脫敏 envelope,不接 raw output", "C0", "P0"),
|
||
("SOC-P0-06", "Prometheus / Alertmanager / Telegram 告警鏈 no-false-green", "C0", "P0"),
|
||
("SOC-P0-07", "Sentry / SigNoz 與主機入侵線索關聯", "C0", "P0"),
|
||
("SOC-P0-08", "Nginx / firewall / route / TLS / gateway drift 關聯到 SIEM", "C0", "P0"),
|
||
("SOC-P0-09", "Gitea / runner / workflow / secret metadata 供應鏈關聯", "C0", "P0"),
|
||
("SOC-P0-10", "CISA KEV / CVE / package / image 風險排序", "C0", "P0"),
|
||
("SOC-P0-11", "Incident case / owner response / escalation queue", "C0", "P0"),
|
||
("SOC-P0-12", "鑑識證據、chain of custody、redaction 與保存期", "C0", "P0"),
|
||
("SOC-P1-13", "Suricata / NDR passive telemetry lane", "C1", "P1"),
|
||
("SOC-P1-14", "Web / API appsec logging 與 OWASP ASVS 驗證", "C1", "P1"),
|
||
("SOC-P1-15", "Backup / restore / DR recovery proof 串回 incident", "C1", "P1"),
|
||
("SOC-P1-16", "SOC KPI / dashboard / LOGBOOK / executive reporting", "C1", "P1"),
|
||
("SOC-P1-17", "SOAR draft / case automation 只建立候選,不自動封鎖", "C1", "P1"),
|
||
("SOC-P1-18", "Wazuh active response dry-run 與 rollback gate", "C1", "P1"),
|
||
("SOC-P1-19", "Kali active / credentialed scan approval package", "C1", "P1"),
|
||
("SOC-P1-20", "NDR / IPS / firewall containment promotion criteria", "C1", "P1"),
|
||
]
|
||
|
||
REQUIRED_OWNER_FIELDS = [
|
||
"control_id",
|
||
"owner_role",
|
||
"owner_team",
|
||
"decision",
|
||
"decision_reason",
|
||
"affected_scope_aliases",
|
||
"asset_owner_map_ref",
|
||
"signal_source_refs",
|
||
"wazuh_manager_ref",
|
||
"wazuh_agent_status_refs",
|
||
"wazuh_event_refs",
|
||
"kali_scope_ref",
|
||
"kali_health_ref",
|
||
"kali_finding_envelope_ref",
|
||
"prometheus_alert_ref",
|
||
"alertmanager_route_ref",
|
||
"signoz_trace_ref",
|
||
"sentry_issue_ref",
|
||
"host_forensic_refs",
|
||
"fim_or_persistence_refs",
|
||
"network_detection_refs",
|
||
"gateway_config_diff_refs",
|
||
"runner_workflow_refs",
|
||
"container_sbom_refs",
|
||
"kev_or_cve_refs",
|
||
"incident_case_ref",
|
||
"severity_mapping_ref",
|
||
"confidence_mapping_ref",
|
||
"noise_budget_ref",
|
||
"dedupe_fingerprint_ref",
|
||
"redacted_evidence_refs",
|
||
"raw_payload_absence_attestation",
|
||
"secret_value_absence_attestation",
|
||
"chain_of_custody_ref",
|
||
"retention_policy_ref",
|
||
"maintenance_window",
|
||
"rollback_owner",
|
||
"rollback_plan_ref",
|
||
"validation_metrics",
|
||
"postcheck_owner",
|
||
"cross_project_sync_ref",
|
||
"followup_owner",
|
||
]
|
||
|
||
REVIEWER_CHECKS = [
|
||
"owner role / team 必填",
|
||
"asset alias 必須脫敏",
|
||
"Wazuh event ref 不得是 raw payload",
|
||
"Kali finding 只能接 normalized envelope",
|
||
"Kali active scan 必須獨立批准",
|
||
"Kali /execute 必須維持封鎖",
|
||
"Prometheus / Alertmanager reload 未授權",
|
||
"Telegram 實發未授權",
|
||
"Sentry / SigNoz 只能作關聯證據",
|
||
"route 200 不得當資安通過",
|
||
"agent active 不得當入侵清除",
|
||
"dashboard up 不得當事件結案",
|
||
"host forensic refs 必須含時間窗",
|
||
"FIM / persistence refs 必須標示來源",
|
||
"network detection refs 不得含 raw packet payload",
|
||
"secret value / hash / partial token 一律拒收",
|
||
"runner / workflow / deploy key 只收 metadata",
|
||
"CVE / KEV 必須有 owner 與 SLA",
|
||
"false positive handling 必須可追蹤",
|
||
"dedupe fingerprint 必須穩定",
|
||
"noise budget 必須列收斂策略",
|
||
"case escalation 必須有 owner",
|
||
"maintenance window 必須存在",
|
||
"rollback owner 必須存在",
|
||
"postcheck 必須獨立",
|
||
"cross-project sync 必須存在",
|
||
"LOGBOOK 更新不能含內部逐字稿",
|
||
"前台不得顯示個人 namespace 原文",
|
||
"SOAR 只能 draft 不得 auto block",
|
||
"active response 先 dry-run",
|
||
"NDR / IPS 不能直接進 blocking",
|
||
"firewall containment 必須 break-glass 或維護窗口",
|
||
"package patch 需維護窗口",
|
||
"backup / restore proof 不能用備份存在代替",
|
||
"all accepted / authorized / executed counters 必須維持 0",
|
||
"runtime gate 必須維持 0",
|
||
]
|
||
|
||
OUTCOME_LANES = [
|
||
"waiting_soc_owner_packet",
|
||
"request_wazuh_event_supplement",
|
||
"request_kali_scope_supplement",
|
||
"request_host_forensic_supplement",
|
||
"request_alert_chain_supplement",
|
||
"request_gateway_diff_supplement",
|
||
"request_supply_chain_supplement",
|
||
"request_kev_cve_supplement",
|
||
"quarantine_secret_or_raw_payload",
|
||
"reject_claim_without_cross_evidence",
|
||
"ready_for_soc_reviewer_review",
|
||
"waiting_runtime_authorization",
|
||
"blocked_no_rollback_or_postcheck",
|
||
"route_to_high_value_config_gate",
|
||
]
|
||
|
||
BLOCKED_ACTIONS = [
|
||
"call_wazuh_api_live",
|
||
"enable_wazuh_active_response",
|
||
"install_wazuh_agent",
|
||
"restart_wazuh_agent",
|
||
"change_wazuh_rule",
|
||
"change_wazuh_decoder",
|
||
"store_raw_wazuh_payload",
|
||
"read_wazuh_password",
|
||
"disable_wazuh_tls_verification",
|
||
"call_kali_scan",
|
||
"call_kali_execute",
|
||
"run_kali_active_scan",
|
||
"run_kali_credentialed_scan",
|
||
"run_nmap_scan",
|
||
"run_nuclei_scan",
|
||
"run_nikto_scan",
|
||
"run_trivy_scan_live",
|
||
"run_lynis_scan_live",
|
||
"update_kali_packages",
|
||
"reboot_kali_host",
|
||
"change_kali_service",
|
||
"ssh_to_host",
|
||
"sudo_action",
|
||
"read_host_live_log",
|
||
"read_host_env",
|
||
"write_host_file",
|
||
"kill_process",
|
||
"isolate_host",
|
||
"docker_restart",
|
||
"docker_compose_up",
|
||
"docker_compose_down",
|
||
"systemctl_restart",
|
||
"systemctl_stop",
|
||
"systemctl_start",
|
||
"nginx_test",
|
||
"nginx_reload",
|
||
"nginx_conf_write",
|
||
"certbot_renew",
|
||
"dns_change",
|
||
"route_change",
|
||
"upstream_change",
|
||
"firewall_drop",
|
||
"firewall_allow",
|
||
"port_close",
|
||
"port_open",
|
||
"wireguard_change",
|
||
"nodeport_change",
|
||
"network_policy_apply",
|
||
"argocd_sync",
|
||
"kubectl_apply",
|
||
"kubectl_delete",
|
||
"helm_upgrade",
|
||
"rbac_change",
|
||
"k8s_secret_change",
|
||
"prometheus_reload",
|
||
"alertmanager_reload",
|
||
"grafana_dashboard_apply",
|
||
"signoz_rule_apply",
|
||
"sentry_config_change",
|
||
"langfuse_config_change",
|
||
"otel_collector_reload",
|
||
"receiver_route_change",
|
||
"silence_policy_change",
|
||
"telegram_send",
|
||
"notification_route_change",
|
||
"webhook_receiver_change",
|
||
"remote_write_change",
|
||
"exporter_deploy",
|
||
"live_alert_fire",
|
||
"alert_chain_smoke_live",
|
||
"create_soar_case_live",
|
||
"run_soar_playbook",
|
||
"auto_block_ip",
|
||
"auto_quarantine_endpoint",
|
||
"auto_rotate_secret",
|
||
"workflow_modification",
|
||
"gitea_action_dispatch",
|
||
"runner_config_change",
|
||
"deploy_key_change",
|
||
"webhook_change",
|
||
"repo_secret_change",
|
||
"secret_store_read",
|
||
"collect_password",
|
||
"collect_private_key",
|
||
"collect_runner_token",
|
||
"collect_webhook_secret",
|
||
"collect_cookie_or_session",
|
||
"collect_secret_hash",
|
||
"collect_partial_token",
|
||
"store_raw_packet",
|
||
"store_raw_log",
|
||
"store_unredacted_screenshot",
|
||
"database_migration",
|
||
"production_write",
|
||
"open_runtime_gate",
|
||
"add_action_button",
|
||
"force_push",
|
||
"sync_git_refs",
|
||
"switch_github_primary",
|
||
"change_codeowners",
|
||
"change_branch_protection",
|
||
"change_cors",
|
||
"disable_rate_limit",
|
||
]
|
||
|
||
EXECUTION_BOUNDARIES = {
|
||
"not_authorization": True,
|
||
"runtime_execution_authorized": False,
|
||
"wazuh_api_live_query_authorized": False,
|
||
"wazuh_active_response_authorized": False,
|
||
"kali_scan_authorized": False,
|
||
"kali_execute_authorized": False,
|
||
"active_scan_authorized": False,
|
||
"credentialed_scan_authorized": False,
|
||
"host_write_authorized": False,
|
||
"ssh_write_authorized": False,
|
||
"firewall_change_authorized": False,
|
||
"nginx_reload_authorized": False,
|
||
"prometheus_reload_authorized": False,
|
||
"alertmanager_reload_authorized": False,
|
||
"telegram_send_authorized": False,
|
||
"soar_case_create_authorized": False,
|
||
"auto_block_authorized": False,
|
||
"secret_value_collection_allowed": False,
|
||
"raw_payload_storage_allowed": False,
|
||
"production_write_authorized": False,
|
||
"runtime_gate_open": False,
|
||
"action_buttons_allowed": False,
|
||
}
|
||
|
||
|
||
def git_short_sha(root: Path) -> str:
|
||
try:
|
||
result = subprocess.run(
|
||
["git", "rev-parse", "--short", "HEAD"],
|
||
cwd=root,
|
||
check=True,
|
||
capture_output=True,
|
||
text=True,
|
||
)
|
||
return result.stdout.strip()
|
||
except Exception:
|
||
return "unknown"
|
||
|
||
|
||
def build_report(root: Path, generated_at: str | None) -> dict[str, Any]:
|
||
report_time = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds")
|
||
c0_candidates = [item for item in CONTROL_CANDIDATES if item[2] == "C0"]
|
||
c1_candidates = [item for item in CONTROL_CANDIDATES if item[2] == "C1"]
|
||
p0_candidates = [item for item in CONTROL_CANDIDATES if item[3] == "P0"]
|
||
p1_candidates = [item for item in CONTROL_CANDIDATES if item[3] == "P1"]
|
||
|
||
return {
|
||
"schema_version": "soc_siem_kali_wazuh_integration_control_v1",
|
||
"generated_at": report_time,
|
||
"git_commit": git_short_sha(root),
|
||
"status": "soc_siem_kali_wazuh_integration_control_ready_no_runtime_action",
|
||
"standard_frameworks": [
|
||
{"framework_id": item["framework_id"], **item} for item in STANDARD_FRAMEWORKS
|
||
],
|
||
"operating_roles": [
|
||
{
|
||
"role_id": role_id,
|
||
"label": label,
|
||
"responsibility": responsibility,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for role_id, label, responsibility in OPERATING_ROLES
|
||
],
|
||
"incident_lifecycle_stages": [
|
||
{
|
||
"stage_id": stage_id,
|
||
"label": label,
|
||
"control_intent": control_intent,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for stage_id, label, control_intent in INCIDENT_LIFECYCLE_STAGES
|
||
],
|
||
"maturity_stages": [
|
||
{
|
||
"stage_id": stage_id,
|
||
"label": label,
|
||
"entry_criteria": entry_criteria,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for stage_id, label, entry_criteria in MATURITY_STAGES
|
||
],
|
||
"validation_gates": [
|
||
{
|
||
"gate_id": gate_id,
|
||
"accepted": False,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for gate_id in VALIDATION_GATES
|
||
],
|
||
"control_domains": [
|
||
{
|
||
"domain_id": domain_id,
|
||
"label": label,
|
||
"control_tier": tier,
|
||
"owner_response_required": True,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for domain_id, label, tier in CONTROL_DOMAINS
|
||
],
|
||
"signal_sources": [
|
||
{
|
||
"source_id": source_id,
|
||
"label": label,
|
||
"redacted_evidence_only": True,
|
||
"live_query_authorized": False,
|
||
}
|
||
for source_id, label in SIGNAL_SOURCES
|
||
],
|
||
"control_candidates": [
|
||
{
|
||
"control_id": control_id,
|
||
"title": title,
|
||
"control_tier": tier,
|
||
"priority": priority,
|
||
"owner_response_required": True,
|
||
"runtime_gate_open": False,
|
||
}
|
||
for control_id, title, tier, priority in CONTROL_CANDIDATES
|
||
],
|
||
"required_owner_fields": REQUIRED_OWNER_FIELDS,
|
||
"reviewer_checks": [
|
||
{"check_id": f"soc_review_{index:02d}", "instruction": instruction}
|
||
for index, instruction in enumerate(REVIEWER_CHECKS, start=1)
|
||
],
|
||
"outcome_lanes": [
|
||
{"lane_id": lane_id, "runtime_gate_open": False} for lane_id in OUTCOME_LANES
|
||
],
|
||
"blocked_actions": BLOCKED_ACTIONS,
|
||
"summary": {
|
||
"standard_framework_count": len(STANDARD_FRAMEWORKS),
|
||
"operating_role_count": len(OPERATING_ROLES),
|
||
"incident_lifecycle_stage_count": len(INCIDENT_LIFECYCLE_STAGES),
|
||
"maturity_stage_count": len(MATURITY_STAGES),
|
||
"validation_gate_count": len(VALIDATION_GATES),
|
||
"control_domain_count": len(CONTROL_DOMAINS),
|
||
"c0_control_domain_count": sum(1 for _, _, tier in CONTROL_DOMAINS if tier == "C0"),
|
||
"c1_control_domain_count": sum(1 for _, _, tier in CONTROL_DOMAINS if tier == "C1"),
|
||
"signal_source_count": len(SIGNAL_SOURCES),
|
||
"control_candidate_count": len(CONTROL_CANDIDATES),
|
||
"c0_control_candidate_count": len(c0_candidates),
|
||
"c1_control_candidate_count": len(c1_candidates),
|
||
"p0_control_candidate_count": len(p0_candidates),
|
||
"p1_control_candidate_count": len(p1_candidates),
|
||
"required_owner_field_count": len(REQUIRED_OWNER_FIELDS),
|
||
"reviewer_check_count": len(REVIEWER_CHECKS),
|
||
"outcome_lane_count": len(OUTCOME_LANES),
|
||
"blocked_action_count": len(BLOCKED_ACTIONS),
|
||
"coverage_percent_after_soc_integration_control": 78,
|
||
"monitoring_alerting_observability_coverage_percent_after_soc_control": 78,
|
||
"security_evidence_tooling_coverage_percent_after_soc_control": 88,
|
||
"wazuh_event_ref_received_count": 0,
|
||
"kali_scope_ref_accepted_count": 0,
|
||
"kali_finding_envelope_accepted_count": 0,
|
||
"siem_correlation_rule_accepted_count": 0,
|
||
"alert_route_accepted_count": 0,
|
||
"incident_case_accepted_count": 0,
|
||
"forensic_evidence_accepted_count": 0,
|
||
"owner_response_received_count": 0,
|
||
"owner_response_accepted_count": 0,
|
||
"active_response_enabled_count": 0,
|
||
"kali_active_scan_authorized_count": 0,
|
||
"kali_execute_authorized_count": 0,
|
||
"prometheus_reload_authorized_count": 0,
|
||
"alertmanager_reload_authorized_count": 0,
|
||
"telegram_send_authorized_count": 0,
|
||
"soar_case_create_authorized_count": 0,
|
||
"auto_block_authorized_count": 0,
|
||
"runtime_gate_count": 0,
|
||
"action_button_count": 0,
|
||
},
|
||
"execution_boundaries": EXECUTION_BOUNDARIES,
|
||
}
|
||
|
||
|
||
def main() -> int:
|
||
parser = argparse.ArgumentParser(description="IwoooS SOC / SIEM / Kali / Wazuh 整合控制矩陣")
|
||
parser.add_argument("--root", default=".", help="repo root")
|
||
parser.add_argument("--output", help="寫出 JSON 報告")
|
||
parser.add_argument("--generated-at", help="固定報告時間,供 committed snapshot 使用")
|
||
args = parser.parse_args()
|
||
|
||
root = Path(args.root).resolve()
|
||
report = build_report(root, args.generated_at)
|
||
payload = json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)
|
||
|
||
if args.output:
|
||
output = Path(args.output)
|
||
output.parent.mkdir(parents=True, exist_ok=True)
|
||
output.write_text(payload + "\n", encoding="utf-8")
|
||
else:
|
||
print(payload)
|
||
|
||
summary = report["summary"]
|
||
print(
|
||
"SOC_SIEM_KALI_WAZUH_INTEGRATION_CONTROL_OK "
|
||
f"frameworks={summary['standard_framework_count']} "
|
||
f"roles={summary['operating_role_count']} "
|
||
f"lifecycle={summary['incident_lifecycle_stage_count']} "
|
||
f"gates={summary['validation_gate_count']} "
|
||
f"domains={summary['control_domain_count']} "
|
||
f"signals={summary['signal_source_count']} "
|
||
f"candidates={summary['control_candidate_count']} "
|
||
f"runtime_gate={summary['runtime_gate_count']}",
|
||
file=sys.stderr,
|
||
)
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|