Skip to content

Migrate the tenant and organisation validation ClusterPolicies to ValidatingPolicy #4995

Open

Description

@devantler

🤖 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 ClusterPolicy manifests, 28 are named in no tests/**/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 the ClusterPolicy. 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 ClusterPolicy in 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 ./tests and scripts/validate-kyverno-fixture-evaluation.sh (CI's ⚖️ Validate cluster policies step), the layer builds in platform/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 ClusterPolicy before the rewrite.
  • Each is a ValidatingPolicy with the same failure action, scope and exclusions, and the old ClusterPolicy is deleted in the same PR.
  • kyverno test ./tests and the fixture-evaluation check pass in CI.
  • After deploy, each new policy reports ready and no ClusterPolicy of 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.

Activity

  1. added theissue type on Oct 17, 2026
  2. moved this to 🫴 Ready in 🌊 Project Boardon Oct 17, 2026
  3. updated Effort High and Priority High on Oct 17, 2026
  4. self-assigned this
    on Oct 17, 2026
  5. devantler commented on Oct 17, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Progress — test-first step for the two untested policies (platform#5031, merged 2026-10-17 21:18Z)

    • restrict-arc-openbao-listener now has CLI tests: the audited listener passes, the same name outside openbao fails, and extra data, binaryData or a changed listener each fail.
    • restrict-arc-retirement has 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) and preserve-retirement-journal. The journal that the policy reads by API call is supplied through values.yaml, per resource.
    • Each pinned rule was broken on purpose, and a fixture failed every time.

    Still to do before this policy's rewrite: fence-pool-retirement, fence-scale-set-retirement and fence-listener-retirement. They compare the request against whole recorded baseline specs, so their fixtures need a full baseline record in values.yaml. The other ten policies already had tests, so the CEL rewrite itself has not started.

  6. added a commit that references this issue on Oct 19, 2026
  7. devantler commented on Oct 19, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Consumer note for the remaining batches: the platform-tenant-template starter applies these policies to its rendered scaffold from Platform main. Moving restrict-tenant-secret-stores (#5094) turned the starter's main red 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 a ValidatingPolicy against custom resource kinds). The starter's network boundary check still depends on restrict-tenant-network-policies being a ClusterPolicy with its two rule names, so that batch should land together with devantler-tech/platform-tenant-template#242.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Fields

Priority

High

Effort

High

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions