Kyverno CLI

Apply and test policies outside a cluster.

The Kyverno Command Line Interface (CLI) is designed to validate and test policy behavior to resources prior to adding them to a cluster. The CLI can be used in CI/CD pipelines to assist with the resource authoring process to ensure they conform to standards prior to them being deployed. It can be used as a kubectl plugin or as a standalone CLI.

Building and Installing the CLI

Install via Krew

You can use Krew to install the Kyverno CLI:

1# Install Kyverno CLI using kubectl krew plugin manager
2kubectl krew install kyverno
3
4# test the Kyverno CLI
5kubectl kyverno version  

Install via AUR (archlinux)

You can install the Kyverno CLI via your favorite AUR helper (e.g. yay)

1yay -S kyverno-git

Building the CLI from source

You can also build the CLI binary from the Git repository (requires Go).

1git clone https://github.com/kyverno/kyverno
2cd kyverno
3make cli
4mv ./cmd/cli/kubectl-kyverno/kyverno /usr/local/bin/kyverno

CLI Commands

When using the Kyverno CLI with kustomize, it is recommended to use the “standalone” version as opposed to the version embedded inside kubectl.

Apply

The apply command is used to perform a dry run on one or more policies with a given set of input resources. This can be useful to determine a policy’s effectiveness prior to committing to a cluster. In the case of mutate policies, the apply command can show the mutated resource as an output. The input resources can either be resource manifests (one or multiple) or can be taken from a running Kubernetes cluster.

Apply to a resource:

1kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml

Apply a policy to all matching resources in a cluster based on the current kubectl context:

1kyverno apply /path/to/policy.yaml --cluster

The resources can also be passed from stdin:

1kustomize build nginx/overlays/envs/prod/ | kyverno apply /path/to/policy.yaml --resource -

Apply multiple policies to multiple resources:

1kyverno apply /path/to/policy1.yaml /path/to/folderFullOfPolicies --resource /path/to/resource1.yaml --resource /path/to/resource2.yaml --cluster

Apply a mutation policy to a specific resource:

1kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml
2
3applying 1 policy to 1 resource... 
4
5mutate policy <policy_name> applied to <resource_name>:
6<final mutated resource output>

Save the mutated resource to a file:

1kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml -o newresource.yaml

Save the mutated resource to a directory:

1kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml -o foo/

Apply a policy containing variables using the --set or -s flag to pass in the values. Variables that begin with {{request.object}} normally do not need to be specified as these will be read from the resource.

1kyverno apply /path/to/policy.yaml --resource /path/to/resource.yaml --set <variable1>=<value1>,<variable2>=<value2>

Use -f or --values-file for applying multiple policies to multiple resources while passing a file containing variables and their values. Variables specified can be of various types include AdmissionReview fields, ConfigMap context data (Kyverno 1.3.6), and API call context data (Kyverno 1.3.6).

1kyverno apply /path/to/policy1.yaml /path/to/policy2.yaml --resource /path/to/resource1.yaml --resource /path/to/resource2.yaml -f /path/to/value.yaml

Format of value.yaml:

 1policies:
 2  - name: <policy1 name>
 3    resources:
 4      - name: <resource1 name>
 5        values:
 6          <variable1 in policy1>: <value>
 7          <variable2 in policy1>: <value>
 8      - name: <resource2 name>
 9        values:
10          <variable1 in policy1>: <value>
11          <variable2 in policy1>: <value>
12  - name: <policy2 name>
13    resources:
14      - name: <resource1 name>
15        values:
16          <variable1 in policy2>: <value>
17          <variable2 in policy2>: <value>
18      - name: <resource2 name>
19        values:
20          <variable1 in policy2>: <value>
21          <variable2 in policy2>: <value>

Example:

Policy manifest (add_network_policy.yaml):

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: add-networkpolicy
 5  annotations:
 6    policies.kyverno.io/category: Workload Management
 7    policies.kyverno.io/description: By default, Kubernetes allows communications across
 8      all pods within a cluster. Network policies and, a CNI that supports network policies,
 9      must be used to restrict communications. A default NetworkPolicy should be configured
