Applying Validating Admission Policies using Kyverno CLI
The Kyverno Command Line Interface (CLI) allows applying policies outside of Kubernetes clusters and can validate and test policy behavior prior to adding them to a cluster.
The two commands used for testing are apply
and test
:
- The
apply
command is used to perform a dry run on one or more policies for the given manifest(s). - The
test
command is used to test a given set of resources against one or more policies to check the desired results defined in a special test manifest.
In this post, I will show you how you can apply/test Kubernetes ValidatingAdmissionPolicies that were first introduced in 1.26 with the enhancements to the Kyverno CLI in v1.11.
Applying ValidatingAdmissionPolicies using kyverno apply
In this section, you will create a ValidatingAdmissionPolicy that checks the number of Deployment replicas. You will then apply this policy to two Deployments, one of which violates the policy:
1cat << EOF > check-deployment-replicas.yaml
2apiVersion: admissionregistration.k8s.io/v1alpha1
3kind: ValidatingAdmissionPolicy
4metadata:
5 name: check-deployments-replicas
6spec:
7 failurePolicy: Fail
8 matchConstraints:
9 resourceRules:
10 - apiGroups: ["apps"]
11 apiVersions: ["v1"]
12 operations: ["CREATE", "UPDATE"]
13 resources: ["deployments"]
14 validations:
15 - expression: "object.spec.replicas <= 2"
16 message: "Replicas must be less than or equal 2"
17EOF
The following deployment satisfies the rules declared in the above policy.
1cat << EOF > deployment-pass.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: nginx-pass
6spec:
7 replicas: 2
8 selector:
9 matchLabels:
10 app: nginx-pass
11 template:
12 metadata:
13 labels:
14 app: nginx-pass
15 spec:
16 containers:
17 - name: nginx-server
18 image: nginx
19EOF
Let’s apply the policy to the resource using kyverno apply
as follows.
1kyverno apply ./check-deployment-replicas.yaml --resource deployment-pass.yaml
The output should be the following.
1Applying 1 policy rule(s) to 1 resource(s)...
2
3pass: 1, fail: 0, warn: 0, error: 0, skip: 0
Let’s try to create another deployment that violates the policy.
1cat << EOF > deployment-fail.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: nginx-fail
6spec:
7 replicas: 3
8 selector:
9 matchLabels:
10 app: nginx-fail
11 template:
12 metadata:
13 labels:
14 app: nginx-fail
15 spec:
16 containers:
17 - name: nginx-server
18 image: nginx
19EOF
Then apply the policy to the resource as follows.
1kyverno apply ./check-deployment-replicas.yaml --resource deployment-fail.yaml
The output should be as shown.
1Applying 1 policy rule(s) to 1 resource(s)...
2
3pass: 0, fail: 1, warn: 0, error: 0, skip: 0
Testing ValidatingAdmissionPolicies using kyverno test
In this section, you will create a ValidatingAdmissionPolicy that ensures no hostPath
volumes are in use for Deployments. You will then create two Deployments to test them against the policy and check the desired results.
To proceed, you need to create a directory containing the necessary manifests. In this example, I created a directory called test-dir
.
Let’s start with creating the policy.
1cat << EOF > ./test-dir/disallow-host-path.yaml
2apiVersion: admissionregistration.k8s.io/v1alpha1
3kind: ValidatingAdmissionPolicy
4metadata:
5 name: disallow-host-path
6spec:
7 failurePolicy: Fail
8 matchConstraints:
9 resourceRules:
10 - apiGroups: ["apps"]
11 apiVersions: ["v1"]
12 operations: ["CREATE", "UPDATE"]
13 resources: ["deployments"]
14 validations:
15 - expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
16 message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."
17EOF
Then, create the two Deployments, one of which violates the policy.
1cat << EOF > ./test-dir/deployments.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata:
5 name: deployment-pass
6spec:
7 replicas: 1
8 selector:
9 matchLabels:
10 app: nginx
11 template:
12 metadata:
13 labels:
14 app: nginx
15 spec:
16 containers:
17 - name: nginx-server
18 image: nginx
19 volumeMounts:
20 - name: temp
21 mountPath: /scratch
22 volumes:
23 - name: temp
24 emptyDir: {}
25---
26apiVersion: apps/v1
27kind: Deployment
28metadata:
29 name: deployment-fail
30spec:
31 replicas: 1
32 selector:
33 matchLabels:
34 app: nginx
35 template:
36 metadata:
37 labels:
38 app: nginx
39 spec:
40 containers:
41 - name: nginx-server
42 image: nginx
43 volumeMounts:
44 - name: udev
45 mountPath: /data
46 volumes:
47 - name: udev
48 hostPath:
49 path: /etc/udev
50EOF
The tests are defined in a file named kyverno-test.yaml
so you will create two tests, one for each Deployment and test them against the policy. Notice the use of a new field in the test manifest called isValidatingAdmissionPolicy
.
1cat << EOF > ./test-dir/kyverno-test.yaml
2name: disallow-host-path-test
3policies:
4 - disallow-host-path.yaml
5resources:
6 - deployments.yaml
7results:
8 - policy: disallow-host-path
9 resource: deployment-pass
10 isValidatingAdmissionPolicy: true
11 kind: Deployment
12 result: pass
13 - policy: disallow-host-path
14 resource: deployment-fail
15 isValidatingAdmissionPolicy: true
16 kind: Deployment
17 result: fail
18EOF
Now, we’re ready to test the two Deployments against a ValidatingAdmissionPolicy.
1kyverno test ./test-dir
The output should be as shown below.
1Executing disallow-host-path-test...
2
3│────│────────────────────│──────│────────────────────────────│────────│────────│
4│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
5│────│────────────────────│──────│────────────────────────────│────────│────────│
6│ 1 │ disallow-host-path │ │ Deployment/deployment-pass │ Pass │ Ok │
7│ 2 │ disallow-host-path │ │ Deployment/deployment-fail │ Pass │ Ok │
8│────│────────────────────│──────│────────────────────────────│────────│────────│
9
10Test Summary: 2 tests passed and 0 tests failed
As expected, the two tests passed because the actual result of each test matches the desired result as defined in the test manifest.
Conclusion
This blog post explains how to apply ValidatingAdmissionPolicies to resources using the Kyverno CLI. With Kyverno, it’s easy to apply Kubernetes ValidatingAdmissionPolicies in your CI/CD pipelines and to test new ValidatingAdmissionPolicies before they are deployed to your clusters. This is one of many exciting features coming with Kyverno v1.11.