fix(iwooos): 接上 Wazuh 只讀 API 邊界

This commit is contained in:
ogt
2026-06-24 21:19:23 +08:00
parent 279f953144
commit 70afde06f9
10 changed files with 1275 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
# IwoooS Wazuh 只讀 API Release Handoff
> 狀態source-side 修補完成,等待具備正式 Gitea push / release 權限的 lane 合併與部署。
> 本文件不包含 secret、token、內網 Wazuh URL、raw log、raw Wazuh payload 或工作視窗逐字稿。
## 根因判定
`https://awoooi.wooo.work/api/iwooos/wazuh` production 目前回 `404 {"detail":"Not Found"}`,同時 `https://awoooi.wooo.work/zh-TW/iwooos``200`
判定根因:
- production `/api` 目前落到 FastAPI 後端。
- 既有 `apps/web/src/app/api/iwooos/wazuh/route.ts` 是 Next.js route沒有被 public gateway 暴露到這條 production path。
- FastAPI 後端原本沒有 `/api/iwooos/wazuh` 相容 route因此回 404。
- 這個 404 不能被解讀成 Wazuh manager 一定故障,也不能被解讀成 Wazuh 已未安裝。
## Source-Side 修補
本地 commit
- `codex/iwooos-wazuh-boundary-guard-20260624` 分支 HEAD`fix(iwooos): 接上 Wazuh 只讀 API 邊界`
變更範圍:
- `apps/api/src/api/v1/iwooos.py`
- `apps/api/src/main.py`
- `apps/api/tests/test_iwooos_wazuh_api.py`
- `scripts/security/wazuh-readonly-route-boundary-guard.py`
- `scripts/security/wazuh-readonly-production-readback.py`
- `scripts/security/wazuh-readonly-release-gate.py`
- `scripts/security/security-mirror-progress-guard.py`
- `docs/security/wazuh-readonly-release-gate.snapshot.json`
- `docs/LOGBOOK.md`
完成內容:
- 新增 FastAPI `GET /api/iwooos/wazuh`
- 新增 FastAPI `GET /api/v1/iwooos/wazuh`
- 預設回 `disabled_waiting_iwooos_wazuh_owner_gate`,避免 production 繼續用 404 表示未啟用。
- live Wazuh 查詢仍需 `IWOOOS_WAZUH_READONLY_ENABLED=true` 與 server-side env`WAZUH_API_BASE_URL``WAZUH_API_USERNAME``WAZUH_API_PASSWORD`
- 強制 Wazuh base URL 使用 HTTPS。
- 回傳資料只允許 metadataagent alias、status、OS 類別、last_seen_present 與 aggregate counts。
- 不回傳 raw Wazuh payload、agent 原名、內網 IP、token、password 或 secret。
- 新增 source guard阻擋硬編 Wazuh 內網 URL / port、帳密、關 TLS、假 SOC dashboard、假 CVE、raw payload 與 legacy dashboard component 回流。
- 新增 production readback 腳本,部署後可直接驗證 public API 不再 404、schema / status / boundary 正確,且沒有 raw payload、內網 IP、agent 原名或 secret 洩漏。
- 新增 release gate snapshot 與 guard固定 source-side 已完成、Gitea push / production deploy / production readback 尚未完成,避免後續把 predeploy 404 誤判成通過。
## 已完成驗證
已在 `/Users/ogt/codex-workspaces/awoooi-dev` 執行:
```bash
pytest apps/api/tests/test_iwooos_wazuh_api.py
python3 scripts/security/wazuh-readonly-route-boundary-guard.py --root .
python3 scripts/security/wazuh-readonly-release-gate.py --root .
python3 scripts/security/security-mirror-progress-guard.py --root .
python3 scripts/ops/doc-secrets-sanity-check.py docs apps/api/src/api/v1/iwooos.py apps/web/src/app/api/iwooos/wazuh/route.ts scripts/security/wazuh-readonly-route-boundary-guard.py
python3 -m py_compile apps/api/src/api/v1/iwooos.py scripts/security/wazuh-readonly-route-boundary-guard.py scripts/security/security-mirror-progress-guard.py
git diff --check
```
驗證結果:
- `pytest apps/api/tests/test_iwooos_wazuh_api.py``4 passed`
- `wazuh-readonly-route-boundary-guard``route=2 public_ui_files=1 forbidden=0 runtime_gate=0`
- `wazuh-readonly-release-gate``source=1 push=0 deploy=0 readback=0 runtime_gate=0`
- `security-mirror-progress-guard``SECURITY_MIRROR_PROGRESS_GUARD_OK`
- `doc-secrets-sanity-check``DOC_SECRET_SANITY_OK scanned_files=967`
- `py_compile`:通過。
- `git diff --check`:通過。
尚未部署前的 production 現況記錄:
```bash
python3 scripts/security/wazuh-readonly-production-readback.py --allow-predeploy-404 --json
```
預期只可回 `status=predeploy_404_observed`。正式部署驗收不得加 `--allow-predeploy-404`
## Release 前 Gate
合併 / 部署前需確認:
- 使用具備正式權限的 Gitea lane 合併 `codex/iwooos-wazuh-boundary-guard-20260624` 分支 HEAD 或同等 patch不得 force push。
- 不得複製舊 workspace 的內嵌明文 Gitea token。
- 不得把 Wazuh URL、帳密、token、cookie、private key、runner token 或 webhook secret 寫入 repo。
- 不得為了讓 API 變 200 而直接改 Nginx、Docker、K8s、firewall、Wazuh manager、Wazuh rule、Wazuh decoder 或 Wazuh active response。
- 若要啟用 live metadata query必須由正式 secrets / env 注入 `IWOOOS_WAZUH_READONLY_ENABLED=true` 與 Wazuh server-side env且要先有 owner gate。
## Production Readback 預期
部署後、尚未啟用 Wazuh env 時:
```bash
curl -sS https://awoooi.wooo.work/api/iwooos/wazuh
```
預期:
- HTTP `200`
- `schema_version=iwooos_wazuh_readonly_status_v1`
- `status=disabled_waiting_iwooos_wazuh_owner_gate`
- `configured=false`
- `runtime_gate_count=0`
- `active_response_authorized=false`
- `host_write_authorized=false`
- 不含內網 IP、agent 原名、token、password、raw payload。
正式驗收命令:
```bash
python3 scripts/security/wazuh-readonly-production-readback.py --json
```
正式驗收不接受 404若仍回 404代表 FastAPI 相容 route 尚未部署或 gateway 尚未接到新 API。
若 owner gate 與 server-side env 已正式啟用:
- 成功時可回 `readonly_metadata_available`
- Wazuh 不可達時可回 `wazuh_readonly_metadata_unavailable`
- 任何情況都不得回 raw payload、agent 原名、內網 IP、secret。
- 任何情況都不得因 route 可用而自動打開 active response、host write、Kali active scan 或 SOAR action。
## 完成度
| 項目 | 完成度 | 狀態 |
|---|---:|---|
| Wazuh public API 404 source-side 修補 | `100%` | 已完成本地分支 HEAD |
| Wazuh route boundary source guard | `100%` | 已納入 `security-mirror-progress-guard` |
| Production readback 驗收腳本 | `100%` | 已完成;正式部署後不得接受 404 |
| Wazuh release gate snapshot / guard | `100%` | 已完成;固定 push/deploy/readback 仍 blocked |
| Gitea push | `0%` | 受控 workspace HTTPS credential 缺失 |
| Production deploy / readback | `0%` | 等待 release lane |
| Wazuh server-side env enable | `0%` | 等待 owner gate 與 secrets 注入 |
| Wazuh event refs / host forensic refs accepted | `0%` | 尚未收到合格證據 |
| Wazuh active response / host write / Kali active scan | `0%` | 必須維持 false |
## 下一步優先序
1. 解決受控 workspace Gitea HTTPS push 認證,或由正式 release lane 合併 `codex/iwooos-wazuh-boundary-guard-20260624` 分支 HEAD。
2. 部署後先驗證 `/api/iwooos/wazuh` 不再 404且預設 disabled 邊界正確。
3. 另開 owner gate 決定是否啟用 server-side Wazuh read-only metadata query。
4. 收件 Wazuh manager health ref、agent status ref、event refs、host forensic refs 與 containment / recovery proof。
5. 仍禁止 active response、host write、firewall / Nginx / Docker / K8s runtime action、Kali active scan、secret 明文收集。

