Merge remote-tracking branch 'gitea/main' into codex/github-private-backup-readback-20260627
This commit is contained in:
@@ -26,6 +26,9 @@ from src.services.iwooos_wazuh_readonly_status import (
|
||||
from src.services.iwooos_wazuh_live_metadata_gate import (
|
||||
load_latest_iwooos_wazuh_live_metadata_gate,
|
||||
)
|
||||
from src.services.iwooos_wazuh_owner_evidence_preflight import (
|
||||
load_latest_iwooos_wazuh_owner_evidence_preflight,
|
||||
)
|
||||
from src.services.public_redaction import redact_public_lan_topology
|
||||
|
||||
|
||||
@@ -79,6 +82,34 @@ async def get_iwooos_wazuh_live_metadata_gate() -> dict[str, Any]:
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/api/v1/iwooos/wazuh-owner-evidence-preflight",
|
||||
response_model=dict[str, Any],
|
||||
summary="取得 Wazuh 負責人證據收件預檢讀回",
|
||||
description=(
|
||||
"讀取已提交的 Wazuh 代理清單負責人證據收件預檢,回傳公開安全的欄位數、"
|
||||
"審查檢查、分流、拒收內容計數與 0 / false 邊界。此端點不查 Wazuh、"
|
||||
"不讀主機、不保存原始載荷、不收機密明文、不啟用主動回應、不改 Nginx / "
|
||||
"Docker / K8s / firewall。"
|
||||
),
|
||||
)
|
||||
async def get_iwooos_wazuh_owner_evidence_preflight() -> dict[str, Any]:
|
||||
"""回傳 Wazuh manager registry 負責人證據收件預檢只讀狀態。"""
|
||||
try:
|
||||
payload = await asyncio.to_thread(load_latest_iwooos_wazuh_owner_evidence_preflight)
|
||||
return redact_public_lan_topology(payload)
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
except (json.JSONDecodeError, ValueError) as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"IwoooS Wazuh 負責人證據預檢無效:{exc}",
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/api/v1/iwooos/runtime-security-readback",
|
||||
response_model=dict[str, Any],
|
||||
|
||||
@@ -21,6 +21,7 @@ _SNAPSHOT_FILES = {
|
||||
"wazuh_coverage": "wazuh-managed-host-coverage-gate.snapshot.json",
|
||||
"wazuh_runtime": "wazuh-agent-visibility-runtime-gate.snapshot.json",
|
||||
"wazuh_live_metadata_gate": "wazuh-readonly-live-metadata-env-gate.snapshot.json",
|
||||
"wazuh_owner_evidence_preflight": "wazuh-agent-visibility-owner-evidence-preflight.snapshot.json",
|
||||
"kali_status": "kali-integration-status.snapshot.json",
|
||||
"soc_control": "soc-siem-kali-wazuh-integration-control.snapshot.json",
|
||||
"alert_readability": "telegram-alert-readability-guard.snapshot.json",
|
||||
@@ -33,6 +34,7 @@ _EXPECTED_SCHEMAS = {
|
||||
"wazuh_coverage": "wazuh_managed_host_coverage_gate_v1",
|
||||
"wazuh_runtime": "wazuh_agent_visibility_runtime_gate_v1",
|
||||
"wazuh_live_metadata_gate": "iwooos_wazuh_readonly_live_metadata_env_gate_v1",
|
||||
"wazuh_owner_evidence_preflight": "wazuh_agent_visibility_owner_evidence_preflight_v1",
|
||||
"kali_status": "kali_integration_status_v1",
|
||||
"soc_control": "soc_siem_kali_wazuh_integration_control_v1",
|
||||
"alert_readability": "telegram_alert_readability_guard_v1",
|
||||
@@ -73,6 +75,7 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
owner_gap_summary = _summary(snapshots["owner_gap"])
|
||||
wazuh_summary = _summary(snapshots["wazuh_coverage"])
|
||||
live_metadata_gate_summary = _summary(snapshots["wazuh_live_metadata_gate"])
|
||||
owner_evidence_preflight_summary = _summary(snapshots["wazuh_owner_evidence_preflight"])
|
||||
soc_summary = _summary(snapshots["soc_control"])
|
||||
alert_summary = _summary(snapshots["alert_readability"])
|
||||
dispatch_summary = _summary(snapshots["owner_dispatch"])
|
||||
@@ -95,7 +98,7 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
"source_refs": source_refs,
|
||||
"summary": {
|
||||
"source_snapshot_count": len(source_refs),
|
||||
"p0_lane_count": 8,
|
||||
"p0_lane_count": 9,
|
||||
"control_plane_visibility_percent": _average_percent(
|
||||
soc_summary.get("coverage_percent_after_soc_integration_control"),
|
||||
intrusion_summary.get("coverage_percent_after_prevention_control"),
|
||||
@@ -139,6 +142,36 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
"wazuh_live_metadata_gate_live_query_authorized_count": _int(
|
||||
live_metadata_gate_summary.get("wazuh_api_live_query_authorized_count")
|
||||
),
|
||||
"wazuh_owner_evidence_required_field_count": _int(
|
||||
owner_evidence_preflight_summary.get("required_field_count")
|
||||
),
|
||||
"wazuh_owner_evidence_reviewer_check_count": _int(
|
||||
owner_evidence_preflight_summary.get("reviewer_check_count")
|
||||
),
|
||||
"wazuh_owner_evidence_outcome_lane_count": _int(
|
||||
owner_evidence_preflight_summary.get("outcome_lane_count")
|
||||
),
|
||||
"wazuh_owner_evidence_forbidden_payload_count": _int(
|
||||
owner_evidence_preflight_summary.get("forbidden_payload_count")
|
||||
),
|
||||
"wazuh_owner_evidence_expected_alias_count": _int(
|
||||
owner_evidence_preflight_summary.get("expected_scope_alias_count")
|
||||
),
|
||||
"wazuh_owner_evidence_registry_export_received_count": _int(
|
||||
owner_evidence_preflight_summary.get("registry_export_received_count")
|
||||
),
|
||||
"wazuh_owner_evidence_registry_export_accepted_count": _int(
|
||||
owner_evidence_preflight_summary.get("registry_export_accepted_count")
|
||||
),
|
||||
"wazuh_owner_evidence_received_count": _int(
|
||||
owner_evidence_preflight_summary.get("owner_evidence_received_count")
|
||||
),
|
||||
"wazuh_owner_evidence_accepted_count": _int(
|
||||
owner_evidence_preflight_summary.get("owner_evidence_accepted_count")
|
||||
),
|
||||
"wazuh_owner_evidence_runtime_gate_count": _int(
|
||||
owner_evidence_preflight_summary.get("runtime_gate_count")
|
||||
),
|
||||
"kali_active_scan_authorized_count": _int(soc_summary.get("kali_active_scan_authorized_count")),
|
||||
"kali_execute_authorized_count": _int(soc_summary.get("kali_execute_authorized_count")),
|
||||
"kali_finding_envelope_accepted_count": _int(soc_summary.get("kali_finding_envelope_accepted_count")),
|
||||
@@ -206,6 +239,30 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
},
|
||||
["docs/security/wazuh-readonly-live-metadata-env-gate.snapshot.json"],
|
||||
),
|
||||
_lane(
|
||||
"wazuh_owner_evidence_preflight",
|
||||
snapshots["wazuh_owner_evidence_preflight"].get(
|
||||
"status",
|
||||
"owner_evidence_preflight_ready_no_runtime_action",
|
||||
),
|
||||
0,
|
||||
"locked",
|
||||
"補齊 manager registry 脫敏封包、逐主機矩陣、Dashboard API 狀態與負責人決策",
|
||||
{
|
||||
"required_fields": owner_evidence_preflight_summary.get("required_field_count", 0),
|
||||
"reviewer_checks": owner_evidence_preflight_summary.get("reviewer_check_count", 0),
|
||||
"outcome_lanes": owner_evidence_preflight_summary.get("outcome_lane_count", 0),
|
||||
"forbidden_payloads": owner_evidence_preflight_summary.get("forbidden_payload_count", 0),
|
||||
"owner_received": owner_evidence_preflight_summary.get("owner_evidence_received_count", 0),
|
||||
"owner_accepted": owner_evidence_preflight_summary.get("owner_evidence_accepted_count", 0),
|
||||
"registry_export_accepted": owner_evidence_preflight_summary.get(
|
||||
"registry_export_accepted_count",
|
||||
0,
|
||||
),
|
||||
"runtime_gate": owner_evidence_preflight_summary.get("runtime_gate_count", 0),
|
||||
},
|
||||
["docs/security/wazuh-agent-visibility-owner-evidence-preflight.snapshot.json"],
|
||||
),
|
||||
_lane(
|
||||
"wazuh_dashboard_api",
|
||||
"degraded_api_connection_not_green",
|
||||
@@ -303,6 +360,7 @@ def load_latest_iwooos_runtime_security_readback(
|
||||
"告警格式合約不代表通知已實發或已取得 receipt",
|
||||
"Wazuh 正式只讀路由 disabled 或退化時仍是 P0 紅燈",
|
||||
"Wazuh 即時中繼資料必須先通過負責人、機密中繼資料、唯讀範圍與啟用後讀回",
|
||||
"Wazuh 負責人證據預檢 ready 不代表已收件、已接受或可啟用 active response",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -421,6 +479,9 @@ def _require_runtime_boundaries(snapshots: dict[str, dict[str, Any]]) -> None:
|
||||
"secret_value_collection_allowed_count",
|
||||
"wazuh_api_live_query_authorized_count",
|
||||
"wazuh_active_response_authorized_count",
|
||||
"active_response_authorized_count",
|
||||
"registry_export_accepted_count",
|
||||
"owner_evidence_accepted_count",
|
||||
"post_enable_readback_passed_count",
|
||||
):
|
||||
if key in summary and _int(summary.get(key)) != 0:
|
||||
|
||||
264
apps/api/src/services/iwooos_wazuh_owner_evidence_preflight.py
Normal file
264
apps/api/src/services/iwooos_wazuh_owner_evidence_preflight.py
Normal file
@@ -0,0 +1,264 @@
|
||||
"""
|
||||
IwoooS Wazuh owner evidence preflight readback.
|
||||
|
||||
This module only exposes committed, public-safe preflight metadata. It never
|
||||
queries Wazuh, never reads secret values, and never authorizes active response,
|
||||
host writes, scans, restarts, reloads, or gateway changes.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from src.services.snapshot_paths import default_security_dir
|
||||
|
||||
_DEFAULT_SECURITY_DIR = default_security_dir(Path(__file__))
|
||||
_SNAPSHOT_FILE = "wazuh-agent-visibility-owner-evidence-preflight.snapshot.json"
|
||||
_EXPECTED_SCHEMA = "wazuh_agent_visibility_owner_evidence_preflight_v1"
|
||||
|
||||
_REQUIRED_FALSE_BOUNDARIES = {
|
||||
"agent_identity_public_display_allowed",
|
||||
"host_write_authorized",
|
||||
"internal_ip_public_display_allowed",
|
||||
"raw_wazuh_payload_storage_allowed",
|
||||
"runtime_execution_authorized",
|
||||
"secret_value_collection_allowed",
|
||||
"wazuh_active_response_authorized",
|
||||
"wazuh_api_live_query_authorized",
|
||||
}
|
||||
|
||||
|
||||
def load_latest_iwooos_wazuh_owner_evidence_preflight(
|
||||
security_dir: Path | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Load the committed Wazuh owner evidence preflight as a public-safe payload."""
|
||||
directory = security_dir or _DEFAULT_SECURITY_DIR
|
||||
snapshot = _load_snapshot(directory)
|
||||
_require_boundaries(snapshot)
|
||||
|
||||
summary = _summary(snapshot)
|
||||
contract = snapshot.get("registry_export_contract")
|
||||
contract = contract if isinstance(contract, dict) else {}
|
||||
merged_summary = {
|
||||
"required_field_count": _int(summary.get("required_field_count")),
|
||||
"reviewer_check_count": _int(summary.get("reviewer_check_count")),
|
||||
"outcome_lane_count": _int(summary.get("outcome_lane_count")),
|
||||
"forbidden_payload_count": _int(summary.get("forbidden_payload_count")),
|
||||
"expected_scope_alias_count": _int(summary.get("expected_scope_alias_count")),
|
||||
"per_host_required_field_count": _int(summary.get("per_host_required_field_count")),
|
||||
"allowed_collection_method_count": _len(contract.get("allowed_collection_methods")),
|
||||
"registry_export_received_count": _int(summary.get("registry_export_received_count")),
|
||||
"registry_export_accepted_count": _int(summary.get("registry_export_accepted_count")),
|
||||
"owner_evidence_received_count": _int(summary.get("owner_evidence_received_count")),
|
||||
"owner_evidence_accepted_count": _int(summary.get("owner_evidence_accepted_count")),
|
||||
"owner_evidence_rejected_count": _int(summary.get("owner_evidence_rejected_count")),
|
||||
"owner_evidence_quarantined_count": _int(summary.get("owner_evidence_quarantined_count")),
|
||||
"runtime_gate_count": _int(summary.get("runtime_gate_count")),
|
||||
"wazuh_api_live_query_authorized_count": 0,
|
||||
"active_response_authorized_count": _int(summary.get("active_response_authorized_count")),
|
||||
"host_write_authorized_count": _int(summary.get("host_write_authorized_count")),
|
||||
"secret_value_collection_allowed_count": _int(summary.get("secret_value_collection_allowed_count")),
|
||||
}
|
||||
|
||||
return {
|
||||
"schema_version": "iwooos_wazuh_owner_evidence_preflight_readback_v1",
|
||||
"status": snapshot.get("status", "owner_evidence_preflight_ready_no_runtime_action"),
|
||||
"mode": "committed_snapshot_readback_redacted_metadata_only",
|
||||
"source_refs": [
|
||||
f"docs/security/{_SNAPSHOT_FILE}",
|
||||
"scripts/security/wazuh-agent-visibility-owner-evidence-preflight.py",
|
||||
],
|
||||
"summary": merged_summary,
|
||||
"items": _items(merged_summary),
|
||||
"boundary_markers": _boundary_markers(merged_summary),
|
||||
"boundaries": {
|
||||
"wazuh_api_live_query_authorized": False,
|
||||
"wazuh_active_response_authorized": False,
|
||||
"host_write_authorized": False,
|
||||
"secret_value_collection_allowed": False,
|
||||
"raw_wazuh_payload_storage_allowed": False,
|
||||
"agent_identity_public_display_allowed": False,
|
||||
"internal_ip_public_display_allowed": False,
|
||||
"runtime_execution_authorized": False,
|
||||
"not_authorization": True,
|
||||
},
|
||||
"no_false_green_rules": [
|
||||
"負責人證據預檢 ready 不代表已收件或已接受",
|
||||
"Wazuh 儀表板可見不是 manager registry counts 已驗收",
|
||||
"Dashboard index pattern 三綠勾不可替代 API connection、API version 或 manager registry",
|
||||
"agent service active、TCP 連線或舊截圖不可替代逐主機 registry matrix",
|
||||
"收件封包若夾帶原始紀錄、內網識別、agent 原名或機密,必須隔離,不得渲染到前台",
|
||||
"active response、host write、firewall、Nginx、Docker、K8s 或 secret 變更一律不是這個預檢授權",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _load_snapshot(directory: Path) -> dict[str, Any]:
|
||||
path = directory / _SNAPSHOT_FILE
|
||||
if not path.is_file():
|
||||
raise FileNotFoundError(f"{path}: Wazuh 負責人證據預檢快照不存在")
|
||||
with path.open(encoding="utf-8") as handle:
|
||||
payload = json.load(handle)
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError(f"{path}: expected JSON object")
|
||||
if payload.get("schema_version") != _EXPECTED_SCHEMA:
|
||||
raise ValueError(f"{path}: expected schema_version={_EXPECTED_SCHEMA}")
|
||||
return payload
|
||||
|
||||
|
||||
def _summary(payload: dict[str, Any]) -> dict[str, Any]:
|
||||
summary = payload.get("summary")
|
||||
return summary if isinstance(summary, dict) else {}
|
||||
|
||||
|
||||
def _int(value: Any) -> int:
|
||||
return value if isinstance(value, int) else 0
|
||||
|
||||
|
||||
def _len(value: Any) -> int:
|
||||
return len(value) if isinstance(value, list) else 0
|
||||
|
||||
|
||||
def _items(summary: dict[str, int]) -> list[dict[str, Any]]:
|
||||
return [
|
||||
_item(
|
||||
"scope_aliases",
|
||||
"EV-0",
|
||||
"scope_aliases_ready",
|
||||
"warn",
|
||||
{
|
||||
"expected_scope_aliases": summary["expected_scope_alias_count"],
|
||||
"allowed_collection_methods": summary["allowed_collection_method_count"],
|
||||
},
|
||||
),
|
||||
_item(
|
||||
"registry_counts",
|
||||
"EV-1",
|
||||
"waiting_redacted_counts",
|
||||
"warn",
|
||||
{
|
||||
"registry_export_received": summary["registry_export_received_count"],
|
||||
"registry_export_accepted": summary["registry_export_accepted_count"],
|
||||
},
|
||||
),
|
||||
_item(
|
||||
"per_host_matrix",
|
||||
"EV-2",
|
||||
"waiting_per_host_matrix",
|
||||
"warn",
|
||||
{"per_host_required_fields": summary["per_host_required_field_count"]},
|
||||
),
|
||||
_item(
|
||||
"time_window",
|
||||
"EV-3",
|
||||
"waiting_time_window",
|
||||
"warn",
|
||||
{"owner_received": summary["owner_evidence_received_count"]},
|
||||
),
|
||||
_item(
|
||||
"health_refs",
|
||||
"EV-4",
|
||||
"waiting_health_refs",
|
||||
"warn",
|
||||
{"reviewer_checks": summary["reviewer_check_count"]},
|
||||
),
|
||||
_item(
|
||||
"redaction",
|
||||
"EV-5",
|
||||
"reject_sensitive_payloads",
|
||||
"locked",
|
||||
{
|
||||
"forbidden_payloads": summary["forbidden_payload_count"],
|
||||
"quarantined": summary["owner_evidence_quarantined_count"],
|
||||
},
|
||||
),
|
||||
_item(
|
||||
"owner_decision",
|
||||
"EV-6",
|
||||
"waiting_owner_decision",
|
||||
"warn",
|
||||
{
|
||||
"owner_received": summary["owner_evidence_received_count"],
|
||||
"owner_accepted": summary["owner_evidence_accepted_count"],
|
||||
},
|
||||
),
|
||||
_item(
|
||||
"runtime_boundary",
|
||||
"EV-7",
|
||||
"runtime_closed",
|
||||
"locked",
|
||||
{
|
||||
"runtime_gate": summary["runtime_gate_count"],
|
||||
"live_query": summary["wazuh_api_live_query_authorized_count"],
|
||||
"active_response": summary["active_response_authorized_count"],
|
||||
"host_write": summary["host_write_authorized_count"],
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def _item(
|
||||
item_id: str,
|
||||
check: str,
|
||||
state_key: str,
|
||||
tone: str,
|
||||
metrics: dict[str, int],
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"item_id": item_id,
|
||||
"check": check,
|
||||
"state_key": state_key,
|
||||
"tone": tone,
|
||||
"metrics": metrics,
|
||||
}
|
||||
|
||||
|
||||
def _boundary_markers(summary: dict[str, int]) -> list[str]:
|
||||
return [
|
||||
f"必要欄位={summary['required_field_count']}",
|
||||
f"審查檢查={summary['reviewer_check_count']}",
|
||||
f"結果分流={summary['outcome_lane_count']}",
|
||||
f"拒收敏感類型={summary['forbidden_payload_count']}",
|
||||
f"公開節點別名={summary['expected_scope_alias_count']}",
|
||||
f"逐主機矩陣欄位={summary['per_host_required_field_count']}",
|
||||
f"允許收集方式={summary['allowed_collection_method_count']}",
|
||||
f"registry export 已收件={summary['registry_export_received_count']}",
|
||||
f"registry export 已接受={summary['registry_export_accepted_count']}",
|
||||
f"負責人證據已收件={summary['owner_evidence_received_count']}",
|
||||
f"負責人證據已接受={summary['owner_evidence_accepted_count']}",
|
||||
f"負責人證據已隔離={summary['owner_evidence_quarantined_count']}",
|
||||
f"執行期閘門={summary['runtime_gate_count']}",
|
||||
f"Wazuh 即時查詢={summary['wazuh_api_live_query_authorized_count']}",
|
||||
f"Wazuh 主動回應={summary['active_response_authorized_count']}",
|
||||
f"主機寫入={summary['host_write_authorized_count']}",
|
||||
f"機密明文收集={summary['secret_value_collection_allowed_count']}",
|
||||
"原始 Wazuh 載荷保存=false",
|
||||
"agent 身分前台顯示=false",
|
||||
"內網識別前台顯示=false",
|
||||
"不是執行授權=true",
|
||||
]
|
||||
|
||||
|
||||
def _require_boundaries(payload: dict[str, Any]) -> None:
|
||||
summary = _summary(payload)
|
||||
for key in (
|
||||
"registry_export_accepted_count",
|
||||
"owner_evidence_accepted_count",
|
||||
"runtime_gate_count",
|
||||
"active_response_authorized_count",
|
||||
"host_write_authorized_count",
|
||||
"secret_value_collection_allowed_count",
|
||||
):
|
||||
if _int(summary.get(key)) != 0:
|
||||
raise ValueError(f"Wazuh 負責人證據預檢 summary.{key} 必須維持 0")
|
||||
|
||||
boundaries = payload.get("execution_boundaries")
|
||||
if not isinstance(boundaries, dict):
|
||||
raise ValueError("Wazuh 負責人證據預檢 execution_boundaries 缺失")
|
||||
for key in _REQUIRED_FALSE_BOUNDARIES:
|
||||
if boundaries.get(key) is not False:
|
||||
raise ValueError(f"Wazuh 負責人證據預檢 execution_boundaries.{key} 必須維持 false")
|
||||
if boundaries.get("not_authorization") is not True:
|
||||
raise ValueError("Wazuh 負責人證據預檢 not_authorization 必須維持 true")
|
||||
@@ -20,8 +20,8 @@ def test_iwooos_runtime_security_readback_preserves_zero_runtime_gates() -> None
|
||||
|
||||
assert payload["schema_version"] == "iwooos_runtime_security_readback_v1"
|
||||
assert payload["status"] == "blocked_waiting_owner_evidence_and_runtime_gates"
|
||||
assert payload["summary"]["source_snapshot_count"] == 9
|
||||
assert payload["summary"]["p0_lane_count"] == 8
|
||||
assert payload["summary"]["source_snapshot_count"] == 10
|
||||
assert payload["summary"]["p0_lane_count"] == 9
|
||||
assert payload["summary"]["runtime_gate_count"] == 0
|
||||
assert payload["summary"]["owner_response_received_count"] == 0
|
||||
assert payload["summary"]["owner_response_accepted_count"] == 0
|
||||
@@ -36,6 +36,16 @@ def test_iwooos_runtime_security_readback_preserves_zero_runtime_gates() -> None
|
||||
assert payload["summary"]["wazuh_live_metadata_gate_readonly_scope_accepted_count"] == 0
|
||||
assert payload["summary"]["wazuh_live_metadata_gate_post_enable_readback_count"] == 0
|
||||
assert payload["summary"]["wazuh_live_metadata_gate_live_query_authorized_count"] == 0
|
||||
assert payload["summary"]["wazuh_owner_evidence_required_field_count"] == 28
|
||||
assert payload["summary"]["wazuh_owner_evidence_reviewer_check_count"] == 15
|
||||
assert payload["summary"]["wazuh_owner_evidence_outcome_lane_count"] == 8
|
||||
assert payload["summary"]["wazuh_owner_evidence_forbidden_payload_count"] == 22
|
||||
assert payload["summary"]["wazuh_owner_evidence_expected_alias_count"] == 6
|
||||
assert payload["summary"]["wazuh_owner_evidence_registry_export_received_count"] == 0
|
||||
assert payload["summary"]["wazuh_owner_evidence_registry_export_accepted_count"] == 0
|
||||
assert payload["summary"]["wazuh_owner_evidence_received_count"] == 0
|
||||
assert payload["summary"]["wazuh_owner_evidence_accepted_count"] == 0
|
||||
assert payload["summary"]["wazuh_owner_evidence_runtime_gate_count"] == 0
|
||||
assert payload["summary"]["kali_active_scan_authorized_count"] == 0
|
||||
assert payload["summary"]["kali_execute_authorized_count"] == 0
|
||||
assert payload["summary"]["alert_receipt_runtime_send_count"] == 0
|
||||
@@ -53,6 +63,7 @@ def test_iwooos_runtime_security_readback_lanes_are_candidate_only() -> None:
|
||||
"wazuh_registry",
|
||||
"wazuh_live_route",
|
||||
"wazuh_live_metadata_gate",
|
||||
"wazuh_owner_evidence_preflight",
|
||||
"wazuh_dashboard_api",
|
||||
"kali_intake",
|
||||
"alert_readability",
|
||||
@@ -66,6 +77,7 @@ def test_iwooos_runtime_security_readback_lanes_are_candidate_only() -> None:
|
||||
assert all(lane["lane_id"] != "wazuh_registry" or lane["completion_percent"] == 0 for lane in payload["lanes"])
|
||||
assert all(lane["lane_id"] != "wazuh_live_route" or lane["metrics"]["route_degraded"] == 1 for lane in payload["lanes"])
|
||||
assert all(lane["lane_id"] != "wazuh_live_metadata_gate" or lane["completion_percent"] == 0 for lane in payload["lanes"])
|
||||
assert all(lane["lane_id"] != "wazuh_owner_evidence_preflight" or lane["metrics"]["owner_accepted"] == 0 for lane in payload["lanes"])
|
||||
|
||||
|
||||
def test_iwooos_runtime_security_readback_api_is_public_safe(monkeypatch) -> None:
|
||||
@@ -85,6 +97,8 @@ def test_iwooos_runtime_security_readback_api_is_public_safe(monkeypatch) -> Non
|
||||
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_live_query_authorized_count"] == 0
|
||||
assert data["summary"]["wazuh_owner_evidence_accepted_count"] == 0
|
||||
assert data["summary"]["wazuh_owner_evidence_runtime_gate_count"] == 0
|
||||
assert data["boundaries"]["secret_value_collection_allowed"] is False
|
||||
assert "192.168.0." not in response.text
|
||||
assert "工作視窗" not in response.text
|
||||
@@ -169,3 +183,44 @@ def test_iwooos_wazuh_live_metadata_gate_api_is_public_safe(monkeypatch) -> None
|
||||
assert "工作視窗" not in response.text
|
||||
assert "批准!繼續" not in response.text
|
||||
assert "WAZUH_API_PASSWORD" not in response.text
|
||||
|
||||
|
||||
def test_iwooos_wazuh_owner_evidence_preflight_api_is_public_safe(monkeypatch) -> None:
|
||||
monkeypatch.delenv("IWOOOS_WAZUH_READONLY_ENABLED", raising=False)
|
||||
monkeypatch.delenv("WAZUH_API_BASE_URL", raising=False)
|
||||
monkeypatch.delenv("WAZUH_API_USERNAME", raising=False)
|
||||
monkeypatch.delenv("WAZUH_API_PASSWORD", raising=False)
|
||||
|
||||
response = _client().get("/api/v1/iwooos/wazuh-owner-evidence-preflight")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["schema_version"] == "iwooos_wazuh_owner_evidence_preflight_readback_v1"
|
||||
assert data["status"] == "owner_evidence_preflight_ready_no_runtime_action"
|
||||
assert data["summary"]["required_field_count"] == 28
|
||||
assert data["summary"]["reviewer_check_count"] == 15
|
||||
assert data["summary"]["outcome_lane_count"] == 8
|
||||
assert data["summary"]["forbidden_payload_count"] == 22
|
||||
assert data["summary"]["expected_scope_alias_count"] == 6
|
||||
assert data["summary"]["per_host_required_field_count"] == 9
|
||||
assert data["summary"]["registry_export_received_count"] == 0
|
||||
assert data["summary"]["registry_export_accepted_count"] == 0
|
||||
assert data["summary"]["owner_evidence_received_count"] == 0
|
||||
assert data["summary"]["owner_evidence_accepted_count"] == 0
|
||||
assert data["summary"]["runtime_gate_count"] == 0
|
||||
assert data["summary"]["wazuh_api_live_query_authorized_count"] == 0
|
||||
assert data["summary"]["active_response_authorized_count"] == 0
|
||||
assert data["summary"]["host_write_authorized_count"] == 0
|
||||
assert data["summary"]["secret_value_collection_allowed_count"] == 0
|
||||
assert data["boundaries"]["wazuh_api_live_query_authorized"] is False
|
||||
assert data["boundaries"]["wazuh_active_response_authorized"] is False
|
||||
assert data["boundaries"]["host_write_authorized"] is False
|
||||
assert data["boundaries"]["runtime_execution_authorized"] is False
|
||||
assert data["boundaries"]["not_authorization"] is True
|
||||
assert len(data["items"]) == 8
|
||||
assert any(marker == "必要欄位=28" for marker in data["boundary_markers"])
|
||||
assert any(rule.startswith("負責人證據預檢 ready") for rule in data["no_false_green_rules"])
|
||||
assert "192.168.0." not in response.text
|
||||
assert "工作視窗" not in response.text
|
||||
assert "批准!繼續" not in response.text
|
||||
assert "WAZUH_API_PASSWORD" not in response.text
|
||||
|
||||
@@ -20300,7 +20300,7 @@
|
||||
},
|
||||
"runtimeSecurityReadback": {
|
||||
"eyebrow": "IwoooS Runtime 資安讀回",
|
||||
"title": "八條 P0 資安線先接到同一張讀回板",
|
||||
"title": "九條 P0 資安線先接到同一張讀回板",
|
||||
"subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全 aggregate 讀回;它不保存 raw Wazuh payload、不啟動掃描、不送訊息、不改主機。",
|
||||
"statusLabel": "讀回狀態",
|
||||
"statusDetail": "讀回成功只代表 IwoooS 能看見目前的證據邊界;runtime 寫入、主動回應、掃描、重啟、Nginx reload、workflow 修改與機密操作仍全部關閉。",
|
||||
@@ -20361,6 +20361,10 @@
|
||||
"title": "Wazuh 即時中繼資料閘門",
|
||||
"body": "正式路由讀回後仍必須補負責人回覆、機密來源中繼資料、管理節點健康、唯讀範圍與啟用後讀回;即時查詢授權維持 0。"
|
||||
},
|
||||
"wazuh_owner_evidence_preflight": {
|
||||
"title": "Wazuh 負責人證據預檢",
|
||||
"body": "把 manager registry 脫敏封包、逐主機矩陣、Dashboard API 狀態、拒收敏感類型與負責人決策先變成可驗收格式;收件、接受與執行期仍為 0。"
|
||||
},
|
||||
"wazuh_dashboard_api": {
|
||||
"title": "Wazuh Dashboard API",
|
||||
"body": "API connection / API version 還要補 readback;index pattern 通過不能宣稱 Wazuh 全綠。"
|
||||
@@ -20553,8 +20557,24 @@
|
||||
"subtitle": "這張卡把 Wazuh 管理器代理清單真相的必要欄位、審查檢查、拒收分流與禁止內容公開給操作員;目前尚未收到或接受任何負責人證據,也不授權主機操作。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"boundaryTitle": "Owner evidence 收件邊界",
|
||||
"loadingBoundary": "正在讀取負責人證據預檢",
|
||||
"boundaryTitle": "負責人證據收件邊界",
|
||||
"boundaryIntro": "以下鍵值固定:收件格式已準備好,且新增 6 個公開節點別名與逐主機匯出矩陣要求;registry export、已收件、已接受與執行閘門仍為 0。任何原始紀錄、未脫敏截圖、內網位址、代理原名或機密都必須拒收或隔離。",
|
||||
"status": {
|
||||
"loading": "正在讀取 Wazuh 負責人證據預檢",
|
||||
"failed": "Wazuh 負責人證據預檢尚未部署或讀取失敗",
|
||||
"ready": "Wazuh 負責人證據預檢已讀回,但收件、接受與執行期仍為 0"
|
||||
},
|
||||
"states": {
|
||||
"scope_aliases_ready": "公開別名已定義",
|
||||
"waiting_redacted_counts": "待脫敏計數",
|
||||
"waiting_per_host_matrix": "待逐主機矩陣",
|
||||
"waiting_time_window": "待時間窗",
|
||||
"waiting_health_refs": "待健康參照",
|
||||
"reject_sensitive_payloads": "拒收敏感內容",
|
||||
"waiting_owner_decision": "待負責人決策",
|
||||
"runtime_closed": "執行期關閉"
|
||||
},
|
||||
"summary": {
|
||||
"fields": {
|
||||
"label": "必要欄位",
|
||||
|
||||
@@ -20300,7 +20300,7 @@
|
||||
},
|
||||
"runtimeSecurityReadback": {
|
||||
"eyebrow": "IwoooS Runtime 資安讀回",
|
||||
"title": "八條 P0 資安線先接到同一張讀回板",
|
||||
"title": "九條 P0 資安線先接到同一張讀回板",
|
||||
"subtitle": "這張板讀取後端彙整的只讀快照,並附上 Wazuh 正式只讀路由的公開安全 aggregate 讀回;它不保存 raw Wazuh payload、不啟動掃描、不送訊息、不改主機。",
|
||||
"statusLabel": "讀回狀態",
|
||||
"statusDetail": "讀回成功只代表 IwoooS 能看見目前的證據邊界;runtime 寫入、主動回應、掃描、重啟、Nginx reload、workflow 修改與機密操作仍全部關閉。",
|
||||
@@ -20361,6 +20361,10 @@
|
||||
"title": "Wazuh 即時中繼資料閘門",
|
||||
"body": "正式路由讀回後仍必須補負責人回覆、機密來源中繼資料、管理節點健康、唯讀範圍與啟用後讀回;即時查詢授權維持 0。"
|
||||
},
|
||||
"wazuh_owner_evidence_preflight": {
|
||||
"title": "Wazuh 負責人證據預檢",
|
||||
"body": "把 manager registry 脫敏封包、逐主機矩陣、Dashboard API 狀態、拒收敏感類型與負責人決策先變成可驗收格式;收件、接受與執行期仍為 0。"
|
||||
},
|
||||
"wazuh_dashboard_api": {
|
||||
"title": "Wazuh Dashboard API",
|
||||
"body": "API connection / API version 還要補 readback;index pattern 通過不能宣稱 Wazuh 全綠。"
|
||||
@@ -20553,8 +20557,24 @@
|
||||
"subtitle": "這張卡把 Wazuh 管理器代理清單真相的必要欄位、審查檢查、拒收分流與禁止內容公開給操作員;目前尚未收到或接受任何負責人證據,也不授權主機操作。",
|
||||
"checkLabel": "檢核",
|
||||
"stateLabel": "狀態",
|
||||
"boundaryTitle": "Owner evidence 收件邊界",
|
||||
"loadingBoundary": "正在讀取負責人證據預檢",
|
||||
"boundaryTitle": "負責人證據收件邊界",
|
||||
"boundaryIntro": "以下鍵值固定:收件格式已準備好,且新增 6 個公開節點別名與逐主機匯出矩陣要求;registry export、已收件、已接受與執行閘門仍為 0。任何原始紀錄、未脫敏截圖、內網位址、代理原名或機密都必須拒收或隔離。",
|
||||
"status": {
|
||||
"loading": "正在讀取 Wazuh 負責人證據預檢",
|
||||
"failed": "Wazuh 負責人證據預檢尚未部署或讀取失敗",
|
||||
"ready": "Wazuh 負責人證據預檢已讀回,但收件、接受與執行期仍為 0"
|
||||
},
|
||||
"states": {
|
||||
"scope_aliases_ready": "公開別名已定義",
|
||||
"waiting_redacted_counts": "待脫敏計數",
|
||||
"waiting_per_host_matrix": "待逐主機矩陣",
|
||||
"waiting_time_window": "待時間窗",
|
||||
"waiting_health_refs": "待健康參照",
|
||||
"reject_sensitive_payloads": "拒收敏感內容",
|
||||
"waiting_owner_decision": "待負責人決策",
|
||||
"runtime_closed": "執行期關閉"
|
||||
},
|
||||
"summary": {
|
||||
"fields": {
|
||||
"label": "必要欄位",
|
||||
|
||||
@@ -40,6 +40,8 @@ import {
|
||||
type IwoooSSecurityControlCoverageResponse,
|
||||
type IwoooSWazuhLiveMetadataGateItem,
|
||||
type IwoooSWazuhLiveMetadataGateResponse,
|
||||
type IwoooSWazuhOwnerEvidencePreflightItem,
|
||||
type IwoooSWazuhOwnerEvidencePreflightResponse,
|
||||
} from '@/lib/api-client'
|
||||
|
||||
type PostureMetric = {
|
||||
@@ -2365,14 +2367,6 @@ const wazuhLiveMetadataEnvGateBoundaries = [
|
||||
'not_authorization=true',
|
||||
] as const
|
||||
|
||||
const wazuhOwnerEvidencePreflightSummary = [
|
||||
{ key: 'fields', value: '23', icon: ClipboardCheck, tone: 'steady' },
|
||||
{ key: 'aliases', value: '6', icon: Server, tone: 'warn' },
|
||||
{ key: 'checks', value: '10', icon: ListChecks, tone: 'steady' },
|
||||
{ key: 'received', value: '0', icon: FileWarning, tone: 'locked' },
|
||||
{ key: 'accepted', value: '0', icon: Lock, tone: 'locked' },
|
||||
] as const
|
||||
|
||||
const wazuhOwnerEvidencePreflightItems: WazuhOwnerEvidencePreflightItem[] = [
|
||||
{ key: 'scopeAliases', check: 'EV-0', state: '6 個別名', icon: Server, tone: 'warn' },
|
||||
{ key: 'registryCounts', check: 'EV-1', state: '待脫敏計數', icon: Server, tone: 'warn' },
|
||||
@@ -2384,14 +2378,25 @@ const wazuhOwnerEvidencePreflightItems: WazuhOwnerEvidencePreflightItem[] = [
|
||||
{ key: 'runtimeBoundary', check: 'EV-7', state: '不開執行', icon: Lock, tone: 'locked' },
|
||||
] as const
|
||||
|
||||
const wazuhOwnerEvidencePreflightItemKeyById: Record<IwoooSWazuhOwnerEvidencePreflightItem['item_id'], WazuhOwnerEvidencePreflightItem['key']> = {
|
||||
scope_aliases: 'scopeAliases',
|
||||
registry_counts: 'registryCounts',
|
||||
per_host_matrix: 'perHostMatrix',
|
||||
time_window: 'timeWindow',
|
||||
health_refs: 'healthRefs',
|
||||
redaction: 'redaction',
|
||||
owner_decision: 'ownerDecision',
|
||||
runtime_boundary: 'runtimeBoundary',
|
||||
}
|
||||
|
||||
const wazuhOwnerEvidencePreflightBoundaries = [
|
||||
'wazuh_agent_visibility_owner_evidence_preflight_visible=true',
|
||||
'wazuh_agent_visibility_owner_evidence_required_field_count=23',
|
||||
'wazuh_agent_visibility_owner_evidence_reviewer_check_count=10',
|
||||
'wazuh_agent_visibility_owner_evidence_required_field_count=28',
|
||||
'wazuh_agent_visibility_owner_evidence_reviewer_check_count=15',
|
||||
'wazuh_agent_visibility_owner_evidence_expected_scope_alias_count=6',
|
||||
'wazuh_agent_visibility_owner_evidence_per_host_required_field_count=9',
|
||||
'wazuh_agent_visibility_owner_evidence_outcome_lane_count=5',
|
||||
'wazuh_agent_visibility_owner_evidence_forbidden_payload_count=18',
|
||||
'wazuh_agent_visibility_owner_evidence_outcome_lane_count=8',
|
||||
'wazuh_agent_visibility_owner_evidence_forbidden_payload_count=22',
|
||||
'wazuh_agent_visibility_owner_evidence_registry_export_received_count=0',
|
||||
'wazuh_agent_visibility_owner_evidence_registry_export_accepted_count=0',
|
||||
'wazuh_agent_visibility_owner_evidence_received_count=0',
|
||||
@@ -9115,6 +9120,92 @@ function IwoooSWazuhLiveMetadataEnvGateBoard() {
|
||||
function IwoooSWazuhOwnerEvidencePreflightBoard() {
|
||||
const t = useTranslations('iwooos.wazuhOwnerEvidencePreflight')
|
||||
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
|
||||
const [data, setData] = useState<IwoooSWazuhOwnerEvidencePreflightResponse | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [failed, setFailed] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
let mounted = true
|
||||
|
||||
async function loadPreflight() {
|
||||
setLoading(true)
|
||||
setFailed(false)
|
||||
try {
|
||||
const payload = await apiClient.getIwoooSWazuhOwnerEvidencePreflight()
|
||||
if (mounted) {
|
||||
setData(payload)
|
||||
}
|
||||
} catch {
|
||||
if (mounted) {
|
||||
setData(null)
|
||||
setFailed(true)
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadPreflight()
|
||||
return () => {
|
||||
mounted = false
|
||||
}
|
||||
}, [])
|
||||
|
||||
const summary = data?.summary
|
||||
const summaryItems = [
|
||||
{
|
||||
key: 'fields',
|
||||
value: summary ? String(summary.required_field_count) : loading ? '...' : '28',
|
||||
icon: ClipboardCheck,
|
||||
tone: 'steady',
|
||||
},
|
||||
{
|
||||
key: 'aliases',
|
||||
value: summary ? String(summary.expected_scope_alias_count) : loading ? '...' : '6',
|
||||
icon: Server,
|
||||
tone: 'warn',
|
||||
},
|
||||
{
|
||||
key: 'checks',
|
||||
value: summary ? String(summary.reviewer_check_count) : loading ? '...' : '15',
|
||||
icon: ListChecks,
|
||||
tone: 'steady',
|
||||
},
|
||||
{
|
||||
key: 'received',
|
||||
value: summary ? String(summary.owner_evidence_received_count) : loading ? '...' : '0',
|
||||
icon: FileWarning,
|
||||
tone: 'locked',
|
||||
},
|
||||
{
|
||||
key: 'accepted',
|
||||
value: summary ? String(summary.owner_evidence_accepted_count) : loading ? '...' : '0',
|
||||
icon: Lock,
|
||||
tone: 'locked',
|
||||
},
|
||||
] as const
|
||||
const preflightItems = data?.items?.length
|
||||
? data.items.map(item => {
|
||||
const key = wazuhOwnerEvidencePreflightItemKeyById[item.item_id]
|
||||
const fallback = wazuhOwnerEvidencePreflightItems.find(candidate => candidate.key === key)
|
||||
return {
|
||||
key,
|
||||
check: item.check,
|
||||
state: t(`states.${item.state_key}` as never),
|
||||
icon: fallback?.icon ?? FileWarning,
|
||||
tone: item.tone,
|
||||
}
|
||||
})
|
||||
: wazuhOwnerEvidencePreflightItems
|
||||
const boundaryMarkers = data?.boundary_markers?.length
|
||||
? data.boundary_markers
|
||||
: loading
|
||||
? [t('loadingBoundary')]
|
||||
: wazuhOwnerEvidencePreflightBoundaries
|
||||
const statusText = loading ? t('status.loading') : failed ? t('status.failed') : t('status.ready')
|
||||
const statusTone: 'steady' | 'warn' | 'locked' = loading || failed ? 'warn' : 'locked'
|
||||
|
||||
return (
|
||||
<section
|
||||
@@ -9132,10 +9223,14 @@ function IwoooSWazuhOwnerEvidencePreflightBoard() {
|
||||
<p style={{ fontSize: 12, color: '#315a74', margin: '6px 0 0', lineHeight: 1.55, ...textWrap }}>
|
||||
{t('subtitle')}
|
||||
</p>
|
||||
<div style={{ marginTop: 8, display: 'inline-flex', alignItems: 'center', gap: 8, color: toneColors[statusTone], fontSize: 12, fontWeight: 700, ...textWrap }}>
|
||||
<ToneDot tone={statusTone} />
|
||||
{statusText}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(126px, 1fr))', gap: 8 }}>
|
||||
{wazuhOwnerEvidencePreflightSummary.map(item => {
|
||||
{summaryItems.map(item => {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<div key={item.key} style={{ border: '0.5px solid #c8dbea', borderRadius: 8, padding: 12, background: '#fff' }}>
|
||||
@@ -9163,7 +9258,7 @@ function IwoooSWazuhOwnerEvidencePreflightBoard() {
|
||||
gap: 10,
|
||||
}}
|
||||
>
|
||||
{wazuhOwnerEvidencePreflightItems.map(item => {
|
||||
{preflightItems.map(item => {
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<div
|
||||
@@ -9219,7 +9314,7 @@ function IwoooSWazuhOwnerEvidencePreflightBoard() {
|
||||
{t('boundaryIntro')}
|
||||
</p>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 6 }}>
|
||||
{wazuhOwnerEvidencePreflightBoundaries.map(item => (
|
||||
{boundaryMarkers.map(item => (
|
||||
<code
|
||||
key={item}
|
||||
style={{
|
||||
|
||||
@@ -102,6 +102,7 @@ export interface IwoooSRuntimeSecurityReadbackLane {
|
||||
| 'wazuh_registry'
|
||||
| 'wazuh_live_route'
|
||||
| 'wazuh_live_metadata_gate'
|
||||
| 'wazuh_owner_evidence_preflight'
|
||||
| 'wazuh_dashboard_api'
|
||||
| 'kali_intake'
|
||||
| 'alert_readability'
|
||||
@@ -148,6 +149,16 @@ export interface IwoooSRuntimeSecurityReadbackResponse {
|
||||
wazuh_live_metadata_gate_readonly_scope_accepted_count: number
|
||||
wazuh_live_metadata_gate_post_enable_readback_count: number
|
||||
wazuh_live_metadata_gate_live_query_authorized_count: number
|
||||
wazuh_owner_evidence_required_field_count: number
|
||||
wazuh_owner_evidence_reviewer_check_count: number
|
||||
wazuh_owner_evidence_outcome_lane_count: number
|
||||
wazuh_owner_evidence_forbidden_payload_count: number
|
||||
wazuh_owner_evidence_expected_alias_count: number
|
||||
wazuh_owner_evidence_registry_export_received_count: number
|
||||
wazuh_owner_evidence_registry_export_accepted_count: number
|
||||
wazuh_owner_evidence_received_count: number
|
||||
wazuh_owner_evidence_accepted_count: number
|
||||
wazuh_owner_evidence_runtime_gate_count: number
|
||||
kali_active_scan_authorized_count: number
|
||||
kali_execute_authorized_count: number
|
||||
kali_finding_envelope_accepted_count: number
|
||||
@@ -210,6 +221,53 @@ export interface IwoooSWazuhLiveMetadataGateResponse {
|
||||
no_false_green_rules: string[]
|
||||
}
|
||||
|
||||
export interface IwoooSWazuhOwnerEvidencePreflightItem {
|
||||
item_id:
|
||||
| 'scope_aliases'
|
||||
| 'registry_counts'
|
||||
| 'per_host_matrix'
|
||||
| 'time_window'
|
||||
| 'health_refs'
|
||||
| 'redaction'
|
||||
| 'owner_decision'
|
||||
| 'runtime_boundary'
|
||||
check: string
|
||||
state_key: string
|
||||
tone: IwoooSRuntimeSecurityReadbackTone
|
||||
metrics: Record<string, number>
|
||||
}
|
||||
|
||||
export interface IwoooSWazuhOwnerEvidencePreflightResponse {
|
||||
schema_version: 'iwooos_wazuh_owner_evidence_preflight_readback_v1'
|
||||
status: string
|
||||
mode: string
|
||||
source_refs: string[]
|
||||
summary: {
|
||||
required_field_count: number
|
||||
reviewer_check_count: number
|
||||
outcome_lane_count: number
|
||||
forbidden_payload_count: number
|
||||
expected_scope_alias_count: number
|
||||
per_host_required_field_count: number
|
||||
allowed_collection_method_count: number
|
||||
registry_export_received_count: number
|
||||
registry_export_accepted_count: number
|
||||
owner_evidence_received_count: number
|
||||
owner_evidence_accepted_count: number
|
||||
owner_evidence_rejected_count: number
|
||||
owner_evidence_quarantined_count: number
|
||||
runtime_gate_count: number
|
||||
wazuh_api_live_query_authorized_count: number
|
||||
active_response_authorized_count: number
|
||||
host_write_authorized_count: number
|
||||
secret_value_collection_allowed_count: number
|
||||
}
|
||||
items: IwoooSWazuhOwnerEvidencePreflightItem[]
|
||||
boundary_markers: string[]
|
||||
boundaries: Record<string, boolean>
|
||||
no_false_green_rules: string[]
|
||||
}
|
||||
|
||||
export interface IwoooSSecurityControlCoverageDomain {
|
||||
domain_id:
|
||||
| 'high_value_asset_control'
|
||||
@@ -320,6 +378,11 @@ export const apiClient = {
|
||||
return handleResponse<IwoooSWazuhLiveMetadataGateResponse>(res)
|
||||
},
|
||||
|
||||
async getIwoooSWazuhOwnerEvidencePreflight() {
|
||||
const res = await fetch(`${API_BASE_URL}/iwooos/wazuh-owner-evidence-preflight`, { cache: 'no-store' })
|
||||
return handleResponse<IwoooSWazuhOwnerEvidencePreflightResponse>(res)
|
||||
},
|
||||
|
||||
async getIwoooSSecurityControlCoverage() {
|
||||
const res = await fetch(`${API_BASE_URL}/iwooos/security-control-coverage`, { cache: 'no-store' })
|
||||
return handleResponse<IwoooSSecurityControlCoverageResponse>(res)
|
||||
|
||||
@@ -29513,9 +29513,12 @@ def validate(root: Path) -> None:
|
||||
for expected in [
|
||||
"iwooos-wazuh-owner-evidence-preflight-board",
|
||||
"wazuhOwnerEvidencePreflight",
|
||||
"wazuh_agent_visibility_owner_evidence_required_field_count=23",
|
||||
"wazuh_agent_visibility_owner_evidence_required_field_count=28",
|
||||
"wazuh_agent_visibility_owner_evidence_reviewer_check_count=15",
|
||||
"wazuh_agent_visibility_owner_evidence_expected_scope_alias_count=6",
|
||||
"wazuh_agent_visibility_owner_evidence_per_host_required_field_count=9",
|
||||
"wazuh_agent_visibility_owner_evidence_outcome_lane_count=8",
|
||||
"wazuh_agent_visibility_owner_evidence_forbidden_payload_count=22",
|
||||
"wazuh_agent_visibility_owner_evidence_registry_export_received_count=0",
|
||||
"wazuh_agent_visibility_owner_evidence_registry_export_accepted_count=0",
|
||||
"wazuh_agent_visibility_owner_evidence_runtime_gate_count=0",
|
||||
|
||||
Reference in New Issue
Block a user