Standardizing enforcement of security policies: Diving deep into Kubernetes Validating Admission Policy

Discover why Validating Admission Policy should standardize the policy enforcement in Kubernetes ecosystem. This article discusses benefits, motivation, and how to get started.
Introduction
Kubernetes 1.26 introduced the first alpha release of validating admission policies.
Validating admission policies offer a declarative, in-process alternative to validating admission webhooks. Validation rules for a policy are declared in Common Expression Language (CEL).
Motivation
The current approach to enforcing custom policies within Kubernetes involves use of admission webhooks. It is mainly done via external admission controllers in the ecosystem such as Kyverno and OPA/Gatekeeper.
Admission webhooks are HTTP callbacks that handle admission requests. There are 2 types, either validating or mutating. Mutating webhooks are able to modify objects before they are stored, whereas validating webhooks can reject requests to enforce custom policies.
The diagram below shows phases of the admission control process.
While admission webhooks do offer great flexibility, they come with a few drawbacks when compared to in-process policy enforcement:
- Additional infrastructure: required to host admission webhooks.
- Latency: requires another network hop.
- Less reliable: due to extra infrastructure dependencies.
- "Failing closed or failing open" dilemma: reduce the cluster availability or limit the efficacy of policy enforcement?
- Operationally burdensome: observability, security, and proper release/rollout/rollback plans.
Getting started with Validating Admission Policies
Let’s see how validating admission policies work.
Since this feature is in alpha stage, the feature gate
ValidatingAdmissionPolicy
should be enabled.
We can create a Kubernetes cluster with Kind providing a configuration file that enables the feature gate.
|
|
The content of kind-config.yaml
file:
|
|
The following command checks if the API is enabled:
|
|
Once the ValidatingAdmissionPolicy
is enabled, we are able to create our policies with CEL expressions.
Let’s create a policy that enforces a tag different from latest
in Pod images.
A policy is made up of at least two resources:
- The
ValidatingAdmissionPolicy
describes the logic of a policy. - A
ValidatingAdmissionPolicyBinding
links the above resources together and provides scoping.
Here is our policy. The description of the most important fields are listed as comments, take a look.
|
|
Now we can apply the policy:
|
|
If you try to create a Pod with an untagged image, an error will return with the message we defined:
|
|
The content of pod.yaml
file is below.
|
|
Different values can be substituted in the image
field to test different cases:
Image | Expect |
---|---|
nginx@sha256:af296b188c7b7df99ba960ca614439c99cb7cf252ed7bbc23e90cfda59092305 | pass |
nginx:1.25.0 | pass |
nginx:latest | fail |
nginx | fail |
Comparing policies
See how the same policy is defined in external admission controllers.
Validating Admission Policy:
|
|
OPA/Gatekeeper:
|
|
Kyverno:
|
|
Kyverno with CEL (new):
Kyverno recently has added support for CEL expressions. See the PR. This is a very recent feature, and the API is subject to change. As of this post’s writing, this feature has not yet been documented.
|
|
Conclusion
Looking at the Kubernetes ecosystem as a whole, it is evident that there’s a demand for opinionated policy frameworks. The existence of security regimes such as CIS Kubernetes Benchmarks emphasizes the importance of standardized controls.
Validating Admission Policy is a policy enforcement feature that fulfills a community need and should be the best alternative for the vast majority of validations due to reduced infrastructure footprint and the simplicity of CEL.
In-process admission control has fundamental advantages over webhooks: it is far safer to use in a “fail closed” mode because it removes the network as a possible failure domain.
According to the KEP (Kubernetes Enhancement Proposal) of this feature, it’s not a goal currently to support mutations and to build an in-tree policy framework. Therefore, projects in the ecosystem should not be completely replaced when this feature is graduated. Instead, they should make use of these APIs’ extensibility and configurability.
One of the goals is to provide core functionality as a library and enable other tools to run the same CEL validation checks that the API server does. This should popularize the use of CEL for policies and checks in the Kubernetes ecosystem.
Even though still in alpha stage, we can already observe the impact of Validating Admission Policy: Kyverno is developing a feature which supports CEL expressions in validations, as can be seen in the comparing policies section.
We should expect to see new projects emerging that use CEL in use cases beyond admissions control.
One great example is Marvin, a CLI tool that scans Kubernetes clusters by performing CEL expressions to report potential issues.
Marvin has 30+ built-in checks and also supports custom checks with CEL, allowing you to use virtually the same expression in both cases:
Kubernetes ValidatingAdmissionPolicy
(policy enforcement) and Marvin (cluster scanner).
References
- https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy
- https://kubernetes.io/blog/2022/12/20/validating-admission-policies-alpha
- https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers
- https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/3488-cel-admission-control/README.md
- https://github.com/undistro/marvin