feat(security): expose scanner failures in focused cockpit
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled

This commit is contained in:
ogt
2026-07-14 17:59:04 +08:00
parent 52b870824f
commit ec4210e6bf
6 changed files with 668 additions and 254 deletions

View File

@@ -150,6 +150,28 @@ _SIEM_STAGES = (
"verify_learn",
)
_PUBLIC_DISCOVERY_COLLECTOR_IDS = frozenset(
{
"k8s_replicasets",
"k8s_nodes",
"k8s_pods",
"k8s_deployments",
"k8s_statefulsets",
"k8s_daemonsets",
"k8s_services",
"k8s_configmaps",
"k8s_persistentvolumeclaims",
"k8s_ingresses",
"k8s_cronjobs",
"prometheus_targets",
"database_catalog",
"ai_catalog",
"gitea_bundle_backup",
"gitea_ci",
"domain_tls_inventory",
}
)
def _value(row: Any, name: str, default: Any = None) -> Any:
if row is None:
@@ -162,6 +184,28 @@ def _value(row: Any, name: str, default: Any = None) -> Any:
return getattr(row, name, default)
def _public_discovery_failure(error: Any) -> tuple[str | None, list[str]]:
"""Project only fixed collector identities, never raw scanner errors."""
if not isinstance(error, str) or not error:
return None, []
marker = "asset_collector_failures="
if marker not in error:
return "asset_scan_failed_public_details_unavailable", []
candidates = error.split(marker, 1)[1].split(",")
collector_ids = sorted(
{
candidate.strip()
for candidate in candidates
if candidate.strip() in _PUBLIC_DISCOVERY_COLLECTOR_IDS
}
)
if not collector_ids:
return "asset_scan_failed_public_details_unavailable", []
return "asset_collector_failures", collector_ids
def _count(rows: Iterable[Any], key: str, value: str, count_key: str = "cnt") -> int:
return sum(
int(_value(row, count_key, 0) or 0)
@@ -684,8 +728,7 @@ def build_iwooos_security_asset_control_plane(
for row in inventory_source
)
package_digest_unpinned_count = sum(
int(_value(row, "unpinned_package_count", 0) or 0)
for row in inventory_source
int(_value(row, "unpinned_package_count", 0) or 0) for row in inventory_source
)
certificate_live_unverified_count = sum(
int(_value(row, "unverified_certificate_count", 0) or 0)
@@ -726,10 +769,14 @@ def build_iwooos_security_asset_control_plane(
discovery_fresh = (
discovery_age is not None and discovery_age <= _DISCOVERY_FRESHNESS_SECONDS
)
discovery_status = str(
_value(discovery_row, "latest_status", "missing") or "missing"
)
failure_reason_code, failed_collector_ids = _public_discovery_failure(
_value(discovery_row, "latest_error") if discovery_status == "failed" else None
)
discovery = {
"latest_status": str(
_value(discovery_row, "latest_status", "missing") or "missing"
),
"latest_status": discovery_status,
"latest_scan_depth": str(
_value(discovery_row, "latest_scan_depth", "unknown") or "unknown"
),
@@ -747,6 +794,10 @@ def build_iwooos_security_asset_control_plane(
"age_seconds": discovery_age,
"freshness_slo_seconds": _DISCOVERY_FRESHNESS_SECONDS,
"fresh": discovery_fresh,
"failure_reason_code": failure_reason_code,
"failed_collector_count": len(failed_collector_ids),
"failed_collector_ids": failed_collector_ids,
"raw_error_returned": False,
}
coverage = _rows_by_dimension(coverage_source, _COVERAGE_DIMENSIONS)
@@ -897,8 +948,7 @@ def build_iwooos_security_asset_control_plane(
github_supply_chain_compliant_percent=_percent(
max(
0,
by_type.get("package", 0)
- forbidden_github_supply_chain_asset_count,
by_type.get("package", 0) - forbidden_github_supply_chain_asset_count,
),
by_type.get("package", 0),
),
@@ -909,8 +959,7 @@ def build_iwooos_security_asset_control_plane(
certificate_live_verified_percent=_percent(
max(
0,
by_type.get("certificate", 0)
- certificate_live_unverified_count,
by_type.get("certificate", 0) - certificate_live_unverified_count,
),
by_type.get("certificate", 0),
),
@@ -963,8 +1012,7 @@ def build_iwooos_security_asset_control_plane(
)
)
supply_chain_policy_gap_count = (
forbidden_github_supply_chain_asset_count
+ package_digest_unpinned_count
forbidden_github_supply_chain_asset_count + package_digest_unpinned_count
)
if supply_chain_policy_gap_count > 0:
work_items.append(
@@ -1151,9 +1199,7 @@ def build_iwooos_security_asset_control_plane(
"forbidden_github_supply_chain_asset_count": (
forbidden_github_supply_chain_asset_count
),
"certificate_live_unverified_count": (
certificate_live_unverified_count
),
"certificate_live_unverified_count": (certificate_live_unverified_count),
"certificate_live_unhealthy_count": certificate_live_unhealthy_count,
"automation_coverage_green_percent": _percent(
coverage_green, coverage_total
@@ -1241,13 +1287,11 @@ def build_iwooos_security_asset_control_plane(
"certificate_asset_count": by_type.get("certificate", 0),
"live_tls_verified_count": max(
0,
by_type.get("certificate", 0)
- certificate_live_unverified_count,
by_type.get("certificate", 0) - certificate_live_unverified_count,
),
"live_tls_evidenced_count": max(
0,
by_type.get("certificate", 0)
- certificate_live_unverified_count,
by_type.get("certificate", 0) - certificate_live_unverified_count,
),
"live_tls_healthy_count": max(
0,
@@ -1272,6 +1316,7 @@ def build_iwooos_security_asset_control_plane(
"aggregate_only": True,
"raw_asset_identity_returned": False,
"raw_event_payload_returned": False,
"raw_discovery_error_returned": False,
"secret_value_collection_allowed": False,
"live_scan_triggered": False,
"runtime_action_triggered": False,
@@ -1340,6 +1385,10 @@ def build_unavailable_iwooos_security_asset_control_plane(
"age_seconds": None,
"freshness_slo_seconds": _DISCOVERY_FRESHNESS_SECONDS,
"fresh": False,
"failure_reason_code": reason_code,
"failed_collector_count": 0,
"failed_collector_ids": [],
"raw_error_returned": False,
},
"asset_scopes": [
{
@@ -1532,6 +1581,7 @@ def build_unavailable_iwooos_security_asset_control_plane(
"aggregate_only": True,
"raw_asset_identity_returned": False,
"raw_event_payload_returned": False,
"raw_discovery_error_returned": False,
"secret_value_collection_allowed": False,
"live_scan_triggered": False,
"runtime_action_triggered": False,
@@ -1656,11 +1706,12 @@ class IwoooSSecurityAssetControlPlaneService:
latest.new_assets AS latest_new_assets,
latest.modified_assets AS latest_modified_assets,
latest.disappeared_assets AS latest_disappeared_assets,
latest.error AS latest_error,
successful.ended_at AS latest_success_ended_at
FROM (SELECT 1) seed
LEFT JOIN LATERAL (
SELECT status, scan_depth, started_at, ended_at, total_assets,
new_assets, modified_assets, disappeared_assets
new_assets, modified_assets, disappeared_assets, error
FROM asset_discovery_run
ORDER BY started_at DESC
LIMIT 1