10      for each namespace to default deny all ingress traffic to the pods in the namespace.
11      Application teams can then configure additional NetworkPolicy resources to allow
12      desired traffic to application pods from select sources.
13spec:
14  rules:
15  - name: default-deny-ingress
16    match:
17      resources:
18        kinds:
19        - Namespace
20    generate:
21      kind: NetworkPolicy
22      name: default-deny-ingress
23      namespace: "{{request.object.metadata.name}}"
24      synchronize: true
25      data:
26        spec:
27          # select all pods in the namespace
28          podSelector: {}
29          policyTypes:
30          - Ingress

Resource manifest (required_default_network_policy.yaml):

1kind: Namespace
2apiVersion: v1
3metadata:
4  name: devtest

Apply a policy to a resource using the --set or -s flag:

1kyverno apply /path/to/add_network_policy.yaml --resource /path/to/required_default_network_policy.yaml -s request.object.metadata.name=devtest

Apply a policy to a resource using the --values-file or -f flag:

YAML file containing variables (value.yaml):

1policies:
2  - name: default-deny-ingress
3    resources:
4      - name: devtest
5        values:
6          request.namespace: devtest
1kyverno apply /path/to/add_network_policy.yaml --resource /path/to/required_default_network_policy.yaml -f /path/to/value.yaml

Apply a policy with the Namespace selector:

Use --values-file for passing a file containing Namespace details. Check here to know more about Namespace selector.

1kyverno apply /path/to/policy1.yaml /path/to/policy2.yaml --resource /path/to/resource1.yaml --resource /path/to/resource2.yaml -f /path/to/value.yaml

Format of value.yaml:

1namespaceSelector:
2  - name: <namespace1 name>
3    labels:
4      <namespace label key>: <namespace label value>
5  - name: <namespace2 name>
6    labels:
7      <namespace label key>: <namespace label value>

Example:

Policy manifest (enforce-pod-name.yaml):

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: enforce-pod-name
 5spec:
 6  validationFailureAction: audit
 7  background: true
 8  rules:
 9    - name: validate-name
10      match:
11        resources:
12          kinds:
13            - Pod
14          namespaceSelector:
15            matchExpressions:
16            - key: foo.com/managed-state
17              operator: In
18              values:
19              - managed
20      validate:
21        message: "The Pod must end with -nginx"
22        pattern:
23          metadata:
24            name: "*-nginx"

Resource manifest (nginx.yaml):

1kind: Pod
2apiVersion: v1
3metadata:
4  name: test-nginx
5  namespace: test1
6spec:
7  containers:
8  - name: nginx
9    image: nginx:latest

Namespace manifest (namespace.yaml):

1apiVersion: v1
2kind: Namespace
3metadata:
4  name: test1
5  labels:
6    foo.com/managed-state: managed

YAML file containing variables (value.yaml):

1namespaceSelector:
2  - name: test1
3    labels:
4      foo.com/managed-state: managed

To test the above policy, use the following command:

1kyverno apply /path/to/enforce-pod-name.yaml --resource /path/to/nginx.yaml -f /path/to/value.yaml

Policy Report

Policy reports provide information about policy execution and violations. Use --policy-report with the apply command to generate a policy report for validate policies. mutate and generate policies do not trigger policy reports.

Policy reports can also be generated for a live cluster. While generating a policy report for a live cluster the -r flag, which declares a resource, is assumed to be globally unique. And it doesn’t support naming the resource type (ex., Pod/foo when the cluster contains resources of different types with the same name). To generate a policy report for a live cluster use --cluster with --policy-report.

1kyverno apply policy.yaml --cluster --policy-report

Above example applies a policy.yaml to all resources in the cluster.

Below are the combination of inputs that can be used for generating the policy report from the Kyverno CLI.

Policy Resource Cluster Namespace Interpretation
policy.yaml -r resource.yaml false Apply policy from policy.yaml to the resources specified in resource.yaml
policy.yaml -r resourceName true Apply policy from policy.yaml to the resource with a given name in the cluster
policy.yaml true Apply policy from policy.yaml to all the resources in the cluster
policy.yaml -r resourceName true -n=namespaceName Apply policy from policy.yaml to the resource with a given name in a specific Namespace
policy.yaml true -n=namespaceName Apply policy from policy.yaml to all the resources in a specific Namespace

Example:

