Skip to content
Published on

Kyverno Policy Engine Analysis: Validate, Mutate, Generate Rules Deep Dive

Authors

1. Validate Rules

1.1 Pattern Matching

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-run-as-non-root
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-security-context
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: 'Containers must run as non-root'
        pattern:
          spec:
            containers:
              - securityContext:
                  runAsNonRoot: true

Operators: ?* (non-empty), * (any), X|Y (or), !X (not), >X, <X (numeric comparison).

1.2 deny Rules

rules:
  - name: deny-latest-tag
    validate:
      deny:
        conditions:
          any:
            - key: '{{ request.object.spec.containers[].image }}'
              operator: AnyIn
              value: ['*:latest']

1.3 CEL Expressions

rules:
  - name: check-replica-count
    validate:
      cel:
        expressions:
          - expression: 'object.spec.replicas >= 2'
            message: 'Deployment must have at least 2 replicas'

1.4 foreach

rules:
  - name: check-each-container
    validate:
      foreach:
        - list: 'request.object.spec.containers'
          deny:
            conditions:
              any:
                - key: '{{ element.resources.limits.memory }}'
                  operator: Equals
                  value: ''

2. Mutate Rules

2.1 patchStrategicMerge

rules:
  - name: add-sidecar
    mutate:
      patchStrategicMerge:
        spec:
          template:
            spec:
              containers:
                - name: log-collector
                  image: fluentbit:latest

2.2 patchesJson6902

rules:
  - name: add-annotation
    mutate:
      patchesJson6902: |-
        - op: add
          path: /metadata/annotations/modified-by
          value: kyverno

3. Generate Rules

3.1 data-based Generation

rules:
  - name: generate-default-limitrange
    match:
      any:
        - resources:
            kinds:
              - Namespace
    generate:
      apiVersion: v1
      kind: LimitRange
      name: default-limits
      namespace: '{{ request.object.metadata.name }}'
      synchronize: true
      data:
        spec:
          limits:
            - default:
                cpu: 500m
                memory: 512Mi
              type: Container

3.2 clone-based Generation

rules:
  - name: clone-configmap
    generate:
      apiVersion: v1
      kind: ConfigMap
      name: shared-config
      namespace: '{{ request.object.metadata.name }}'
      synchronize: true
      clone:
        namespace: default
        name: template-configmap

4. Variables and Context

4.1 JMESPath, API Calls, ConfigMap Lookups

rules:
  - name: check-namespace-labels
    context:
      - name: namespaceInfo
        apiCall:
          urlPath: '/api/v1/namespaces/{{ request.namespace }}'
      - name: allowedRegistries
        configMap:
          name: allowed-registries
          namespace: kyverno

5. Summary

  1. validate: Pattern matching, deny conditions, CEL expressions, foreach
  2. mutate: Strategic Merge Patch, JSON Patch for automatic resource modification
  3. generate: data/clone-based auto-generation with synchronize
  4. Variable system: JMESPath, API calls, ConfigMap lookups for dynamic policies
  5. Anchor system: Conditional, negation, equality anchors for fine-grained matching