CEL and Kubescape: Transforming Kubernetes Admission Control
Introduction
Admission control is a crucial part of the Kubernetes security, enabling the approval or modification of API objects as they are submitted to the server. It allows administrators to enforce business logic or policies on what objects can be admitted into a cluster. Kubernetes RBAC is a scalable authorization mechanism, but lacks the fine grained control over different Kubernetes objects. This creates the need for another layer of control which is Admission Policies. To enhance this capability, Kubernetes introduced dynamic admission control webhooks in version 1.7. Despite its benefits, adoption of admission controllers for policy enforcement faces challenges, namely scalability challenges. Maintaining webhook infrastructure as a production service is complex, and handling webhook failures can either reduce cluster availability or undermine policy enforcement. Additionally, the network hop and evaluation time involved in admission control can introduce significant latency, particularly in "serverless” environments where pods are rapidly spun up in response to network requests. Kubernetes 1.30 has brought a significant development to the table with the introduction of the Common Expression Language (CEL) for admission control. This new feature offers an alternative to validating admission webhooks for enforcing custom policies, with a focus on policy enforcement capabilities and CRD validation rules that were previously in beta. The introduction of CEL for admission control enables administrators to define complex and tailored policies, improving the overall security of Kubernetes clusters. This is significant for organizations with complex security requirements, as it allows them to create finely tuned policies that precisely match the security needs of different applications and environments. In this blog post, we'll explore the benefits of Validating Admission Policies, its goals, and how Kubescape maintainers have leveraged it to create a robust and precise cel-admission-library.
Validating Admission Policies Short Primer
The first part of this blog post explains what ValidatingAdmissionPolicies are and explain why they were added and their benefits. If you have been following the development of KEP-3488, through alpha in Kubernetes 1.26, beta in Kubernetes 1.28 and GA in the aforementioned Kubernetes 1.30 and you just want to get started with them, feel free to skip to Using the Kubescape CEL library in your cluster. If you are reading this and thinking: “I already have OPA Gatekeeper or Kyverno up and running to solve this”.
Please join us to get a better understanding of this Kubernetes native feature, what it seeks to achieve and what the benefits of using it are. Also, take into account that this functionality will become the de-facto standard, similar to what happened with OpenTelemetry and GatewayAPI.
Introduction to ValidatingAdmissionPolicies
ValidatingAdmissionPolicies are: A declarative, in-process alternative to validating admission webhooks. They use the Common Expression Language (CEL) to define the policies.
They consist of two main resources:
- ValidatingAdmissionPolicy describes the policy logic
- ValidatingAdmissionPolicyBinding links the above policy to the resources it applies to
The Goals of Validating Admission Policies
The Kubernetes team has established specific goals for Validating Admission Policies to guarantee that it aligns with the community's requirements.:
- Alternative to Webhooks: Validating Admission Policies aims to provide an alternative to webhooks for the majority of validating admission use cases.
- In-Tree Extensions: The feature intends to offer the in-tree extensions required to build policy frameworks for Kubernetes without relying on webhooks.
- Efficient Type Checking: Validating Admission Policies aims to make good use of CEL type checking, even when considering that CRD schemas can be changed at any time, and not all fields of built-in types exist in older Kubernetes versions.
- Polyfill Implementation: The Kubernetes organization plans to provide a polyfill implementation that offers enhancement functionality to Kubernetes versions where this feature is not available.
- Core Functionality as a Library: Validating Admission Policies intends to provide core functionality as a library, enabling use cases like GitOps, CI/CD pipelines, and auditing to run the same CEL validation checks as the API server. Having said that, Polyfill Implementation and Core Functionality as a Library (points 4 and 5 above) have yet to be implemented, and we should keep an eye out for them in the future.
The Benefits of Validating Admission Policies
The Validating Admission Policies functionality offers several advantages over webhooks, making it a more attractive choice for policy enforcement:
- No Infrastructure Requirement: Validating Admission Policies doesn't require you to build infrastructure to host the admission webhook, simplifying the process.
- Reduced Latency: By eliminating the need for an additional network hop, Validating Admission Policies helps reduce latency, ensuring smoother and faster operations.
- Increased Reliability and Scalability: In-process webhooks used by Validating Admission Policies are less prone to failure than webhooks with extra infrastructure dependencies, enhancing the overall reliability. Beyond this, the in-process admission decision makes the Kubernetes control plane more scaleable since it doesn't depend on an external component.
- Lower Operational Burden: Cluster administrators responsible for the observability, security, and release/rollout/rollback plans for webhooks will experience a lower operational burden with Validating Admission Policies.
Kubescape's Cel-Admission-Library
When Validating Admission Policies was first introduced in beta in version 1.26, the maintainers of Kubescape were eager to utilize it. They created the cel-admission-library based on Kubescape controls originally written in Rego. The library includes the following 27 admission controls:
Using the Kubescape CEL library in your cluster
This section originally appeared in Kubernetes Validating Admission Policies: A Practical Example on the Kubernetes blog.
Policies are provided as Kubernetes objects, which are then bound to certain resources by a selector.
Minikube is a quick and easy way to install and configure a Kubernetes cluster for testing. To install Kubernetes v1.26 with the ValidatingAdmissionPolicy feature gate enabled:
bash minikube start --kubernetes-version=1.30.2 --extra-config=apiserver.runtime-config=admissionregistration.k8s.io/v1alpha1 --feature-gates='ValidatingAdmissionPolicy=true'
To install the policies in your cluster:
# Install configuration CRD
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/policy-configuration-definition.yaml
# Install basic configuration
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/basic-control-configuration.yaml
# Install policies
kubectl apply -f https://github.com/kubescape/cel-admission-library/releases/latest/download/kubescape-validating-admission-policies.yaml
To apply policies to objects, create a ValidatingAdmissionPolicyBinding resource. Let’s apply the above Kubescape C-0017 control to any namespace with the label policy=enforced:
# Create a binding
kubectl apply -f - <<EOT
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: c0017-binding
spec:
policyName: kubescape-c-0017-deny-mutable-container-filesystem
matchResources:
namespaceSelector:
matchLabels:
policy: enforced
EOT
# Create a namespace for running the example
kubectl create namespace policy-example
kubectl label namespace policy-example 'policy=enforced'
Now, if you attempt to create an object without specifying a readOnlyRootFilesystem, it will not be created.
The output shows our error:
bash The pods "nginx" is invalid: : ValidatingAdmissionPolicy 'kubescape-c-0017-deny-mutable-container-filesystem' with binding 'c0017-binding' denied request: Pods having containers with mutable filesystem not allowed! (see more at https://hub.armosec.io/docs/c-0017)
Configuration
Policy objects can include configuration, which is provided in a different object. Many of the Kubescape controls require a configuration: which labels to require, which capabilities to allow or deny, which registries to allow containers to be deployed from, etc. Default values for those controls are defined in the ControlConfiguration object. To use this configuration object, or your own object in the same format, add a paramRef.name value to your binding object:
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: c0001-binding
spec:
policyName: kubescape-c-0001-deny-forbidden-container-registries
paramRef:
name: basic-control-configuration
matchResources:
namespaceSelector:
matchLabels:
policy: enforced
Conclusion
The introduction of Validating Admission Policies in Kubernetes 1.30 is a game-changer, offering a more efficient and reliable way to enforce custom policies. With its numerous benefits and well-defined goals, Validating Admission Policies is set to make a significant impact on the Kubernetes landscape. The cel-admission-library created by Kubescape maintainers is a testament to the potential of this new feature, and we encourage you to try it out using Kubescape. We are happy to contribute this library to the Kubernetes community and will continue to develop it for Kubescape and Kubernetes users alike. We hope it becomes useful, either as something you use yourself, or as examples for you to write your own policies. As for the validating admission policy feature itself, we are very excited to see this native functionality generally available on Kubernetes.