Consider the following policy and resources:

policy.yaml

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: require-pod-requests-limits
 5  annotations:
 6    policies.kyverno.io/category: Workload Management
 7    policies.kyverno.io/description: >-
 8      As application workloads share cluster resources, it is important to limit resources
 9      requested and consumed by each pod. It is recommended to require 'resources.requests'
10      and 'resources.limits' per pod. If a namespace level request or limit is specified,
11      defaults are automatically applied to each pod based on the 'LimitRange' configuration.      
12spec:
13  validationFailureAction: audit
14  rules:
15  - name: validate-resources
16    match:
17      resources:
18        kinds:
19        - Pod
20    validate:
21      message: "CPU and memory resource requests and limits are required"
22      pattern:
23        spec:
24          containers:
25          - resources:
26              requests:
27                memory: "?*"
28                cpu: "?*"
29              limits:
30                memory: "?*"

resource1.yaml

 1apiVersion: v1
 2kind: Pod
 3metadata:
 4  name: nginx1
 5  labels:
 6    env: test
 7spec:
 8  containers:
 9  - name: nginx
10    image: nginx
11    imagePullPolicy: IfNotPresent
12    resources:
13      requests:
14        memory: "64Mi"
15        cpu: "250m"
16      limits:
17        memory: "128Mi"
18        cpu: "500m"

resource2.yaml

 1apiVersion: v1
 2kind: Pod
 3metadata:
 4  name: nginx2
 5  labels:
 6    env: test
 7spec:
 8  containers:
 9  - name: nginx
10    image: nginx
11    imagePullPolicy: IfNotPresent

Case 1: Apply a policy manifest to multiple resource manifests

1kyverno apply policy.yaml -r resource1.yaml -r resource2.yaml --policy-report

Case 2: Apply a policy manifest to multiple resources in the cluster

Create the resources by first applying manifests resource1.yaml and resource2.yaml.

1kyverno apply policy.yaml -r nginx1 -r nginx2 --cluster --policy-report

Case 3: Apply a policy manifest to all resources in the cluster

1kyverno apply policy.yaml --cluster --policy-report

Given the contents of policy.yaml shown earlier, this will produce a report validating against all Pods in the cluster.

Case 4: Apply a policy manifest to multiple resources by name within a specific Namespace

1kyverno apply policy.yaml -r nginx1 -r nginx2 --cluster --policy-report -n default

Case 5: Apply a policy manifest to all resources within the default Namespace

1kyverno apply policy.yaml --cluster --policy-report -n default

Given the contents of policy.yaml shown earlier, this will produce a report validating all Pods within the default Namespace.

On applying policy.yaml to the mentioned resources, the following report will be generated:

 1apiVersion: wgpolicyk8s.io/v1alpha1
 2kind: ClusterPolicyReport
 3metadata:
 4  name: clusterpolicyreport
 5results:
 6- message: Validation rule 'validate-resources' succeeded.
 7  policy: require-pod-requests-limits
 8  resources:
 9  - apiVersion: v1
10    kind: Pod
11    name: nginx1
12    namespace: default
13  rule: validate-resources
14  scored: true
15  status: pass
16- message: 'Validation error: CPU and memory resource requests and limits are required; Validation rule validate-resources failed at path /spec/containers/0/resources/limits/'
17  policy: require-pod-requests-limits
18  resources:
19  - apiVersion: v1
20    kind: Pod
21    name: nginx2
22    namespace: default
23  rule: validate-resources
24  scored: true
25  status: fail
26summary:
27  error: 0
28  fail: 1
29  pass: 1
30  skip: 0
31  warn: 0

Test

The test command can test multiple policy resources from a Git repository or local folders. The command recursively looks for YAML files with policy test declarations (described below) and then executes those tests. test is useful when you wish to declare, in advance, what your expected results should be by defining the intent in a manifest. All files applicable to the same test must be co-located. Directory recursion is supported.

Run tests on a set of local files:

1kyverno test /path/to/folderContainingTestYamls

Run tests on a Git repo:

1kyverno test https://github.com/kyverno/policies/main

Use the -f <fileName.yaml> flag to set a custom file name which includes test cases. By default, test will search for a file called test.yaml.

