Reusing ValidatingAdmissionPolicies
Kubernetes vanilla Validating policies consist of the following resources:
- ValidatingAdmissionPolicy: describes the logic in CEL. It optionally accepts
also parameters in
spec.paramKind. - ValidatingAdmissionPolicyBinding: scopes the policy.
Let's see a concrete example. These and others can be reused with Kubewarden's
cel-policy with little effort.
ValidatingAdmissionPolicy​
The following ValidatingAdmissionPolicy is adapted from the Kubernetes docs.
This policy checks that the number of Replicas in Deployments is less or equal to a default maxreplicas of 5. Users can override this default per Namespace or Deployment and pick a smaller number via the use of a parameter.
It is bound with a ValidatingAdmissionPolicyBinding so it only affects
Namespaces that have a label environment set to test.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "replicalimit-policy.example.com"
spec:
failurePolicy: Fail # (1)
matchConstraints: # (2)
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
variables: # (3)
- name: maxReplicas # hardcoded global default
expression: int(5)
paramKind: # (4)
apiVersion: v1
kind: ConfigMap # user-provided override
validations: # (5)
- expression: |
object.spec.replicas <= (
has(params.data.overrideReplicas) && int(params.data.overrideReplicas) < variables.maxReplicas
? int(params.data.overrideReplicas)
: variables.maxReplicas
)
messageExpression: |
'The number of replicas must be less than or equal to ' +
string( has(params.data.overrideReplicas) && int(params.data.overrideReplicas) < variables.maxReplicas
? int(params.data.overrideReplicas)
: variables.maxReplicas)
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "replicalimit-binding-test.example.com"
spec:
policyName: "replicalimit-policy.example.com"
validationActions: [Deny] # (7)
matchResources: # (8)
namespaceSelector:
matchLabels:
environment: test
paramRef: # (4)
name: "replica-limit-override"
namespace: "test"
parameterNotFoundAction: Deny
---
apiVersion: v1
kind: ConfigMap
metadata:
name: replica-limit-override
namespace: test
data:
overrideReplicas: "3"
Here we have an equivalent Kubewarden policy:
Kubewarden's cel-policy​
apiVersion: policies.kubewarden.io/v1
kind: ClusterAdmissionPolicy
metadata:
annotations:
io.kubewarden.policy.category: Resource validation # (9)
io.kubewarden.policy.severity: low # (9)
name: "cel-policy-replica-example"
spec:
module: registry://ghcr.io/kubewarden/policies/cel-policy:v1.4.0
failurePolicy: Fail # (6). Webhook behavior. Defaults to "Fail"
mode: protect # (7). Defaults to "protect"
rules: # (2)
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
contextAwareResources: # (10). Fine-grained perms for accessing resources
- apiVersion: v1
kind: ConfigMap
settings:
failurePolicy: Fail # (1). CEL behavior. Defaults to "Fail"
variables: # (3)
- name: maxReplicas
expression: int(5)
paramKind: # (4)
apiVersion: v1
kind: ConfigMap # user-provided override
paramRef: # (4)
name: "replica-limit-override"
namespace: "test"
parameterNotFoundAction: Deny
validations: # (5)
- expression: |
object.spec.replicas <= (
has(params.data.overrideReplicas) && int(params.data.overrideReplicas) < variables.maxReplicas
? int(params.data.overrideReplicas)
: variables.maxReplicas
)
messageExpression: |
'The number of replicas must be less than or equal to ' +
string( has(params.data.overrideReplicas) && int(params.data.overrideReplicas) < variables.maxReplicas
? int(params.data.overrideReplicas)
: variables.maxReplicas)
backgroundAudit: true # (9). Defaults to "true"
namespaceSelector: # (8)
matchLabels:
environment: test
---
apiVersion: v1
kind: ConfigMap
metadata:
name: replica-limit-override
namespace: test
data:
overrideReplicas: "3"
Notice the commented numbers on both the YAML manifests. Let's expand on them:
| # | VAP field | cel-policy field | |
|---|---|---|---|
| 1 | failurePolicy | settings.failurePolicy | CEL behavior, for when CEL expression evaluates to false, there's CEL runtime errors, or there's invalid or mis-configured CEL. For example, a CEL expression returning false, mising parameters, or missing variables. Not to confuse with (6). |
| 2 | matchConstraints | rules | Both accept the same RuleWithOperations that informs on what kind of Resource the policy applies to. |
| 3 | variables | settings.variables | In Kubewarden's cel-policy, expressions that define variables are in settings.variables. Apart from that, they are equivalent. |
| 4 | paramKind,paramRef | settings.paramKind,settings.paramRef | In Kubewarden's cel-policy, parameter definitions are in settings.paramKind, settings.paramRef. Apart from that, they are equivalent. |
| 5 | validations | settings.validations | In Kubewarden's cel-policy, expressions that define validations are in settings.validations. Apart from that, they are equivalent. |
| 6 | --- | failurePolicy | Webhook behavior, for Kubernetes API Webhook error or timeout, or for matchConditions evaluation. Not to confuse with (1). |
| 7 | validationActions | mode | mode has as options protect and monitor. Auditing is more full featured in Kubewarden, see (9). |
| 8 | matchResources | namespaceSelector, objectSelector | Define ways to constraint using Selectors. Kubewarden's policies have them as namespaceSelector and objectSelector. |
| 9 | auditAnnotations (not pictured) | backgroundAudit, annotations | Use Kubewarden fields instead to set the policy usage in Audit Scanner, and its category and severity for OpenReports. |
| 10 | --- | contextAwareResources permissions | Kubewarden's policies have fine-grained permissions for reading cluster Resources. Here it is used for reading the params. |
matchConditions | matchConditions | Kubewarden's policies have matchConditions (not pictured in this example). | |
--- | Kubewarden-only features | For other features, see the rest of tutorial CEL examples. |
You can use the kwctl tool to migrate a VAP policy to Kubewarden.
This VAP migration how-to describes how to do so.
Yet to be implemented equivalences​
There are some VAP features that aren't yet implemented. If look forward to them, please get in contact with us. These are:
- VAP authorizer library.
- VAP Audit Annotations
(ValidatingAdmissionPolicy
spec.auditAnnotationswhen ValidatingAdmissionPolicyBindingspec.validationActionsis set to "Audit"). This is covered by Kubewarden's Audit Scanner and OpenReports, which allows to audit resources already in the cluster. - CEL resource constraints and estimated cost limit. This is partially covered by Kubewarden's general policy timeout protection.
Applying the policy​
As normal, we can deploy our policy by instantiating its manifest:
$ kubectl apply -f ./cel-policy-example.yaml
And then test it by instantiating a deployment:
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
environment: test
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: test
spec:
replicas: 6
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
EOF
namespace/test created
Error from server: error when creating "STDIN":
admission webhook "clusterwide-cel-policy-replica-example.kubewarden.admission" denied the request:
The number of replicas must be less than or equal to 3