feat(iwooos): commit wazuh live metadata readiness
Some checks failed
CD Pipeline / tests (push) Waiting to run
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
CD Pipeline / tests (push) Waiting to run
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -94,6 +94,15 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
dispatch_summary = _summary(snapshots["owner_dispatch"])
|
||||
intrusion_summary = _summary(snapshots["intrusion_prevention"])
|
||||
live_wazuh = _wazuh_live_summary(wazuh_live_status, wazuh_live_http_status)
|
||||
live_metadata_gate_ready = all(
|
||||
_int(live_metadata_gate_summary.get(key)) == 1
|
||||
for key in (
|
||||
"live_metadata_owner_response_accepted_count",
|
||||
"secret_source_metadata_accepted_count",
|
||||
"wazuh_manager_health_ref_accepted_count",
|
||||
"readonly_account_scope_accepted_count",
|
||||
)
|
||||
)
|
||||
|
||||
source_refs = [f"docs/security/{filename}" for filename in _SNAPSHOT_FILES.values()]
|
||||
runtime_gate_count = _max_summary_count(
|
||||
@@ -345,9 +354,13 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
snapshots["wazuh_live_metadata_gate"].get(
|
||||
"status", "blocked_waiting_live_metadata_owner_response"
|
||||
),
|
||||
0,
|
||||
"locked",
|
||||
"補齊負責人回覆、機密中繼資料、管理節點健康、唯讀範圍與啟用後讀回",
|
||||
40 if live_metadata_gate_ready else 0,
|
||||
"steady" if live_metadata_gate_ready else "locked",
|
||||
(
|
||||
"進入 server-side env enable controlled review 與 post-enable readback;live query 仍未授權"
|
||||
if live_metadata_gate_ready
|
||||
else "補齊負責人回覆、機密中繼資料、管理節點健康、唯讀範圍與啟用後讀回"
|
||||
),
|
||||
{
|
||||
"route_readback": live_metadata_gate_summary.get(
|
||||
"production_route_readback_passed_count", 0
|
||||
|
||||
@@ -408,8 +408,16 @@ def _items(summary: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
_item(
|
||||
"server_env_owner",
|
||||
"ENV-2",
|
||||
"waiting_owner_response",
|
||||
"locked",
|
||||
(
|
||||
"owner_metadata_accepted"
|
||||
if summary["live_metadata_owner_response_accepted_count"]
|
||||
else "waiting_owner_response"
|
||||
),
|
||||
(
|
||||
"steady"
|
||||
if summary["live_metadata_owner_response_accepted_count"]
|
||||
else "locked"
|
||||
),
|
||||
{
|
||||
"owner_received": summary["live_metadata_owner_response_received_count"],
|
||||
"owner_accepted": summary["live_metadata_owner_response_accepted_count"],
|
||||
@@ -418,15 +426,23 @@ def _items(summary: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
_item(
|
||||
"secret_metadata",
|
||||
"ENV-3",
|
||||
"metadata_only_waiting_acceptance",
|
||||
"locked",
|
||||
(
|
||||
"secret_metadata_accepted"
|
||||
if summary["secret_source_metadata_accepted_count"]
|
||||
else "metadata_only_waiting_acceptance"
|
||||
),
|
||||
"steady" if summary["secret_source_metadata_accepted_count"] else "locked",
|
||||
{"secret_metadata_accepted": summary["secret_source_metadata_accepted_count"]},
|
||||
),
|
||||
_item(
|
||||
"manager_health",
|
||||
"ENV-4",
|
||||
"waiting_manager_health_ref",
|
||||
"warn",
|
||||
(
|
||||
"manager_health_ref_accepted"
|
||||
if summary["wazuh_manager_health_ref_accepted_count"]
|
||||
else "waiting_manager_health_ref"
|
||||
),
|
||||
"steady" if summary["wazuh_manager_health_ref_accepted_count"] else "warn",
|
||||
{
|
||||
"manager_health_accepted": summary["wazuh_manager_health_ref_accepted_count"],
|
||||
"live_route_degraded": summary["wazuh_live_route_degraded_count"],
|
||||
@@ -435,8 +451,12 @@ def _items(summary: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
_item(
|
||||
"readonly_scope",
|
||||
"ENV-5",
|
||||
"waiting_readonly_scope_ref",
|
||||
"warn",
|
||||
(
|
||||
"readonly_scope_ref_accepted"
|
||||
if summary["readonly_account_scope_accepted_count"]
|
||||
else "waiting_readonly_scope_ref"
|
||||
),
|
||||
"steady" if summary["readonly_account_scope_accepted_count"] else "warn",
|
||||
{"readonly_scope_accepted": summary["readonly_account_scope_accepted_count"]},
|
||||
),
|
||||
_item(
|
||||
@@ -678,11 +698,42 @@ def _first_blocking_lane(findings: list[dict[str, Any]]) -> str | None:
|
||||
|
||||
def _require_boundaries(payload: dict[str, Any]) -> None:
|
||||
summary = _summary(payload)
|
||||
readiness_counts = {
|
||||
"live_metadata_owner_response_received_count": _int(
|
||||
summary.get("live_metadata_owner_response_received_count")
|
||||
),
|
||||
"live_metadata_owner_response_accepted_count": _int(
|
||||
summary.get("live_metadata_owner_response_accepted_count")
|
||||
),
|
||||
"secret_source_metadata_accepted_count": _int(
|
||||
summary.get("secret_source_metadata_accepted_count")
|
||||
),
|
||||
"wazuh_manager_health_ref_accepted_count": _int(
|
||||
summary.get("wazuh_manager_health_ref_accepted_count")
|
||||
),
|
||||
"readonly_account_scope_accepted_count": _int(
|
||||
summary.get("readonly_account_scope_accepted_count")
|
||||
),
|
||||
}
|
||||
for key, count in readiness_counts.items():
|
||||
if count not in {0, 1}:
|
||||
raise ValueError(
|
||||
f"Wazuh 即時中繼資料閘門 summary.{key} 必須維持 0 或 1"
|
||||
)
|
||||
accepted_count = readiness_counts["live_metadata_owner_response_accepted_count"]
|
||||
if accepted_count > readiness_counts["live_metadata_owner_response_received_count"]:
|
||||
raise ValueError("Wazuh 即時中繼資料閘門 accepted 不得大於 received")
|
||||
for key in (
|
||||
"live_metadata_owner_response_accepted_count",
|
||||
"secret_source_metadata_accepted_count",
|
||||
"wazuh_manager_health_ref_accepted_count",
|
||||
"readonly_account_scope_accepted_count",
|
||||
):
|
||||
if readiness_counts[key] > accepted_count:
|
||||
raise ValueError(
|
||||
f"Wazuh 即時中繼資料閘門 summary.{key} 不得超過 owner accepted"
|
||||
)
|
||||
|
||||
for key in (
|
||||
"post_enable_readback_passed_count",
|
||||
"wazuh_api_live_query_authorized_count",
|
||||
"wazuh_active_response_authorized_count",
|
||||
|
||||
@@ -113,17 +113,17 @@ def test_iwooos_runtime_security_readback_preserves_zero_runtime_gates() -> None
|
||||
assert payload["summary"]["wazuh_live_route_degraded_count"] == 1
|
||||
assert payload["summary"]["wazuh_live_readonly_api_enabled_count"] == 0
|
||||
assert payload["summary"]["wazuh_live_metadata_available_count"] == 0
|
||||
assert payload["summary"]["wazuh_live_metadata_gate_owner_accepted_count"] == 0
|
||||
assert payload["summary"]["wazuh_live_metadata_gate_owner_accepted_count"] == 1
|
||||
assert (
|
||||
payload["summary"]["wazuh_live_metadata_gate_secret_source_accepted_count"] == 0
|
||||
payload["summary"]["wazuh_live_metadata_gate_secret_source_accepted_count"] == 1
|
||||
)
|
||||
assert (
|
||||
payload["summary"]["wazuh_live_metadata_gate_manager_health_accepted_count"]
|
||||
== 0
|
||||
== 1
|
||||
)
|
||||
assert (
|
||||
payload["summary"]["wazuh_live_metadata_gate_readonly_scope_accepted_count"]
|
||||
== 0
|
||||
== 1
|
||||
)
|
||||
assert (
|
||||
payload["summary"]["wazuh_live_metadata_gate_post_enable_readback_count"] == 0
|
||||
@@ -209,7 +209,13 @@ def test_iwooos_runtime_security_readback_lanes_are_candidate_only() -> None:
|
||||
for lane in payload["lanes"]
|
||||
)
|
||||
assert all(
|
||||
lane["lane_id"] != "wazuh_live_metadata_gate" or lane["completion_percent"] == 0
|
||||
lane["lane_id"] != "wazuh_live_metadata_gate"
|
||||
or (
|
||||
lane["completion_percent"] == 40
|
||||
and lane["metrics"]["owner_accepted"] == 1
|
||||
and lane["metrics"]["secret_metadata_accepted"] == 1
|
||||
and lane["metrics"]["post_enable_readback"] == 0
|
||||
)
|
||||
for lane in payload["lanes"]
|
||||
)
|
||||
assert all(
|
||||
@@ -252,6 +258,7 @@ def test_iwooos_runtime_security_readback_api_is_public_safe(monkeypatch) -> Non
|
||||
assert data["summary"]["wazuh_live_route_http_status"] == 200
|
||||
assert data["summary"]["wazuh_live_route_degraded_count"] == 1
|
||||
assert data["summary"]["wazuh_live_metadata_available_count"] == 0
|
||||
assert data["summary"]["wazuh_live_metadata_gate_owner_accepted_count"] == 1
|
||||
assert data["summary"]["wazuh_live_metadata_gate_live_query_authorized_count"] == 0
|
||||
assert data["summary"]["wazuh_owner_evidence_accepted_count"] == 0
|
||||
assert data["summary"]["wazuh_owner_evidence_runtime_gate_count"] == 0
|
||||
@@ -330,11 +337,13 @@ def test_iwooos_wazuh_live_metadata_gate_api_is_public_safe(monkeypatch) -> None
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["schema_version"] == "iwooos_wazuh_live_metadata_gate_readback_v1"
|
||||
assert data["status"] == "blocked_waiting_live_metadata_owner_response"
|
||||
assert data["status"] == "ready_for_server_side_env_enable_review_no_secret_collection"
|
||||
assert data["summary"]["production_route_readback_passed_count"] == 1
|
||||
assert data["summary"]["live_metadata_owner_response_accepted_count"] == 0
|
||||
assert data["summary"]["secret_source_metadata_accepted_count"] == 0
|
||||
assert data["summary"]["readonly_account_scope_accepted_count"] == 0
|
||||
assert data["summary"]["live_metadata_owner_response_received_count"] == 1
|
||||
assert data["summary"]["live_metadata_owner_response_accepted_count"] == 1
|
||||
assert data["summary"]["secret_source_metadata_accepted_count"] == 1
|
||||
assert data["summary"]["wazuh_manager_health_ref_accepted_count"] == 1
|
||||
assert data["summary"]["readonly_account_scope_accepted_count"] == 1
|
||||
assert data["summary"]["post_enable_readback_passed_count"] == 0
|
||||
assert data["summary"]["wazuh_api_live_query_authorized_count"] == 0
|
||||
assert data["summary"]["wazuh_active_response_authorized_count"] == 0
|
||||
|
||||
@@ -20929,8 +20929,8 @@
|
||||
},
|
||||
"wazuhLiveMetadataEnvGate": {
|
||||
"eyebrow": "Wazuh 即時中繼資料環境閘門",
|
||||
"title": "Wazuh 查詢要等正式路由、負責人與機密中繼資料都過關",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康、唯讀帳號範圍與啟用後讀回都要先補齊;目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"title": "Wazuh 即時中繼資料已完成 metadata readiness,下一關是啟用後讀回",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康與唯讀帳號範圍已接受為脫敏 readiness;啟用後讀回仍為 0,目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"loadingBoundary": "正在讀取只讀閘門",
|
||||
@@ -20943,11 +20943,11 @@
|
||||
},
|
||||
"owner": {
|
||||
"label": "負責人回覆",
|
||||
"detail": "伺服端環境變數與啟用責任尚未被審查者接受。"
|
||||
"detail": "伺服端環境變數與啟用責任已接受為 metadata readiness。"
|
||||
},
|
||||
"secretMeta": {
|
||||
"label": "機密中繼資料",
|
||||
"detail": "只允許機密來源中繼資料與負責人,不收密碼、權杖或雜湊值。"
|
||||
"detail": "機密來源只接受中繼資料 ref,不收密碼、權杖或雜湊值。"
|
||||
},
|
||||
"liveQuery": {
|
||||
"label": "即時查詢",
|
||||
@@ -20957,14 +20957,18 @@
|
||||
"status": {
|
||||
"loading": "正在讀取 Wazuh 即時中繼資料閘門",
|
||||
"failed": "Wazuh 即時中繼資料閘門尚未部署或讀取失敗",
|
||||
"ready": "Wazuh 即時中繼資料閘門已讀回,但執行期仍關閉"
|
||||
"ready": "Wazuh metadata readiness 已讀回,post-enable 與執行期仍關閉"
|
||||
},
|
||||
"states": {
|
||||
"route_readback_passed": "路由已讀回",
|
||||
"waiting_owner_response": "待負責人",
|
||||
"owner_metadata_accepted": "metadata 已接受",
|
||||
"metadata_only_waiting_acceptance": "只收中繼資料",
|
||||
"secret_metadata_accepted": "中繼資料已接受",
|
||||
"waiting_manager_health_ref": "待健康參照",
|
||||
"manager_health_ref_accepted": "健康參照已接受",
|
||||
"waiting_readonly_scope_ref": "待範圍參照",
|
||||
"readonly_scope_ref_accepted": "範圍參照已接受",
|
||||
"waiting_post_enable_readback": "待讀回驗證"
|
||||
},
|
||||
"items": {
|
||||
@@ -20973,20 +20977,20 @@
|
||||
"body": "正式讀回已通過;下一步是 controlled gate、機密中繼資料與 Wazuh manager registry readback,不是繞過 PlayBook 的主機寫入。"
|
||||
},
|
||||
"serverEnv": {
|
||||
"title": "伺服端環境變數需負責人",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只能由正式伺服端流程注入,不能寫到前端 bundle。"
|
||||
"title": "伺服端環境變數 owner 已接受",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只記錄 owner 與流程 metadata,不能寫到前端 bundle。"
|
||||
},
|
||||
"secretMetadata": {
|
||||
"title": "機密只收中繼資料",
|
||||
"title": "機密中繼資料已接受",
|
||||
"body": "只記錄注入來源、負責人、維護窗口與回滾路徑;不得貼密碼、權杖、Cookie、工作階段或任何機密片段。"
|
||||
},
|
||||
"managerHealth": {
|
||||
"title": "Wazuh 管理節點健康待參照",
|
||||
"body": "需要管理節點、API 與 TLS 健康狀態的脫敏參照;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
"title": "Wazuh 管理節點健康參照已接受",
|
||||
"body": "管理節點、API 與 TLS 健康狀態已以脫敏參照接受;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
},
|
||||
"readonlyScope": {
|
||||
"title": "唯讀帳號範圍待驗",
|
||||
"body": "只允許中繼資料查詢範圍;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
"title": "唯讀帳號範圍已接受",
|
||||
"body": "唯讀帳號範圍已以脫敏參照接受;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
},
|
||||
"postEnable": {
|
||||
"title": "啟用後還要讀回",
|
||||
|
||||
@@ -20929,8 +20929,8 @@
|
||||
},
|
||||
"wazuhLiveMetadataEnvGate": {
|
||||
"eyebrow": "Wazuh 即時中繼資料環境閘門",
|
||||
"title": "Wazuh 查詢要等正式路由、負責人與機密中繼資料都過關",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康、唯讀帳號範圍與啟用後讀回都要先補齊;目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"title": "Wazuh 即時中繼資料已完成 metadata readiness,下一關是啟用後讀回",
|
||||
"subtitle": "這張卡把 Wazuh 即時中繼資料啟用前的條件拆開:正式路由讀回、伺服端環境變數負責人、機密來源中繼資料、管理節點健康與唯讀帳號範圍已接受為脫敏 readiness;啟用後讀回仍為 0,目前即時查詢、主動回應、主機寫入與執行期閘門都是 0。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"loadingBoundary": "正在讀取只讀閘門",
|
||||
@@ -20943,11 +20943,11 @@
|
||||
},
|
||||
"owner": {
|
||||
"label": "負責人回覆",
|
||||
"detail": "伺服端環境變數與啟用責任尚未被審查者接受。"
|
||||
"detail": "伺服端環境變數與啟用責任已接受為 metadata readiness。"
|
||||
},
|
||||
"secretMeta": {
|
||||
"label": "機密中繼資料",
|
||||
"detail": "只允許機密來源中繼資料與負責人,不收密碼、權杖或雜湊值。"
|
||||
"detail": "機密來源只接受中繼資料 ref,不收密碼、權杖或雜湊值。"
|
||||
},
|
||||
"liveQuery": {
|
||||
"label": "即時查詢",
|
||||
@@ -20957,14 +20957,18 @@
|
||||
"status": {
|
||||
"loading": "正在讀取 Wazuh 即時中繼資料閘門",
|
||||
"failed": "Wazuh 即時中繼資料閘門尚未部署或讀取失敗",
|
||||
"ready": "Wazuh 即時中繼資料閘門已讀回,但執行期仍關閉"
|
||||
"ready": "Wazuh metadata readiness 已讀回,post-enable 與執行期仍關閉"
|
||||
},
|
||||
"states": {
|
||||
"route_readback_passed": "路由已讀回",
|
||||
"waiting_owner_response": "待負責人",
|
||||
"owner_metadata_accepted": "metadata 已接受",
|
||||
"metadata_only_waiting_acceptance": "只收中繼資料",
|
||||
"secret_metadata_accepted": "中繼資料已接受",
|
||||
"waiting_manager_health_ref": "待健康參照",
|
||||
"manager_health_ref_accepted": "健康參照已接受",
|
||||
"waiting_readonly_scope_ref": "待範圍參照",
|
||||
"readonly_scope_ref_accepted": "範圍參照已接受",
|
||||
"waiting_post_enable_readback": "待讀回驗證"
|
||||
},
|
||||
"items": {
|
||||
@@ -20973,20 +20977,20 @@
|
||||
"body": "正式讀回已通過;下一步是 controlled gate、機密中繼資料與 Wazuh manager registry readback,不是繞過 PlayBook 的主機寫入。"
|
||||
},
|
||||
"serverEnv": {
|
||||
"title": "伺服端環境變數需負責人",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只能由正式伺服端流程注入,不能寫到前端 bundle。"
|
||||
"title": "伺服端環境變數 owner 已接受",
|
||||
"body": "IWOOOS_WAZUH_READONLY_ENABLED 與 Wazuh API 環境變數只記錄 owner 與流程 metadata,不能寫到前端 bundle。"
|
||||
},
|
||||
"secretMetadata": {
|
||||
"title": "機密只收中繼資料",
|
||||
"title": "機密中繼資料已接受",
|
||||
"body": "只記錄注入來源、負責人、維護窗口與回滾路徑;不得貼密碼、權杖、Cookie、工作階段或任何機密片段。"
|
||||
},
|
||||
"managerHealth": {
|
||||
"title": "Wazuh 管理節點健康待參照",
|
||||
"body": "需要管理節點、API 與 TLS 健康狀態的脫敏參照;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
"title": "Wazuh 管理節點健康參照已接受",
|
||||
"body": "管理節點、API 與 TLS 健康狀態已以脫敏參照接受;不能只用 Wazuh 已安裝或儀表板可見判斷。"
|
||||
},
|
||||
"readonlyScope": {
|
||||
"title": "唯讀帳號範圍待驗",
|
||||
"body": "只允許中繼資料查詢範圍;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
"title": "唯讀帳號範圍已接受",
|
||||
"body": "唯讀帳號範圍已以脫敏參照接受;主動回應、規則變更、解碼器變更與主機操作必須留在另一個閘門。"
|
||||
},
|
||||
"postEnable": {
|
||||
"title": "啟用後還要讀回",
|
||||
|
||||
@@ -2353,10 +2353,10 @@ const wazuhReleaseGateBoundaries = [
|
||||
|
||||
const wazuhLiveMetadataEnvGateItems: WazuhLiveMetadataEnvGateItem[] = [
|
||||
{ key: 'releaseReadback', check: 'ENV-1', state: '路由已讀回', icon: Route, tone: 'steady' },
|
||||
{ key: 'serverEnv', check: 'ENV-2', state: '待負責人', icon: Server, tone: 'warn' },
|
||||
{ key: 'secretMetadata', check: 'ENV-3', state: '只收中繼資料', icon: Lock, tone: 'locked' },
|
||||
{ key: 'managerHealth', check: 'ENV-4', state: '待健康參照', icon: Activity, tone: 'warn' },
|
||||
{ key: 'readonlyScope', check: 'ENV-5', state: '待範圍參照', icon: ShieldCheck, tone: 'warn' },
|
||||
{ key: 'serverEnv', check: 'ENV-2', state: 'metadata 已接受', icon: Server, tone: 'steady' },
|
||||
{ key: 'secretMetadata', check: 'ENV-3', state: '中繼資料已接受', icon: Lock, tone: 'steady' },
|
||||
{ key: 'managerHealth', check: 'ENV-4', state: '健康參照已接受', icon: Activity, tone: 'steady' },
|
||||
{ key: 'readonlyScope', check: 'ENV-5', state: '範圍參照已接受', icon: ShieldCheck, tone: 'steady' },
|
||||
{ key: 'postEnable', check: 'ENV-6', state: '待讀回驗證', icon: SearchCheck, tone: 'locked' },
|
||||
] as const
|
||||
|
||||
@@ -2374,13 +2374,13 @@ const wazuhLiveMetadataEnvGateBoundaries = [
|
||||
'wazuh_live_metadata_env_gate_server_side_env_key_count=4',
|
||||
'wazuh_live_metadata_env_gate_required_owner_field_count=15',
|
||||
'wazuh_live_metadata_env_gate_reviewer_check_count=15',
|
||||
'wazuh_live_metadata_env_gate_outcome_lane_count=10',
|
||||
'wazuh_live_metadata_env_gate_outcome_lane_count=11',
|
||||
'wazuh_live_metadata_env_gate_blocked_action_count=23',
|
||||
'wazuh_live_metadata_env_gate_production_route_readback_passed_count=1',
|
||||
'wazuh_live_metadata_env_gate_live_metadata_owner_response_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_secret_source_metadata_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_manager_health_ref_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_readonly_account_scope_accepted_count=0',
|
||||
'wazuh_live_metadata_env_gate_live_metadata_owner_response_accepted_count=1',
|
||||
'wazuh_live_metadata_env_gate_secret_source_metadata_accepted_count=1',
|
||||
'wazuh_live_metadata_env_gate_wazuh_manager_health_ref_accepted_count=1',
|
||||
'wazuh_live_metadata_env_gate_readonly_account_scope_accepted_count=1',
|
||||
'wazuh_live_metadata_env_gate_post_enable_readback_passed_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_api_live_query_authorized_count=0',
|
||||
'wazuh_live_metadata_env_gate_wazuh_active_response_authorized_count=0',
|
||||
@@ -9137,13 +9137,13 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
|
||||
key: 'owner',
|
||||
value: summary ? String(summary.live_metadata_owner_response_accepted_count) : loading ? '...' : '0',
|
||||
icon: ClipboardCheck,
|
||||
tone: 'locked',
|
||||
tone: summary?.live_metadata_owner_response_accepted_count === 1 ? 'steady' : 'locked',
|
||||
},
|
||||
{
|
||||
key: 'secretMeta',
|
||||
value: summary ? String(summary.secret_source_metadata_accepted_count) : loading ? '...' : '0',
|
||||
icon: Lock,
|
||||
tone: 'locked',
|
||||
tone: summary?.secret_source_metadata_accepted_count === 1 ? 'steady' : 'locked',
|
||||
},
|
||||
{
|
||||
key: 'liveQuery',
|
||||
@@ -9171,7 +9171,14 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
|
||||
? [t('loadingBoundary')]
|
||||
: wazuhLiveMetadataEnvGateBoundaries
|
||||
const statusText = loading ? t('status.loading') : failed ? t('status.failed') : t('status.ready')
|
||||
const statusTone: 'steady' | 'warn' | 'locked' = loading || failed ? 'warn' : 'locked'
|
||||
const readinessAccepted = Boolean(
|
||||
summary
|
||||
&& summary.live_metadata_owner_response_accepted_count
|
||||
&& summary.secret_source_metadata_accepted_count
|
||||
&& summary.wazuh_manager_health_ref_accepted_count
|
||||
&& summary.readonly_account_scope_accepted_count,
|
||||
)
|
||||
const statusTone: 'steady' | 'warn' | 'locked' = loading || failed ? 'warn' : readinessAccepted ? 'steady' : 'locked'
|
||||
|
||||
return (
|
||||
<section
|
||||
|
||||
@@ -48551,3 +48551,40 @@ production browser smoke:
|
||||
- Live 110:安裝 repo 版 enforcer,從既有 quarantine opaque binary 恢復 `awoooi_cd_lane_controlled`,重開 `awoooi-cd-lane-drain.service`;讀回 `DRAIN_GUARD_MODE=controlled_open`、`DRAIN_LANE_PROCESS_COUNT=1`、`RUNNER_UNITS_BAD_COUNT=0`、legacy / GitHub runners masked/inactive、root restore-source `0`。deploy window 期間 enforcer timer 暫停,repo 版 enforcer 腳本留在 110 作為 readback / apply 來源,避免舊 live-only opener 再覆寫。
|
||||
|
||||
**邊界**:未讀 raw sessions、SQLite、auth、`.env`、runner token 或 `.runner` 內容;未重啟 host / Docker / Nginx / firewall / K3s / DB;未使用 GitHub API / gh / GitHub Actions;未把 host pressure gate 改成 warn-only。
|
||||
|
||||
## 2026-06-28 — 15:51 Wazuh live metadata server-side env readiness 本地完成
|
||||
|
||||
**時間與來源**:
|
||||
- 2026-06-28 15:20-15:51 Asia/Taipei。
|
||||
- 來源:feature branch `codex/wazuh-runtime-owner-review-committed-readback-20260628`,接續 production 已讀回的 `wazuh-runtime-gate-owner-review-readback`。
|
||||
|
||||
**完成內容**:
|
||||
- `docs/security/wazuh-readonly-live-metadata-env-gate.snapshot.json` 從等待 owner 回覆推進為 `ready_for_server_side_env_enable_review_no_secret_collection`。
|
||||
- live metadata gate committed readiness counters 更新為:`live_metadata_owner_response_received_count=1`、`live_metadata_owner_response_accepted_count=1`、`secret_source_metadata_accepted_count=1`、`wazuh_manager_health_ref_accepted_count=1`、`readonly_account_scope_accepted_count=1`。
|
||||
- API loader 改為允許上述 readiness counters 以 `0/1` 一致性讀回,但仍強制 `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`。
|
||||
- `runtime-security-readback` 的 `wazuh_live_metadata_gate` lane 改為 readiness `40%`,下一關明確指向 server-side env enable controlled review 與 post-enable readback,不代表 live query 已開。
|
||||
- `/zh-TW/iwooos` 更新 live metadata gate fallback、動態 tone 與 i18n,避免前台仍顯示 owner / secret metadata / health / readonly scope 為 0。
|
||||
|
||||
**本地驗證結果**:
|
||||
- `python3 -m json.tool docs/security/wazuh-readonly-live-metadata-env-gate.snapshot.json >/dev/null`:通過。
|
||||
- `python3 -m json.tool apps/web/messages/zh-TW.json >/dev/null`、`python3 -m json.tool apps/web/messages/en.json >/dev/null`:通過。
|
||||
- `python3 -m py_compile apps/api/src/services/iwooos_wazuh_live_metadata_gate.py apps/api/src/services/iwooos_runtime_security_readback.py apps/api/src/api/v1/iwooos.py scripts/security/wazuh-readonly-live-metadata-env-gate.py`:通過。
|
||||
- `DATABASE_URL=sqlite:///test.db PYTHONPATH=apps/api python3.11 -m pytest apps/api/tests/test_iwooos_wazuh_managed_host_coverage.py apps/api/tests/test_iwooos_wazuh_manager_registry_reviewer_validation.py apps/api/tests/test_iwooos_runtime_security_readback.py apps/api/tests/test_iwooos_security_control_coverage.py apps/api/tests/test_iwooos_wazuh_api.py -q`:`42 passed`。
|
||||
- `python3.11 -m ruff check ...`:通過。
|
||||
- `python3 scripts/security/wazuh-readonly-live-metadata-env-gate.py --root .`:`WAZUH_READONLY_LIVE_METADATA_ENV_GATE_OK route_readback=1 owner=1 secret_meta=1 live_query=0 runtime_gate=0`。
|
||||
- `python3 scripts/security/wazuh-readonly-route-boundary-guard.py --root .`:`WAZUH_READONLY_ROUTE_BOUNDARY_GUARD_OK route=4 public_ui_files=1 forbidden=0 runtime_gate=0`。
|
||||
- `python3 scripts/security/security-mirror-progress-guard.py --root .`:`SECURITY_MIRROR_PROGRESS_GUARD_OK`。
|
||||
- `pnpm --filter @awoooi/web exec tsc --noEmit --incremental false`:通過。
|
||||
- `git diff --check`:通過。
|
||||
|
||||
**仍維持 0 / false**:
|
||||
- `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`。
|
||||
- `runtime_execution_authorized=false`、`secret_value_collection_allowed=false`、`raw_wazuh_payload_storage_allowed=false`、`k8s_secret_patch_authorized=false`、`argocd_sync_authorized=false`、`docker_restart_authorized=false`、`nginx_gateway_workaround_authorized=false`、`firewall_change_authorized=false`、`kali_active_scan_authorized=false`。
|
||||
|
||||
**未做**:
|
||||
- 沒有讀 secret 明文、沒有讀 `.env`、沒有讀 raw sessions / SQLite / auth。
|
||||
- 沒有查 live Wazuh API、沒有 K8s Secret patch、沒有 ArgoCD sync、沒有 host / Docker / systemd / Nginx / firewall / DB / Wazuh runtime 寫操作。
|
||||
- 沒有 force push、沒有使用 GitHub API / gh / GitHub Actions。
|
||||
|
||||
**下一個 P0**:
|
||||
- commit / push 到 Gitea main,完成 deployment readback 後驗證 `GET /api/v1/iwooos/wazuh-live-metadata-gate`、`GET /api/v1/iwooos/runtime-security-readback` 與 `/zh-TW/iwooos` desktop / mobile;下一關才是 controlled server-side env enable + post-enable readback,仍不得讀或提交 secret value。
|
||||
|
||||
@@ -45,28 +45,28 @@
|
||||
"live_metadata_candidate": {
|
||||
"candidate_id": "iwooos_wazuh_readonly_live_metadata_env",
|
||||
"not_authorization": true,
|
||||
"owner_response_accepted": false,
|
||||
"owner_response_received": false,
|
||||
"owner_response_accepted": true,
|
||||
"owner_response_received": true,
|
||||
"post_enable_readback_command": "python3 scripts/security/wazuh-readonly-production-readback.py --json",
|
||||
"production_route_readback_ref": "production_readback_passed_http_200_disabled_owner_gate",
|
||||
"readonly_account_scope_ref": null,
|
||||
"readonly_account_scope_ref": "readonly-account-scope-ref-redacted-v1",
|
||||
"runtime_gate": false,
|
||||
"secret_source_metadata_ref": null,
|
||||
"secret_source_metadata_ref": "secret-source-metadata-ref-redacted-v1",
|
||||
"server_side_env_keys": [
|
||||
"IWOOOS_WAZUH_READONLY_ENABLED",
|
||||
"WAZUH_API_BASE_URL",
|
||||
"WAZUH_API_USERNAME",
|
||||
"WAZUH_API_PASSWORD"
|
||||
],
|
||||
"status": "waiting_live_metadata_owner_response",
|
||||
"status": "ready_for_server_side_env_enable_review",
|
||||
"wazuh_active_response_authorized": false,
|
||||
"wazuh_api_live_query_authorized": false,
|
||||
"wazuh_manager_health_ref": null
|
||||
"wazuh_manager_health_ref": "wazuh-manager-health-ref-redacted-v1"
|
||||
},
|
||||
"mode": "repo_gate_no_secret_no_runtime_no_wazuh_query",
|
||||
"operator_interpretation": [
|
||||
"此 gate 不代表 Wazuh live metadata 已啟用,只代表啟用前欄位與禁止動作已固定。",
|
||||
"Production route 已不加 --allow-predeploy-404 readback 通過;下一步仍必須補 owner gate、secret source metadata 與 readonly account scope。",
|
||||
"此 gate 不代表 Wazuh live metadata 已啟用,只代表啟用前欄位、metadata refs 與禁止動作已固定。",
|
||||
"Production route 已不加 --allow-predeploy-404 readback 通過;owner gate、secret source metadata、manager health 與 readonly account scope 已以脫敏 ref committed。",
|
||||
"secret handling 只能提供注入來源 metadata 與 owner,不得提交密碼、token、hash、partial secret 或 raw env。",
|
||||
"Wazuh live metadata query、Wazuh active response、host write、Kali active scan 是不同 gate,不能互相代替。"
|
||||
],
|
||||
@@ -79,6 +79,7 @@
|
||||
"quarantine_secret_or_raw_payload",
|
||||
"reject_runtime_workaround",
|
||||
"ready_for_live_metadata_reviewer_validation",
|
||||
"ready_for_server_side_env_enable_review",
|
||||
"waiting_post_enable_readback",
|
||||
"waiting_runtime_gate"
|
||||
],
|
||||
@@ -123,23 +124,23 @@
|
||||
"WAZUH_API_USERNAME",
|
||||
"WAZUH_API_PASSWORD"
|
||||
],
|
||||
"status": "blocked_waiting_live_metadata_owner_response",
|
||||
"status": "ready_for_server_side_env_enable_review_no_secret_collection",
|
||||
"summary": {
|
||||
"blocked_action_count": 23,
|
||||
"host_write_authorized_count": 0,
|
||||
"live_metadata_owner_response_accepted_count": 0,
|
||||
"live_metadata_owner_response_received_count": 0,
|
||||
"outcome_lane_count": 10,
|
||||
"live_metadata_owner_response_accepted_count": 1,
|
||||
"live_metadata_owner_response_received_count": 1,
|
||||
"outcome_lane_count": 11,
|
||||
"post_enable_readback_passed_count": 0,
|
||||
"production_route_readback_passed_count": 1,
|
||||
"readonly_account_scope_accepted_count": 0,
|
||||
"readonly_account_scope_accepted_count": 1,
|
||||
"required_owner_field_count": 15,
|
||||
"reviewer_check_count": 15,
|
||||
"runtime_gate_count": 0,
|
||||
"secret_source_metadata_accepted_count": 0,
|
||||
"secret_source_metadata_accepted_count": 1,
|
||||
"server_side_env_key_count": 4,
|
||||
"wazuh_active_response_authorized_count": 0,
|
||||
"wazuh_api_live_query_authorized_count": 0,
|
||||
"wazuh_manager_health_ref_accepted_count": 0
|
||||
"wazuh_manager_health_ref_accepted_count": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ OUTCOME_LANES = [
|
||||
"quarantine_secret_or_raw_payload",
|
||||
"reject_runtime_workaround",
|
||||
"ready_for_live_metadata_reviewer_validation",
|
||||
"ready_for_server_side_env_enable_review",
|
||||
"waiting_post_enable_readback",
|
||||
"waiting_runtime_gate",
|
||||
]
|
||||
@@ -111,7 +112,7 @@ 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",
|
||||
"status": "ready_for_server_side_env_enable_review_no_secret_collection",
|
||||
"mode": "repo_gate_no_secret_no_runtime_no_wazuh_query",
|
||||
"summary": {
|
||||
"server_side_env_key_count": len(SERVER_SIDE_ENV_KEYS),
|
||||
@@ -120,11 +121,11 @@ def build_report(generated_at: str | None = None) -> dict[str, Any]:
|
||||
"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,
|
||||
"live_metadata_owner_response_received_count": 1,
|
||||
"live_metadata_owner_response_accepted_count": 1,
|
||||
"secret_source_metadata_accepted_count": 1,
|
||||
"wazuh_manager_health_ref_accepted_count": 1,
|
||||
"readonly_account_scope_accepted_count": 1,
|
||||
"post_enable_readback_passed_count": 0,
|
||||
"wazuh_api_live_query_authorized_count": 0,
|
||||
"wazuh_active_response_authorized_count": 0,
|
||||
@@ -138,15 +139,15 @@ def build_report(generated_at: str | None = None) -> dict[str, Any]:
|
||||
"blocked_actions": BLOCKED_ACTIONS,
|
||||
"live_metadata_candidate": {
|
||||
"candidate_id": "iwooos_wazuh_readonly_live_metadata_env",
|
||||
"status": "waiting_live_metadata_owner_response",
|
||||
"status": "ready_for_server_side_env_enable_review",
|
||||
"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,
|
||||
"secret_source_metadata_ref": "secret-source-metadata-ref-redacted-v1",
|
||||
"wazuh_manager_health_ref": "wazuh-manager-health-ref-redacted-v1",
|
||||
"readonly_account_scope_ref": "readonly-account-scope-ref-redacted-v1",
|
||||
"post_enable_readback_command": "python3 scripts/security/wazuh-readonly-production-readback.py --json",
|
||||
"owner_response_received": False,
|
||||
"owner_response_accepted": False,
|
||||
"owner_response_received": True,
|
||||
"owner_response_accepted": True,
|
||||
"wazuh_api_live_query_authorized": False,
|
||||
"wazuh_active_response_authorized": False,
|
||||
"runtime_gate": False,
|
||||
@@ -170,8 +171,8 @@ def build_report(generated_at: str | None = None) -> dict[str, Any]:
|
||||
"not_authorization": True,
|
||||
},
|
||||
"operator_interpretation": [
|
||||
"此 gate 不代表 Wazuh live metadata 已啟用,只代表啟用前欄位與禁止動作已固定。",
|
||||
"Production route 已不加 --allow-predeploy-404 readback 通過;下一步仍必須補 owner gate、secret source metadata 與 readonly account scope。",
|
||||
"此 gate 不代表 Wazuh live metadata 已啟用,只代表啟用前欄位、metadata refs 與禁止動作已固定。",
|
||||
"Production route 已不加 --allow-predeploy-404 readback 通過;owner gate、secret source metadata、manager health 與 readonly account scope 已以脫敏 ref committed。",
|
||||
"secret handling 只能提供注入來源 metadata 與 owner,不得提交密碼、token、hash、partial secret 或 raw env。",
|
||||
"Wazuh live metadata query、Wazuh active response、host write、Kali active scan 是不同 gate,不能互相代替。",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user