The test declaration file format must be of the following format.

 1name: mytests
 2policies:
 3  - <path/to/policy.yaml>
 4  - <path/to/policy.yaml>
 5resources:
 6  - <path/to/resource.yaml>
 7  - <path/to/resource.yaml>
 8# optional file for declaring variables. see below for example.
 9variables: variables.yaml
10results:
11- policy: <name>
12  rule: <name>
13  resource: <name>
14  status: pass
15- policy: <name>
16  rule: <name>
17  resource: <name>
18  status: fail

If needing to pass variables, a variables.yaml file can be defined with the following format. 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.

 1policies:
 2  - name: exclude-namespaces-example
 3    rules:
 4      - name: exclude-namespaces-dynamically
 5        values:
 6          namespacefilters.data.exclude: asdf
 7    resources:
 8      - name: nonroot-pod
 9        values:
10          namespacefilters.data.exclude: foo
11      - name: root-pod
12        values:
13          namespacefilters.data.exclude: "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"

The test declaration consists of three (optionally four) parts:

  1. The policies element which lists one or more policies to be applied.
  2. The resources element which lists one or more resources to which the policies are applied.
  3. The results element which declares the expected results.
  4. The variables element which defines a file in which variables and their values are stored for use in the policy test.

The test command executes a test declaration by applying the policies to the resources and comparing the results with the expected results. The test passes if the actual results match the expected results.

Example:

Policy manifest (disallow_latest_tag.yaml):

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: disallow-latest-tag
 5  annotations:
 6    policies.kyverno.io/category: Best Practices
 7    policies.kyverno.io/description: >-
 8      The ':latest' tag is mutable and can lead to unexpected errors if the 
 9      image changes. A best practice is to use an immutable tag that maps to 
10      a specific version of an application pod.      
11spec:
12  validationFailureAction: audit
13  rules:
14  - name: require-image-tag
15    match:
16      resources:
17        kinds:
18        - Pod
19    validate:
20      message: "An image tag is required."  
21      pattern:
22        spec:
23          containers:
24          - image: "*:*"
25  - name: validate-image-tag
26    match:
27      resources:
28        kinds:
29        - Pod
30    validate:
31      message: "Using a mutable image tag e.g. 'latest' is not allowed."
32      pattern:
33        spec:
34          containers:
35          - 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 (test.yaml):

 1name: disallow_latest_tag
 2policies:
 3  -  disallow_latest_tag.yaml
 4resources:
 5  -  resource.yaml
 6results:
 7  - policy: disallow-latest-tag
 8    rule: require-image-tag
 9    resource: myapp-pod
10    status: pass
11  - policy: disallow-latest-tag
12    rule: validate-image-tag
13    resource: myapp-pod
14    status: pass
1kyverno test <PathToDirs>

The example above applies a test on the policy and the resource defined in the test YAML.

# TEST RESULT
1 myapp-pod with disallow-latest-tag/require-image-tag pass
2 myapp-pod with disallow-latest-tag/validate-image-tag pass

Validate

The validate command validates that a policy is syntactically valid. It can validate multiple policy resource description files or even an entire folder containing policy resource description files. Currently supports files with resource description in YAML. The policies can also be passed from stdin.

Example:

1kyverno validate /path/to/policy1.yaml /path/to/policy2.yaml /path/to/folderFullOfPolicies

Passing policy from stdin:

1kustomize build nginx/overlays/envs/prod/ | kyverno validate -

Use the -o <yaml/json> flag to display the mutated policy.

Example:

1kyverno validate /path/to/policy1.yaml /path/to/policy2.yaml /path/to/folderFullOfPolicies -o yaml

Policy can also be validated with CRDs. Use the -c flag to pass the CRD. You can pass multiple CRD files or even an entire folder containing CRDs.

Example:

1kyverno validate /path/to/policy1.yaml -c /path/to/crd.yaml -c /path/to/folderFullOfCRDs

Version

Prints the version of Kyverno used by the CLI.

Example:

1kyverno version
2Version: 1.4.2
3Time: 2021-08-11T20:09:26Z
4Git commit ID: fb6e0f18ea89c9b60c604e5135f38040fafbc1e4

Last modified August 27, 2021 at 1:39 PM PST: CLI updates (737974d)