Back to 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.

View on GitHub

Policy Definition

apiVersion: policies.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: exclude-namespaces-example
annotations:
policies.kyverno.io/title: Exclude Namespaces Dynamically in ValidatingPolicy
policies.kyverno.io/category: Sample in Vpol
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Namespace, Pod
policies.kyverno.io/minversion: 1.14.0
kyverno.io/kyverno-version: 1.14.0
kyverno.io/kubernetes-version: "1.30"
policies.kyverno.io/description: 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.
spec:
validationActions:
- Audit
autogen:
podControllers:
controllers: []
evaluation:
background:
enabled: true
matchConstraints:
resourceRules:
- apiGroups:
- apps
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- deployments
- apiGroups:
- batch
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- cronjobs
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- pods
variables:
- name: cm
expression: resource.Get("v1", "configmaps", "default", "namespace-filters")
- name: filter
expression: request.namespace in variables.cm.data['exclude'].split(', ')
validations:
- expression: |
request.kind.kind == 'Pod' ? ( variables.filter || (has(object.metadata.labels) && 'foo' in object.metadata.labels)) : request.kind.kind in ['Deployment', 'CronJob'] ? true : false
messageExpression: "'Pods must have the \"foo\" label in metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + (has(object.metadata.labels) && 'foo' in object.metadata.labels ? ', but the label is present.' : ', but no \"foo\" label is found.')"
- expression: |
request.kind.kind == 'Deployment' ? ( variables.filter || has(object.spec.template.metadata) && has(object.spec.template.metadata.labels) && 'foo' in object.spec.template.metadata.labels) : request.kind.kind in ['Pod', 'CronJob'] ? true : false
messageExpression: "'Deployments must have the \"foo\" label in the Pod template metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + (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.')"
- expression: |
request.kind.kind == 'CronJob' ? ( 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) : request.kind.kind in ['Pod', 'Deployment'] ? true : false
messageExpression: "'CronJobs must have the \"foo\" label in the Pod template metadata.labels unless in namespaces: ' + variables.cm.data['exclude'] + (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.')"

Related Policies