fix(iwooos): add security tool closure readback
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 3m55s
CD Pipeline / build-and-deploy (push) Has started running
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 3m55s
CD Pipeline / build-and-deploy (push) Has started running
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -34,6 +34,9 @@ from src.services.iwooos_security_operating_system import (
|
||||
from src.services.iwooos_security_control_coverage import (
|
||||
load_latest_iwooos_security_control_coverage,
|
||||
)
|
||||
from src.services.iwooos_security_tool_closure_readback import (
|
||||
load_latest_iwooos_security_tool_closure_readback,
|
||||
)
|
||||
from src.services.iwooos_wazuh_allowlisted_check_mode_dry_run import (
|
||||
load_latest_iwooos_wazuh_allowlisted_check_mode_dry_run,
|
||||
)
|
||||
@@ -702,6 +705,38 @@ async def get_iwooos_runtime_security_readback() -> dict[str, Any]:
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/api/v1/iwooos/security-tool-closure-readback",
|
||||
response_model=dict[str, Any],
|
||||
summary="取得 IwoooS 資安工具閉環讀回",
|
||||
description=(
|
||||
"彙整 Wazuh、SBOM / vulnerability、source policy、K8s policy、runtime detection、"
|
||||
"DAST、Sigma / OCSF 與 AI controlled apply 的 committed readback,形成公開安全的"
|
||||
"工具閉環控制台。此端點不查 live host、不讀 secret、不執行 scanner、不送 SOAR、"
|
||||
"不啟用 active response、不開 runtime gate。"
|
||||
),
|
||||
)
|
||||
async def get_iwooos_security_tool_closure_readback() -> dict[str, Any]:
|
||||
"""回傳 IwoooS 資安工具閉環公開安全只讀總表。"""
|
||||
try:
|
||||
alert_receipt_readback = await _alertmanager_receipt_readback()
|
||||
payload = await asyncio.to_thread(
|
||||
load_latest_iwooos_security_tool_closure_readback,
|
||||
alert_receipt_readback=alert_receipt_readback,
|
||||
)
|
||||
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 security tool closure readback 無效:{exc}",
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/api/v1/iwooos/security-control-coverage",
|
||||
response_model=dict[str, Any],
|
||||
|
||||
511
apps/api/src/services/iwooos_security_tool_closure_readback.py
Normal file
511
apps/api/src/services/iwooos_security_tool_closure_readback.py
Normal file
@@ -0,0 +1,511 @@
|
||||
"""
|
||||
IwoooS security tool closure readback.
|
||||
|
||||
This service joins the committed Wazuh, security operating-system and coverage
|
||||
readbacks into a public-safe tool closure cockpit. It does not query live hosts,
|
||||
read secrets, run scanners, trigger SOAR, or authorize runtime actions.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from src.services.iwooos_security_control_coverage import (
|
||||
load_latest_iwooos_security_control_coverage,
|
||||
)
|
||||
from src.services.iwooos_security_operating_system import (
|
||||
load_latest_iwooos_security_operating_system,
|
||||
)
|
||||
from src.services.iwooos_wazuh_allowlisted_check_mode_dry_run import (
|
||||
load_latest_iwooos_wazuh_allowlisted_check_mode_dry_run,
|
||||
)
|
||||
from src.services.iwooos_wazuh_managed_host_coverage import (
|
||||
load_latest_iwooos_wazuh_managed_host_coverage,
|
||||
)
|
||||
from src.services.iwooos_wazuh_manager_registry_reviewer_validation import (
|
||||
load_latest_iwooos_wazuh_manager_registry_reviewer_validation,
|
||||
)
|
||||
from src.services.iwooos_wazuh_runtime_controlled_apply_preflight import (
|
||||
load_latest_iwooos_wazuh_runtime_controlled_apply_preflight,
|
||||
)
|
||||
from src.services.iwooos_wazuh_runtime_gate_owner_review_readback import (
|
||||
load_latest_iwooos_wazuh_runtime_gate_owner_review_readback,
|
||||
)
|
||||
|
||||
_SCHEMA_VERSION = "iwooos_security_tool_closure_readback_v1"
|
||||
_REQUIRED_ZERO_SUMMARY_KEYS = {
|
||||
"runtime_gate_count",
|
||||
"host_write_authorized_count",
|
||||
"active_response_authorized_count",
|
||||
"wazuh_active_response_authorized_count",
|
||||
"secret_value_collection_allowed_count",
|
||||
"secret_value_collected_count",
|
||||
}
|
||||
|
||||
|
||||
def load_latest_iwooos_security_tool_closure_readback(
|
||||
alert_receipt_readback: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Return the public-safe external tool closure rollup."""
|
||||
coverage = load_latest_iwooos_security_control_coverage()
|
||||
security_os = load_latest_iwooos_security_operating_system(
|
||||
alert_receipt_readback=alert_receipt_readback
|
||||
)
|
||||
managed_hosts = load_latest_iwooos_wazuh_managed_host_coverage()
|
||||
registry = load_latest_iwooos_wazuh_manager_registry_reviewer_validation()
|
||||
controlled_apply = load_latest_iwooos_wazuh_runtime_controlled_apply_preflight()
|
||||
owner_review = load_latest_iwooos_wazuh_runtime_gate_owner_review_readback()
|
||||
dry_run = load_latest_iwooos_wazuh_allowlisted_check_mode_dry_run()
|
||||
|
||||
source_payloads = [
|
||||
coverage,
|
||||
security_os,
|
||||
managed_hosts,
|
||||
registry,
|
||||
controlled_apply,
|
||||
owner_review,
|
||||
dry_run,
|
||||
]
|
||||
_require_runtime_boundaries(source_payloads)
|
||||
|
||||
source_summaries = {
|
||||
"coverage": _summary(coverage),
|
||||
"security_os": _summary(security_os),
|
||||
"managed_hosts": _summary(managed_hosts),
|
||||
"registry": _summary(registry),
|
||||
"controlled_apply": _summary(controlled_apply),
|
||||
"owner_review": _summary(owner_review),
|
||||
"dry_run": _summary(dry_run),
|
||||
}
|
||||
tracks = _tool_tracks(source_summaries)
|
||||
summary = _summary_rollup(source_summaries, tracks)
|
||||
|
||||
return {
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"status": "tool_closure_readback_ready_runtime_actions_closed",
|
||||
"mode": "committed_readback_rollup_no_live_tool_execution",
|
||||
"summary": summary,
|
||||
"tool_tracks": tracks,
|
||||
"next_executable_queue": _next_executable_queue(source_summaries),
|
||||
"acceptance_definition": [
|
||||
"wazuh_registry_fim_vulnerability_alert_receipt_green_with_post_verifier",
|
||||
"sbom_and_vulnerability_reports_attached_to_package_and_image_artifacts",
|
||||
"runtime_detection_events_normalized_and_reviewed_without_auto_block",
|
||||
"web_api_dast_scope_rate_limit_and_baseline_report_closed",
|
||||
"ai_controlled_apply_has_selector_diff_check_mode_rollback_post_verifier_km_writeback",
|
||||
],
|
||||
"boundary_markers": _boundary_markers(summary),
|
||||
"boundaries": {
|
||||
"live_host_query_performed": False,
|
||||
"live_wazuh_query_performed": False,
|
||||
"scanner_execution_performed": False,
|
||||
"payload_persisted": False,
|
||||
"runtime_execution_authorized": False,
|
||||
"runtime_gate_open": False,
|
||||
"host_write_authorized": False,
|
||||
"wazuh_active_response_authorized": False,
|
||||
"soar_action_authorized": False,
|
||||
"secret_value_collection_allowed": False,
|
||||
"not_authorization": True,
|
||||
},
|
||||
"no_false_green_rules": [
|
||||
"tool closure readback is a cockpit rollup, not an active scanner or SOAR switch",
|
||||
"Wazuh manager registry accepted does not close FIM, vulnerability, alert receipt, or active response",
|
||||
"SBOM, DAST, runtime detection and policy tracks remain not closed until artifacts and post-verifiers exist",
|
||||
"runtime gate, host write, active response and secret collection must remain zero until a separate post-verifier gate passes",
|
||||
],
|
||||
"source_refs": [
|
||||
*coverage.get("source_refs", []),
|
||||
*security_os.get("source_refs", []),
|
||||
*managed_hosts.get("source_refs", []),
|
||||
*registry.get("source_refs", []),
|
||||
*controlled_apply.get("source_refs", []),
|
||||
*owner_review.get("source_refs", []),
|
||||
*dry_run.get("source_refs", []),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _tool_tracks(source_summaries: dict[str, dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
coverage = source_summaries["coverage"]
|
||||
security_os = source_summaries["security_os"]
|
||||
managed_hosts = source_summaries["managed_hosts"]
|
||||
registry = source_summaries["registry"]
|
||||
controlled_apply = source_summaries["controlled_apply"]
|
||||
owner_review = source_summaries["owner_review"]
|
||||
dry_run = source_summaries["dry_run"]
|
||||
|
||||
expected_hosts = max(
|
||||
_int(managed_hosts.get("expected_host_scope_count")),
|
||||
_int(registry.get("expected_scope_alias_count")),
|
||||
_int(coverage.get("wazuh_expected_host_scope_count")),
|
||||
)
|
||||
accepted_hosts = max(
|
||||
_int(managed_hosts.get("manager_registry_accepted_count")),
|
||||
_int(registry.get("manager_registry_accepted_count")),
|
||||
_int(coverage.get("wazuh_manager_registry_accepted_count")),
|
||||
_int(security_os.get("wazuh_registry_accepted_count")),
|
||||
)
|
||||
registry_ready = expected_hosts > 0 and accepted_hosts >= expected_hosts
|
||||
alert_ready = _int(security_os.get("alert_receipt_accepted_count")) > 0
|
||||
|
||||
controlled_apply_ready_signals = sum(
|
||||
1
|
||||
for key in (
|
||||
"target_selector_count",
|
||||
"source_of_truth_diff_count",
|
||||
"check_mode_plan_count",
|
||||
"rollback_plan_count",
|
||||
"post_apply_verifier_count",
|
||||
"km_playbook_writeback_count",
|
||||
"controlled_apply_preflight_ready_count",
|
||||
)
|
||||
if _int(controlled_apply.get(key)) > 0
|
||||
)
|
||||
owner_review_ready_signals = sum(
|
||||
1
|
||||
for key in (
|
||||
"target_selector_count",
|
||||
"source_of_truth_diff_count",
|
||||
"check_mode_plan_count",
|
||||
"dry_run_evidence_count",
|
||||
"rollback_plan_count",
|
||||
"post_apply_verifier_count",
|
||||
"km_playbook_writeback_count",
|
||||
"owner_review_packet_review_ready_count",
|
||||
)
|
||||
if _int(owner_review.get(key)) > 0
|
||||
)
|
||||
dry_run_ready_signals = sum(
|
||||
1
|
||||
for key in (
|
||||
"allowlisted_target_selector_count",
|
||||
"check_mode_plan_count",
|
||||
"dry_run_evidence_ref_count",
|
||||
"dry_run_result_ref_count",
|
||||
"post_dry_run_verifier_count",
|
||||
"rollback_revalidation_count",
|
||||
"km_playbook_writeback_ready_count",
|
||||
)
|
||||
if _int(dry_run.get(key)) > 0
|
||||
)
|
||||
|
||||
return [
|
||||
_track(
|
||||
track_id="wazuh_detection_response",
|
||||
priority="P0",
|
||||
label="Wazuh detection and response",
|
||||
tool_ids=["wazuh"],
|
||||
ready_signal_count=(1 if registry_ready else 0) + (1 if alert_ready else 0),
|
||||
required_signal_count=6,
|
||||
next_executable_action="close_fim_vulnerability_alert_receipt_then_keep_active_response_gated",
|
||||
required_verifier="wazuh_registry_fim_vulnerability_alert_receipt_post_verifier",
|
||||
source_refs=[
|
||||
"docs/security/wazuh-managed-host-coverage-gate.snapshot.json",
|
||||
"docs/security/iwooos-security-operating-system.snapshot.json",
|
||||
],
|
||||
),
|
||||
_track(
|
||||
track_id="supply_chain_sbom_scan",
|
||||
priority="P0",
|
||||
label="Supply-chain SBOM and vulnerability scan",
|
||||
tool_ids=["trivy", "syft", "grype"],
|
||||
ready_signal_count=0,
|
||||
required_signal_count=5,
|
||||
next_executable_action="attach_sbom_vulnerability_report_and_no_secret_output_guard",
|
||||
required_verifier="sbom_vulnerability_artifact_post_verifier",
|
||||
source_refs=["docs/security/security-asset-control-ledger.snapshot.json"],
|
||||
),
|
||||
_track(
|
||||
track_id="source_control_scorecard",
|
||||
priority="P1",
|
||||
label="Source-control hygiene scorecard",
|
||||
tool_ids=["openssf_scorecard", "gitea_source_policy"],
|
||||
ready_signal_count=0,
|
||||
required_signal_count=4,
|
||||
next_executable_action="map_branch_protection_dependency_update_and_build_policy_readback",
|
||||
required_verifier="source_control_policy_scorecard_verifier",
|
||||
source_refs=["docs/evaluations/runtime_surface_inventory_latest"],
|
||||
),
|
||||
_track(
|
||||
track_id="k8s_policy_attestation",
|
||||
priority="P1",
|
||||
label="Kubernetes policy and image attestation",
|
||||
tool_ids=["kyverno", "cosign"],
|
||||
ready_signal_count=0,
|
||||
required_signal_count=5,
|
||||
next_executable_action="stage_policy_check_mode_image_signature_and_exception_register",
|
||||
required_verifier="k8s_policy_attestation_post_verifier",
|
||||
source_refs=["docs/security/host-service-config-inventory.snapshot.json"],
|
||||
),
|
||||
_track(
|
||||
track_id="runtime_threat_detection",
|
||||
priority="P1",
|
||||
label="Runtime threat detection",
|
||||
tool_ids=["falco"],
|
||||
ready_signal_count=0,
|
||||
required_signal_count=4,
|
||||
next_executable_action="stage_rule_dry_run_event_redaction_and_wazuh_correlation",
|
||||
required_verifier="runtime_detection_event_post_verifier",
|
||||
source_refs=["docs/security/monitoring-alerting-observability-inventory.snapshot.json"],
|
||||
),
|
||||
_track(
|
||||
track_id="web_api_dast",
|
||||
priority="P1",
|
||||
label="Web and API DAST",
|
||||
tool_ids=["owasp_zap_or_equivalent_dast"],
|
||||
ready_signal_count=0,
|
||||
required_signal_count=5,
|
||||
next_executable_action="prepare_bounded_target_selector_rate_limit_and_baseline_report",
|
||||
required_verifier="web_api_dast_scope_and_report_verifier",
|
||||
source_refs=["docs/security/ssh-network-access-inventory.snapshot.json"],
|
||||
),
|
||||
_track(
|
||||
track_id="normalized_detection_schema",
|
||||
priority="P1",
|
||||
label="Normalized detection schema",
|
||||
tool_ids=["sigma", "ocsf"],
|
||||
ready_signal_count=(1 if alert_ready else 0),
|
||||
required_signal_count=4,
|
||||
next_executable_action="normalize_wazuh_alertmanager_app_events_into_review_cards",
|
||||
required_verifier="sigma_ocsf_event_mapping_regression_verifier",
|
||||
source_refs=["docs/security/iwooos-security-operating-system.snapshot.json"],
|
||||
),
|
||||
_track(
|
||||
track_id="ai_agent_controlled_apply",
|
||||
priority="P0",
|
||||
label="AI Agent controlled apply loop",
|
||||
tool_ids=["ai_agent", "mcp", "rag", "km_playbook"],
|
||||
ready_signal_count=min(
|
||||
controlled_apply_ready_signals
|
||||
+ owner_review_ready_signals
|
||||
+ dry_run_ready_signals,
|
||||
9,
|
||||
),
|
||||
required_signal_count=9,
|
||||
next_executable_action="run_allowlisted_check_mode_with_rollback_post_verifier_and_km_writeback",
|
||||
required_verifier="ai_controlled_apply_post_verifier_and_learning_writeback",
|
||||
source_refs=[
|
||||
"docs/security/wazuh-runtime-controlled-apply-preflight.snapshot.json",
|
||||
"docs/security/wazuh-runtime-gate-owner-review-readback.snapshot.json",
|
||||
"docs/security/wazuh-allowlisted-check-mode-dry-run.snapshot.json",
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def _track(
|
||||
*,
|
||||
track_id: str,
|
||||
priority: str,
|
||||
label: str,
|
||||
tool_ids: list[str],
|
||||
ready_signal_count: int,
|
||||
required_signal_count: int,
|
||||
next_executable_action: str,
|
||||
required_verifier: str,
|
||||
source_refs: list[str],
|
||||
) -> dict[str, Any]:
|
||||
ready_count = max(min(ready_signal_count, required_signal_count), 0)
|
||||
missing_count = max(required_signal_count - ready_count, 0)
|
||||
closure_percent = int(round((ready_count / required_signal_count) * 100)) if required_signal_count else 0
|
||||
if missing_count == 0:
|
||||
closure_state = "readback_ready_runtime_gate_still_closed"
|
||||
elif ready_count > 0:
|
||||
closure_state = "partial_readback_missing_verifier"
|
||||
else:
|
||||
closure_state = "required_not_closed"
|
||||
return {
|
||||
"track_id": track_id,
|
||||
"priority": priority,
|
||||
"label": label,
|
||||
"tool_ids": tool_ids,
|
||||
"closure_state": closure_state,
|
||||
"closure_percent": closure_percent,
|
||||
"ready_signal_count": ready_count,
|
||||
"required_signal_count": required_signal_count,
|
||||
"missing_signal_count": missing_count,
|
||||
"runtime_gate_open": False,
|
||||
"active_response_authorized": False,
|
||||
"host_write_authorized": False,
|
||||
"secret_value_collection_allowed": False,
|
||||
"next_executable_action": next_executable_action,
|
||||
"required_verifier": required_verifier,
|
||||
"source_refs": source_refs,
|
||||
}
|
||||
|
||||
|
||||
def _summary_rollup(
|
||||
source_summaries: dict[str, dict[str, Any]],
|
||||
tracks: list[dict[str, Any]],
|
||||
) -> dict[str, Any]:
|
||||
coverage = source_summaries["coverage"]
|
||||
security_os = source_summaries["security_os"]
|
||||
managed_hosts = source_summaries["managed_hosts"]
|
||||
registry = source_summaries["registry"]
|
||||
controlled_apply = source_summaries["controlled_apply"]
|
||||
owner_review = source_summaries["owner_review"]
|
||||
dry_run = source_summaries["dry_run"]
|
||||
|
||||
expected_hosts = max(
|
||||
_int(managed_hosts.get("expected_host_scope_count")),
|
||||
_int(registry.get("expected_scope_alias_count")),
|
||||
_int(coverage.get("wazuh_expected_host_scope_count")),
|
||||
)
|
||||
accepted_hosts = max(
|
||||
_int(managed_hosts.get("manager_registry_accepted_count")),
|
||||
_int(registry.get("manager_registry_accepted_count")),
|
||||
_int(coverage.get("wazuh_manager_registry_accepted_count")),
|
||||
_int(security_os.get("wazuh_registry_accepted_count")),
|
||||
)
|
||||
total_required = sum(_int(track.get("required_signal_count")) for track in tracks)
|
||||
total_ready = sum(_int(track.get("ready_signal_count")) for track in tracks)
|
||||
|
||||
return {
|
||||
"source_readback_count": len(source_summaries),
|
||||
"tool_track_count": len(tracks),
|
||||
"p0_tool_track_count": sum(1 for track in tracks if track.get("priority") == "P0"),
|
||||
"closed_tool_track_count": sum(
|
||||
1 for track in tracks if _int(track.get("missing_signal_count")) == 0
|
||||
),
|
||||
"partial_tool_track_count": sum(
|
||||
1
|
||||
for track in tracks
|
||||
if _int(track.get("ready_signal_count")) > 0
|
||||
and _int(track.get("missing_signal_count")) > 0
|
||||
),
|
||||
"missing_tool_track_count": sum(
|
||||
1 for track in tracks if _int(track.get("ready_signal_count")) == 0
|
||||
),
|
||||
"total_ready_signal_count": total_ready,
|
||||
"total_required_signal_count": total_required,
|
||||
"tool_closure_percent": int(round((total_ready / total_required) * 100))
|
||||
if total_required
|
||||
else 0,
|
||||
"wazuh_expected_host_scope_count": expected_hosts,
|
||||
"wazuh_manager_registry_accepted_count": accepted_hosts,
|
||||
"wazuh_registry_complete_count": 1 if expected_hosts > 0 and accepted_hosts >= expected_hosts else 0,
|
||||
"wazuh_fim_vulnerability_alert_closed_count": 0,
|
||||
"alert_receipt_observed_count": _int(
|
||||
security_os.get("alert_receipt_observed_count")
|
||||
),
|
||||
"alert_receipt_accepted_count": _int(
|
||||
security_os.get("alert_receipt_accepted_count")
|
||||
),
|
||||
"alert_receipt_source_status": str(
|
||||
security_os.get("alert_receipt_source_status") or "not_connected"
|
||||
),
|
||||
"controlled_apply_preflight_ready_count": _int(
|
||||
controlled_apply.get("controlled_apply_preflight_ready_count")
|
||||
),
|
||||
"owner_review_packet_accepted_count": _int(
|
||||
owner_review.get("owner_review_packet_accepted_count")
|
||||
),
|
||||
"allowlisted_dry_run_result_ref_count": _int(
|
||||
dry_run.get("dry_run_result_ref_count")
|
||||
),
|
||||
"supply_chain_scan_closed_count": 0,
|
||||
"runtime_detection_closed_count": 0,
|
||||
"web_api_dast_closed_count": 0,
|
||||
"normalized_detection_schema_closed_count": 0,
|
||||
"runtime_gate_count": 0,
|
||||
"host_write_authorized_count": 0,
|
||||
"active_response_authorized_count": 0,
|
||||
"secret_value_collection_allowed_count": 0,
|
||||
}
|
||||
|
||||
|
||||
def _next_executable_queue(
|
||||
source_summaries: dict[str, dict[str, Any]],
|
||||
) -> list[dict[str, Any]]:
|
||||
managed_hosts = source_summaries["managed_hosts"]
|
||||
registry = source_summaries["registry"]
|
||||
controlled_apply = source_summaries["controlled_apply"]
|
||||
dry_run = source_summaries["dry_run"]
|
||||
expected_hosts = max(
|
||||
_int(managed_hosts.get("expected_host_scope_count")),
|
||||
_int(registry.get("expected_scope_alias_count")),
|
||||
)
|
||||
accepted_hosts = max(
|
||||
_int(managed_hosts.get("manager_registry_accepted_count")),
|
||||
_int(registry.get("manager_registry_accepted_count")),
|
||||
)
|
||||
registry_gate = (
|
||||
"wazuh_registry_complete_move_to_fim_vulnerability_alert"
|
||||
if expected_hosts > 0 and accepted_hosts >= expected_hosts
|
||||
else "complete_wazuh_manager_registry_alias_matrix"
|
||||
)
|
||||
|
||||
return [
|
||||
{
|
||||
"queue_id": "P0-03",
|
||||
"track_id": "wazuh_detection_response",
|
||||
"state": registry_gate,
|
||||
"next_action": "attach_fim_vulnerability_alert_receipt_post_verifier",
|
||||
"runtime_gate_open": False,
|
||||
},
|
||||
{
|
||||
"queue_id": "P0-07",
|
||||
"track_id": "supply_chain_sbom_scan",
|
||||
"state": "sbom_and_scan_artifacts_missing",
|
||||
"next_action": "stage_trivy_syft_grype_check_mode_reports",
|
||||
"runtime_gate_open": False,
|
||||
},
|
||||
{
|
||||
"queue_id": "P0-08",
|
||||
"track_id": "ai_agent_controlled_apply",
|
||||
"state": "preflight_ready_waiting_review_and_dry_run_acceptance",
|
||||
"next_action": "connect_target_selector_diff_check_mode_rollback_post_verifier_km",
|
||||
"ready_signal_count": _int(
|
||||
controlled_apply.get("controlled_apply_preflight_ready_count")
|
||||
)
|
||||
+ _int(dry_run.get("dry_run_result_ref_count")),
|
||||
"runtime_gate_open": False,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
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 _require_runtime_boundaries(payloads: list[dict[str, Any]]) -> None:
|
||||
for payload in payloads:
|
||||
summary = _summary(payload)
|
||||
for key in _REQUIRED_ZERO_SUMMARY_KEYS:
|
||||
if key in summary and _int(summary.get(key)) != 0:
|
||||
raise ValueError(f"{payload.get('schema_version')}: summary.{key} must remain 0")
|
||||
boundaries = payload.get("boundaries")
|
||||
if isinstance(boundaries, dict):
|
||||
for key in (
|
||||
"runtime_execution_authorized",
|
||||
"runtime_gate_open",
|
||||
"host_write_authorized",
|
||||
"wazuh_active_response_authorized",
|
||||
"secret_value_collection_allowed",
|
||||
):
|
||||
if key in boundaries and boundaries.get(key) is not False:
|
||||
raise ValueError(
|
||||
f"{payload.get('schema_version')}: boundaries.{key} must remain false"
|
||||
)
|
||||
|
||||
|
||||
def _boundary_markers(summary: dict[str, Any]) -> list[str]:
|
||||
return [
|
||||
"iwooos_security_tool_closure_readback_visible=true",
|
||||
f"iwooos_security_tool_closure_tool_track_count={summary['tool_track_count']}",
|
||||
f"iwooos_security_tool_closure_p0_tool_track_count={summary['p0_tool_track_count']}",
|
||||
f"iwooos_security_tool_closure_percent={summary['tool_closure_percent']}",
|
||||
f"iwooos_security_tool_closure_wazuh_manager_registry_accepted_count={summary['wazuh_manager_registry_accepted_count']}",
|
||||
f"iwooos_security_tool_closure_alert_receipt_accepted_count={summary['alert_receipt_accepted_count']}",
|
||||
"iwooos_security_tool_closure_runtime_gate_count=0",
|
||||
"host_write_authorized=false",
|
||||
"wazuh_active_response_authorized=false",
|
||||
"secret_value_collection_allowed=false",
|
||||
"not_authorization=true",
|
||||
]
|
||||
Reference in New Issue
Block a user