secrets-engine/src/secrets_engine/audit.py
tegwick 70371649af
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Harden production authorization and service auth
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0217e-8c4c-7383-be6b-f50a6e485306
2026-08-23 14:15:42 +02:00

167 lines
5.6 KiB
Python

"""Allowlisted, non-secret summaries over local append-only evidence."""
from __future__ import annotations
import json
import re
import uuid
from collections import Counter
from dataclasses import asdict, dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
_LABEL = re.compile(r"^[a-z][a-z0-9-]{0,79}$")
_DECISION_REF = re.compile(r"^[A-Z][A-Z0-9-]{2,80}$")
_DELIVERY_RESULTS = {"delivered", "failed", "queued", "skipped-no-topic"}
_VERIFY_RESULT = re.compile(r"^(positive|negative):(pass|fail)$")
_ERROR_RESULT = re.compile(
r"^failed-(Catalog|Decision|PolicyGuard|Backend|Provisioning|Verification|Delivery)Error$"
)
def _safe_label(value: object) -> str:
text = value if isinstance(value, str) else ""
return text if _LABEL.fullmatch(text) else "invalid-label"
def _safe_result(value: object) -> str:
text = value if isinstance(value, str) else ""
if (
_LABEL.fullmatch(text)
or _VERIFY_RESULT.fullmatch(text)
or _ERROR_RESULT.fullmatch(text)
):
return text
return "invalid-label"
def _safe_decision_ref(value: object) -> str:
text = value if isinstance(value, str) else ""
if not text:
return ""
try:
return str(uuid.UUID(text))
except ValueError:
return text if _DECISION_REF.fullmatch(text) else ""
def _safe_timestamp(value: object) -> str:
if not isinstance(value, str):
return ""
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
if parsed.tzinfo is None:
return ""
return parsed.astimezone(timezone.utc).isoformat()
except ValueError:
return ""
@dataclass(frozen=True)
class LaneAuditSummary:
catalog_id: str
operation_records: int
malformed_records: int
first_ts: str
last_ts: str
actions: dict[str, int]
results: dict[str, int]
decision_refs: list[str]
session_cleanup: dict[str, int]
hub_delivery: dict[str, int]
def to_json(self) -> dict[str, Any]:
return asdict(self)
def render(self) -> str:
lines = [
f"Lane audit summary for '{self.catalog_id}'",
f" operation records: {self.operation_records}",
f" malformed records: {self.malformed_records}",
f" first: {self.first_ts or 'n/a'}",
f" last: {self.last_ts or 'n/a'}",
" actions: " + _render_counts(self.actions),
" results: " + _render_counts(self.results),
" decisions: " + (", ".join(self.decision_refs) or "none"),
" session cleanup: " + _render_counts(self.session_cleanup),
" hub delivery: " + _render_counts(self.hub_delivery),
]
return "\n".join(lines)
def _render_counts(counts: dict[str, int]) -> str:
return ", ".join(f"{key}={value}" for key, value in sorted(counts.items())) or "none"
def summarize_lane_evidence(evidence_dir: Path, catalog_id: str) -> LaneAuditSummary:
"""Summarize one lane without returning arbitrary record fields or detail."""
actions: Counter[str] = Counter()
results: Counter[str] = Counter()
cleanup: Counter[str] = Counter()
hub_delivery: Counter[str] = Counter()
decisions: set[str] = set()
timestamps: list[str] = []
malformed = 0
operation_records = 0
for path in sorted(Path(evidence_dir).glob("evidence-*.jsonl")):
try:
lines = path.read_text(encoding="utf-8").splitlines()
except OSError:
malformed += 1
continue
for line in lines:
try:
record = json.loads(line)
except (json.JSONDecodeError, TypeError):
malformed += 1
continue
if not isinstance(record, dict):
malformed += 1
continue
if record.get("catalog_id") != catalog_id:
continue
action = _safe_label(record.get("action"))
result = _safe_result(record.get("result"))
if action == "evidence-delivery":
if result in _DELIVERY_RESULTS:
hub_delivery[result] += 1
else:
hub_delivery["invalid"] += 1
continue
operation_records += 1
actions[action] += 1
results[result] += 1
timestamp = _safe_timestamp(record.get("ts"))
if timestamp:
timestamps.append(timestamp)
decision = _safe_decision_ref(record.get("decision_id"))
if decision:
decisions.add(decision)
detail = record.get("detail")
session = detail.get("session") if isinstance(detail, dict) else None
if isinstance(session, dict):
attempted = session.get("revocation_attempted") is True
succeeded = session.get("revocation_succeeded") is True
if succeeded:
cleanup["succeeded"] += 1
elif attempted:
cleanup["failed"] += 1
else:
cleanup["not-attempted"] += 1
timestamps.sort()
return LaneAuditSummary(
catalog_id=catalog_id,
operation_records=operation_records,
malformed_records=malformed,
first_ts=timestamps[0] if timestamps else "",
last_ts=timestamps[-1] if timestamps else "",
actions=dict(sorted(actions.items())),
results=dict(sorted(results.items())),
decision_refs=sorted(decisions),
session_cleanup=dict(sorted(cleanup.items())),
hub_delivery=dict(sorted(hub_delivery.items())),
)