test
The test
command is used to test a given set of resources against one or more policies to check desired results, declared in advance in a separate test manifest file, against the actual results. test
is useful when you wish to declare what your expected results should be by defining the intent which then assists with locating discrepancies should those results change.
test
works by scanning a given location, which can be either a Git repository or local folder, and executing the tests defined within. The rule types validate
, mutate
, and generate
are currently supported. The command recursively looks for YAML files with policy test declarations (described below) with a specified file name and then executes those tests. All files applicable to the same test must be co-located. Directory recursion is supported. test
supports the auto-gen feature making it possible to test, for example, Deployment resources against a Pod policy.
test
will search for a file named kyverno-test.yaml
and, if found, will execute the tests within.
In each test, there are four desired results which can be tested for. If the actual result of the test, once executed, matches the desired result as defined in the test manifest, it will be scored as a pass
in the command output. For example, if the specified result of a given test of a resource against a policy is declared to be a pass
and the actual result when tested is also a pass
, the command output will show as pass
. If the actual result was instead a skip
, the command output will show as fail
because the two results do not agree. The following are the desired results which can be specified in a test manifest.
- pass: The resource passes the policy definition. For
validate
rules which are written with adeny
statement, this will not be a possible result.mutate
andgenerate
rules can declare a pass. - skip: The resource does not meet either the
match
orexclude
block, or does not pass thepreconditions
statements. Forvalidate
rules which are written with adeny
statement, this is a possible result. If a rule contains certain conditional anchors which are not satisfied, the result may also be scored as askip
. - fail: The resource does not pass the policy definition. Typically used for
validate
rules with pattern-style policy definitions. - warn: Setting the annotation
policies.kyverno.io/scored
to"false"
on a resource or policy which would otherwise fail will be considered awarn
.
Use --detailed-results
for a comprehensive output (default value false
). For help with the test
command, pass the -h
flag for extensive output including usage, flags, and sample manifests.
Note
The Kyverno CLI via thetest
command does not embed the Kubernetes control plane components and therefore is not able to perform the types of initial mutations subjected to a resource as part of an in-cluster creation flow. Take care to ensure the manifests you test account for these modifications.Test File Structures
The test declaration file format of kyverno-test.yaml
must be of the following format.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: kyverno-test
5policies:
6 - <path/to/policy.yaml>
7 - <path/to/policy.yaml>
8resources:
9 - <path/to/resource.yaml>
10 - <path/to/resource.yaml>
11targetResources: # optional key for specifying target resources when testing for mutate existing rules
12 - <path/to/target-resource.yaml>
13 - <path/to/target-resource.yaml>
14exceptions: # optional files for specifying exceptions. See below for an example.
15 - <path/to/exception.yaml>
16 - <path/to/exception.yaml>
17variables: variables.yaml # optional file for declaring variables. see below for example.
18userinfo: user_info.yaml # optional file for declaring admission request information (roles, cluster roles and subjects). see below for example.
19results:
20- policy: <name> # Namespaced Policy is specified as <namespace>/<name>
21 isValidatingAdmissionPolicy: false # when the policy is ValidatingAdmissionPolicy, this field is required.
22 rule: <name> # when the policy is a Kyverno policy, this field is required.
23 resources: # optional, primarily for `validate` rules.
24 - <namespace_1/name_1>
25 - <namespace_2/name_2>
26 patchedResources: <file_name.yaml> # when testing a mutate rule this field is required. File may contain one or more resources separated by ---
27 generatedResource: <file_name.yaml> # when testing a generate rule this field is required.
28 cloneSourceResource: <file_name.yaml> # when testing a generate rule that uses `clone` object this field is required.
29 kind: <kind> # optional
30 result: pass
31checks:
32- match:
33 resource: {} # match results associated with a resource
34 policy: {} # match results associated with a policy
35 rule: {} # match results associated with a rule
36 assert: {} # assertion to validate the content of matched elements
37 error: {} # negative assertion to validate the content of matched elements
The test declaration consists of the following parts:
- The
policies
element which lists one or more policies to be applied. - The
resources
element which lists one or more resources to which the policies are applied. - The
exceptions
element which lists one or more policy exceptions. Cannot be used with ValidatingAdmissionPolicy. Optional. - The
variables
element which defines a file in which variables and their values are stored for use in the policy test. Optional depending on policy content. - The
userinfo
element which declares admission request data for subjects and roles. Optional depending on policy content. - The
results
element which declares the expected results. Depending on the type of rule being tested, this section may vary. - The
checks
element which declares the assertions to be evaluated against the results (see Working with Assertion Trees).
If needing to pass variables, such as those from external data sources like context variables built from API calls or others, a variables.yaml
file can be defined with the same format as accepted with the apply
command. If a variable needs to contain an array of strings, it must be formatted as JSON encoded. Like with the apply
command, variables that begin with request.object
normally do not need to be specified in the variables file as these will be sourced from the resource. Policies which trigger based upon request.operation
equaling CREATE
do not need a variables file. The CLI will assume a value of CREATE
if no variable for request.operation
is defined.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5policies:
6 - name: exclude-namespaces-example
7 rules:
8 - name: exclude-namespaces-dynamically
9 values:
10 namespacefilters.data.exclude: asdf
11 resources:
12 - name: nonroot-pod
13 values:
14 namespacefilters.data.exclude: foo
15 - name: root-pod
16 values:
17 namespacefilters.data.exclude: "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"
A variables file may also optionally specify global variable values without the need to name specific rules or resources avoiding repetition for the same variable and same value.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5globalValues:
6 request.operation: UPDATE
If policies use a namespaceSelector, these can also be specified in the variables file.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5namespaceSelector:
6 - name: test1
7 labels:
8 foo.com/managed-state: managed
The user can also declare a user_info.yaml
file that can be used to pass admission request information such as roles, cluster roles, and subjects.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: UserInfo
3metadata:
4 name: user-info
5clusterRoles:
6- admin
7userInfo:
8 username: someone@somecorp.com
Testing for subresources in Kind/Subresource
matching format also requires a subresources{}
section in the values file.
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5subresources:
6 - subresource:
7 name: <name of subresource>
8 kind: <kind of subresource>
9 group: <group of subresource>
10 version: <version of subresource>
11 parentResource:
12 name: <name of parent resource>
13 kind: <kind of parent resource>
14 group: <group of parent resource>
15 version: <version of parent resource>
Here is an example when testing for subresources:
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5subresources:
6 - subresource:
7 name: "deployments/scale"
8 kind: "Scale"
9 group: "autoscaling"
10 version: "v1"
11 parentResource:
12 name: "deployments"
13 kind: "Deployment"
14 group: "apps"
15 version: "v1"
Test Against Local Files
Test a set of local files in the working directory.
1kyverno test .
Test a set of local files by specifying the directory.
1kyverno test /path/to/folderContainingTestYamls
Test Against Git Repositories
Test an entire Git repository by specifying the branch name within the repo URL. If branch is not specified, main
will be used as a default.
1kyverno test https://github.com/kyverno/policies/release-1.6
Test a specific directory of the repository by specifying the directory within repo URL and the branch with the --git-branch
or -b
flag. Even if testing against main
, when using a directory in the URL of the repo requires passing the --git-branch
or -b
flag.
1kyverno test https://github.com/kyverno/policies/pod-security/restricted -b release-1.6
Use the -f
flag to set a custom file name which includes test cases. By default, test
will search for a file called kyverno-test.yaml
.
Testing Policies with Image Registry Access
For policies which require image registry access to set context variables, those variables may be sourced from a variables file (defined below) or from a “live” registry by passing the --registry
flag.
Test Subset of Resources
In some cases, you may wish to only test a subset of policy, rules, and/ resource combination rather than all those defined in a test manifest. Use the --test-case-selector
flag to specify the exact tests you wish to execute.
1kyverno test . --test-case-selector "policy=add-default-resources, rule=add-default-requests, resource=nginx-demo2"
Examples
The test command executes a test declaration by applying the policies to the resources and comparing the actual results with the desired/expected results. The test passes if the actual results match the expected results.
Below is an example of testing a policy containing two validate
rules against the same resource where each is supposed to pass the policy.
Policy manifest (disallow_latest_tag.yaml
):
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: disallow-latest-tag
5spec:
6 rules:
7 - name: require-image-tag
8 match:
9 any:
10 - resources:
11 kinds:
12 - Pod
13 validate:
14 failureAction: Audit
15 message: "An image tag is required."
16 pattern:
17 spec:
18 containers:
19 - image: "*:*"
20 - name: validate-image-tag
21 match:
22 any:
23 - resources:
24 kinds:
25 - Pod
26 validate:
27 failureAction: Audit
28 message: "Using a mutable image tag e.g. 'latest' is not allowed."
29 pattern:
30 spec:
31 containers:
32 - image: "!*:latest"
Resource manifest (resource.yaml
):
1apiVersion: v1
2kind: Pod
3metadata:
4 name: myapp-pod
5 labels:
6 app: myapp
7spec:
8 containers:
9 - name: nginx
10 image: nginx:1.12
Test manifest (kyverno-test.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: disallow_latest_tag
5policies:
6 - disallow_latest_tag.yaml
7resources:
8 - resource.yaml
9results:
10 - policy: disallow-latest-tag
11 rule: require-image-tag
12 resources:
13 - myapp-pod
14 kind: Pod
15 result: pass
16 - policy: disallow-latest-tag
17 rule: validate-image-tag
18 resources:
19 - myapp-pod
20 kind: Pod
21 result: pass
1$ kyverno test .
2
3Loading test ( kyverno-test.yaml ) ...
4 Loading values/variables ...
5 Loading policies ...
6 Loading resources ...
7 Loading exceptions ...
8 Applying 1 policy to 1 resource ...
9 Checking results ...
10
11│────│─────────────────────│────────────────────│───────────────│────────│────────│
12│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
13│────│─────────────────────│────────────────────│───────────────│────────│────────│
14│ 1 │ disallow-latest-tag │ require-image-tag │ Pod/myapp-pod │ Pass │ Ok │
15│ 2 │ disallow-latest-tag │ validate-image-tag │ Pod/myapp-pod │ Pass │ Ok │
16│────│─────────────────────│────────────────────│───────────────│────────│────────│
17
18
19Test Summary: 2 tests passed and 0 tests failed
In the below case, a mutate
policy which adds default resources to a Pod is being tested against two resources. Notice the addition of the patchedResource
field in the results[]
array, which is a requirement when testing mutate
rules.
Policy manifest (add-default-resources.yaml
):
1apiVersion : kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: add-default-resources
5spec:
6 background: false
7 rules:
8 - name: add-default-requests
9 match:
10 any:
11 - resources:
12 kinds:
13 - Pod
14 preconditions:
15 any:
16 - key: "{{request.operation}}"
17 operator: AnyIn
18 value:
19 - CREATE
20 - UPDATE
21 mutate:
22 patchStrategicMerge:
23 spec:
24 containers:
25 - (name): "*"
26 resources:
27 requests:
28 +(memory): "100Mi"
29 +(cpu): "100m"
Resource manifest (resource.yaml
):
1apiVersion: v1
2kind: Pod
3metadata:
4 name: nginx-demo1
5spec:
6 containers:
7 - name: nginx
8 image: nginx:1.14.2
9---
10apiVersion: v1
11kind: Pod
12metadata:
13 name: nginx-demo2
14spec:
15 containers:
16 - name: nginx
17 image: nginx:latest
18 resources:
19 requests:
20 memory: "200Mi"
21 cpu: "200m"
Variables manifest (values.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5policies:
6- name: add-default-resources
7 resources:
8 - name: nginx-demo1
9 values:
10 request.operation: CREATE
11 - name: nginx-demo2
12 values:
13 request.operation: UPDATE
Test manifest (kyverno-test.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: add-default-resources
5policies:
6 - add-default-resources.yaml
7resources:
8 - resource.yaml
9variables: values.yaml
10results:
11 - policy: add-default-resources
12 rule: add-default-requests
13 resources:
14 - nginx-demo1
15 patchedResources: patchedResource1.yaml
16 kind: Pod
17 result: pass
18 - policy: add-default-resources
19 rule: add-default-requests
20 resources:
21 - nginx-demo2
22 patchedResources: patchedResource2.yaml
23 kind: Pod
24 result: skip
1$ kyverno test .
2
3Executing add-default-resources...
4applying 1 policy to 2 resources...
5
6skipped mutate policy add-default-resources -> resource default/Pod/nginx-demo2
7│───│───────────────────────│──────────────────────│─────────────────────────│────────│
8│ # │ POLICY │ RULE │ RESOURCE │ RESULT │
9│───│───────────────────────│──────────────────────│─────────────────────────│────────│
10│ 1 │ add-default-resources │ add-default-requests │ default/Pod/nginx-demo1 │ Pass │
11│ 2 │ add-default-resources │ add-default-requests │ default/Pod/nginx-demo2 │ Pass │
12│───│───────────────────────│──────────────────────│─────────────────────────│────────│
13
14Test Summary: 2 tests passed and 0 tests failed
In this scenario, a mutate
policy which adds a label to Secrets
based on requests made on a particular ConfigMap
,
note the use of the targetResources
field.
Test manifest (kyverno-test.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: kyverno-test.yaml
5policies:
6- policy.yaml
7resources:
8- trigger-cm.yaml
9targetResources:
10- raw-secret.yaml
11results:
12- patchedResource: mutated-secret.yaml
13 policy: mutate-existing-secret
14 resources:
15 - secret-1
16 result: pass
17 rule: mutate-secret-on-configmap-create
Policy (policy.yaml
):
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: mutate-existing-secret
5spec:
6 rules:
7 - match:
8 any:
9 - resources:
10 kinds:
11 - ConfigMap
12 names:
13 - dictionary-1
14 namespaces:
15 - staging
16 mutate:
17 mutateExistingOnPolicyUpdate: false
18 patchStrategicMerge:
19 metadata:
20 labels:
21 foo: bar
22 targets:
23 - apiVersion: v1
24 kind: Secret
25 name: '*'
26 namespace: staging
27 name: mutate-secret-on-configmap-create
Trigger (trigger-cm.yaml
):
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: dictionary-1
5 namespace: staging
Target (raw-secret.yaml
):
1apiVersion: v1
2kind: Secret
3metadata:
4 name: secret-1
5 namespace: staging
Mutated target (mutated-secret.yaml
):
1apiVersion: v1
2kind: Secret
3metadata:
4 labels:
5 foo: bar
6 name: secret-1
7 namespace: staging
1$ kyverno test .
2Loading test ( 3-test/kyverno-test.yaml ) ...
3 Loading values/variables ...
4 Loading policies ...
5 Loading resources ...
6 Loading exceptions ...
7 Applying 1 policy to 1 resource ...
8 Checking results ...
9
10│────│────────────────────────│───────────────────────────────────│────────────────────────────│────────│────────│
11│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
12│────│────────────────────────│───────────────────────────────────│────────────────────────────│────────│────────│
13│ 1 │ mutate-existing-secret │ mutate-secret-on-configmap-create │ v1/Secret/staging/secret-1 │ Pass │ Ok │
14│────│────────────────────────│───────────────────────────────────│────────────────────────────│────────│────────│
15
16
17Test Summary: 1 tests passed and 0 tests failed
If you don’t specify an entry in the resources
field in the results the CLI will check results for all trigger and target resources involved in the test and will match them against the resources specified in the patchedResources
file:
Patched resources (mutated-resources.yaml
):
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: dictionary-1
5 namespace: staging
6---
7apiVersion: v1
8kind: Secret
9metadata:
10 labels:
11 foo: bar
12 name: secret-1
13 namespace: staging
14---
Loading test ( 5-test-with-selection/kyverno-test.yaml ) ...
Loading values/variables ...
Loading policies ...
Loading resources ...
Loading exceptions ...
Applying 1 policy to 1 resource ...
Checking results ...
│────│────────────────────────│───────────────────────────────────│───────────────────────────────────│────────│────────│
│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
│────│────────────────────────│───────────────────────────────────│───────────────────────────────────│────────│────────│
│ 1 │ mutate-existing-secret │ mutate-secret-on-configmap-create │ v1/Secret/staging/secret-1 │ Pass │ Ok │
│ 2 │ mutate-existing-secret │ mutate-secret-on-configmap-create │ v1/ConfigMap/staging/dictionary-1 │ Pass │ Ok │
│────│────────────────────────│───────────────────────────────────│───────────────────────────────────│────────│────────│
Test Summary: 2 tests passed and 0 tests failed
In the following policy test, a generate
policy rule is applied which generates a new resource from an existing resource present in resource.yaml
. To test the generate
policy, the addition of a generatedResource
field in the results[]
array is required which is used to test against the resource generated by the policy.
Policy manifest (add_network_policy.yaml
):
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: add-networkpolicy
5spec:
6 rules:
7 - name: default-deny
8 match:
9 any:
10 - resources:
11 kinds:
12 - Namespace
13 generate:
14 apiVersion: networking.k8s.io/v1
15 kind: NetworkPolicy
16 name: default-deny
17 namespace: "{{request.object.metadata.name}}"
18 synchronize: true
19 data:
20 spec:
21 podSelector: {}
22 policyTypes:
23 - Ingress
24 - Egress
Resource manifest (resource.yaml
):
1apiVersion: v1
2kind: Namespace
3metadata:
4 name: hello-world-namespace
Generated Resource (generatedResource.yaml
):
1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4 name: default-deny
5 namespace: hello-world-namespace
6spec:
7 podSelector: {}
8 policyTypes:
9 - Ingress
10 - Egress
Test manifest (kyverno-test.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: deny-all-traffic
5policies:
6 - add_network_policy.yaml
7resources:
8 - resource.yaml
9results:
10 - policy: add-networkpolicy
11 rule: default-deny
12 resources:
13 - hello-world-namespace
14 generatedResource: generatedResource.yaml
15 kind: Namespace
16 result: pass
1$ kyverno test .
2Executing deny-all-traffic...
3applying 1 policy to 1 resource...
4
5│───│───────────────────│──────────────│──────────────────────────────────│────────│
6│ # │ POLICY │ RULE │ RESOURCE │ RESULT │
7│───│───────────────────│──────────────│──────────────────────────────────│────────│
8│ 1 │ add-networkpolicy │ default-deny │ /Namespace/hello-world-namespace │ Pass │
9│───│───────────────────│──────────────│──────────────────────────────────│────────│
10Test Summary: 1 tests passed and 0 tests failed
In the following policy test, a validate
rule ensures that Pods aren’t allowed to access host namespaces. A Policy Exception is used to exempt Pods and Deployments beginning with the name important-tool
in the delta
namespace from this rule. The exceptions
field is used in the Test manifest to declare a Policy Exception manifest. It is expected that resources that violate the rule but match policy exceptions will be skipped. Otherwise, they will fail.
Policy manifest (disallow-host-namespaces.yaml
):
1apiVersion: kyverno.io/v2beta1
2kind: ClusterPolicy
3metadata:
4 name: disallow-host-namespaces
5spec:
6 background: false
7 rules:
8 - name: host-namespaces
9 match:
10 any:
11 - resources:
12 kinds:
13 - Pod
14 validate:
15 failureAction: Enforce
16 message: >-
17 Sharing the host namespaces is disallowed. The fields spec.hostNetwork,
18 spec.hostIPC, and spec.hostPID must be unset or set to `false`.
19 pattern:
20 spec:
21 =(hostPID): "false"
22 =(hostIPC): "false"
23 =(hostNetwork): "false"
Policy Exception manifest (delta-exception.yaml
):
1apiVersion: kyverno.io/v2
2kind: PolicyException
3metadata:
4 name: delta-exception
5 namespace: delta
6spec:
7 exceptions:
8 - policyName: disallow-host-namespaces
9 ruleNames:
10 - host-namespaces
11 - autogen-host-namespaces
12 match:
13 any:
14 - resources:
15 kinds:
16 - Pod
17 - Deployment
18 namespaces:
19 - delta
20 names:
21 - important-tool*
Resource manifest (resource.yaml
):
Both Deployments violate the policy but only one matches an exception. The Deployment without an exception will fail while the one with an exception will be skipped.
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: important-tool
5 namespace: delta
6 labels:
7 app: busybox
8spec:
9 replicas: 1
10 selector:
11 matchLabels:
12 app: busybox
13 template:
14 metadata:
15 labels:
16 app: busybox
17 spec:
18 hostIPC: true
19 containers:
20 - image: busybox:1.35
21 name: busybox
22 command: ["sleep", "1d"]
23---
24apiVersion: apps/v1
25kind: Deployment
26metadata:
27 name: not-important
28 namespace: gamma
29 labels:
30 app: busybox
31spec:
32 replicas: 1
33 selector:
34 matchLabels:
35 app: busybox
36 template:
37 metadata:
38 labels:
39 app: busybox
40 spec:
41 hostIPC: true
42 containers:
43 - image: busybox:1.35
44 name: busybox
45 command: ["sleep", "1d"]
Test manifest (kyverno-test.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: disallow-host-namespaces-test-exception
5policies:
6- disallow-host-namespace.yaml
7resources:
8- resource.yaml
9exceptions:
10- delta-exception.yaml
11results:
12 - kind: Deployment
13 policy: disallow-host-namespaces
14 resources:
15 - important-tool
16 rule: host-namespaces
17 result: skip
18 - kind: Deployment
19 policy: disallow-host-namespaces
20 resources:
21 - not-important
22 rule: host-namespaces
23 result: fail
1kyverno test .
2
3Loading test ( .kyverno-test/kyverno-test.yaml ) ...
4 Loading values/variables ...
5 Loading policies ...
6 Loading resources ...
7 Loading exceptions ...
8 Applying 1 policy to 2 resources with 1 exception ...
9 Checking results ...
10
11│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
12│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
13│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
14│ 1 │ disallow-host-namespaces │ host-namespaces │ Deployment/important-tool │ Pass │ Ok │
15│ 2 │ disallow-host-namespaces │ host-namespaces │ Deployment/not-important │ Pass │ Ok │
16│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
17
18
19Test Summary: 2 tests passed and 0 tests failed
For many more examples of test cases, please see the kyverno/policies repository which strives to have test cases for all the sample policies which appear on the website.
Testing ValidatingAdmissionPolicies
Below is an example of testing a ValidatingAdmissionPolicy against two resources, one of which violates the policy.
Policy manifest (disallow-host-path.yaml):
1apiVersion: admissionregistration.k8s.io/v1
2kind: ValidatingAdmissionPolicy
3metadata:
4 name: disallow-host-path
5spec:
6 failurePolicy: Fail
7 matchConstraints:
8 resourceRules:
9 - apiGroups: ["apps"]
10 apiVersions: ["v1"]
11 operations: ["CREATE", "UPDATE"]
12 resources: ["deployments"]
13 validations:
14 - expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
15 message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."
Resource manifest (deployments.yaml):
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: deployment-pass
5spec:
6 replicas: 1
7 selector:
8 matchLabels:
9 app: nginx
10 template:
11 metadata:
12 labels:
13 app: nginx
14 spec:
15 containers:
16 - name: nginx-server
17 image: nginx
18 volumeMounts:
19 - name: temp
20 mountPath: /scratch
21 volumes:
22 - name: temp
23 emptyDir: {}
24---
25apiVersion: apps/v1
26kind: Deployment
27metadata:
28 name: deployment-fail
29spec:
30 replicas: 1
31 selector:
32 matchLabels:
33 app: nginx
34 template:
35 metadata:
36 labels:
37 app: nginx
38 spec:
39 containers:
40 - name: nginx-server
41 image: nginx
42 volumeMounts:
43 - name: udev
44 mountPath: /data
45 volumes:
46 - name: udev
47 hostPath:
48 path: /etc/udev
Test manifest (kyverno-test.yaml):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: disallow-host-path-test
5policies:
6 - disallow-host-path.yaml
7resources:
8 - deployments.yaml
9results:
10 - policy: disallow-host-path
11 resources:
12 - deployment-pass
13 isValidatingAdmissionPolicy: true
14 kind: Deployment
15 result: pass
16 - policy: disallow-host-path
17 resources:
18 - deployment-fail
19 isValidatingAdmissionPolicy: true
20 kind: Deployment
21 result: fail
1$ kyverno test .
2
3Loading test ( kyverno-test.yaml ) ...
4 Loading values/variables ...
5 Loading policies ...
6 Loading resources ...
7 Applying 1 policy to 2 resources ...
8 Checking results ...
9
10│────│────────────────────│──────│────────────────────────────│────────│────────│
11│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
12│────│────────────────────│──────│────────────────────────────│────────│────────│
13│ 1 │ disallow-host-path │ │ Deployment/deployment-pass │ Pass │ Ok │
14│ 2 │ disallow-host-path │ │ Deployment/deployment-fail │ Pass │ Ok │
15│────│────────────────────│──────│────────────────────────────│────────│────────│
16
17
18Test Summary: 2 tests passed and 0 tests failed
In the below example, a ValidatingAdmissionPolicy
and its corresponding ValidatingAdmissionPolicyBinding
are tested against six resources. Two of these resources do not match the binding, two match the binding but violate the policy, and the remaining two match the binding and do not violate the policy.
Policy manifest (check-deployment-replicas.yaml
):
1apiVersion: admissionregistration.k8s.io/v1
2kind: ValidatingAdmissionPolicy
3metadata:
4 name: "check-deployment-replicas"
5spec:
6 matchConstraints:
7 resourceRules:
8 - apiGroups:
9 - apps
10 apiVersions:
11 - v1
12 operations:
13 - CREATE
14 - UPDATE
15 resources:
16 - deployments
17 validations:
18 - expression: object.spec.replicas <= 2
19---
20apiVersion: admissionregistration.k8s.io/v1
21kind: ValidatingAdmissionPolicyBinding
22metadata:
23 name: "check-deployment-replicas-binding"
24spec:
25 policyName: "check-deployment-replicas"
26 validationActions: [Deny]
27 matchResources:
28 namespaceSelector:
29 matchExpressions:
30 - key: environment
31 operator: In
32 values:
33 - staging
34 - production
Resource manifest (resource.yaml
):
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: testing-deployment-1
5 namespace: testing
6 labels:
7 app: busybox
8spec:
9 replicas: 4
10 selector:
11 matchLabels:
12 app: busybox
13 template:
14 metadata:
15 labels:
16 app: busybox
17 spec:
18 containers:
19 - name: busybox
20 image: busybox:latest
21---
22apiVersion: apps/v1
23kind: Deployment
24metadata:
25 name: testing-deployment-2
26 namespace: testing
27 labels:
28 app: busybox
29spec:
30 replicas: 2
31 selector:
32 matchLabels:
33 app: busybox
34 template:
35 metadata:
36 labels:
37 app: busybox
38 spec:
39 containers:
40 - name: busybox
41 image: busybox:latest
42---
43apiVersion: apps/v1
44kind: Deployment
45metadata:
46 name: staging-deployment-1
47 namespace: staging
48 labels:
49 app: nginx
50spec:
51 replicas: 4
52 selector:
53 matchLabels:
54 app: nginx
55 template:
56 metadata:
57 labels:
58 app: nginx
59 spec:
60 containers:
61 - name: nginx
62 image: nginx:latest
63---
64apiVersion: apps/v1
65kind: Deployment
66metadata:
67 name: staging-deployment-2
68 namespace: staging
69 labels:
70 app: nginx
71spec:
72 replicas: 2
73 selector:
74 matchLabels:
75 app: nginx
76 template:
77 metadata:
78 labels:
79 app: nginx
80 spec:
81 containers:
82 - name: nginx
83 image: nginx:latest
84---
85apiVersion: apps/v1
86kind: Deployment
87metadata:
88 name: production-deployment-1
89 namespace: production
90 labels:
91 app: nginx
92spec:
93 replicas: 4
94 selector:
95 matchLabels:
96 app: nginx
97 template:
98 metadata:
99 labels:
100 app: nginx
101 spec:
102 containers:
103 - name: nginx
104 image: nginx:latest
105---
106apiVersion: apps/v1
107kind: Deployment
108metadata:
109 name: production-deployment-2
110 namespace: production
111 labels:
112 app: nginx
113spec:
114 replicas: 2
115 selector:
116 matchLabels:
117 app: nginx
118 template:
119 metadata:
120 labels:
121 app: nginx
122 spec:
123 containers:
124 - name: nginx
125 image: nginx:latest
The above resource manifest contains the following:
Two Deployments named
testing-deployment-1
andtesting-deployment-2
in thetesting
namespace. The first Deployment has four replicas, while the second Deployment has two.Two Deployments named
staging-deployment-1
andstaging-deployment-2
in thestaging
namespace. The first Deployment has four replicas, while the second Deployment has two.Two Deployments named
production-deployment-1
andproduction-deployment-2
in theproduction
namespace. The first Deployment has four replicas, while the second Deployment has two.
Variables manifest (values.yaml
):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4 name: values
5namespaceSelector:
6 - name: staging
7 labels:
8 environment: staging
9 - name: production
10 labels:
11 environment: production
12 - name: testing
13 labels:
14 environment: testing
Test manifest (kyverno-test.yaml):
1apiVersion: cli.kyverno.io/v1alpha1
2kind: Test
3metadata:
4 name: kyverno-test.yaml
5policies:
6- policy.yaml
7resources:
8- resource.yaml
9variables: values.yaml
10results:
11- kind: Deployment
12 policy: check-deployment-replicas
13 isValidatingAdmissionPolicy: true
14 resources:
15 - testing-deployment-1
16 - testing-deployment-2
17 result: skip
18- kind: Deployment
19 policy: check-deployment-replicas
20 isValidatingAdmissionPolicy: true
21 resources:
22 - staging-deployment-1
23 - production-deployment-1
24 result: fail
25- kind: Deployment
26 policy: check-deployment-replicas
27 isValidatingAdmissionPolicy: true
28 resources:
29 - staging-deployment-2
30 - production-deployment-2
31 result: pass
1$ kyverno test .
2
3Loading test ( kyverno-test.yaml ) ...
4 Loading values/variables ...
5 Loading policies ...
6 Loading resources ...
7 Loading exceptions ...
8 Applying 1 policy to 6 resources ...
9 Checking results ...
10
11│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
12│ ID │ POLICY │ RULE │ RESOURCE │ RESULT │ REASON │
13│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
14│ 1 │ check-deployment-replicas │ │ Deployment/testing-deployment-1 │ Pass │ Excluded │
15│ 2 │ check-deployment-replicas │ │ Deployment/testing-deployment-2 │ Pass │ Excluded │
16│ 3 │ check-deployment-replicas │ │ Deployment/staging-deployment-1 │ Pass │ Ok │
17│ 4 │ check-deployment-replicas │ │ Deployment/production-deployment-1 │ Pass │ Ok │
18│ 5 │ check-deployment-replicas │ │ Deployment/staging-deployment-2 │ Pass │ Ok │
19│ 6 │ check-deployment-replicas │ │ Deployment/production-deployment-2 │ Pass │ Ok │
20│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
21
22
23Test Summary: 6 tests passed and 0 tests failed
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.