Selecting Resources

Identifying and filtering resources for rule evaluation.

The match and exclude filters control the scope to which rules are applied. They have the same structure and can each contain only one of the two elements:

  • any: specify resource filters on which Kyverno will perform the logical OR operation while choosing resources
  • all: specify resource filters on which Kyverno will perform the logical AND operation while choosing resources

Resource Filters

The following resource filters can be specified under an any or all clause.

  • resources: select resources by names, namespaces, kinds, operations, label selectors, annotations, and namespace selectors.
  • subjects: select users, user groups, and service accounts
  • roles: select namespaced roles
  • clusterRoles: select cluster wide roles

At least one element must be specified in a match.(any/all).resources.kinds or exclude block. The kind attribute is mandatory when working with the resources element. Wildcards (*) are supported in the resources.kinds and subjects fields.

In addition, a user may specify the group and apiVersion with a kind in the match / exclude declarations for a policy rule, known as GVK format.

Supported formats:

  • Group/Version/Kind
  • Version/Kind
  • Kind

To resolve kind naming conflicts, specify the API group and version. For example, the Kubernetes API, Calico, and Antrea all register a Custom Resource with the name NetworkPolicy. These can be distinguished as:

  • networking.k8s.io/v1/NetworkPolicy
  • crd.antrea.io/v1alpha1/NetworkPolicy

Wildcards are supported with the following formats when used in the resources.kinds field:

  • Group/*/Kind
  • Group/*/*
  • */Kind
  • *

Subresources may be specified with either a / or . as a separator between parent and subresource. For example, Pods/status or Pods.status will match on the /status subresource for a Pod. They may be combined with previous naming as well, for example apps/v1/Deployment/scale or v1/Pod.eviction. Wildcards are also supported when referencing subresources, for example */Node/status. Some subresources are shared by multiple API resources, for example the Scale resource. Due to this, matching on Scale may apply to resources like Deployment as well as ReplicationController since Scale is common between both. Use of a parent resource followed by its subresource is necessary to be explicit in the matching decision. Specifying a subresource in the format PodExecOptions is not supported.

When Kyverno receives an AdmissionReview request (i.e., from a validation or mutation webhook), it first checks to see if the resource and user information matches or should be excluded from processing. If both checks pass, then the rule logic to mutate, validate, or generate resources is applied.

Match statements

In every rule, there must be a single match statement to function as the filter to which the rule will apply. Although the match statement can be complex having many different elements, there must be at least one. The most common type of element in a match statement is one which filters on categories of Kubernetes resources, for example Pods, Deployments, Services, Namespaces, etc. Variable substitution is not currently supported in match or exclude statements. match statements also require an any or all expression allowing greater flexibility in treating multiple conditions.

In this snippet, the match statement matches on all resources that EITHER have the kind Service with name “staging” OR have the kind Service and are being created in the “prod” Namespace.

 1match:
 2  any:
 3  - resources:
 4      kinds: 
 5      - Service
 6      names: 
 7      - staging
 8      operations:
 9      - CREATE
10  - resources:
11      kinds: 
12      - Service
13      namespaces:
14      - prod
15      operations:
16      - CREATE

The operations[] list is optional but recommended. When operations[] is absent, the default behavior is to match on CREATE and UPDATE requests.

By combining multiple elements in the match statement, you can be more selective as to which resources you wish to process. Additionally, wildcards are supported for even greater control. For example, by adding the resources.names field, the previous match statement can further filter out Services that begin with the text “prod-” OR have the name “staging”. resources.names takes in a list of names and would match all resources which have either of those names.

 1match:
 2  any:
 3  - resources:
 4      names: 
 5      - "prod-*"
 6      - "staging"
 7      kinds:
 8      - Service
 9      operations:
10      - CREATE
11  - resources:
12      kinds:
13      - Service
14      operations:
15      - CREATE
16    subjects:
17    - kind: User
18      name: dave

match.any[0] will now match on only Services that begin with the name “prod-” OR have the name “staging” and not those which begin with “dev-” or any other prefix. match.any[1] will match all Services being created by the dave user regardless of the name of the Service. And since these two are specified under the any key, the entire rule will act on all Services with names prod-* or staging OR on all services being created by the dave user. In both match and exclude statements, wildcards are supported to make selection more flexible.

In this snippet, the match statement matches only resources that have the group networking.k8s.io, version v1 and kind NetworkPolicy. By adding Group,Version,Kind in the match statement, you can be more selective as to which resources you wish to process.

1match:
2  any:
3  - resources:
4      kinds:
5      - networking.k8s.io/v1/NetworkPolicy

By specifying the kind in version/kind format, only specific versions of the resource kind will be matched.

1match:
2  any:
3  - resources:
4      kinds:
5      - v1/NetworkPolicy

