All Policies

Exclude Namespaces Dynamically in ValidatingPolicy

It's common where policy lookups need to consider a mapping to many possible values rather than a static mapping. This is a sample which demonstrates how to dynamically look up an allow list of Namespaces from a ConfigMap where the ConfigMap stores an array of strings. This policy validates that any Pods created outside of the list of Namespaces have the label `foo` applied.

Policy Definition

/other-vpol/exclude-namespaces-dynamically/exclude-namespaces-dynamically.yaml

 1apiVersion: policies.kyverno.io/v1alpha1
 2kind: ValidatingPolicy
 3metadata:
 4  name: exclude-namespaces-example
 5  annotations:
 6    policies.kyverno.io/title: Exclude Namespaces Dynamically in ValidatingPolicy
 7    policies.kyverno.io/category: Sample in Vpol 
 8    policies.kyverno.io/severity: medium
 9    policies.kyverno.io/subject: Namespace, Pod
10    policies.kyverno.io/minversion: 1.14.0
11    kyverno.io/kyverno-version: 1.14.0
12    kyverno.io/kubernetes-version: "1.30"
13    policies.kyverno.io/description: >-
14      It's common where policy lookups need to consider a mapping to many possible values rather than a
15      static mapping. This is a sample which demonstrates how to dynamically look up an allow list of Namespaces from a ConfigMap
16      where the ConfigMap stores an array of strings. This policy validates that any Pods created
17      outside of the list of Namespaces have the label `foo` applied.
18spec:
19  validationActions: 
20    - Audit
21  autogen:
22   podControllers:
23     controllers: []
24  evaluation:
25    background:
26      enabled: true  
27  matchConstraints:
28    resourceRules:
29      - apiGroups: ["apps"]
30        apiVersions: ["v1"]
31        operations: ["CREATE", "UPDATE"]
32        resources:
33          - deployments
34      - apiGroups: ["batch"]
35        apiVersions: ["v1"]
36        operations: ["CREATE", "UPDATE"]
37        resources:
38          - cronjobs
39      - apiGroups: [""]
40        apiVersions: ["v1"]
41        operations: ["CREATE", "UPDATE"]
42        resources:
43          - pods
44  variables: 
45     - name: cm
46       expression: >- 
47         resource.Get("v1", "configmaps", "default", "namespace-filters")
48     - name: filter
49       expression: "request.namespace in variables.cm.data['exclude'].split(', ')"
50  validations:
51  - expression: >
52      request.kind.kind == 'Pod' ? 
53      ( variables.filter || (has(object.metadata.labels) && 'foo' in object.metadata.labels)) : 
54      request.kind.kind in ['Deployment', 'CronJob'] ? true : false
55    messageExpression: >-
56      'Pods must have the "foo" label in metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + 
57      (has(object.metadata.labels) && 'foo' in object.metadata.labels ? ', but the label is present.' : ', but no "foo" label is found.')
58  - expression: >
59      request.kind.kind == 'Deployment' ? 
60      (  variables.filter || has(object.spec.template.metadata) && has(object.spec.template.metadata.labels) && 'foo' in object.spec.template.metadata.labels) : 
61      request.kind.kind in ['Pod', 'CronJob'] ? true : false
62    messageExpression: >-
63      'Deployments must have the "foo" label in the Pod template metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + 
64      (has(object.spec.template.metadata) && has(object.spec.template.metadata.labels) && 'foo' in object.spec.template.metadata.labels ? ', but the label is present.' : ', but no "foo" label is found.')
65  - expression: >
66      request.kind.kind == 'CronJob' ? 
67      ( variables.filter || has(object.spec.jobTemplate.spec.template.metadata) && has(object.spec.jobTemplate.spec.template.metadata.labels) && 'foo' in object.spec.jobTemplate.spec.template.metadata.labels) : 
68      request.kind.kind in ['Pod', 'Deployment'] ? true : false
69    messageExpression: >-
70      'CronJobs must have the "foo" label in the Pod template metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + 
71      (has(object.spec.jobTemplate.spec.template.metadata) && has(object.spec.jobTemplate.spec.template.metadata.labels) && 'foo' in object.spec.jobTemplate.spec.template.metadata.labels ? ', but the label is present.' : ', but no "foo" label is found.')