SecurityIntermediate40 min

Policy Management with Kyverno

Learn how to use Kyverno to validate, mutate, and generate Kubernetes resources — enforcing security and compliance policies as code.

What Is Kyverno?

Kyverno is a Kubernetes-native policy engine that lets you manage policies as Kubernetes resources — no new language to learn, just YAML.

With Kyverno, you can:

  • Validate — reject resources that don't meet requirements
  • Mutate — automatically modify resources to add defaults or fix configurations
  • Generate — create additional resources when certain conditions are met
  • Verify images — ensure only signed container images are deployed

How Kyverno Works

Kyverno runs as a dynamic admission controller in your Kubernetes cluster:

  1. When a resource is created or updated, the Kubernetes API server sends an admission webhook to Kyverno
  2. Kyverno evaluates the resource against all matching policies
  3. Based on the policy rules, Kyverno can allow, reject, or modify the request
  4. Results are captured as Kubernetes events and Policy Reports

This all happens transparently — developers don't need to install anything or change their workflow.

Enabling Kyverno in Kuberise.io

In your enabler file, enable both Kyverno (the operator) and the policy chart:

# app-of-apps/values-{name}.yaml (e.g. values-webshop.yaml)
ArgocdApplications:
  kyverno:
    enabled: true
  policy:
    enabled: true

Then add your policy YAML files in the appropriate directory:

  • All clusters: values/defaults/platform/policy/ — policies applied everywhere
  • Specific cluster: values/{cluster}/platform/policy/ — cluster-specific policies

Workshop: Validating Resources

Let's create a policy that requires all pods in the default namespace to have a team label.

Step 1: Create the Validation Policy

# values/{cluster}/platform/policy/required-labels.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  rules:
  - name: check-team
    match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - default
    skipBackgroundRequests: true
    validate:
      allowExistingViolations: true
      failureAction: Enforce
      message: "The label 'team' is required on all pods"
      pattern:
        metadata:
          labels:
            team: "?*"

Step 2: Test It

# This should FAIL — no team label
kubectl run nginx --image nginx

# This should SUCCEED — team label is present
kubectl run nginx --image nginx --labels='team=alpha'

Step 3: Check Policy Reports

kubectl get policyreport -o wide

Policy Reports give you visibility into which resources comply with your policies and which don't — even for resources that existed before the policy was created.

Workshop: Mutating Resources

Mutation policies automatically modify resources. Let's create a policy that adds a default project label to any pod that doesn't already have one.

Step 1: Create the Mutation Policy

# values/{cluster}/platform/policy/add-labels.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-labels
spec:
  rules:
  - name: add-project
    skipBackgroundRequests: true
    match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - default
    mutate:
      patchStrategicMerge:
        metadata:
          labels:
            +(project): bravo

The +() syntax means "add this label only if it doesn't already exist."

Step 2: Test It

# Create a pod — it should automatically get 'project=bravo' label
kubectl run nginx --image nginx --labels='team=alpha'

# Verify the labels
kubectl get pod nginx --show-labels

Step 3: Verify

kubectl get policyreport -o wide

Workshop: Generating Resources

Generate policies automatically create new resources when a trigger condition is met. A common use case is syncing image pull secrets to new namespaces.

Step 1: Grant Kyverno Access to Secrets

Kyverno needs RBAC permissions to manage secrets:

# values/{cluster}/platform/policy/kyverno-clusterroles.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kyverno:secrets:view
  labels:
    rbac.kyverno.io/aggregate-to-admission-controller: "true"
    rbac.kyverno.io/aggregate-to-reports-controller: "true"
    rbac.kyverno.io/aggregate-to-background-controller: "true"
rules:
- apiGroups: ['']
  resources: [secrets]
  verbs: [get, list, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kyverno:secrets:manage
  labels:
    rbac.kyverno.io/aggregate-to-background-controller: "true"
rules:
- apiGroups: ['']
  resources: [secrets]
  verbs: [create, update, delete]

Step 2: Create a Source Secret

kubectl -n default create secret docker-registry regcred \
  --docker-server=myinternalreg.corp.com \
  --docker-username=john.doe \
  --docker-password=Passw0rd123! \
  [email protected]

Step 3: Create the Generate Policy

# values/{cluster}/platform/policy/generate-secret.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: sync-secrets
spec:
  rules:
  - name: sync-image-pull-secret
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      apiVersion: v1
      kind: Secret
      name: regcred
      namespace: "{{request.object.metadata.name}}"
      synchronize: true
      clone:
        namespace: default
        name: regcred

This policy clones the regcred secret into every new namespace automatically. The synchronize: true flag keeps the cloned secrets in sync — if you update the source secret, all copies update too.

Step 4: Test It

# Create a new namespace — the secret should be automatically created
kubectl create ns test

# Verify the secret was generated
kubectl get secrets -n test

Key Takeaways

  1. Kyverno policies are Kubernetes-native — they're just YAML, stored in Git alongside your other configurations
  2. Validation policies enforce standards (required labels, resource limits, allowed registries)
  3. Mutation policies add sensible defaults automatically, reducing developer burden
  4. Generate policies propagate shared resources (secrets, configmaps, network policies) across namespaces
  5. Policy Reports provide audit visibility into compliance across your cluster