Wildcards are supported in the kinds field allowing you to match on every resource type in the cluster. Selector labels support wildcards (* or ?) for keys as well as values in the following paths.

  • match.any.resources.selector.matchLabels
  • match.all.resources.selector.matchLabels
  • exclude.any.resources.selector.matchLabels
  • exclude.all.resources.selector.matchLabels

Supported formats:

  • *
  • *pattern*
  • *pattern
  • pattern?
  • patte?rn

In the below policy, all resource kinds are checked for the existence of a label having key app.kubernetes.io/name.

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: require-labels
 5spec:
 6  validationFailureAction: Audit
 7  background: false
 8  rules:
 9  - name: check-for-labels
10    match:
11      any:
12      - resources:
13          kinds:
14          - "*"
15          operations:
16          - CREATE
17    validate:
18      message: "The label `app.kubernetes.io/name` is required."
19      pattern:
20        metadata:
21          labels:
22            app.kubernetes.io/name: "?*"

Matches for Namespaced resources can also be selected using Namespace labels by using the namespaceSelector field. This field allows selection in two granular ways: by using matchLabels or matchExpressions. When using matchLabels, a map of Namespace labels can be used to specify the match. For more advanced selection logic, use the matchExpressions element.

In the below example, Kyverno will only consider matching Pods as those in a Namespace which contains the label organization: engineering.

1match:
2  any:
3  - resources:
4      kinds:
5      - Pod
6      namespaceSelector:
7        matchLabels:
8          organization: engineering

And in this example, Kyverno will select Pods in a Namespace where the label key namespacekind does not equal the value platform or ci.

 1match:
 2  any:
 3  - resources:
 4      kinds:
 5      - Pod
 6      namespaceSelector:
 7        matchExpressions:
 8        - key: namespacekind
 9          operator: NotIn
10          values:
11          - platform
12          - ci

Here are some other examples of match statements.

Match a Deployment or StatefulSet with a specific label

This is an example that selects a Deployment OR a StatefulSet with a label app=critical.

Condition checks inside the resources block follow the logic “AND across types but an OR within list types”. For example, if a rule match contains a list of kinds and a list of namespaces, the rule will be evaluated if the request contains any one (OR) of the kinds AND any one (OR) of the namespaces. Conditions inside clusterRoles, roles, and subjects are always evaluated using a logical OR operation, as each request can only have a single instance of these values.

In the below snippet, kinds and selector are peer/sibling elements, and so they are ANDed together.

 1match:
 2  any:
 3  # AND across kinds and namespaceSelector
 4  - resources:
 5      # OR inside list of kinds
 6      kinds:
 7      - Deployment
 8      - StatefulSet
 9      operations:
10      - CREATE
11      - UPDATE
12      selector:
13        matchLabels:
14          app: critical

This pattern can be leveraged to produce very fine-grained control over the selection of resources, for example the snippet as shown below which combines match elements that include resources, subjects, roles, and clusterRoles.

Advanced match statement

 1spec:
 2  # validationFailureAction controls admission control behaviors,
 3  # when a policy rule fails:
 4  # - use 'Enforce' to block resource creation or modification
 5  # - use 'Audit' to allow resource updates and report policy violations
 6  validationFailureAction: Enforce
 7  # Each policy has a list of rules applied in declaration order
 8  rules:
 9    # Rules must have a unique name
10    - name: check-pod-controller-labels
11      # Each rule matches specific resource described by "match" field.
12      match:
13        any:
14        - resources:
15            kinds: # Required, list of kinds
16            - Deployment
17            - StatefulSet
18            # Optional resource names. Supports wildcards (* and ?)
19            names: 
20            - "mongo*"
21            - "postgres*"
22            # Optional list of namespaces. Supports wildcards (* and ?)
23            operations:
24            - CREATE
25            - UPDATE
26            namespaces:
27            - "dev*"
28            - test
29            # Optional label selectors. Values support wildcards (* and ?)
30            selector:
31              matchLabels:
32                app: mongodb
33              matchExpressions:
34                - {key: tier, operator: In, values: [database]}
35          # Optional users or service accounts to be matched
36          subjects:
37          - kind: User
38            name: mary@somecorp.com
39          # Optional clusterroles to be matched
40          clusterRoles: 
41          - cluster-admin

Match Deployments in Namespaces using labels

This example selects Deployments in Namespaces that have a label type=connector or type=compute using a namespaceSelector.

Here, kinds and namespaceSelector are peer elements under match.resources and are evaluated using a logical AND operation.

 1spec:
 2  rules:
 3    - name: check-min-replicas
 4      match:
 5        any:
 6        # AND across resources and selector
 7        - resources:
 8            # OR inside list of kinds
 9            kinds:
