fix(iwooos): expose security runtime gaps truthfully
Some checks failed
CD Pipeline / select-latest-carrier (push) Successful in 58s
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m53s
CD Pipeline / revalidate-deploy-carrier (push) Successful in 38s
CD Pipeline / revalidate-post-deploy-carrier (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-22 12:47:43 +08:00
parent 50c7a7f7f5
commit 2babb1b155
5 changed files with 358 additions and 85 deletions

View File

@@ -33,6 +33,104 @@ _WINDOW_HOURS = 24
_STRICT_RUNTIME_SCHEMA_VERSION = "ai_agent_strict_runtime_completion_v2"
_STRICT_RUNTIME_SOURCE_ID = "autonomous_strict_runtime"
_WORK_ITEM_ORDER = {
"source_health": 0,
"asset_discovery": 10,
"asset_scope": 20,
"asset_ownership": 30,
"automation_coverage": 40,
"telemetry_detection": 50,
"siem_pipeline": 60,
"endpoint_xdr_wazuh": 70,
"incident_response_soar": 80,
"vulnerability_exposure": 90,
"identity_zero_trust": 100,
"data_secrets_privacy": 110,
"backup_dr_resilience": 120,
"siem_soc_threat_intel": 130,
"security_audit": 140,
"ai_security_automation": 150,
"supply_chain_policy": 160,
"certificate_live_verification": 170,
"network_dns_tls": 180,
"appsec_api": 190,
"asset_relationship": 200,
"audit_integrity": 210,
}
_SECURITY_DOMAIN_WORK_ITEMS: tuple[tuple[str, str, str, str, str], ...] = (
(
"endpoint_xdr_wazuh",
"AIA-P0-006-07",
"P0",
"接通 Wazuh / XDR 全資產 runtime 證據",
"把 manager、agent、host、service 與事件 identity 接入資產圖驗證偵測、隔離候選、postcheck 與復原證據。",
),
(
"incident_response_soar",
"AIA-P0-007-02",
"P0",
"封閉事件應變與 SOAR 處置",
"將 open incident 串接 owner、decision、bounded apply、獨立 verifier、rollback 與 durable closure receipt。",
),
(
"vulnerability_exposure",
"AIA-P0-006-08",
"P0",
"接入 CVE 與外部暴露面驗證",
"以 SBOM、映像掃描、DAST 與 public exposure verifier 產生可追溯 finding、修復與複驗。",
),
(
"identity_zero_trust",
"AIA-P0-006-09",
"P0",
"建立 IAM 與 Zero Trust runtime 稽核",
"盤點人員、服務與 Agent identity驗證最小權限、存取審查、失效權限與 break-glass 使用紀錄。",
),
(
"data_secrets_privacy",
"AIA-P0-006-10",
"P0",
"建立資料、Secret 與隱私控制證據",
"驗證 secret rotation、at-rest/in-transit encryption、敏感資料流與資料保留不得讀取 secret value。",
),
(
"telemetry_detection",
"AIA-P0-006-11",
"P0",
"補齊全資產監控與偵測覆蓋",
"將每項資產綁定 telemetry、alert rule、owner、SLO 與可驗證的失效告警 receipt。",
),
(
"backup_dr_resilience",
"AIA-P0-006-12",
"P0",
"完成備份、還原演練與 DR 證據",
"把 backup target、freshness、checksum、restore drill、RPO/RTO 與獨立 verifier 接入資產圖。",
),
(
"siem_soc_threat_intel",
"AIA-P0-007-03",
"P0",
"完成 SIEM / SOC 威脅情報閉環",
"將 threat intel、規則命中、case、處置、驗證與 learning receipt 綁在同一事件與同一 run。",
),
(
"network_dns_tls",
"AIA-P1-006-13",
"P1",
"封閉網路、DNS 與 TLS 控制缺口",
"對 public route、DNS、certificate chain、expiry 與 network policy 建立持續驗證與受控修復。",
),
(
"appsec_api",
"AIA-P1-006-14",
"P1",
"完成 AppSec、API 與 DAST 證據鏈",
"把 SAST、DAST、API contract、dependency finding、修復 commit 與 production verifier 串成同一證據鏈。",
),
)
_ASSET_TYPES = (
"host",
"container",
@@ -684,8 +782,10 @@ def _work_item(
title: str,
gap_count: int,
next_action: str,
*,
gap_percent: int | None = None,
) -> dict[str, Any]:
return {
item = {
"work_item_id": work_item_id,
"priority": priority,
"control_id": control_id,
@@ -693,7 +793,11 @@ def _work_item(
"gap_count": gap_count,
"status": "open",
"next_action": next_action,
"order": _WORK_ITEM_ORDER.get(control_id, 999),
}
if gap_percent is not None:
item["gap_percent"] = max(0, min(100, gap_percent))
return item
def _strict_runtime_completion_projection(row: Any) -> dict[str, Any]:
@@ -1283,7 +1387,38 @@ def build_iwooos_security_asset_control_plane(
)
)
work_items.sort(key=lambda item: (item["priority"], item["work_item_id"]))
domain_by_id = {
str(domain["domain_id"]): domain for domain in security_program_domains
}
active_control_ids = {str(item["control_id"]) for item in work_items}
for (
domain_id,
work_item_id,
priority,
title,
next_action,
) in _SECURITY_DOMAIN_WORK_ITEMS:
domain = domain_by_id.get(domain_id)
if not domain or int(domain.get("controlled_percent", 0)) >= 100:
continue
if domain_id in active_control_ids:
continue
work_items.append(
_work_item(
work_item_id,
priority,
domain_id,
title,
1,
next_action,
gap_percent=max(0, 100 - int(domain.get("controlled_percent", 0))),
)
)
active_control_ids.add(domain_id)
work_items.sort(
key=lambda item: (item["priority"], item["order"], item["work_item_id"])
)
overall_control_percent = round(
sum(function["controlled_percent"] for function in control_functions)
/ len(control_functions)
@@ -1829,8 +1964,7 @@ async def _read_strict_runtime_source() -> tuple[dict[str, Any], dict[str, Any]]
readback
)
if (
strict_runtime.get("schema_version")
!= _STRICT_RUNTIME_SCHEMA_VERSION
strict_runtime.get("schema_version") != _STRICT_RUNTIME_SCHEMA_VERSION
or strict_runtime.get("runtime_contract_schema_version")
!= AI_AUTOMATION_RUNTIME_CONTRACT_SCHEMA_VERSION
):
@@ -2056,21 +2190,45 @@ class IwoooSSecurityAssetControlPlaneService:
source_id="security_compliance",
statement=_sql(
"""
WITH recent AS MATERIALIZED (
SELECT snapshot_id, asset_id, dimension, status, detected_at
FROM asset_compliance_snapshot
ORDER BY snapshot_id DESC
LIMIT 100000
), latest AS (
SELECT DISTINCT ON (asset_id, dimension)
asset_id, dimension, status
FROM recent
ORDER BY asset_id, dimension, detected_at DESC
WITH dimensions(dimension) AS (
SELECT unnest(ARRAY[
'ssl_cert_valid', 'cve_scan', 'secret_rotated',
'backup_tested', 'audit_log_enabled',
'access_reviewed', 'encryption_at_rest'
]::text[])
)
SELECT dimension, status, count(*) AS cnt
FROM latest
GROUP BY dimension, status
ORDER BY dimension, status
SELECT
dimensions.dimension,
CASE
WHEN latest.detected_at IS NULL
OR latest.detected_at < NOW() - INTERVAL '36 hours'
THEN 'unknown'
ELSE latest.status
END AS status,
count(*) AS cnt
FROM asset_inventory asset
CROSS JOIN dimensions
LEFT JOIN LATERAL (
SELECT snapshot.status, snapshot.detected_at
FROM asset_compliance_snapshot snapshot
WHERE snapshot.asset_id = asset.asset_id
AND snapshot.dimension = dimensions.dimension
ORDER BY snapshot.detected_at DESC, snapshot.snapshot_id DESC
LIMIT 1
) latest ON true
WHERE asset.lifecycle_state = 'active'
GROUP BY dimensions.dimension, CASE
WHEN latest.detected_at IS NULL
OR latest.detected_at < NOW() - INTERVAL '36 hours'
THEN 'unknown'
ELSE latest.status
END
ORDER BY dimensions.dimension, CASE
WHEN latest.detected_at IS NULL
OR latest.detected_at < NOW() - INTERVAL '36 hours'
THEN 'unknown'
ELSE latest.status
END
"""
),
result_mode="all",
@@ -2225,30 +2383,36 @@ class IwoooSSecurityAssetControlPlaneService:
source_id="audit_runtime",
statement=_sql(
"""
WITH k8s AS (
SELECT
count(*) AS total,
count(*) FILTER (WHERE success IS FALSE) AS failed
FROM audit_logs
WHERE project_id = 'awoooi'
AND created_at >= NOW() - INTERVAL '24 hours'
), mcp AS (
SELECT
count(*) AS total,
count(*) FILTER (WHERE success IS FALSE) AS failed
FROM mcp_audit_log
WHERE created_at >= NOW() - INTERVAL '24 hours'
), asset_changes AS (
SELECT
count(*) AS total,
count(*) FILTER (WHERE ai_analysis IS NOT NULL) AS analyzed
FROM asset_change_event
WHERE detected_at >= NOW() - INTERVAL '24 hours'
)
SELECT
(SELECT count(*) FROM audit_logs
WHERE project_id = 'awoooi'
AND created_at >= NOW() - INTERVAL '24 hours')
AS k8s_audit_count_24h,
(SELECT count(*) FROM audit_logs
WHERE project_id = 'awoooi'
AND created_at >= NOW() - INTERVAL '24 hours'
AND success IS FALSE)
AS k8s_audit_failure_count_24h,
(SELECT count(*) FROM mcp_audit_log
WHERE created_at >= NOW() - INTERVAL '24 hours')
AS mcp_audit_count_24h,
(SELECT count(*) FROM mcp_audit_log
WHERE created_at >= NOW() - INTERVAL '24 hours'
AND success IS FALSE)
AS mcp_audit_failure_count_24h,
(SELECT count(*) FROM asset_change_event
WHERE detected_at >= NOW() - INTERVAL '24 hours')
AS asset_change_count_24h,
(SELECT count(*) FROM asset_change_event
WHERE detected_at >= NOW() - INTERVAL '24 hours'
AND ai_analysis IS NOT NULL)
AS asset_change_ai_analysis_count_24h
k8s.total AS k8s_audit_count_24h,
k8s.failed AS k8s_audit_failure_count_24h,
mcp.total AS mcp_audit_count_24h,
mcp.failed AS mcp_audit_failure_count_24h,
asset_changes.total AS asset_change_count_24h,
asset_changes.analyzed AS asset_change_ai_analysis_count_24h
FROM k8s
CROSS JOIN mcp
CROSS JOIN asset_changes
"""
),
result_mode="one",

View File

@@ -71,6 +71,8 @@ def _ready_payload(
*,
discovery_status: str = "success",
discovery_error: str | None = None,
coverage_rows: list[SimpleNamespace] | None = None,
compliance_rows: list[SimpleNamespace] | None = None,
automation_rows: list[SimpleNamespace] | None = None,
runtime_receipt_counts: dict[str, int] | None = None,
strict_runtime: dict | None = None,
@@ -98,30 +100,38 @@ def _ready_payload(
_row(asset_type="monitoring_target", cnt=3, unowned_count=0, stale_count=0),
_row(asset_type="ai_agent", cnt=1, unowned_count=0, stale_count=0),
]
coverage = [
_row(dimension=dimension, status="green", cnt=20)
for dimension in (
"auto_monitoring",
"auto_alerting",
"auto_rule_creation",
"auto_rule_matching",
"auto_playbook",
"auto_remediation",
"auto_km_creation",
)
]
compliance = [
_row(dimension=dimension, status="compliant", cnt=20)
for dimension in (
"ssl_cert_valid",
"cve_scan",
"secret_rotated",
"backup_tested",
"audit_log_enabled",
"access_reviewed",
"encryption_at_rest",
)
]
coverage = (
coverage_rows
if coverage_rows is not None
else [
_row(dimension=dimension, status="green", cnt=20)
for dimension in (
"auto_monitoring",
"auto_alerting",
"auto_rule_creation",
"auto_rule_matching",
"auto_playbook",
"auto_remediation",
"auto_km_creation",
)
]
)
compliance = (
compliance_rows
if compliance_rows is not None
else [
_row(dimension=dimension, status="compliant", cnt=20)
for dimension in (
"ssl_cert_valid",
"cve_scan",
"secret_rotated",
"backup_tested",
"audit_log_enabled",
"access_reviewed",
"encryption_at_rest",
)
]
)
automation = (
automation_rows
if automation_rows is not None
@@ -226,6 +236,11 @@ def test_builds_live_asset_siem_audit_and_ai_control_plane_without_false_closure
}
assert domain_by_id["endpoint_xdr_wazuh"]["status"] == "not_evidenced"
assert domain_by_id["siem_soc_threat_intel"]["controlled_percent"] == 50
work_item_by_control = {item["control_id"]: item for item in payload["work_items"]}
assert work_item_by_control["endpoint_xdr_wazuh"]["priority"] == "P0"
assert work_item_by_control["endpoint_xdr_wazuh"]["gap_count"] == 1
assert work_item_by_control["endpoint_xdr_wazuh"]["gap_percent"] == 100
assert payload["work_items"][0]["order"] <= payload["work_items"][1]["order"]
assert len(payload["siem"]["pipeline"]) == 8
assert payload["security_audit"]["mcp_tool_audit_count_24h"] == 11
assert payload["summary"]["package_digest_unpinned_count"] == 0
@@ -256,6 +271,36 @@ def test_builds_live_asset_siem_audit_and_ai_control_plane_without_false_closure
assert 'secret_value_collection_allowed": true' not in public_text.lower()
def test_uncovered_security_domains_are_explicit_ordered_p0_work_items() -> None:
payload = _ready_payload(coverage_rows=[], compliance_rows=[])
work_item_by_control = {item["control_id"]: item for item in payload["work_items"]}
for control_id in (
"endpoint_xdr_wazuh",
"incident_response_soar",
"identity_zero_trust",
"data_secrets_privacy",
"vulnerability_exposure",
"telemetry_detection",
"backup_dr_resilience",
"siem_soc_threat_intel",
):
assert work_item_by_control[control_id]["priority"] == "P0"
p0_orders = [
item["order"] for item in payload["work_items"] if item["priority"] == "P0"
]
assert p0_orders == sorted(p0_orders)
assert all(item["order"] < 999 for item in payload["work_items"])
assert [item["control_id"] for item in payload["work_items"][:5]] == [
"asset_scope",
"asset_ownership",
"automation_coverage",
"telemetry_detection",
"endpoint_xdr_wazuh",
]
def test_projects_canonical_runtime_receipts_without_false_same_run_closure() -> None:
payload = _ready_payload(
automation_rows=[
@@ -318,8 +363,7 @@ def test_projects_exact_authoritative_same_run_runtime_closure() -> None:
assert payload["ai_automation"]["same_run_closed_loop_proven"] is True
assert payload["ai_automation"]["same_run_closed_loop_count"] == 1
assert all(
item["work_item_id"] != "AIA-P0-008-01"
for item in payload["work_items"]
item["work_item_id"] != "AIA-P0-008-01" for item in payload["work_items"]
)
assert payload["completion"]["overall_percent"] == round(
sum(
@@ -372,8 +416,7 @@ def test_strict_runtime_projection_fails_closed_on_contract_or_receipt_drift() -
assert payload["completion"]["strict_runtime_closure_percent"] == 0
assert payload["ai_automation"]["same_run_closed_loop_proven"] is False
assert any(
item["work_item_id"] == "AIA-P0-008-01"
for item in payload["work_items"]
item["work_item_id"] == "AIA-P0-008-01" for item in payload["work_items"]
)
@@ -886,8 +929,14 @@ def test_service_bounds_source_concurrency_for_database_budget(monkeypatch) -> N
for statement in statements
if "asset_compliance_snapshot" in statement
)
assert "ORDER BY snapshot_id DESC" in compliance_query
assert "LIMIT 100000" in compliance_query
assert "CROSS JOIN dimensions" in compliance_query
assert "LEFT JOIN LATERAL" in compliance_query
assert (
"ORDER BY snapshot.detected_at DESC, snapshot.snapshot_id DESC"
in compliance_query
)
assert "latest.detected_at < NOW() - INTERVAL '36 hours'" in compliance_query
assert "THEN 'unknown'" in compliance_query
inventory_query = next(
statement for statement in statements if "FROM asset_inventory" in statement
)
@@ -908,6 +957,12 @@ def test_service_bounds_source_concurrency_for_database_budget(monkeypatch) -> N
assert "executor_returncode_trusted" in siem_query
assert "learning_writeback_count_24h" in siem_query
assert "ansible_learning_writeback_recorded" in siem_query
audit_query = next(
statement for statement in statements if "WITH k8s AS" in statement
)
assert "count(*) FILTER (WHERE success IS FALSE)" in audit_query
assert "CROSS JOIN mcp" in audit_query
assert "CROSS JOIN asset_changes" in audit_query
assert "repository_readback_verified" in siem_query