#!/usr/bin/env python3
"""
IwoooS Wazuh 只讀 live metadata env gate。

本工具只固定 server-side env / secret 注入 / production readback 的
owner gate。它不讀 secret value、不查 Wazuh API、不改 K8s / ArgoCD /
Docker / Nginx / firewall、不部署、不推送，也不啟用 active response。
"""

from __future__ import annotations

import argparse
import json
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/wazuh-readonly-live-metadata-env-gate.snapshot.json")

SERVER_SIDE_ENV_KEYS = [
    "IWOOOS_WAZUH_READONLY_ENABLED",
    "WAZUH_API_BASE_URL",
    "WAZUH_API_USERNAME",
    "WAZUH_API_PASSWORD",
]

REQUIRED_OWNER_FIELDS = [
    "wazuh_live_metadata_owner",
    "release_readback_ref",
    "secret_injection_owner",
    "secret_source_metadata_ref",
    "wazuh_manager_health_ref",
    "wazuh_api_tls_validation_ref",
    "readonly_account_scope_ref",
    "agent_alias_mapping_policy",
    "post_enable_readback_command",
    "rollback_owner",
    "maintenance_window",
    "validation_plan",
    "no_secret_value_attestation",
    "no_raw_payload_attestation",
    "active_response_separate_gate_ack",
]

REVIEWER_CHECKS = [
    "production_route_readback_passed_before_env_enable",
    "server_side_env_keys_present_as_metadata_only",
    "secret_value_absent",
    "secret_source_metadata_ref_present",
    "wazuh_api_base_url_https_only",
    "readonly_account_scope_present",
    "wazuh_manager_health_ref_present",
    "agent_alias_mapping_policy_present",
    "post_enable_readback_command_present",
    "rollback_owner_present",
    "maintenance_window_present",
    "validation_plan_present",
    "no_raw_wazuh_payload",
    "active_response_gate_separate",
    "runtime_gate_stays_zero_until_reviewer_acceptance",
]

OUTCOME_LANES = [
    "waiting_release_readback",
    "waiting_live_metadata_owner_response",
    "request_secret_source_metadata_supplement",
    "request_wazuh_manager_health_supplement",
    "request_readonly_account_scope_supplement",
    "quarantine_secret_or_raw_payload",
    "reject_runtime_workaround",
    "ready_for_live_metadata_reviewer_validation",
    "waiting_post_enable_readback",
    "waiting_runtime_gate",
]

BLOCKED_ACTIONS = [
    "collect_wazuh_password",
    "collect_wazuh_token",
    "collect_wazuh_raw_payload",
    "hardcode_wazuh_base_url",
    "hardcode_wazuh_username",
    "hardcode_wazuh_password",
    "disable_tls_verification",
    "enable_env_before_production_route_readback",
    "enable_env_without_secret_owner",
    "enable_wazuh_live_metadata_without_owner_gate",
    "enable_wazuh_active_response",
    "wazuh_manager_restart",
    "wazuh_rule_change",
    "wazuh_decoder_change",
    "k8s_secret_manual_patch",
    "argocd_manual_sync",
    "docker_restart",
    "nginx_or_gateway_workaround_for_404",
    "firewall_change",
    "host_write",
    "kali_active_scan",
    "production_deploy_without_release_lane",
    "mark_predeploy_404_as_passed_readback",
]


def now_iso() -> str:
    return datetime.now(TAIPEI).replace(microsecond=0).isoformat()


def build_report(generated_at: str | None = None) -> dict[str, Any]:
    return {
        "schema_version": "iwooos_wazuh_readonly_live_metadata_env_gate_v1",
        "generated_at": generated_at or now_iso(),
        "status": "blocked_waiting_live_metadata_owner_response",
        "mode": "repo_gate_no_secret_no_runtime_no_wazuh_query",
        "summary": {
            "server_side_env_key_count": len(SERVER_SIDE_ENV_KEYS),
            "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),
            "production_route_readback_passed_count": 1,
            "live_metadata_owner_response_received_count": 0,
            "live_metadata_owner_response_accepted_count": 0,
            "secret_source_metadata_accepted_count": 0,
            "wazuh_manager_health_ref_accepted_count": 0,
            "readonly_account_scope_accepted_count": 0,
            "post_enable_readback_passed_count": 0,
            "wazuh_api_live_query_authorized_count": 0,
            "wazuh_active_response_authorized_count": 0,
            "host_write_authorized_count": 0,
            "runtime_gate_count": 0,
        },
        "server_side_env_keys": SERVER_SIDE_ENV_KEYS,
        "required_owner_fields": REQUIRED_OWNER_FIELDS,
        "reviewer_checks": REVIEWER_CHECKS,
        "outcome_lanes": OUTCOME_LANES,
        "blocked_actions": BLOCKED_ACTIONS,
        "live_metadata_candidate": {
            "candidate_id": "iwooos_wazuh_readonly_live_metadata_env",
            "status": "waiting_live_metadata_owner_response",
            "production_route_readback_ref": "production_readback_passed_http_200_disabled_owner_gate",
            "server_side_env_keys": SERVER_SIDE_ENV_KEYS,
            "secret_source_metadata_ref": None,
            "wazuh_manager_health_ref": None,
            "readonly_account_scope_ref": None,
            "post_enable_readback_command": "python3 scripts/security/wazuh-readonly-production-readback.py --json",
            "owner_response_received": False,
            "owner_response_accepted": False,
            "wazuh_api_live_query_authorized": False,
            "wazuh_active_response_authorized": False,
            "runtime_gate": False,
            "not_authorization": True,
        },
        "execution_boundaries": {
            "repo_write_authorized": False,
            "production_deploy_authorized": False,
            "runtime_execution_authorized": False,
            "secret_value_collection_allowed": False,
            "wazuh_api_live_query_authorized": False,
            "wazuh_active_response_authorized": False,
            "raw_wazuh_payload_storage_allowed": False,
            "host_write_authorized": False,
            "kali_active_scan_authorized": False,
            "k8s_secret_patch_authorized": False,
            "argocd_sync_authorized": False,
            "docker_restart_authorized": False,
            "nginx_gateway_workaround_authorized": False,
            "firewall_change_authorized": False,
            "not_authorization": True,
        },
        "operator_interpretation": [
            "此 gate 不代表 Wazuh live metadata 已啟用，只代表啟用前欄位與禁止動作已固定。",
            "Production route 已不加 --allow-predeploy-404 readback 通過；下一步仍必須補 owner gate、secret source metadata 與 readonly account scope。",
            "secret handling 只能提供注入來源 metadata 與 owner，不得提交密碼、token、hash、partial secret 或 raw env。",
            "Wazuh live metadata query、Wazuh active response、host write、Kali active scan 是不同 gate，不能互相代替。",
        ],
    }


def validate(root: Path) -> None:
    snapshot_path = root / SNAPSHOT_PATH
    if not snapshot_path.exists():
        raise SystemExit(f"BLOCKED Wazuh live metadata env gate snapshot missing: {SNAPSHOT_PATH}")
    snapshot = json.loads(snapshot_path.read_text(encoding="utf-8"))
    expected = build_report(snapshot.get("generated_at"))

    for key in ("schema_version", "status", "mode"):
        if snapshot.get(key) != expected[key]:
            raise SystemExit(f"BLOCKED Wazuh live metadata env gate {key} mismatch")
    for key, expected_value in expected["summary"].items():
        actual = snapshot.get("summary", {}).get(key)
        if actual != expected_value:
            raise SystemExit(
                f"BLOCKED Wazuh live metadata env gate summary.{key}: "
                f"expected {expected_value!r}, got {actual!r}"
            )
    for key, value in snapshot.get("execution_boundaries", {}).items():
        if key == "not_authorization":
            if value is not True:
                raise SystemExit("BLOCKED Wazuh live metadata env gate not_authorization must be true")
        elif value is not False:
            raise SystemExit(f"BLOCKED Wazuh live metadata env gate execution_boundaries.{key}: expected false")


def main() -> int:
    parser = argparse.ArgumentParser(description="IwoooS Wazuh 只讀 live metadata env gate")
    parser.add_argument("--root", default=".", help="repository 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(args.generated_at)
    if args.output:
        output = Path(args.output)
        output.parent.mkdir(parents=True, exist_ok=True)
        output.write_text(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8")
    validate(root)
    summary = report["summary"]
    print(
        "WAZUH_READONLY_LIVE_METADATA_ENV_GATE_OK "
        f"route_readback={summary['production_route_readback_passed_count']} "
        f"owner={summary['live_metadata_owner_response_accepted_count']} "
        f"secret_meta={summary['secret_source_metadata_accepted_count']} "
        f"live_query={summary['wazuh_api_live_query_authorized_count']} "
        f"runtime_gate={summary['runtime_gate_count']}"
    )
    return 0


if __name__ == "__main__":
    sys.exit(main())