View File

@@ -0,0 +1,96 @@
{
"execution_boundaries": {
"agent_identity_public_display_allowed": false,
"force_push_allowed": false,
"host_read_authorized": false,
"host_write_authorized": false,
"internal_ip_public_display_allowed": false,
"kali_active_scan_authorized": false,
"not_authorization": true,
"production_deploy_authorized": false,
"raw_wazuh_payload_storage_allowed": false,
"runtime_execution_authorized": false,
"secret_value_collection_allowed": false,
"wazuh_active_response_authorized": false,
"wazuh_api_live_query_authorized": false
},
"generated_at": "2026-06-24T21:36:00+08:00",
"missing_required_source_paths": [],
"mode": "repo_release_gate_no_runtime_no_secret_collection",
"operator_interpretation": [
"此 gate 通過不代表 production 已部署,只代表 source-side Wazuh read-only API 與 guard 可交接。",
"正式 release 前不得用 predeploy 404 當成功,也不得為了修 404 直接改 Nginx、Docker、K8s、firewall 或 Wazuh secret。",
"live Wazuh metadata query 必須另走 owner gate 與 server-side envactive response、host write、Kali active scan 仍為 0 / false。"
],
"release_gates": [
{
"gate_id": "source_side_fastapi_route",
"required_evidence": "FastAPI /api/iwooos/wazuh 與 /api/v1/iwooos/wazuh source path present",
"runtime_authorized": false,
"status": "passed"
},
{
"gate_id": "source_boundary_guard",
"required_evidence": "wazuh-readonly-route-boundary-guard.py 通過",
"runtime_authorized": false,
"status": "passed"
},
{
"gate_id": "production_readback_script",
"required_evidence": "wazuh-readonly-production-readback.py 可在 release 後不接受 404",
"runtime_authorized": false,
"status": "passed"
},
{
"gate_id": "gitea_branch_push",
"required_evidence": "具備正式權限的 lane 推送或合併 codex/iwooos-wazuh-boundary-guard-20260624",
"runtime_authorized": false,
"status": "blocked_credential_required"
},
{
"gate_id": "production_deploy",
"required_evidence": "Gitea CD / deploy marker 指向已合併 Wazuh fix 的 commit",
"runtime_authorized": false,
"status": "blocked_waiting_release_lane"
},
{
"gate_id": "production_readback",
"required_evidence": "python3 scripts/security/wazuh-readonly-production-readback.py --json 通過且不回 404",
"runtime_authorized": false,
"status": "blocked_waiting_deploy"
},
{
"gate_id": "wazuh_live_metadata_env",
"required_evidence": "server-side env 與 owner gate不得硬編 secret",
"runtime_authorized": false,
"status": "blocked_owner_gate_required"
}
],
"required_source_paths": [
"apps/api/src/api/v1/iwooos.py",
"apps/api/tests/test_iwooos_wazuh_api.py",
"apps/web/src/app/api/iwooos/wazuh/route.ts",
"docs/security/IWOOOS-WAZUH-READONLY-API-RELEASE-HANDOFF.md",
"scripts/security/wazuh-readonly-production-readback.py",
"scripts/security/wazuh-readonly-route-boundary-guard.py"
],
"schema_version": "iwooos_wazuh_readonly_release_gate_v1",
"status": "blocked_waiting_gitea_push_and_production_deploy",
"summary": {
"active_response_authorized_count": 0,
"gitea_push_complete_count": 0,
"host_forensics_ref_accepted_count": 0,
"host_write_authorized_count": 0,
"missing_required_source_path_count": 0,
"predeploy_404_observed_count": 1,
"production_deploy_complete_count": 0,
"production_readback_passed_count": 0,
"production_readback_script_complete_count": 1,
"release_handoff_complete_count": 1,
"route_boundary_guard_complete_count": 1,
"runtime_gate_count": 0,
"source_side_fix_complete_count": 1,
"wazuh_event_ref_accepted_count": 0,
"wazuh_server_side_env_enabled_count": 0
}
}