diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index 56499565..23b0dd51 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -171,6 +171,30 @@ class AiOpsSignalSpec: _AI_OPS_SIGNAL_SPECS: tuple[AiOpsSignalSpec, ...] = ( + AiOpsSignalSpec( + event_type="wazuh_dashboard_api_readback_degraded", + title="Wazuh Dashboard / API 讀回退化", + lane="siem_observability_readback_degraded", + source_tokens=( + "wazuh_dashboard_api_readback_degraded", + "check-stored-api", + "check-api", + "dashboard agent list", + "agent list disappeared", + "agents disappeared", + "wazuh api check", + ), + gate_tokens=("429", "500", "unreachable", "registry", "readback", "dashboard", "api"), + impact="Dashboard 顯示與 Wazuh API / manager registry 讀回不一致;這是觀測盲點,不可宣稱 agent 全部消失或已恢復", + next_step="建立 Wazuh dashboard/API mismatch candidate,要求 manager registry 只讀計數、stored API 狀態、rate-limit / TLS trust 與 owner 回覆", + recommendation_lines=( + "├ 比對 dashboard stored API、Wazuh API 只讀 metadata、manager registry counts 與 agent transport evidence", + "├ 在 registry 未驗收前維持 no-false-green:agent_total / active / disconnected / last_seen 皆不得補假值", + "└ 回寫 IwoooS Wazuh visibility gate、AwoooP timeline、KM / PlayBook / Verifier", + ), + forbidden_summary="不重啟 Wazuh、不重新註冊 agent、不改 stored API / secret / firewall、不宣稱 registry 已恢復;先補只讀 evidence。", + default_severity="P1", + ), AiOpsSignalSpec( event_type="wazuh_intrusion_signal", title="Wazuh 入侵訊號", @@ -346,6 +370,8 @@ def _aiops_signal_target(text: str, spec: AiOpsSignalSpec) -> str: return target or spec.event_type if spec.event_type == "backup_restore_escrow_signal": return "backup_restore" + if spec.event_type == "wazuh_dashboard_api_readback_degraded": + return "wazuh_dashboard_api" if spec.event_type == "nginx_config_drift": return "public_gateway" if spec.event_type == "supply_chain_drift": diff --git a/apps/api/tests/test_telegram_message_templates.py b/apps/api/tests/test_telegram_message_templates.py index 2a529190..47e14794 100644 --- a/apps/api/tests/test_telegram_message_templates.py +++ b/apps/api/tests/test_telegram_message_templates.py @@ -164,6 +164,32 @@ syscheck integrity changed on /etc/nginx/sites-enabled/awoooi.conf assert "super-secret" not in result +def test_wazuh_dashboard_api_degraded_alert_becomes_readback_gap_event_packet() -> None: + """Wazuh Dashboard/API mismatch 必須轉成讀回退化事件卡,不可誤報成已修復。""" + raw_alert = """ +wazuh_dashboard_api_readback_degraded dashboard agent list disappeared +POST /api/check-stored-api status=429 POST /api/check-api status=500 +https://127.0.0.1:55000 is unreachable manager registry readback blocked +full_log=/var/ossec/logs/alerts/alerts.json Authorization: Bearer abcdefghijklmnopqrstuvwxyz +""" + + result = format_aiops_signal_alert_card(raw_alert) + + assert "P1 AIOps 訊號|Wazuh Dashboard / API 讀回退化" in result + assert "ai_automation_alert_card_v1" in result + assert "wazuh_dashboard_api_readback_degraded" in result + assert "siem_observability_readback_degraded" in result + assert "candidate_only" in result + assert "runtime_write_gate=0" in result + assert "manager registry 只讀計數" in result + assert "no-false-green" in result + assert "不重啟 Wazuh" in result + assert "不重新註冊 agent" in result + assert "127.0.0.1:55000" not in result + assert "/var/ossec" not in result + assert "abcdefghijkl" not in result + + def test_nginx_drift_alert_becomes_public_gateway_event_packet() -> None: """Nginx drift 應進 Public Gateway gate,而不是直接要求 reload。""" raw_alert = """ diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 99603e5e..c48fe4a1 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -36,6 +36,33 @@ - 整體治理完成度維持 `41.9%`;Status Cleanup 仍 `gates=5/5 blocked`、`owner_flags=0/6`、`apply_allowed=false`、`memory_write_authorized=false`。 - 本輪沒有更新 `project_current_status` / memory,沒有 Wazuh live query / active response / runtime deploy,沒有 host、Nginx、Docker、K8s、firewall、workflow、repo refs、backup、restore 或 migration 操作。 - 本輪只交付 read-only API / client / report model,未宣稱可視 UI 已恢復或正式展示完成。 + +## 2026-06-25|Wazuh Dashboard / API mismatch AI 事件卡 source-side guard + +**背景**:前一輪已建立 Wazuh agent visibility no-false-green guard,但 P0-D「Wazuh agent disappearance alert card」仍只停在待補項。這一輪把 Dashboard 顯示 agent 消失、但 agent transport / manager service 尚有只讀證據的狀態,從一般 Wazuh 入侵訊號拆成獨立 AI 事件類型,避免 operator 收到看不懂的 raw 429/500 或被誤導成 agent 全部消失。 + +**完成**: +- `TelegramGateway` 新增 `wazuh_dashboard_api_readback_degraded`,lane 為 `siem_observability_readback_degraded`。 +- 新事件卡固定 `candidate_only / runtime_write_gate=0`,下一步指向 manager registry 只讀計數、stored API 狀態、rate-limit / TLS trust 與 owner response。 +- 禁止事項固定:不重啟 Wazuh、不重新註冊 agent、不改 stored API / secret / firewall、不宣稱 registry 已恢復。 +- `telegram-alert-readability-guard.py` 已把測試合約調為 `11`、AIOps signal lanes 調為 `7`;`iwooos-config-control-guard.py` 與 snapshot 同步固定新計數。 +- `docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md` 與 `docs/security/TELEGRAM-ALERT-READABILITY-GUARD.md` 已補 Wazuh Dashboard/API mismatch 分類規則。 + +**驗證**: +- `DATABASE_URL=postgresql://postgres:postgres@localhost:5432/awoooi_test pytest apps/api/tests/test_telegram_message_templates.py -q`:`73 passed`。 +- `python3 scripts/security/telegram-alert-readability-guard.py --root .`:`tests=11 ai_lanes=7 host_lanes=6 runtime_gate=0`。 +- `python3 scripts/security/iwooos-config-control-guard.py --root .`:通過。 +- `python3 scripts/security/security-mirror-progress-guard.py --root .`:通過。 +- `python3 scripts/ops/doc-secrets-sanity-check.py ...`:通過。 + +**完成度**: +- Wazuh Dashboard / API mismatch formatter / test / guard:`100%` source-side。 +- P0-D Wazuh agent disappearance alert card:`70%` source-side、`0%` delivery receipt。 +- SOC / Wazuh no-false-green 納管:`45% -> 52%`。 +- Wazuh manager agent registry 驗收、IwoooS production live readback、Dashboard stored API 修復、active response、host write:仍維持 `0% / 0`。 + +**邊界**:本輪沒有送 Telegram、沒有修改 Alertmanager receiver、沒有 Wazuh / 112 / Docker / Nginx / firewall / secret / agent enrollment 寫入,沒有 active scan,也沒有把工作視窗對話放進前端或文件。 + ## 2026-06-24|23:15 110 cold-start monitor live-sync gate readback **背景**:23:04 已把 MOMO source absence classifier 納入 repo-side cold-start v1.42,但這不等於 110 上 `/home/wooo/scripts/full-stack-cold-start-check.sh` 已更新。為避免下次重啟時 operator 以 live 110 舊腳本輸出做錯判,本輪只做部署 parity 的 read-only 驗證與 SOP gate 補強。 diff --git a/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md b/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md index 577c7969..7113eff5 100644 --- a/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md +++ b/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md @@ -73,6 +73,7 @@ Host / runner 資源告警的第一版落地: - `TelegramGateway.send_alert_notification()` 與 `send_text()` 現在也會把 Wazuh、Kali、Nginx drift、Backup / Restore / Escrow、Provider freshness、Supply-chain drift 類訊號轉成同一版 `ai_automation_alert_card_v1`。 - 事件類型固定映射: + - `wazuh_dashboard_api_readback_degraded` → `siem_observability_readback_degraded` - `wazuh_intrusion_signal` → `security_intrusion_triage` - `kali_assessment_signal` → `security_assessment_review` - `nginx_config_drift` → `public_gateway_config_drift` @@ -80,6 +81,7 @@ Host / runner 資源告警的第一版落地: - `provider_freshness_signal` → `source_provider_freshness_triage` - `supply_chain_drift` → `supply_chain_drift_review` - 所有上述卡片都必須顯示 `candidate_only / runtime_write_gate=0`,並把下一步導向 owner evidence、reviewer acceptance、rendered diff / freshness / restore / SIEM readback、KM / PlayBook / Verifier 沉澱。 +- Wazuh Dashboard 顯示 agent 消失但 agent transport 或 manager service 仍有只讀證據時,必須優先分類為 `wazuh_dashboard_api_readback_degraded`;在 manager registry counts 未驗收前,不得把它寫成「所有 agent 已消失」或「agent 已恢復」。 - formatter 會在 Telegram 最後出口脫敏 URL、內網 IP、絕對路徑、Bearer token、token / password / secret / api key 類 assignment;Top evidence 最多保留三行摘要。 - 這只把 raw signal 變成 AI 自動化候選,不代表允許 Wazuh 封鎖、Kali active scan、`nginx -t` / reload、backup / restore / remote delete、provider switch、package upgrade、workflow dispatch 或 production write。 diff --git a/docs/security/TELEGRAM-ALERT-READABILITY-GUARD.md b/docs/security/TELEGRAM-ALERT-READABILITY-GUARD.md index 1c7b1348..3be3b34b 100644 --- a/docs/security/TELEGRAM-ALERT-READABILITY-GUARD.md +++ b/docs/security/TELEGRAM-ALERT-READABILITY-GUARD.md @@ -26,8 +26,8 @@ |------|--------| | source formatter markers | `11` | | 最後出口合約 | `3` | -| 測試合約 | `10` | -| AIOps signal lanes | `6` | +| 測試合約 | `11` | +| AIOps signal lanes | `7` | | Host resource lanes | `6` | | raw output 阻擋 marker | `12` | | required output marker | `6` | @@ -37,7 +37,8 @@ - `TelegramGateway._send_request()` 必須套用 `normalize_telegram_send_message_payload()`。 - `send_alert_notification()` 與 `send_text()` 必須先走 `normalize_alert_notification_payload()`。 - Host CPU / load / root Node.js / Prisma / Next build 只能轉成 `主機資源壓力` AI 事件卡。 -- Wazuh、Kali、Nginx drift、backup / restore、provider freshness、supply-chain 類訊號只能轉成 AIOps 候選事件卡。 +- Wazuh Dashboard / API 讀回退化、Wazuh 入侵訊號、Kali、Nginx drift、backup / restore、provider freshness、supply-chain 類訊號只能轉成 AIOps 候選事件卡。 +- Wazuh Dashboard 顯示 agent 消失但 manager registry 尚未驗收時,必須轉成 `wazuh_dashboard_api_readback_degraded`,不得把它誤寫為 agent 全部消失或已恢復。 - 外部版本檢查 URL、套件樹路徑、workspace 路徑、runner toolcache 路徑、raw Wazuh path、raw Nginx path、內網 IP、token-like 字串、raw Prisma JSON 不得出現在格式化後訊息。 ## 3. 驗收邊界 diff --git a/docs/security/WAZUH-AGENT-DISAPPEARANCE-INCIDENT-READBACK-2026-06-24.md b/docs/security/WAZUH-AGENT-DISAPPEARANCE-INCIDENT-READBACK-2026-06-24.md index 6f2440e2..501c5a55 100644 --- a/docs/security/WAZUH-AGENT-DISAPPEARANCE-INCIDENT-READBACK-2026-06-24.md +++ b/docs/security/WAZUH-AGENT-DISAPPEARANCE-INCIDENT-READBACK-2026-06-24.md @@ -73,7 +73,7 @@ | P0-A | Wazuh manager agent registry 只讀驗收 | owner 提供脫敏 `agent_total / active / disconnected / last_seen` ref,或經 server-side secret metadata 啟用 IwoooS 只讀 API | `40%` | | P0-B | Dashboard stored API / rate-limit / TLS trust 修復 gate | 查明 `/api/check-stored-api` 429/500 根因;維修前有 owner、rollback、postcheck;維修後 Dashboard 與 API count 一致 | `35%` | | P0-C | IwoooS live metadata route 正式部署 | `/api/iwooos/wazuh` 不再 404,回傳 schema `iwooos_wazuh_readonly_status_v1`,不洩漏 agent identity / internal IP / secret | `55%` source-side、`0%` production | -| P0-D | Wazuh agent disappearance alert card | 產出 `ai_automation_alert_card_v1`,包含 agent count delta、Dashboard API status、manager health、next gate、owner | `20%` | +| P0-D | Wazuh agent disappearance alert card | 產出 `ai_automation_alert_card_v1`,包含 agent count delta、Dashboard API status、manager health、next gate、owner;本輪已新增 `wazuh_dashboard_api_readback_degraded` formatter / test / guard | `70%` source-side、`0%` delivery receipt | | P0-E | 112/Wazuh owner response | 回覆 owner role/team、decision、reason、affected scope、redacted evidence refs、rollback owner、followup owner | `0%` | | P1-A | 110/188 agent receipt heartbeat | 每台 host 定期只讀確認 service active、manager target、1514 established、last evidence ref | `45%` | | P1-B | Dashboard no-false-green | Dashboard 429/500 或 Wazuh API check failure 要進 IwoooS incident,不可顯示綠燈 | `15%` | @@ -84,7 +84,7 @@ 1. 請 Wazuh/112 owner 補脫敏 agent registry evidence:`agent_total`、`active`、`disconnected`、`never_connected`、`last_seen` 時間窗,不提供密碼或 raw payload。 2. 啟用 IwoooS `/api/iwooos/wazuh` 前,先完成 production route readback、server-side env owner、secret source metadata、readonly account scope 與 rollback owner。 3. 若 owner 批准維修 Dashboard stored API,必須先做 read-only preflight:rate-limit 現況、stored API 指向、TLS trust、API user scope、Dashboard 與 manager 版本、回滾方式。 -4. 補 IwoooS AI 事件卡:當 Dashboard 顯示 agents 空白但 110/188 agent 仍 connected 時,分類為 `wazuh_dashboard_api_readback_degraded`,而不是 `all_agents_missing`。 +4. 補 IwoooS AI 事件卡正式 readback:source-side formatter 已能把 Dashboard/API mismatch 分類為 `wazuh_dashboard_api_readback_degraded`;下一步需接 delivery receipt、AwoooP timeline 與 IwoooS 前台 readback。 ## 7. 完成度 @@ -92,5 +92,5 @@ - 真正 agent registry 驗收:`0%`。 - IwoooS live readback production:`0%`。 - Dashboard stored API 修復:`0%`。 -- SOC / Wazuh no-false-green 納管:`45%`。 +- SOC / Wazuh no-false-green 納管:`52%`。 - active response / host write / auto block:`0%`,保持關閉。 diff --git a/docs/security/telegram-alert-readability-guard.snapshot.json b/docs/security/telegram-alert-readability-guard.snapshot.json index 2f97ffeb..b30c5502 100644 --- a/docs/security/telegram-alert-readability-guard.snapshot.json +++ b/docs/security/telegram-alert-readability-guard.snapshot.json @@ -1,5 +1,6 @@ { "ai_signal_lanes": [ + "wazuh_dashboard_api_readback_degraded", "wazuh_intrusion_signal", "kali_assessment_signal", "nginx_config_drift", @@ -54,8 +55,8 @@ "required_marker": "normalize_alert_notification_payload" } ], - "generated_at": "2026-06-19T02:01:35+08:00", - "git_commit": "7d032eab", + "generated_at": "2026-06-25T09:07:58+08:00", + "git_commit": "3a179e7f", "host_resource_lanes": [ "orphan_browser_smoke_runaway_process", "ci_runner_load_saturation", @@ -93,7 +94,7 @@ "status": "telegram_alert_readability_guard_ready_no_runtime_action", "summary": { "action_button_count": 0, - "ai_signal_lane_count": 6, + "ai_signal_lane_count": 7, "blocked_raw_output_marker_count": 12, "bot_api_call_authorized_count": 0, "final_exit_contract_count": 3, @@ -105,11 +106,12 @@ "secret_value_collection_allowed_count": 0, "source_formatter_marker_count": 11, "telegram_send_authorized_count": 0, - "test_contract_count": 10 + "test_contract_count": 11 }, "test_contracts": [ "test_ci_runner_load_alert_becomes_capacity_event_packet", "test_wazuh_alert_becomes_aiops_signal_event_packet", + "test_wazuh_dashboard_api_degraded_alert_becomes_readback_gap_event_packet", "test_nginx_drift_alert_becomes_public_gateway_event_packet", "test_aiops_signal_formatter_covers_non_host_alert_lanes", "test_send_alert_notification_normalizes_host_resource_raw_dump", diff --git a/scripts/security/iwooos-config-control-guard.py b/scripts/security/iwooos-config-control-guard.py index be4db431..0258d846 100644 --- a/scripts/security/iwooos-config-control-guard.py +++ b/scripts/security/iwooos-config-control-guard.py @@ -995,8 +995,8 @@ ARTIFACT_SPECS = [ "list_counts": { "source_markers": 11, "final_exit_contracts": 3, - "test_contracts": 10, - "ai_signal_lanes": 6, + "test_contracts": 11, + "ai_signal_lanes": 7, "host_resource_lanes": 6, "blocked_raw_output_markers": 12, "required_output_markers": 6, @@ -1004,8 +1004,8 @@ ARTIFACT_SPECS = [ "summary_counts": { "source_formatter_marker_count": 11, "final_exit_contract_count": 3, - "test_contract_count": 10, - "ai_signal_lane_count": 6, + "test_contract_count": 11, + "ai_signal_lane_count": 7, "host_resource_lane_count": 6, "blocked_raw_output_marker_count": 12, "required_output_marker_count": 6, diff --git a/scripts/security/telegram-alert-readability-guard.py b/scripts/security/telegram-alert-readability-guard.py index bc63f553..96b5ddc4 100644 --- a/scripts/security/telegram-alert-readability-guard.py +++ b/scripts/security/telegram-alert-readability-guard.py @@ -56,6 +56,7 @@ FINAL_EXIT_CONTRACTS = [ TEST_CONTRACTS = [ "test_ci_runner_load_alert_becomes_capacity_event_packet", "test_wazuh_alert_becomes_aiops_signal_event_packet", + "test_wazuh_dashboard_api_degraded_alert_becomes_readback_gap_event_packet", "test_nginx_drift_alert_becomes_public_gateway_event_packet", "test_aiops_signal_formatter_covers_non_host_alert_lanes", "test_send_alert_notification_normalizes_host_resource_raw_dump", @@ -67,6 +68,7 @@ TEST_CONTRACTS = [ ] AI_SIGNAL_LANES = [ + "wazuh_dashboard_api_readback_degraded", "wazuh_intrusion_signal", "kali_assessment_signal", "nginx_config_drift",