Kubernetes Admission Policy Testing
Kubernetes Admission Policy Testing ensures policies are enforced correctly, validating configurations before they reach the cluster.
Kubernetes Admission Policy Testing is the discipline of verifying that admission policies — whether expressed as webhooks, ValidatingAdmissionPolicy objects, Pod Security Standards, or third-party policy-engine rules — behave exactly as intended before they are relied upon in production, covering both positive tests confirming compliant objects are allowed and negative tests confirming non-compliant objects are correctly rejected or flagged.
Levels of Policy Testing
Unit Testing Individual Expressions
For CEL-based policies, testing the expression logic in isolation against a range of crafted object fixtures — compliant, non-compliant, and edge cases with missing optional fields — verifies the expression's correctness without needing a running cluster, catching logic errors early and cheaply.
kubectl apply -f policy.yaml --dry-run=server
Integration Testing Against a Live API Server
Applying representative test objects directly against a staging cluster with the policy installed confirms the full request path — matching, evaluation, and response — behaves as intended, including interactions between multiple policies that might not be apparent from testing any single policy in isolation.
kubectl apply -f test-fixtures/compliant-pod.yaml --dry-run=server
kubectl apply -f test-fixtures/noncompliant-pod.yaml --dry-run=server
End-to-End Testing Within CI Pipelines
Incorporating policy tests into a continuous integration pipeline — applying a suite of known compliant and non-compliant manifests against an ephemeral or shared test cluster and asserting the expected outcome for each — catches policy regressions automatically whenever a policy definition changes, rather than relying on manual verification before each change is merged.
Building a Policy Test Suite
Structuring Test Fixtures
A well-organized test suite pairs each policy with a directory of fixture manifests explicitly labeled as expected to pass or expected to fail, making the intent of each test case clear to anyone reviewing or extending the suite later.
policies/
require-resource-limits/
policy.yaml
fixtures/
pass-with-limits.yaml
fail-missing-limits.yaml
fail-partial-limits.yaml
Covering Edge Cases Deliberately
Beyond obviously compliant and non-compliant cases, testing objects with missing optional fields, empty collections, and boundary values (exactly at a configured threshold rather than clearly above or below it) surfaces the CEL expression errors and off-by-one mistakes that straightforward test cases would not reveal.
Testing Across Enforcement Actions
Verifying Warn and Audit Output
For policies configured with Warn or Audit actions, testing should confirm not only that the object is allowed through, but that the expected warning message or audit annotation is actually produced, since a policy that silently fails to generate its warning provides no observational value even while technically not blocking anything.
kubectl apply -f fixtures/fail-missing-limits.yaml --dry-run=server 2>&1 | grep Warning
Testing the Transition Between Actions
Before escalating a policy from Audit/Warn to Deny/enforce, re-running the full test suite with the action temporarily set to Deny in a staging environment confirms the escalation behaves as expected against the same fixtures used during the observation period, rather than assuming the transition is purely a configuration change with no behavioral surprises.
Testing Policy Interactions
Multiple Policies Acting on the Same Resource
Because multiple validating policies can match the same resource simultaneously, and all must pass for a request to be admitted, testing a representative object against the full set of policies active in a target namespace — not just the policy under test in isolation — reveals interaction effects, such as one policy's mutation invalidating another policy's assumption.
Testing Mutating and Validating Order
For clusters using mutating webhooks alongside validating policies, testing should account for the fact that validation always evaluates the post-mutation object; a test fixture representing the pre-mutation input may pass or fail differently than expected if the test does not account for mutations applied earlier in the chain.
Maintaining Tests Over Time
Updating Fixtures With API Changes
As Kubernetes API versions evolve and new fields are introduced, periodically reviewing test fixtures against the current API schema prevents a test suite from silently testing against an outdated object shape that no longer reflects what real clients actually submit.
Treating Policy Test Failures as Blocking
Integrating policy tests as a required, blocking check in the same CI pipeline used for application code changes ensures a policy regression is caught before merge, with the same rigor applied to changes that could otherwise silently weaken security enforcement across the cluster.