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.')