10            - Deployment
11            operations:
12            - CREATE
13            - UPDATE
14            namespaceSelector:
15              matchExpressions:
16                - key: type 
17                  operator: In
18                  values: 
19                  - connector
20                  - compute

Combining match and exclude

In cases where a subset of the resources selected in a match block need to be omitted from processing, you may optionally use an exclude block. For example, you wish to only process Pods which do not have the label env=prod. An exclude block can be used to select those with the label env=prod. An exclude block must therefore be a subset of the match block.

All match and exclude conditions must be satisfied for a resource to be selected for the policy rule. In other words, the match and exclude conditions are evaluated using a logical AND operation. Elements in the exclude block follow the same specifications as those in the match block.

Exclude cluster-admin ClusterRole

Here is an example of a rule that matches all Pods excluding those created by using the cluster-admin ClusterRole.

 1spec:
 2  rules:
 3    - name: match-pods-except-cluster-admin
 4      match:
 5        any:
 6        - resources:
 7            kinds:
 8            - Pod
 9            operations:
10            - CREATE
11            - UPDATE
12      exclude:
13        any:
14        - clusterRoles:
15          - cluster-admin

Exclude prod-alpha Namespace

This rule matches all Pods except those in the prod-alpha Namespace.

 1spec:
 2  rules:
 3    - name: match-pods-except-admin
 4      match:
 5        any:
 6        - resources:
 7            kinds:
 8            - Pod
 9            operations:
10            - CREATE
11            - UPDATE
12      exclude:
13        any:
14        - resources:
15            namespaces:
16            - prod-alpha

Match a label and exclude users and roles

The following example matches all resources with label app=critical excluding the resources created by ClusterRole cluster-admin OR by the user John.

 1spec:
 2  rules:
 3    - name: match-criticals-except-given-rbac
 4      match:
 5        any:
 6        - resources:
 7            kind:
 8            - Pod
 9            operations:
10            - CREATE
11            - UPDATE
12            selector:
13              matchLabels:
14                app: critical
15      exclude:
16        any:
17        - clusterRoles:
18          - cluster-admin
19        - subjects:
20          - kind: User
21            name: John

Match a label and exclude users

A variation on the above sample, this snippet uses any and all statements to exclude multiple users.

 1spec:
 2  validationFailureAction: Enforce
 3  background: false
 4  rules:
 5    - name: match-criticals-except-given-users
 6      match:
 7        all:
 8        - resources:
 9            kinds:
10            - Pod
11            operations:
12            - CREATE
13            - UPDATE
14            selector:
15              matchLabels:
16                app: critical
17      exclude:
18        any:
19        - subjects:
20          - kind: User
21            name: susan
22          - kind: User
23            name: dave

Match all Pods using annotations

Here is an example of a rule that matches all Pods having imageregistry: "https://hub.docker.com/" annotations.

 1spec:
 2  rules:
 3    - name: match-pod-annotations
 4      match:
 5        any:
 6        - resources:
 7            annotations:
 8              imageregistry: "https://hub.docker.com/"
 9            kinds:
10              - Pod
11            operations:
12            - CREATE
13            - UPDATE

Configure webhooks

Webhook configurations can be configured using policies. Webhook operations per resource is dynamically set if there are match/exclude operations mentioned in the policies applied. If for a resource no operations are set in match or exclude blocks, default operations are applied in the webhooks rules. Default operations for validating resources are CONNECT, CREATE, UPDATE, DELETE and for mutating resources are CREATE, UPDATE.

For a policy like this:

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: require-labels
 5  annotations:
 6    pod-policies.kyverno.io/autogen-controllers: none
 7spec:
 8  validationFailureAction: Audit
 9  background: false
10  rules:
11    - name: require-team
12      match:
13        any:
14          - resources:
15              kinds:
16              - Namespace
17              operations:
18              - CREATE
19      validate:
20        message: 'The label `team` is required.'
21        pattern:
22          metadata:
23            labels:
24              team: '?*'
25    - name: require-match
26      match:
27        any:
28          - resources:
29              kinds:
30              - Deployment
31              operations:
32              - UPDATE
33      validate:
34        message: 'The label `match` is required.'
35        pattern:
36          metadata:
37            labels:
38              match: '?*'

The webhook rules would look like this:

 1  rules:
 2  - apiGroups:
 3    - ""
 4    apiVersions:
 5    - v1
 6    operations:
 7    - CREATE
 8    resources:
 9    - namespaces
10    scope: '*'
11  - apiGroups:
12    - apps
13    apiVersions:
14    - v1
15    operations:
16    - UPDATE
17    resources:
18    - deployments
19    scope: '*'

Last modified June 08, 2024 at 6:16 PM PST: Docsy bump to 0.10.0 and docs fixes/enhancements (#1274) (ed2056b)