fix(security): repair canonical asset integrity
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m32s
CD Pipeline / build-and-deploy (push) Successful in 7m58s
CD Pipeline / post-deploy-checks (push) Successful in 2m25s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m32s
CD Pipeline / build-and-deploy (push) Successful in 7m58s
CD Pipeline / post-deploy-checks (push) Successful in 2m25s
This commit is contained in:
@@ -114,6 +114,8 @@ async def scan_once(
|
||||
error_msg: str | None = None
|
||||
|
||||
try:
|
||||
await _assert_asset_key_integrity()
|
||||
|
||||
# 2026-04-19 v3 擴充: 多資源類型掃描 + relationship 提取
|
||||
# 資源類型: pods (container), deployments/statefulsets/daemonsets (k8s_workload),
|
||||
# services (k8s_resource), nodes (host), configmaps (k8s_resource)
|
||||
@@ -917,6 +919,61 @@ async def _finalize_discovery_run(
|
||||
"err": (error or "")[:2000] if error else None,
|
||||
"tags": ["asset_scanner", "discovery", *scope],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def _assert_asset_key_integrity() -> None:
|
||||
"""Fail closed before discovery when canonical asset identity is corrupt."""
|
||||
from sqlalchemy import text as _sql
|
||||
|
||||
from src.db.base import get_db_context
|
||||
|
||||
async with get_db_context(_PROJECT_ID) as db:
|
||||
# A corrupt-but-valid unique index can make the planner incorrectly
|
||||
# assume the heap is unique. Inspect the heap before trusting it.
|
||||
await db.execute(_sql("SET LOCAL enable_indexscan = 'off'"))
|
||||
await db.execute(_sql("SET LOCAL enable_indexonlyscan = 'off'"))
|
||||
await db.execute(_sql("SET LOCAL enable_bitmapscan = 'off'"))
|
||||
row = (
|
||||
await db.execute(
|
||||
_sql(
|
||||
"""
|
||||
SELECT
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM (
|
||||
SELECT asset_key
|
||||
FROM asset_inventory
|
||||
GROUP BY asset_key
|
||||
HAVING COUNT(*) > 1
|
||||
) AS duplicate_groups
|
||||
) AS duplicate_group_count,
|
||||
COALESCE((
|
||||
SELECT
|
||||
index_row.indisvalid
|
||||
AND index_row.indisready
|
||||
AND index_row.indislive
|
||||
AND index_row.indisunique
|
||||
FROM pg_constraint AS constraint_row
|
||||
JOIN pg_index AS index_row
|
||||
ON index_row.indexrelid = constraint_row.conindid
|
||||
WHERE constraint_row.conrelid =
|
||||
'asset_inventory'::regclass
|
||||
AND constraint_row.conname =
|
||||
'asset_inventory_asset_key_key'
|
||||
), FALSE) AS unique_index_healthy
|
||||
"""
|
||||
)
|
||||
)
|
||||
).one()
|
||||
|
||||
duplicate_group_count = int(row[0] or 0)
|
||||
unique_index_healthy = bool(row[1])
|
||||
if duplicate_group_count or not unique_index_healthy:
|
||||
raise RuntimeError(
|
||||
"asset_inventory_key_integrity_failed "
|
||||
f"duplicate_groups={duplicate_group_count} "
|
||||
f"unique_index_healthy={str(unique_index_healthy).lower()}"
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user