Repository navigation
Migrate the tenant and organisation validation ClusterPolicies to ValidatingPolicy #4995
Description
🤖 Generated by the Agentic Engineer (interactive Claude Code session)
Evidence and problem
Kyverno 1.20 is planned to remove ClusterPolicy (#4984). These 12 validation policies in k8s/bases/infrastructure/cluster-policies/best-practices/ guard tenants, GitHub organisation management and retirements; each must exist as a ValidatingPolicy (policies.kyverno.io) before 1.20 is installed:
audit-privileged-rbac, restrict-arc-openbao-listener, restrict-arc-retirement, restrict-explicit-dns-records, restrict-github-team-external-identity, restrict-github-team-management, restrict-homepage-service-groups, restrict-tenant-issuer-refs, restrict-tenant-network-policies, restrict-tenant-route-hostnames, restrict-tenant-secret-stores, restrict-unifi-management-policies.
Ten of the twelve already have Kyverno CLI tests; restrict-arc-openbao-listener and restrict-arc-retirement have none.
How every migration batch works
- Test first. Of the 49
ClusterPolicymanifests, 28 are named in notests/**/kyverno-test.yaml(counted 2026-10-17 by policy name). Before rewriting a policy, add a Kyverno CLI test that pins its current behaviour — at least one resource it must act on and one it must leave alone — and see it pass against theClusterPolicy. The same test, pointed at the new kind, must pass unchanged in its expected results. - Keep the action. Each rewritten policy keeps its failure action as recorded in
tests/policy-failure-actions.json(Enforce stays Enforce, Audit stays Audit), its match scope and its exclusions. - No gap in enforcement. Add the new policy and delete the
ClusterPolicyin the same PR, so Flux applies the replacement before it prunes the old one. Kinds whose two versions could both act on the same request (mutation or generation) say how double application is avoided. - Confirm the capability first. For each rule, confirm the replacement kind can express it at Kyverno 1.19.1 (the running version). A rule it cannot express is recorded on Migrate Kyverno ClusterPolicy and Policy before Kyverno 1.20 removes them #4984 and blocks only that policy, not the batch.
- Validate with
kyverno test ./testsandscripts/validate-kyverno-fixture-evaluation.sh(CI's⚖️ Validate cluster policiesstep), the layer builds inplatform/AGENTS.md, and after deploy a read-only check that each new policy reports ready and the old one is gone.
Acceptance criteria
- Every policy listed above has a CLI test that passed against the
ClusterPolicybefore the rewrite. - Each is a
ValidatingPolicywith the same failure action, scope and exclusions, and the oldClusterPolicyis deleted in the same PR. -
kyverno test ./testsand the fixture-evaluation check pass in CI. - After deploy, each new policy reports ready and no
ClusterPolicyof these names remains.
Priority High, Effort High, Service class Risk reduction. These rules keep tenants inside their boundaries; losing them in a 1.20 upgrade would be silent. Effort includes adding the missing tests, the CEL rewrite, review and one production deploy. No prerequisite; #4994 removes the time pressure but is not required first. Part of #4984.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Projects
- StatusShow more project fields🫴 Ready
Activity
chore: agent-claim #4995 nonce=5a07cfd33a60dbf076c44f3e52a87dcd
test(kyverno): pin two restrict-arc-retirement rules before the rewrite
test(kyverno): pin restrict-arc-retirement's namespace deletion rule
test(kyverno): pin restrict-arc-retirement's credential-sync update rule
test(kyverno): pin restrict-arc-retirement's journal preservation rule
test(kyverno): drop a trailing blank line from a retirement fixture
devantler commentedon Oct 17, 2026
Progress — test-first step for the two untested policies (platform#5031, merged 2026-10-17 21:18Z)
restrict-arc-openbao-listenernow has CLI tests: the audited listener passes, the same name outsideopenbaofails, and extra data,binaryDataor a changed listener each fail.restrict-arc-retirementhas CLI tests for 5 of its 8 rules:fence-retired-listener-pod,fence-retired-secret,preserve-retiring-namespace,fence-credential-recreation(the update path past baseline) andpreserve-retirement-journal. The journal that the policy reads by API call is supplied throughvalues.yaml, per resource.Still to do before this policy's rewrite:
fence-pool-retirement,fence-scale-set-retirementandfence-listener-retirement. They compare the request against whole recorded baseline specs, so their fixtures need a full baseline record invalues.yaml. The other ten policies already had tests, so the CEL rewrite itself has not started.chore: agent-claim #4995 nonce=385a7501212f9e3181dc120a75460228
devantler commentedon Oct 19, 2026
Consumer note for the remaining batches: the platform-tenant-template starter applies these policies to its rendered scaffold from Platform
main. Movingrestrict-tenant-secret-stores(#5094) turned the starter'smainred until devantler-tech/platform-tenant-template#241 adapted it (it also had to move its Kyverno CLI to 1.19.1: 1.18.2 cannot evaluate aValidatingPolicyagainst custom resource kinds). The starter's network boundary check still depends onrestrict-tenant-network-policiesbeing aClusterPolicywith its two rule names, so that batch should land together with devantler-tech/platform-tenant-template#242.