kyverno · git:20261018.90b97a9 · 2026-10-18 · sha256 39858b91b0cb15f7
kyverno git:20261018.90b97a9A
Immutable. This exact content never changes and is served at /api/v1/blob/39858b91b0cb15f7.
---
name: kyverno
description: Generate, test, audit, debug, and migrate Kyverno policies using the new CEL-based policy types (ValidatingPolicy, MutatingPolicy, GeneratingPolicy, ImageValidatingPolicy — all apiVersion policies.kyverno.io/v1). Covers matchConstraints, matchConditions, CEL validations/mutations, generator.Apply(), Audit→Deny promotion, PolicyException, kyverno-cli testing, and migration from legacy ClusterPolicy or PodSecurityPolicy. Use when asked to "write a Kyverno policy", "test a ValidatingPolicy", "audit my cluster for violations", "why is my policy not firing", or "migrate from ClusterPolicy".
argument-hint: "[generate|test|audit|debug|migrate] [policy description or file path]"
title: "Kyverno Command"
sidebar_label: "kyverno"
custom_edit_url: null
---
Write, test, audit, debug, and migrate Kyverno policies using the new CEL-based policy types.
All new policies use `apiVersion: policies.kyverno.io/v1`. Legacy `ClusterPolicy` (`kyverno.io/v1`) still works but is deprecated in v1.17 and planned for removal in v1.20.
---
## Interactive Wizard (fires when no arguments are provided)
When invoked with no arguments, ask before proceeding:
**Q1 — Mode?**
```
What do you need?
1. generate — write a new production-ready Kyverno policy
2. test — write kyverno-test.yaml fixtures and run kyverno-cli
3. audit — analyse PolicyReport data from a running cluster
4. debug — diagnose why a policy is not behaving as expected
5. migrate — convert a legacy ClusterPolicy or PodSecurityPolicy
Score a cluster or manifests against NSA/CIS/SOC2 before choosing policies → /platform-skills:kubescape
No Kyverno and none planned (Kubernetes ≥ 1.30): Kubescape's ready-made CEL
ValidatingAdmissionPolicies → /platform-skills:kubescape vap
Enter 1–5 or mode name:
```
**Q2 — Context** (after mode selected, one at a time):
- **generate**: `Describe the policy — what should it validate, mutate, or enforce? (e.g. "require app.kubernetes.io/team label on all Deployments"):`
- **test**: `Paste or describe the policy to test:`
- **audit**: `Paste the PolicyReport JSON or run: kubectl get policyreport -A -o json | jq '[.items[].results[] | select(.result == "fail")]'`
- **debug**: `Describe the symptom — is the policy not blocking, not mutating, or not appearing in PolicyReport?`
- **migrate**: `Paste the existing ClusterPolicy or PodSecurityPolicy YAML to migrate:`
Then proceed into the relevant mode below.
---
## Mode: generate
Write a production-ready Kyverno policy from a description.
Steps:
1. Ask for: policy type (ValidatingPolicy / MutatingPolicy / GeneratingPolicy / ImageValidatingPolicy), target resource kinds, whether cluster-wide or namespace-scoped, and whether to start in Audit or Deny mode
2. Start in `validationActions: [Audit]` unless the user explicitly requests Deny — blocking admission with an untested policy is high blast radius
3. Generate the policy with:
- `apiVersion: policies.kyverno.io/v1`
- `annotations` block: `policies.kyverno.io/title`, `category`, `severity`, `description`
- `matchConstraints.resourceRules` targeting only the required kinds and operations
- `matchConditions` to exclude system namespaces (`kube-system`, `kube-public`, and platform tooling namespaces) — this replaces the old `exclude` block
- For `ValidatingPolicy`: `validations` with CEL boolean expressions; use `messageExpression` for dynamic messages that include the resource name
- For `MutatingPolicy`: `mutations` with `patchType: ApplyConfiguration` (prefer for adds/merges) or `patchType: JSONPatch` (for precise path operations); use `jsonpatch.escapeKey()` for special characters in paths
- For `GeneratingPolicy`: `variables` with `dyn()` for inline resource definitions; `generate` with `generator.Apply(namespace, [resources])`; set `evaluation.synchronize.enabled: true`
- For `ImageValidatingPolicy`: `matchImageReferences` with glob or CEL; `attestors` with cosign keyless or key-based; `validations` using `verifyImageSignatures()` CEL function
4. Show the kyverno-cli command to dry-run: `kyverno apply <policy.yaml> --resource <manifest.yaml> --detailed-results`
Reference: `references/kyverno.md` → ValidatingPolicy, MutatingPolicy, GeneratingPolicy, ImageValidatingPolicy
## Mode: test
Write a `kyverno-test.yaml` manifest and companion resource fixtures.
Steps:
1. Read the policy — identify: kind, `matchConstraints` resource rules, `matchConditions`, and what each validation expression approves vs denies
2. For each validation, create:
- A **passing resource** — a manifest that satisfies the CEL expression (result: pass)
- A **failing resource** — a manifest that violates the CEL expression (result: fail)
- If `matchConditions` exclude a namespace, a **resource in an excluded namespace** (result: skip)
3. Build `kyverno-test.yaml`:
```yaml
name: <policy-name>-test
policies:
- <policy-file>.yaml
resources:
- resources/<passing-manifest>.yaml
- resources/<failing-manifest>.yaml
results:
- policy: <policy-name>
rule: <validation-name-or-autogen>
resource: <passing-resource-name>
kind: <Kind>
result: pass
- policy: <policy-name>
rule: <validation-name-or-autogen>
resource: <failing-resource-name>
kind: <Kind>
result: fail
```
4. Run: `kyverno test .` — all results must match
5. Note: CEL `resource.Get()` / `resource.List()` (used in GeneratingPolicy) are not available in CLI tests — those require cluster-side testing
Reference: `references/kyverno.md` → kyverno-cli Testing
## Mode: audit
Analyse PolicyReport data from a running cluster and produce an actionable violation summary.
Steps:
1. Collect violation data:
```bash
kubectl get policyreport -A -o json \
| jq '[.items[].results[] | select(.result == "fail")]'
kubectl get clusterpolicyreport -o json \
| jq '[.items[].results[] | select(.result == "fail")]'
```
2. Group violations by policy (highest severity first), then by resource kind — identify highest-volume policies first
3. For each violated policy:
- State the policy name, severity, and current `validationActions`
- List affected resources (namespace/name)
- Assess fix effort: update the resource manifest, or use PolicyException for a legitimate carve-out?
4. Recommend remediation order: fix high-severity violations first; PolicyException is a last resort requiring documented justification
5. Show the promote command for each zero-violation policy:
```bash
kubectl patch validatingpolicy <name> \
--type merge \
-p '{"spec":{"validationActions":["Deny"]}}'
```
6. Flag any policy in `[Deny]` mode with active PolicyReport violations — indicates a suppressed PolicyException that needs review
Reference: `references/kyverno.md` → Audit → Enforce Promotion, PolicyReport
## Mode: debug
Diagnose why a Kyverno policy is not behaving as expected.
Steps:
1. Collect:
- Policy YAML: `kubectl get validatingpolicy <name> -o yaml`
- Resource YAML: `kubectl get <kind> <name> -n <ns> -o yaml`
- Admission events: `kubectl describe <kind> <name> -n <ns>`
- Kyverno admission controller logs: `kubectl logs -n kyverno -l app.kubernetes.io/component=admission-controller --tail=100`
- Background controller logs (for GeneratingPolicy/MutatingPolicy existing): `kubectl logs -n kyverno -l app.kubernetes.io/component=background-controller --tail=100`
- PolicyReport: `kubectl get policyreport -n <ns> -o yaml`
2. Check in order:
- **Webhook not registered**: `kubectl get validatingwebhookconfigurations` — if missing, Kyverno is not running or failed to register
- **matchConstraints not covering the resource**: compare `spec.matchConstraints.resourceRules` kinds, apiGroups, and operations against the actual resource
- **matchConditions filtering out the resource**: evaluate each `matchConditions` expression against the resource manually with `kyverno apply`
- **validationActions is [Audit] not [Deny]**: policy reports violation but doesn't block — check PolicyReport, not admission events
- **background scan not yet run**: existing resources may not appear in PolicyReport until next background scan (default interval 1h); check `evaluation.background.enabled: true`
- **MutatingPolicy mutateExisting not set**: existing resources are not patched — set `evaluation.mutateExisting.enabled: true`
- **CEL expression syntax error**: look for CEL evaluation error in admission events; test the expression with `kyverno apply` CLI
- **PolicyException suppressing**: `kubectl get policyexception -A` — check if an exception covers this resource and policy
3. State the most likely root cause with the exact field to change
4. Show the corrected policy section and the command: `kyverno apply <policy.yaml> --resource <manifest.yaml> --detailed-results`
Reference: `references/kyverno.md` → Troubleshooting
## Mode: migrate
Migrate from legacy `ClusterPolicy` (`kyverno.io/v1`) or PodSecurityPolicy to the new policy types.
### From legacy ClusterPolicy
Map each rule type to the new kind:
| Legacy rule type | New kind |
|---|---|
| `validate` rule | `ValidatingPolicy` |
| `mutate` rule | `MutatingPolicy` |
| `generate` rule | `GeneratingPolicy` |
| `verifyImages` rule | `ImageValidatingPolicy` |
Key syntax changes:
- `spec.rules[].match.any[].resources` → `spec.matchConstraints.resourceRules[]`
- `spec.rules[].exclude` → `spec.matchConditions` with CEL negation
- `validate.pattern` (JMESPath anchors) → `validations[].expression` (CEL boolean)
- `validate.deny.conditions` → `validations[].expression` with inverted CEL
- `mutate.patchStrategicMerge` → `mutations[].patchType: ApplyConfiguration` with `Object{...}` CEL
- `mutate.patchesJSON6902` → `mutations[].patchType: JSONPatch` with `[JSONPatch{...}]` CEL
- `generate.data` / `generate.clone` → `generate[].expression` using `generator.Apply()` and `resource.Get()`
- `verifyImages[].attestors` → `attestors[]` + `validations[].expression` using `verifyImageSignatures()`
- `validationFailureAction: Enforce` → `validationActions: [Deny]`
- `validationFailureAction: Audit` → `validationActions: [Audit]`
Migration workflow:
1. Write the new-style policy in `[Audit]` mode
2. Deploy alongside the existing ClusterPolicy — both can coexist
3. Verify PolicyReport shows identical violations from the new policy
4. Switch new policy to `[Deny]`
5. Remove the legacy ClusterPolicy
### From PodSecurityPolicy
Map each PSP field to a `ValidatingPolicy`:
| PSP field | ValidatingPolicy CEL expression |
|---|---|
| `privileged: false` | `object.spec.containers.all(c, !has(c.securityContext) \|\| !c.securityContext.?privileged.orValue(false))` |
| `hostNetwork: false` | `!has(object.spec.hostNetwork) \|\| object.spec.hostNetwork == false` |
| `runAsNonRoot: true` | `object.spec.containers.all(c, has(c.securityContext) && c.securityContext.runAsNonRoot == true)` |
| `readOnlyRootFilesystem: true` | `object.spec.containers.all(c, has(c.securityContext) && c.securityContext.readOnlyRootFilesystem == true)` |
Deploy all new policies in `[Audit]` mode first, fix workloads, then switch to `[Deny]` before removing PSPs.
Reference: `references/kyverno.md` → Common Policy Patterns