#!/usr/bin/env python3 """IwoooS 資安作戰系統產生器。 本工具只產生 repo 內 snapshot,將主流資安框架、SOC / CSIRT / DevSecOps 分工、即時危害分流、告警訊息合約、Wazuh / Kali / Nginx / host / CI/CD 驗證節點與 AI 自動化閉環,收斂成一份可重跑的作戰系統。 它不連線主機、不呼叫 Wazuh / Kali、不 SSH、不讀 secret、不送 Telegram、 不 reload Nginx / Alertmanager、不改 firewall / K8s / workflow,也不啟用 active response、active scan、SOAR 或 auto block。 """ from __future__ import annotations import argparse import json import re import subprocess import sys from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Any TAIPEI = timezone(timedelta(hours=8)) SNAPSHOT_PATH = Path("docs/security/iwooos-security-operating-system.snapshot.json") SCHEMA_VERSION = "iwooos_security_operating_system_v1" REFERENCE_FRAMEWORKS = [ ("nist_csf_2_0", "NIST CSF 2.0", "https://www.nist.gov/cyberframework"), ("nist_sp_800_61_r3", "NIST SP 800-61 Rev. 3", "https://csrc.nist.gov/pubs/sp/800/61/r3/final"), ("cis_controls_v8_1", "CIS Controls v8.1", "https://www.cisecurity.org/controls/v8-1"), ("cisa_zero_trust", "CISA Zero Trust Maturity Model", "https://www.cisa.gov/resources-tools/resources/zero-trust-maturity-model"), ("cisa_kev", "CISA Known Exploited Vulnerabilities", "https://www.cisa.gov/known-exploited-vulnerabilities-catalog"), ("first_epss", "FIRST EPSS", "https://www.first.org/epss/"), ("mitre_attack", "MITRE ATT&CK Enterprise", "https://attack.mitre.org/matrices/enterprise/"), ("mitre_d3fend", "MITRE D3FEND", "https://d3fend.mitre.org/"), ("owasp_asvs", "OWASP ASVS", "https://owasp.org/www-project-application-security-verification-standard/"), ("owasp_samm", "OWASP SAMM", "https://owaspsamm.org/"), ("wazuh_xdr_siem", "Wazuh XDR / SIEM", "https://documentation.wazuh.com/current/index.html"), ("wazuh_active_response", "Wazuh Active Response", "https://documentation.wazuh.com/current/user-manual/capabilities/active-response/index.html"), ("prometheus_alertmanager", "Prometheus Alertmanager", "https://prometheus.io/docs/alerting/latest/alertmanager/"), ("opentelemetry", "OpenTelemetry", "https://opentelemetry.io/docs/what-is-opentelemetry/"), ("ocsf", "Open Cybersecurity Schema Framework", "https://ocsf.io/"), ("sigma", "Sigma detection rules", "https://sigmahq.io/sigma/"), ("slsa", "SLSA", "https://slsa.dev/"), ("spdx_cyclonedx", "SPDX / CycloneDX", "https://spdx.dev/"), ("sigstore_cosign", "Sigstore / Cosign", "https://docs.sigstore.dev/cosign/signing/signing_with_containers/"), ("nist_ai_rmf", "NIST AI RMF", "https://www.nist.gov/itl/ai-risk-management-framework"), ] OPERATING_ROLES = [ ("security_program_owner", "資安作戰負責人", "維護控制面、優先序、完成度與停止線。"), ("soc_reviewer", "SOC 審查人", "審查告警、SIEM、Wazuh、Kali 與 no-false-green evidence。"), ("incident_commander", "事故指揮", "統一 severity、scope、containment 候選與跨專案同步。"), ("platform_owner", "平台負責人", "負責 host、Docker、systemd、Nginx、K8s、ArgoCD 與 public gateway 影響判讀。"), ("service_owner", "服務負責人", "負責產品、API、網站、admin、webhook 與 AI provider route 的驗證。"), ("evidence_custodian", "證據保管人", "維護脫敏 refs、chain of custody、retention 與 raw absence attestation。"), ("change_manager", "變更管理人", "確認維護窗口、rollback owner、postcheck、operator notification 與 freeze。"), ("supply_chain_owner", "供應鏈負責人", "負責 workflow、runner、Harbor、SBOM、SLSA、Cosign、KEV / package SLA。"), ("ai_security_reviewer", "AI 安全審查人", "審核 AI agent tool 權限、prompt redaction、過度代理與成本邊界。"), ("executive_risk_owner", "風險負責人", "接受風險、例外期限、資源優先序與治理報告。"), ] SEVERITY_LANES = [ ("SEV0", "已確認入侵或 active exploitation", "15 分鐘內形成 case / freeze / containment 候選;不得無 owner 直接執行。"), ("SEV1", "公開入口高風險、KEV、credential exposure、Wazuh agent 消失", "30 分鐘內形成 owner packet、證據缺口與維護窗口草案。"), ("SEV2", "Nginx / firewall / runner / workflow / runtime drift", "4 小時內完成 diff、owner、rollback 與 postcheck 計畫。"), ("SEV3", "告警噪音、coverage gap、dashboard degradation", "1 個工作日內進入 backlog 與 no-false-green 修正。"), ("SEV4", "治理、文件、成熟度與低風險 hardening", "納入週期報告與例外期限,不得混成緊急事件。"), ] WORKSTREAMS = [ ("P0-01", "asset_exposure_graph", "P0", "資產 / 暴露面總圖", "host、domain、route、service、port、package、repo、runner、secret metadata、backup、AI agent"), ("P0-02", "wazuh_registry_truth", "P0", "Wazuh manager registry truth", "agent total、active、disconnected、last seen、expected minimum、dashboard / API mismatch"), ("P0-03", "host_intrusion_forensics", "P0", "主機入侵與鑑識", "auth、sudo、process、network、FIM、persistence、package、service、Docker event"), ("P0-04", "gateway_config_control", "P0", "Nginx / Gateway config-control", "source-to-live diff、rendered diff、nginx test ref、route smoke、rollback"), ("P0-05", "network_access_baseline", "P0", "SSH / firewall / WireGuard / NodePort baseline", "before / after、actor、impact、operator notification、restoration evidence"), ("P0-06", "secret_identity_hygiene", "P0", "身分與 secret metadata", "SSH、sudo、deploy key、runner token name、webhook secret name、OIDC、break-glass"), ("P0-07", "alert_readability_receipt", "P0", "告警可讀性與 receipt", "Telegram / Alertmanager / Wazuh alert card、dedupe、noise budget、receipt"), ("P0-08", "incident_case_gate", "P0", "Incident case gate", "case id、timeline、owner、decision、containment、recovery、postcheck、lesson learned"), ("P0-09", "kev_exposure_patch_priority", "P0", "KEV / exposure / package SLA", "CISA KEV、EPSS、public exposure、asset criticality、maintenance window"), ("P0-10", "backup_restore_forensic_retention", "P0", "備份 / 還原 / 鑑識保存", "restore drill、offsite、escrow、chain of custody、retention、rollback proof"), ("P0-11", "runner_workflow_supply_chain", "P0", "Runner / workflow / supply-chain", "Gitea、workflow、runner、deploy key、Harbor、SBOM、Cosign、SLSA"), ("P0-12", "ai_agent_permission_gate", "P0", "AI Agent 權限閘", "tool allowlist、redaction、cost、privacy、approval、excessive agency"), ("P1-01", "kali_evidence_envelope", "P1", "Kali 112 evidence envelope", "health、tool version、scope、normalized finding、active scan approval packet"), ("P1-02", "detection_as_code", "P1", "Detection-as-code", "ATT&CK、D3FEND、Sigma、測試資料、false-positive budget、rule owner"), ("P1-03", "ndr_passive_sensor", "P1", "NDR passive sensor", "Suricata、Zeek、DNS / TLS / HTTP / flow logs;不開 IPS"), ("P1-04", "k8s_docker_hardening", "P1", "K8s / Docker hardening", "CIS / NSA-CISA 對照、Pod Security、RBAC、NetworkPolicy、audit log"), ("P1-05", "appsec_api_asvs", "P1", "AppSec / API ASVS", "auth、authorization、session、rate limit、CORS、security headers、webhook abuse case"), ("P1-06", "sbom_slsa_cosign", "P1", "SBOM / SLSA / Cosign", "SPDX、CycloneDX、VEX、provenance、artifact signing、verify"), ("P1-07", "soar_dry_run_case_enrichment", "P1", "SOAR dry-run / case enrichment", "TheHive / Cortex 類 case draft、enrichment、blast radius、rollback"), ("P1-08", "grc_exception_register", "P1", "GRC / exception register", "risk register、accepted risk、expiry、audit evidence、control owner"), ("P2-01", "ueba_behavior_baseline", "P2", "UEBA / 行為基線", "使用者、service account、runner、AI agent、host process、egress baseline"), ("P2-02", "purple_team_validation", "P2", "Purple-team / tabletop", "ATT&CK emulation、BAS / canary、偵測回歸;需授權 scope"), ("P2-03", "mdr_247_process", "P2", "MDR / 24x7 流程", "on-call、升級、SLA、交接、值班報表、演練"), ("P2-04", "exposure_management_graph", "P2", "Exposure management graph", "外部攻擊面、弱點、身份、雲端、repo、AI agent、資料流"), ] ALERT_CONTRACT_FIELDS = [ "event_title", "severity_and_confidence", "asset_alias_and_scope", "what_happened_plain_language", "why_it_matters", "redacted_evidence_refs", "ai_triage_lane", "next_candidate_action", "owner_gate_and_verification", ] AUTOMATION_LOOP_STAGES = [ "sensor_evidence", "normalizer_redaction", "ai_triage_lane", "candidate_generation", "owner_gate", "execution_boundary", "verifier_readback", "learning_writeback", ] VERIFICATION_STAGES = [ "source_guard", "snapshot_schema", "redaction_guard", "owner_packet_preflight", "wazuh_registry_readback", "kali_scope_readback", "alert_receipt_readback", "route_desktop_mobile_smoke", "postcheck_metrics", "cross_session_sync", "logbook_update", "no_false_green_review", ] NO_FALSE_GREEN_RULES = [ "route_200_is_not_security_clearance", "dashboard_up_is_not_agent_registry", "agent_active_is_not_intrusion_closed", "alert_quiet_is_not_alert_chain_healthy", "backup_fresh_is_not_restore_drill", "cd_success_is_not_runtime_authorization", "ui_visible_is_not_owner_acceptance", "awooop_approval_is_not_security_approval", "external_agent_claim_is_not_forensic_proof", "transport_connection_is_not_registry_acceptance", "source_snapshot_is_not_live_truth", "general_continue_is_not_maintenance_window", ] CROSS_SESSION_SYNC_CHECKPOINTS = [ "fetch_gitea_main_before_work", "share_commit_and_run_ids", "share_production_readback", "declare_runtime_boundaries", "freeze_same_host_or_same_gateway_edits", "record_owner_gate_state", "update_logbook_after_stage", ] BLOCKED_ACTIONS = [ "ssh_write", "host_live_secret_read", "wazuh_active_response_enable", "kali_active_scan", "kali_execute", "nginx_reload", "firewall_change", "docker_restart", "systemd_restart", "argocd_sync", "kubectl_apply", "workflow_modification", "secret_rotation", "telegram_live_send", "soar_action", "auto_block", "production_write", "force_push", ] FORBIDDEN_TEXT_PATTERNS = [ re.compile(r"\b(?:10|127|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}\b"), re.compile(r"Authorization\s*:", re.IGNORECASE), re.compile(r"Bearer\s+[A-Za-z0-9._-]{10,}", re.IGNORECASE), re.compile(r"Basic\s+[A-Za-z0-9+/=]{10,}", re.IGNORECASE), re.compile(r"password\s*[:=]\s*['\"][^'\"]+['\"]", re.IGNORECASE), re.compile(r"token\s*[:=]\s*['\"][^'\"]+['\"]", re.IGNORECASE), re.compile(r"cookie\s*[:=]\s*['\"][^'\"]+['\"]", re.IGNORECASE), re.compile(r"", re.IGNORECASE), ] 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_snapshot(root: Path, generated_at: str) -> dict[str, Any]: p0 = [item for item in WORKSTREAMS if item[2] == "P0"] p1 = [item for item in WORKSTREAMS if item[2] == "P1"] p2 = [item for item in WORKSTREAMS if item[2] == "P2"] return { "schema_version": SCHEMA_VERSION, "generated_at": generated_at, "git_commit": git_short_sha(root), "status": "iwooos_security_operating_system_ready_no_runtime_action", "mode": "repo_snapshot_guard_frontstage_only", "reference_frameworks": [ {"framework_id": framework_id, "label": label, "source_url": source_url} for framework_id, label, source_url in REFERENCE_FRAMEWORKS ], "operating_roles": [ {"role_id": role_id, "label": label, "responsibility": responsibility, "runtime_gate_open": False} for role_id, label, responsibility in OPERATING_ROLES ], "severity_lanes": [ {"severity": severity, "label": label, "triage_target": target, "runtime_gate_open": False} for severity, label, target in SEVERITY_LANES ], "workstreams": [ { "workstream_id": workstream_id, "lane_id": lane_id, "priority": priority, "title": title, "scope": scope, "owner_packet_required": True, "runtime_gate_open": False, } for workstream_id, lane_id, priority, title, scope in WORKSTREAMS ], "alert_message_contract": [ {"field_id": field_id, "required": True, "raw_payload_allowed": False} for field_id in ALERT_CONTRACT_FIELDS ], "automation_loop_stages": [ {"stage_id": stage_id, "runtime_gate_open": False} for stage_id in AUTOMATION_LOOP_STAGES ], "verification_stages": [ {"stage_id": stage_id, "accepted": False} for stage_id in VERIFICATION_STAGES ], "no_false_green_rules": [ {"rule_id": rule_id, "enforced": True} for rule_id in NO_FALSE_GREEN_RULES ], "cross_session_sync_checkpoints": [ {"checkpoint_id": checkpoint_id, "required": True} for checkpoint_id in CROSS_SESSION_SYNC_CHECKPOINTS ], "blocked_actions": BLOCKED_ACTIONS, "summary": { "reference_framework_count": len(REFERENCE_FRAMEWORKS), "operating_role_count": len(OPERATING_ROLES), "severity_lane_count": len(SEVERITY_LANES), "workstream_count": len(WORKSTREAMS), "p0_workstream_count": len(p0), "p1_workstream_count": len(p1), "p2_workstream_count": len(p2), "alert_contract_field_count": len(ALERT_CONTRACT_FIELDS), "automation_loop_stage_count": len(AUTOMATION_LOOP_STAGES), "verification_stage_count": len(VERIFICATION_STAGES), "no_false_green_rule_count": len(NO_FALSE_GREEN_RULES), "cross_session_sync_checkpoint_count": len(CROSS_SESSION_SYNC_CHECKPOINTS), "blocked_action_count": len(BLOCKED_ACTIONS), "source_control_artifact_percent": 100, "evidence_weighted_security_operating_system_percent": 56, "soc_siem_framework_percent": 92, "wazuh_manager_registry_acceptance_percent": 0, "runtime_response_percent": 0, "owner_response_received_count": 0, "owner_response_accepted_count": 0, "wazuh_registry_accepted_count": 0, "kali_scope_accepted_count": 0, "alert_receipt_accepted_count": 0, "incident_case_accepted_count": 0, "host_forensics_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, }, "execution_boundaries": { "runtime_execution_authorized": False, "host_write_authorized": False, "wazuh_active_response_authorized": False, "kali_active_scan_authorized": False, "kali_execute_authorized": False, "nginx_reload_authorized": False, "firewall_change_authorized": False, "secret_value_collection_allowed": False, "telegram_live_send_authorized": False, "soar_action_authorized": False, "auto_block_authorized": False, "production_write_authorized": False, "not_authorization": True, }, } def load_json(path: Path) -> dict[str, Any]: return json.loads(path.read_text(encoding="utf-8")) def assert_equal(label: str, actual: Any, expected: Any) -> None: if actual != expected: raise SystemExit(f"BLOCKED {label}: expected {expected!r}, got {actual!r}") def assert_false(label: str, actual: Any) -> None: assert_equal(label, actual, False) def collect_string_values(value: Any) -> list[str]: if isinstance(value, str): return [value] if isinstance(value, list): values: list[str] = [] for item in value: values.extend(collect_string_values(item)) return values if isinstance(value, dict): values = [] for item in value.values(): values.extend(collect_string_values(item)) return values return [] def validate_no_forbidden_text(snapshot: dict[str, Any]) -> None: for text in collect_string_values(snapshot): for pattern in FORBIDDEN_TEXT_PATTERNS: if pattern.search(text): raise SystemExit("BLOCKED iwooos_security_operating_system: snapshot contains forbidden sensitive text") def validate(root: Path) -> None: snapshot = load_json(root / SNAPSHOT_PATH) assert_equal("schema_version", snapshot.get("schema_version"), SCHEMA_VERSION) assert_equal("status", snapshot.get("status"), "iwooos_security_operating_system_ready_no_runtime_action") assert_equal("mode", snapshot.get("mode"), "repo_snapshot_guard_frontstage_only") summary = snapshot.get("summary", {}) expected_counts = { "reference_framework_count": 20, "operating_role_count": 10, "severity_lane_count": 5, "workstream_count": 24, "p0_workstream_count": 12, "p1_workstream_count": 8, "p2_workstream_count": 4, "alert_contract_field_count": 9, "automation_loop_stage_count": 8, "verification_stage_count": 12, "no_false_green_rule_count": 12, "cross_session_sync_checkpoint_count": 7, "blocked_action_count": 18, "source_control_artifact_percent": 100, "evidence_weighted_security_operating_system_percent": 56, "soc_siem_framework_percent": 92, "wazuh_manager_registry_acceptance_percent": 0, "runtime_response_percent": 0, "owner_response_received_count": 0, "owner_response_accepted_count": 0, "wazuh_registry_accepted_count": 0, "kali_scope_accepted_count": 0, "alert_receipt_accepted_count": 0, "incident_case_accepted_count": 0, "host_forensics_accepted_count": 0, "runtime_gate_count": 0, "action_button_count": 0, } for key, expected in expected_counts.items(): assert_equal(f"summary.{key}", summary.get(key), expected) boundaries = snapshot.get("execution_boundaries", {}) for key, value in boundaries.items(): if key == "not_authorization": assert_equal(f"execution_boundaries.{key}", value, True) else: assert_false(f"execution_boundaries.{key}", value) validate_no_forbidden_text(snapshot) def main() -> int: parser = argparse.ArgumentParser(description="IwoooS 資安作戰系統") parser.add_argument("--root", default=".", help="repo root") parser.add_argument("--output", help="寫出 JSON snapshot") parser.add_argument("--generated-at", help="固定報告時間,供 committed snapshot 使用") parser.add_argument("--json", action="store_true") args = parser.parse_args() root = Path(args.root).resolve() generated_at = args.generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds") if args.output: output = Path(args.output) if not output.is_absolute(): output = root / output snapshot = build_snapshot(root, generated_at) output.parent.mkdir(parents=True, exist_ok=True) output.write_text(json.dumps(snapshot, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8") validate(root) snapshot = load_json(root / SNAPSHOT_PATH) if args.json: print(json.dumps(snapshot, ensure_ascii=False, sort_keys=True)) return 0 summary = snapshot["summary"] print( "IWOOOS_SECURITY_OPERATING_SYSTEM_OK " f"frameworks={summary['reference_framework_count']} " f"workstreams={summary['workstream_count']} " f"p0={summary['p0_workstream_count']} " f"alert_contract={summary['alert_contract_field_count']} " f"evidence_percent={summary['evidence_weighted_security_operating_system_percent']} " f"runtime_gate={summary['runtime_gate_count']}" ) return 0 if __name__ == "__main__": sys.exit(main())