railiance-platform/argocd/platform-addons/secret-annotation-guard
codex 800cbfa870 feat(security): reject secret last-applied annotations (CUST-WP-0073)
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e7fb-275d-7db0-b1df-39ed943427da
2026-09-28 14:51:25 +02:00
..
kustomization.yaml feat(security): reject secret last-applied annotations (CUST-WP-0073) 2026-09-28 14:51:25 +02:00
policy.yaml feat(security): reject secret last-applied annotations (CUST-WP-0073) 2026-09-28 14:51:25 +02:00
README.md feat(security): reject secret last-applied annotations (CUST-WP-0073) 2026-09-28 14:51:25 +02:00

Secret annotation guard

Implemented under the existing CUST-WP-0073-T03; no new platform workplan. Native admission policy denies the last-applied annotation on Secret CREATE and UPDATE, including an empty value. No new workload or controller.

Before the first manual sync, run scripts/secret_annotation_maintenance.py on railiance01 through the supervised admin path, first without arguments, then with --clean. It removes only the duplicate annotation; it never prints kubectl output or Secret values. Concurrent Secret churn can stop cleanup; inspect the receipt before retrying. Preserve only names, counts and booleans.

Declare the policy through the pinned secret-annotation-guard Argo Application; automated sync and prune are off. Platform-addons AppProject must allow both admission kinds. Sync policy first and inspect typeChecking; bind only after cleanup. Test clean CREATE/UPDATE and denied annotated CREATE/UPDATE using synthetic data in whitehat; verify client-side apply is denied, then delete only the test fixture. Secret writers must use server-side apply or replace.

Rollback is a manual Argo sync of a reviewed revision without the binding (with explicit resource-scoped pruning), or attended break-glass deletion of the binding followed by Git reconciliation. Removing the binding reopens this leak path. The policy does not rotate credentials or isolate agent accounts.