Lab 03 — Kyverno Policies
Mission Information
Section titled “Mission Information”| Item | Details |
|---|---|
| Lab ID | K8S-COMPLIANCE-LAB-03 |
| Difficulty | Intermediate to Advanced |
| Estimated Time | 5–7 Hours |
| Environment | Kubernetes Training Cluster |
| Platform | Kubernetes, Kyverno, Helm and kubectl |
| Cost | Free |
| Primary Role | Kubernetes Security Engineer |
| Supporting Roles | DevSecOps Engineer, Platform Engineer, Cloud Security Engineer, Compliance Analyst |
| Module | Kubernetes Benchmarks & Compliance |
| Previous Lab | Lab 02 — Gatekeeper Policies |
| Next Lab | Lab 04 — Compliance Automation |
Mission Scenario
Section titled “Mission Scenario”CloudNova Technologies has deployed OPA Gatekeeper to enforce several Kubernetes governance controls.
The platform team has now identified additional requirements that extend beyond policy validation.
The organisation needs a policy engine that can:
- Validate incoming Kubernetes resources
- Mutate resources automatically
- Generate supporting resources
- Verify container images
- Audit existing workloads
- Produce policy reports
- Enforce configuration standards using Kubernetes-native YAML
Current issues include:
- Workloads missing recommended security settings
- Containers running without resource limits
- Images using mutable tags
- Missing ownership labels
- Service Account tokens mounted unnecessarily
- Workloads without seccomp configuration
- Namespace security labels applied inconsistently
- Developers manually adding repetitive security settings
- Policy exceptions not formally documented
- Limited reporting on policy violations
CloudNova Technologies has selected Kyverno to extend its policy-as-code and compliance automation capabilities.
Your mission is to deploy Kyverno, implement validation and mutation policies, generate supporting security configurations, test compliant and non-compliant workloads, and produce an enterprise policy-governance assessment.
Learning Objectives
Section titled “Learning Objectives”By completing this lab, you will learn how to:
- Explain Kyverno architecture
- Compare Kyverno with OPA Gatekeeper
- Install Kyverno using Helm
- Validate Kyverno components
- Create ClusterPolicies
- Create Namespaced Policies
- Configure Audit and Enforce modes
- Validate required labels
- Require non-root containers
- Block privileged workloads
- Require resource requests and limits
- Restrict mutable image tags
- Require seccomp profiles
- Mutate workloads automatically
- Disable automatic Service Account token mounting
- Generate namespace security resources
- Review PolicyReports
- Configure policy exceptions
- Produce an enterprise governance report
Enterprise Kyverno Architecture
Section titled “Enterprise Kyverno Architecture”Developer or CI/CD Pipeline
│
▼
Kubernetes API Server
│
▼
Kyverno
┌─────────┼─────────┐ │ │ │
Validate Mutate Generate
│ │ │
└─────────┼─────────┘
│
▼
Policy Decision
┌─────────┴─────────┐ │ │
Allowed Rejected
│
▼
Policy Reports and Audit EvidenceEnterprise Policy Workflow
Section titled “Enterprise Policy Workflow”Policy Requirement
│
▼
Policy as Kubernetes YAML
│
▼
Audit Mode
│
▼
Violation Analysis
│
▼
Remediation and Exceptions
│
▼
Enforce Mode
│
▼
Continuous ComplianceKyverno Policy Capabilities
Section titled “Kyverno Policy Capabilities”| Capability | Purpose |
|---|---|
| Validate | Reject or report non-compliant resources |
| Mutate | Automatically modify incoming resources |
| Generate | Create or synchronise supporting resources |
| Verify Images | Verify image signatures and attestations |
| Cleanup | Remove resources based on policy conditions |
| Policy Reports | Record policy results and violations |
| Exceptions | Allow controlled policy exclusions |
Lab Outcomes
Section titled “Lab Outcomes”By the end of this lab, you will have:
- Installed Kyverno
- Verified its controllers and webhooks
- Created validation policies
- Created mutation policies
- Created a generation policy
- Configured Audit mode
- Configured Enforce mode
- Required workload labels
- Blocked privileged containers
- Required non-root execution
- Required resource controls
- Restricted mutable image tags
- Applied seccomp defaults
- Disabled unnecessary Service Account token mounting
- Reviewed policy reports
- Tested policy exceptions
- Produced an enterprise Kyverno assessment
Important Security Notice
Section titled “Important Security Notice”Perform this lab only in an authorised training cluster.
Do not:
- Apply untested policies directly to production
- Place all new policies in Enforce mode immediately
- Create broad exclusions without approval
- Exclude security namespaces without documented justification
- Delete policy reports before evidence collection
- Disable Kyverno webhooks to bypass controls
- Use mutation to hide insecure workload design
- Assume a mutated workload is automatically production-ready
Prerequisites
Section titled “Prerequisites”Before starting, ensure that you have:
- A Kubernetes training cluster
kubectl- Helm
- Cluster administrator permissions
- Internet access
- Visual Studio Code
- Git Bash or PowerShell
- Basic Kubernetes YAML knowledge
- Completion of Lab 02 recommended
Tools Used
Section titled “Tools Used”| Tool | Purpose |
|---|---|
| Kubernetes | Policy enforcement platform |
| Kyverno | Kubernetes-native policy engine |
| Helm | Kyverno installation |
| kubectl | Cluster administration and testing |
| jq | JSON review |
| VS Code | Policy development |
| Git Bash / PowerShell | Command execution |
Recommended Lab File Structure
Section titled “Recommended Lab File Structure”lab-03-kyverno-policies/├── policies/│ ├── validate-required-labels.yaml│ ├── validate-non-root.yaml│ ├── validate-no-privileged.yaml│ ├── validate-resources.yaml│ ├── validate-image-digest.yaml│ ├── validate-seccomp.yaml│ ├── mutate-security-defaults.yaml│ ├── mutate-disable-token.yaml│ └── generate-network-policy.yaml├── exceptions/│ └── temporary-policy-exception.yaml├── manifests/│ ├── compliant-deployment.yaml│ ├── missing-labels.yaml│ ├── root-container.yaml│ ├── privileged-container.yaml│ ├── missing-resources.yaml│ ├── mutable-image.yaml│ ├── missing-seccomp.yaml│ └── mutation-test.yaml├── reports/│ ├── policy-inventory.md│ ├── audit-results.md│ ├── enforcement-results.md│ ├── exception-review.md│ └── kyverno-governance-report.md└── evidence/ ├── kyverno-version.txt ├── kyverno-pods.txt ├── webhook-configurations.txt ├── policy-results.txt ├── policy-reports.txt └── admission-events.txtTask 01 — Create the Lab Workspace
Section titled “Task 01 — Create the Lab Workspace”Git Bash
Section titled “Git Bash”mkdir -p lab-03-kyverno-policies/{policies,exceptions,manifests,reports,evidence}cd lab-03-kyverno-policiesPowerShell
Section titled “PowerShell”New-Item -ItemType Directory -Force ` -Path lab-03-kyverno-policies\policies
New-Item -ItemType Directory -Force ` -Path lab-03-kyverno-policies\exceptions
New-Item -ItemType Directory -Force ` -Path lab-03-kyverno-policies\manifests
New-Item -ItemType Directory -Force ` -Path lab-03-kyverno-policies\reports
New-Item -ItemType Directory -Force ` -Path lab-03-kyverno-policies\evidence
Set-Location lab-03-kyverno-policiesTask 02 — Verify Cluster Access
Section titled “Task 02 — Verify Cluster Access”kubectl cluster-infoReview the current context.
kubectl config current-contextReview permissions.
kubectl auth can-i create clusterpolicies.kyverno.ioExpected:
yesTask 03 — Add the Kyverno Helm Repository
Section titled “Task 03 — Add the Kyverno Helm Repository”helm repo add kyverno https://kyverno.github.io/kyverno/Update repositories.
helm repo updateReview available chart versions.
helm search repo kyverno/kyvernoTask 04 — Install Kyverno
Section titled “Task 04 — Install Kyverno”helm install kyverno kyverno/kyverno \ --namespace kyverno \ --create-namespaceWait for the installation.
kubectl get pods \ -n kyverno \ -wTask 05 — Validate Kyverno Components
Section titled “Task 05 — Validate Kyverno Components”Review Pods.
kubectl get pods \ -n kyvernoReview Deployments.
kubectl get deployments \ -n kyvernoTypical components include:
- Admission Controller
- Background Controller
- Cleanup Controller
- Reports Controller
Save evidence.
kubectl get pods \ -n kyverno \ -o wide \ > evidence/kyverno-pods.txtTask 06 — Record the Kyverno Version
Section titled “Task 06 — Record the Kyverno Version”helm list \ -n kyvernohelm status kyverno \ -n kyvernoSave the installed chart and application version.
helm list \ -n kyverno \ > evidence/kyverno-version.txtTask 07 — Review Kyverno CRDs
Section titled “Task 07 — Review Kyverno CRDs”kubectl get crds | grep kyvernoReview resources such as:
- ClusterPolicy
- Policy
- PolicyException
- AdmissionReport
- ClusterAdmissionReport
- PolicyReport
- ClusterPolicyReport
Task 08 — Review Admission Webhooks
Section titled “Task 08 — Review Admission Webhooks”kubectl get validatingwebhookconfigurationskubectl get mutatingwebhookconfigurationsSave evidence.
kubectl get validatingwebhookconfigurations \ > evidence/webhook-configurations.txtkubectl get mutatingwebhookconfigurations \ >> evidence/webhook-configurations.txtTask 09 — Create the Training Namespace
Section titled “Task 09 — Create the Training Namespace”Create manifests/namespace.yaml.
apiVersion: v1kind: Namespacemetadata: name: kyverno-lab labels: environment: training owner: cloud-security pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io-audit: restricted pod-security.kubernetes.io/warn: restrictedApply it.
kubectl apply \ -f manifests/namespace.yamlTask 10 — Understand Kyverno Validation Modes
Section titled “Task 10 — Understand Kyverno Validation Modes”Kyverno validation policies commonly operate in two modes.
- Records policy violations
- Allows resource creation
- Supports staged rollout
- Helps identify existing non-compliance
Enforce
Section titled “Enforce”- Rejects non-compliant resources
- Prevents insecure configurations
- Should be used after testing and remediation
Recommended enterprise rollout:
Policy Development
│
▼
Development Testing
│
▼
Audit Mode
│
▼
Violation Review
│
▼
Remediation
│
▼
Enforce ModeTask 11 — Create a Required Labels Policy
Section titled “Task 11 — Create a Required Labels Policy”Create policies/validate-required-labels.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-enterprise-labels annotations: policies.kyverno.io/title: Require Enterprise Labels policies.kyverno.io/category: Governance policies.kyverno.io/severity: medium policies.kyverno.io/subject: Deployment policies.kyverno.io/description: >- Requires application, owner, and environment labels on Deployments.spec: validationFailureAction: Audit background: true rules: - name: validate-required-labels match: any: - resources: kinds: - Deployment namespaces: - kyverno-lab validate: message: >- Deployments must define app, owner, and environment labels. pattern: metadata: labels: app: "?*" owner: "?*" environment: "?*" spec: template: metadata: labels: app: "?*" owner: "?*" environment: "?*"Apply it.
kubectl apply \ -f policies/validate-required-labels.yamlVerify.
kubectl get clusterpolicy require-enterprise-labelsTask 12 — Test Missing Labels in Audit Mode
Section titled “Task 12 — Test Missing Labels in Audit Mode”Create manifests/missing-labels.yaml.
apiVersion: apps/v1kind: Deploymentmetadata: name: missing-labels namespace: kyverno-labspec: replicas: 1 selector: matchLabels: app: missing-labels template: metadata: labels: app: missing-labels spec: containers: - name: application image: nginx:1.27-alpineApply it.
kubectl apply \ -f manifests/missing-labels.yamlExpected:
- Resource is allowed because the policy is in Audit mode.
- A policy violation is recorded.
Task 13 — Review Policy Reports
Section titled “Task 13 — Review Policy Reports”kubectl get policyreports \ -ADescribe the report.
kubectl describe policyreport \ -n kyverno-labReview:
- Policy name
- Rule name
- Resource
- Result
- Severity
- Message
Task 14 — Switch Required Labels to Enforce Mode
Section titled “Task 14 — Switch Required Labels to Enforce Mode”Edit the policy.
spec: validationFailureAction: EnforceApply the updated policy.
kubectl apply \ -f policies/validate-required-labels.yamlDelete the earlier test Deployment.
kubectl delete deployment missing-labels \ -n kyverno-labAttempt to recreate it.
kubectl apply \ -f manifests/missing-labels.yamlExpected:
Admission deniedTask 15 — Create a Non-Root Policy
Section titled “Task 15 — Create a Non-Root Policy”Create policies/validate-non-root.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-non-root-containers annotations: policies.kyverno.io/title: Require Non-Root Containers policies.kyverno.io/category: Pod Security policies.kyverno.io/severity: highspec: validationFailureAction: Enforce background: true rules: - name: require-run-as-non-root match: any: - resources: kinds: - Pod namespaces: - kyverno-lab validate: message: >- Pods must set runAsNonRoot to true at Pod or container level. anyPattern: - spec: securityContext: runAsNonRoot: true - spec: containers: - securityContext: runAsNonRoot: trueApply it.
kubectl apply \ -f policies/validate-non-root.yamlTask 16 — Test a Root Container
Section titled “Task 16 — Test a Root Container”Create manifests/root-container.yaml.
apiVersion: v1kind: Podmetadata: name: root-container namespace: kyverno-lab labels: app: root-container owner: cloud-security environment: trainingspec: securityContext: runAsUser: 0 containers: - name: application image: nginx:1.27-alpine securityContext: runAsNonRoot: falseApply it.
kubectl apply \ -f manifests/root-container.yamlExpected:
Admission deniedTask 17 — Create a No-Privileged Policy
Section titled “Task 17 — Create a No-Privileged Policy”Create policies/validate-no-privileged.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: disallow-privileged-containers annotations: policies.kyverno.io/title: Disallow Privileged Containers policies.kyverno.io/category: Pod Security policies.kyverno.io/severity: criticalspec: validationFailureAction: Enforce background: true rules: - name: block-privileged-containers match: any: - resources: kinds: - Pod namespaces: - kyverno-lab validate: message: Privileged containers are prohibited. pattern: spec: containers: - securityContext: privileged: "false"Apply it.
kubectl apply \ -f policies/validate-no-privileged.yamlTask 18 — Test a Privileged Container
Section titled “Task 18 — Test a Privileged Container”Create manifests/privileged-container.yaml.
apiVersion: v1kind: Podmetadata: name: privileged-container namespace: kyverno-lab labels: app: privileged-container owner: cloud-security environment: trainingspec: securityContext: runAsNonRoot: true containers: - name: application image: nginx:1.27-alpine securityContext: privileged: true runAsNonRoot: trueApply it.
kubectl apply \ -f manifests/privileged-container.yamlExpected:
Admission deniedTask 19 — Create a Resource Requirements Policy
Section titled “Task 19 — Create a Resource Requirements Policy”Create policies/validate-resources.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-resource-requests-and-limits annotations: policies.kyverno.io/title: Require Resource Requests and Limits policies.kyverno.io/category: Reliability policies.kyverno.io/severity: mediumspec: validationFailureAction: Enforce background: true rules: - name: validate-container-resources match: any: - resources: kinds: - Pod namespaces: - kyverno-lab validate: message: >- Every container must define CPU and memory requests and limits. pattern: spec: containers: - resources: requests: cpu: "?*" memory: "?*" limits: cpu: "?*" memory: "?*"Apply it.
kubectl apply \ -f policies/validate-resources.yamlTask 20 — Test Missing Resources
Section titled “Task 20 — Test Missing Resources”Create manifests/missing-resources.yaml.
apiVersion: v1kind: Podmetadata: name: missing-resources namespace: kyverno-lab labels: app: missing-resources owner: cloud-security environment: trainingspec: securityContext: runAsNonRoot: true containers: - name: application image: nginx:1.27-alpine securityContext: privileged: false runAsNonRoot: trueApply it.
kubectl apply \ -f manifests/missing-resources.yamlExpected:
Admission deniedTask 21 — Require Immutable Image Digests
Section titled “Task 21 — Require Immutable Image Digests”Create policies/validate-image-digest.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-image-digests annotations: policies.kyverno.io/title: Require Image Digests policies.kyverno.io/category: Software Supply Chain policies.kyverno.io/severity: highspec: validationFailureAction: Audit background: true rules: - name: validate-image-digest match: any: - resources: kinds: - Pod namespaces: - kyverno-lab validate: message: >- Container images must be referenced using an immutable sha256 digest. foreach: - list: request.object.spec.containers deny: conditions: all: - key: "{{ element.image }}" operator: NotMatches value: "*@sha256:*"Apply it.
kubectl apply \ -f policies/validate-image-digest.yamlTask 22 — Test a Mutable Image Reference
Section titled “Task 22 — Test a Mutable Image Reference”Create manifests/mutable-image.yaml.
apiVersion: v1kind: Podmetadata: name: mutable-image namespace: kyverno-lab labels: app: mutable-image owner: cloud-security environment: trainingspec: securityContext: runAsNonRoot: true containers: - name: application image: nginx:1.27-alpine securityContext: privileged: false runAsNonRoot: true resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128MiApply it.
kubectl apply \ -f manifests/mutable-image.yamlBecause the policy is in Audit mode, the Pod may be admitted while the violation is reported.
Review the report before moving the policy to Enforce mode.
Task 23 — Create a Seccomp Policy
Section titled “Task 23 — Create a Seccomp Policy”Create policies/validate-seccomp.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: require-runtime-default-seccomp annotations: policies.kyverno.io/title: Require RuntimeDefault Seccomp policies.kyverno.io/category: Pod Security policies.kyverno.io/severity: highspec: validationFailureAction: Enforce background: true rules: - name: require-seccomp match: any: - resources: kinds: - Pod namespaces: - kyverno-lab validate: message: >- Pods must use the RuntimeDefault seccomp profile. pattern: spec: securityContext: seccompProfile: type: RuntimeDefaultApply it.
kubectl apply \ -f policies/validate-seccomp.yamlTask 24 — Test a Pod Without Seccomp
Section titled “Task 24 — Test a Pod Without Seccomp”Create manifests/missing-seccomp.yaml.
apiVersion: v1kind: Podmetadata: name: missing-seccomp namespace: kyverno-lab labels: app: missing-seccomp owner: cloud-security environment: trainingspec: securityContext: runAsNonRoot: true containers: - name: application image: nginx:1.27-alpine securityContext: privileged: false runAsNonRoot: true resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128MiApply it.
kubectl apply \ -f manifests/missing-seccomp.yamlExpected:
Admission deniedTask 25 — Create a Security Defaults Mutation Policy
Section titled “Task 25 — Create a Security Defaults Mutation Policy”Create policies/mutate-security-defaults.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: add-security-defaults annotations: policies.kyverno.io/title: Add Security Defaults policies.kyverno.io/category: Pod Security policies.kyverno.io/severity: mediumspec: rules: - name: add-pod-security-context match: any: - resources: kinds: - Pod namespaces: - kyverno-lab mutate: patchStrategicMerge: spec: securityContext: +(runAsNonRoot): true +(seccompProfile): type: RuntimeDefault containers: - (name): "*" securityContext: +(allowPrivilegeEscalation): false +(privileged): false +(readOnlyRootFilesystem): true +(capabilities): drop: - ALLApply it.
kubectl apply \ -f policies/mutate-security-defaults.yamlTask 26 — Test Automatic Mutation
Section titled “Task 26 — Test Automatic Mutation”Create manifests/mutation-test.yaml.
apiVersion: v1kind: Podmetadata: name: mutation-test namespace: kyverno-lab labels: app: mutation-test owner: cloud-security environment: trainingspec: containers: - name: application image: nginx:1.27-alpine resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128MiApply it.
kubectl apply \ -f manifests/mutation-test.yamlInspect the resulting Pod.
kubectl get pod mutation-test \ -n kyverno-lab \ -o yamlReview whether Kyverno added:
runAsNonRootRuntimeDefaultseccompallowPrivilegeEscalation: falseprivileged: falsereadOnlyRootFilesystem: true- Dropped capabilities
Task 27 — Mutate Service Account Token Mounting
Section titled “Task 27 — Mutate Service Account Token Mounting”Create policies/mutate-disable-token.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: disable-service-account-token-mount annotations: policies.kyverno.io/title: Disable Service Account Token Mount policies.kyverno.io/category: Identity policies.kyverno.io/severity: mediumspec: rules: - name: disable-automatic-token-mount match: any: - resources: kinds: - Pod namespaces: - kyverno-lab mutate: patchStrategicMerge: spec: +(automountServiceAccountToken): falseApply it.
kubectl apply \ -f policies/mutate-disable-token.yamlCreate a new Pod and verify:
kubectl get pod <pod-name> \ -n kyverno-lab \ -o jsonpath='{.spec.automountServiceAccountToken}{"\n"}'Expected:
falseTask 28 — Create a Generated NetworkPolicy
Section titled “Task 28 — Create a Generated NetworkPolicy”Create policies/generate-network-policy.yaml.
apiVersion: kyverno.io/v1kind: ClusterPolicymetadata: name: generate-default-deny-network-policy annotations: policies.kyverno.io/title: Generate Default Deny NetworkPolicy policies.kyverno.io/category: Network Security policies.kyverno.io/severity: highspec: rules: - name: generate-default-deny match: any: - resources: kinds: - Namespace names: - kyverno-lab-generated generate: generateExisting: true synchronize: true apiVersion: networking.k8s.io/v1 kind: NetworkPolicy name: default-deny-all namespace: "{{ request.object.metadata.name }}" data: spec: podSelector: {} policyTypes: - Ingress - EgressApply it.
kubectl apply \ -f policies/generate-network-policy.yamlCreate the namespace.
kubectl create namespace kyverno-lab-generatedVerify the generated policy.
kubectl get networkpolicy \ -n kyverno-lab-generatedTask 29 — Review All Kyverno Policies
Section titled “Task 29 — Review All Kyverno Policies”kubectl get clusterpoliciesDescribe a policy.
kubectl describe clusterpolicy require-non-root-containersReview:
- Validation failure action
- Background scanning
- Rule count
- Readiness
- Generated resources
- Policy conditions
Task 30 — Review Policy Reports
Section titled “Task 30 — Review Policy Reports”kubectl get policyreports \ -Akubectl get clusterpolicyreportsExport policy-report evidence.
kubectl get policyreports \ -A \ -o yaml \ > evidence/policy-reports.txtTask 31 — Review Admission Reports
Section titled “Task 31 — Review Admission Reports”kubectl get admissionreports \ -Akubectl get clusteradmissionreportsReview recent policy decisions and affected resources.
Task 32 — Review Kyverno Controller Logs
Section titled “Task 32 — Review Kyverno Controller Logs”List controller Pods.
kubectl get pods \ -n kyvernoReview admission-controller logs.
kubectl logs \ -n kyverno \ deployment/kyverno-admission-controllerReview reports-controller logs.
kubectl logs \ -n kyverno \ deployment/kyverno-reports-controllerSearch for:
- Policy errors
- Admission denials
- Mutation failures
- Background-scan failures
- Webhook timeouts
- Generate-policy failures
Task 33 — Create a Compliant Deployment
Section titled “Task 33 — Create a Compliant Deployment”Create manifests/compliant-deployment.yaml.
apiVersion: apps/v1kind: Deploymentmetadata: name: compliant-application namespace: kyverno-lab labels: app: compliant-application owner: cloud-security environment: trainingspec: replicas: 2 selector: matchLabels: app: compliant-application template: metadata: labels: app: compliant-application owner: cloud-security environment: training spec: automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 101 runAsGroup: 101 seccompProfile: type: RuntimeDefault containers: - name: application image: nginx:1.27-alpine ports: - name: http containerPort: 8080 securityContext: privileged: false allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128Mi volumeMounts: - name: temporary-files mountPath: /tmp - name: cache mountPath: /var/cache/nginx - name: runtime mountPath: /var/run volumes: - name: temporary-files emptyDir: {} - name: cache emptyDir: {} - name: runtime emptyDir: {}The digest policy is currently in Audit mode, allowing the tagged training image while recording the violation.
Apply it.
kubectl apply \ -f manifests/compliant-deployment.yamlMonitor rollout.
kubectl rollout status \ deployment/compliant-application \ -n kyverno-labTask 34 — Validate the Mutated Deployment
Section titled “Task 34 — Validate the Mutated Deployment”Review the created Pod.
kubectl get pods \ -n kyverno-labkubectl get pod <pod-name> \ -n kyverno-lab \ -o yamlConfirm:
- Security context exists
- Service Account token mounting is disabled
- Seccomp is configured
- Capabilities are dropped
- Resource controls exist
- Required labels exist
Task 35 — Design a Policy Exception
Section titled “Task 35 — Design a Policy Exception”Exceptions should be:
- Business justified
- Time limited
- Resource specific
- Policy specific
- Approved
- Logged
- Reviewed
- Automatically expired where possible
Document:
Exception ID:
Policy:
Rule:
Resource:
Namespace:
Business Justification:
Risk:
Compensating Controls:
Requested By:
Approved By:
Start Time:
Expiration Time:
Review Date:
Status:Task 36 — Create a Temporary Policy Exception
Section titled “Task 36 — Create a Temporary Policy Exception”Create exceptions/temporary-policy-exception.yaml.
apiVersion: kyverno.io/v2kind: PolicyExceptionmetadata: name: temporary-image-tag-exception namespace: kyverno annotations: cloudnova.io/owner: platform-security cloudnova.io/expiry: "2026-08-01T18:00:00Z"spec: exceptions: - policyName: require-image-digests ruleNames: - validate-image-digest match: any: - resources: kinds: - Pod namespaces: - kyverno-lab names: - approved-exception-testThe API version and feature configuration must match the installed Kyverno version.
Apply only after validating support.
kubectl apply \ -f exceptions/temporary-policy-exception.yamlTask 37 — Test the Policy Exception
Section titled “Task 37 — Test the Policy Exception”Create a Pod named:
approved-exception-testUse a tagged image.
Confirm:
- The named resource receives the approved exception.
- Other tagged-image workloads remain subject to policy.
- The exception is visible and documented.
- The expiration date is tracked operationally.
Task 38 — Compare Gatekeeper and Kyverno
Section titled “Task 38 — Compare Gatekeeper and Kyverno”Complete the comparison.
| Capability | Gatekeeper | Kyverno |
|---|---|---|
| Policy language | Rego | Kubernetes YAML |
| Validation | Yes | Yes |
| Mutation | Yes | Yes |
| Resource generation | Limited / External Patterns | Native Generate Rules |
| Image verification | Additional integration | Native policy capability |
| Background scanning | Yes | Yes |
| Policy reports | Supported | Supported |
| Kubernetes-native authoring | Partial | Strong |
| Learning curve | Rego knowledge required | Familiar YAML patterns |
| Best fit | Complex policy logic | Kubernetes-native policy operations |
Document which engine is most appropriate for:
- Platform governance
- Security validation
- Mutation
- Resource generation
- Image verification
- Complex custom logic
Task 39 — Build the Policy Inventory
Section titled “Task 39 — Build the Policy Inventory”Create reports/policy-inventory.md.
| Policy | Type | Mode | Scope | Severity | Owner |
|---|---|---|---|---|---|
| Require enterprise labels | Validate | Enforce | kyverno-lab | Medium | Platform |
| Require non-root | Validate | Enforce | kyverno-lab | High | Security |
| Disallow privileged | Validate | Enforce | kyverno-lab | Critical | Security |
| Require resources | Validate | Enforce | kyverno-lab | Medium | Platform |
| Require image digest | Validate | Audit | kyverno-lab | High | DevSecOps |
| Require seccomp | Validate | Enforce | kyverno-lab | High | Security |
| Add security defaults | Mutate | Active | kyverno-lab | Medium | Platform |
| Disable token mount | Mutate | Active | kyverno-lab | Medium | IAM |
| Generate NetworkPolicy | Generate | Active | Selected namespace | High | Network Security |
Task 40 — Perform the Enterprise Kyverno Assessment
Section titled “Task 40 — Perform the Enterprise Kyverno Assessment”Complete the assessment.
| Security Domain | Expected Control | Status |
|---|---|---|
| Kyverno availability | Controllers healthy | |
| Webhook security | Webhooks active and trusted | |
| Policy ownership | Owner assigned | |
| Policy documentation | Purpose and risk documented | |
| Audit rollout | Tested before enforcement | |
| Required labels | Enforced | |
| Non-root execution | Enforced | |
| Privileged containers | Blocked | |
| Resource controls | Enforced | |
| Image digests | Audited or enforced | |
| Seccomp | Enforced | |
| Service Account token | Disabled where unnecessary | |
| Mutation controls | Reviewed | |
| Generated resources | Validated | |
| Policy reports | Reviewed | |
| Exceptions | Controlled and time limited | |
| Controller logs | Monitored | |
| Policy changes | Change controlled | |
| Evidence | Retained |
Rate each area as:
- Effective
- Partially Effective
- Ineffective
- Not Applicable
Task 41 — Assign the Governance Risk Rating
Section titled “Task 41 — Assign the Governance Risk Rating”Critical Risk
Section titled “Critical Risk”Examples:
- Kyverno unavailable in production
- Admission webhook fail-open without approval
- Privileged containers allowed
- Broad policy bypass configured
- Security policies deleted without authorisation
- Untrusted policy changes applied directly to production
High Risk
Section titled “High Risk”Examples:
- Non-root policy absent
- Digest enforcement absent
- Seccomp not required
- Service Account tokens mounted unnecessarily
- Critical policies remain in Audit mode
- Exceptions have no expiry
- Mutation policy introduces insecure defaults
Medium Risk
Section titled “Medium Risk”Examples:
- Missing resource controls
- Incomplete policy reports
- Policy ownership unclear
- Manual exception review
- Missing policy documentation
- Background scanning disabled
Low Risk
Section titled “Low Risk”Examples:
- Naming inconsistency
- Missing annotations
- Reporting format issue
- Minor metadata gap
Task 42 — Create the Enterprise Governance Report
Section titled “Task 42 — Create the Enterprise Governance Report”Create reports/kyverno-governance-report.md.
Assessment Title:Enterprise Kyverno Policy Governance Assessment
Assessment Date:
Assessor:
Cluster:
Environment:
Kyverno Version:
Namespace:
Policies Reviewed:
Validation Policies:
Mutation Policies:
Generation Policies:
Policies in Audit Mode:
Policies in Enforce Mode:
Critical Violations:
High Violations:
Medium Violations:
Low Violations:
Required Labels:
Non-Root Enforcement:
Privileged Container Enforcement:
Resource Controls:
Image Digest Enforcement:
Seccomp Enforcement:
Service Account Token Control:
Generated Network Policies:
Policy Reports:
Controller Health:
Webhook Health:
Exception Count:
Expired Exceptions:
Policy Ownership:
Change-Control Status:
Critical Risks:
High Risks:
Medium Risks:
Low Risks:
Required Remediation:
Residual Risk:
Overall Rating:
Production Decision:
Approved
Conditionally Approved
Rejected
Approvals:
Kubernetes Security:
Platform Engineering:
Cloud Security:
Compliance:Task 43 — Collect Evidence
Section titled “Task 43 — Collect Evidence”Collect:
- Kyverno version
- Helm release
- Controller Pods
- CRDs
- Webhooks
- ClusterPolicies
- Namespaced Policies
- PolicyExceptions
- Policy reports
- Admission reports
- Controller logs
- Compliant workload
- Rejected workload results
- Mutated resource output
- Generated NetworkPolicy
- Policy inventory
- Enterprise assessment
- Governance report
Suggested filenames:
01-kyverno-version.txt02-helm-release.txt03-controller-pods.txt04-kyverno-crds.txt05-webhook-configurations.txt06-clusterpolicies.yaml07-policyexceptions.yaml08-policyreports.yaml09-admissionreports.yaml10-controller-logs.txt11-compliant-workload.yaml12-rejected-workload-results.txt13-mutated-resource.yaml14-generated-networkpolicy.yaml15-policy-inventory.md16-enterprise-assessment.md17-kyverno-governance-report.mdTask 44 — Clean Up Test Resources
Section titled “Task 44 — Clean Up Test Resources”Delete test workloads.
kubectl delete pod \ mutation-test \ mutable-image \ --namespace kyverno-lab \ --ignore-not-foundkubectl delete deployment \ compliant-application \ --namespace kyverno-lab \ --ignore-not-foundDelete the generated namespace.
kubectl delete namespace kyverno-lab-generated \ --ignore-not-foundDelete the training namespace.
kubectl delete namespace kyverno-labTask 45 — Decide Whether to Retain Kyverno
Section titled “Task 45 — Decide Whether to Retain Kyverno”Retain Kyverno when:
- The cluster is dedicated to continued policy training.
- Later labs depend on it.
- The organisation is evaluating policy automation.
- Policies and reports must remain available.
Remove it only when the cluster is temporary and no later lab depends on the installation.
helm uninstall kyverno \ -n kyvernokubectl delete namespace kyvernoDo not remove Kyverno from a shared or production cluster without approved change control.
Enterprise Kyverno Governance Checklist
Section titled “Enterprise Kyverno Governance Checklist”| Control | Status |
|---|---|
| Kyverno installed successfully | ☐ |
| Admission Controller healthy | ☐ |
| Background Controller healthy | ☐ |
| Reports Controller healthy | ☐ |
| Cleanup Controller healthy | ☐ |
| Validating webhooks active | ☐ |
| Mutating webhooks active | ☐ |
| Policy ownership documented | ☐ |
| Audit mode tested | ☐ |
| Enforce mode tested | ☐ |
| Required labels enforced | ☐ |
| Non-root execution enforced | ☐ |
| Privileged containers blocked | ☐ |
| Resource controls enforced | ☐ |
| Image digest policy configured | ☐ |
| Seccomp profile enforced | ☐ |
| Security defaults mutated | ☐ |
| Service Account token mounting controlled | ☐ |
| Supporting resources generated | ☐ |
| Policy reports reviewed | ☐ |
| Admission reports reviewed | ☐ |
| Controller logs reviewed | ☐ |
| Policy exceptions controlled | ☐ |
| Exception expiry documented | ☐ |
| Policy inventory completed | ☐ |
| Evidence retained | ☐ |
| Governance report approved | ☐ |
Remediation Priorities
Section titled “Remediation Priorities”Immediate
Section titled “Immediate”- Restore unhealthy Kyverno controllers.
- Remove unauthorised policy exclusions.
- Block privileged containers.
- Enforce non-root execution.
- Correct failing webhooks.
- Remove expired exceptions.
- Investigate unauthorised policy changes.
Short-Term
Section titled “Short-Term”- Move critical policies from Audit to Enforce.
- Require seccomp profiles.
- Enforce resource controls.
- Disable unnecessary Service Account token mounting.
- Implement image digest enforcement.
- Establish policy ownership.
- Integrate policy reports with compliance monitoring.
Long-Term
Section titled “Long-Term”- Add signed-image verification.
- Integrate Kyverno with GitOps.
- Test policies in CI/CD before cluster deployment.
- Automate exception expiry.
- Implement central multi-cluster policy management.
- Create policy maturity metrics.
- Continuously evaluate policy performance and coverage.
Skills Developed
Section titled “Skills Developed”By completing this lab, you will be able to:
- Install and validate Kyverno
- Create Kubernetes-native policies
- Configure validation controls
- Configure mutation rules
- Generate supporting resources
- Apply Audit and Enforce modes
- Block privileged and root containers
- Require resource controls
- Enforce seccomp settings
- Restrict mutable image references
- Disable unnecessary token mounting
- Review policy and admission reports
- Manage controlled policy exceptions
- Compare Kyverno with Gatekeeper
- Produce enterprise policy-governance reports
Knowledge Check
Section titled “Knowledge Check”Question 1
Section titled “Question 1”What is the main advantage of Kyverno for Kubernetes teams?
Answer: Kyverno allows teams to create and manage policies using Kubernetes-native YAML without requiring a separate policy language for common Kubernetes governance use cases.
Question 2
Section titled “Question 2”What is the difference between Audit and Enforce mode?
Answer: Audit mode records violations while allowing the resource, whereas Enforce mode rejects resources that violate policy.
Question 3
Section titled “Question 3”What does a Kyverno mutation policy do?
Answer: It automatically modifies an incoming Kubernetes resource by adding or changing approved configuration before the resource is stored.
Question 4
Section titled “Question 4”Why should mutation not replace secure application design?
Answer: Mutation can add standard defaults, but workload owners must still understand and maintain secure configurations rather than relying entirely on automatic changes.
Question 5
Section titled “Question 5”What is the purpose of a generate policy?
Answer: A generate policy automatically creates or synchronises supporting Kubernetes resources when matching resources are created.
Question 6
Section titled “Question 6”Why should policies first be tested in Audit mode?
Answer: Audit mode identifies affected workloads and operational impact before enforcement begins, reducing the risk of disrupting legitimate applications.
Question 7
Section titled “Question 7”Why are policy exceptions high-risk?
Answer: Exceptions weaken enforcement and may create unmanaged security gaps when they are broad, permanent, undocumented, or not reviewed.
Question 8
Section titled “Question 8”Why should immutable image digests be required?
Answer: Digests identify exact image content and prevent a mutable tag from resolving to a different image after approval.
Question 9
Section titled “Question 9”Does Kyverno replace Pod Security Admission?
Answer: No. Kyverno complements Pod Security Admission and can enforce additional organisation-specific governance and compliance requirements.
Question 10
Section titled “Question 10”What evidence should be retained for a Kyverno governance review?
Answer: Policies, controller health, webhook configuration, policy reports, admission reports, exceptions, enforcement tests, logs, findings, and approvals should be retained.
Lab Summary
Section titled “Lab Summary”In this lab, you deployed Kyverno and implemented enterprise Kubernetes policy-as-code controls using native YAML resources.
You created validation policies to:
- Require ownership and environment labels
- Enforce non-root execution
- Block privileged containers
- Require resource requests and limits
- Audit mutable image references
- Require RuntimeDefault seccomp profiles
You also created mutation policies that:
- Applied security defaults
- Disabled unnecessary Service Account token mounting
In addition, you implemented a generate policy to create a default-deny NetworkPolicy automatically.
You tested policies in Audit and Enforce modes, reviewed PolicyReports and AdmissionReports, examined Kyverno controller logs, evaluated controlled exceptions, compared Kyverno with OPA Gatekeeper, and produced an enterprise governance assessment.
Kyverno provides a powerful Kubernetes-native approach to:
- Prevent insecure configurations
- Standardise workload defaults
- Generate required supporting resources
- Audit existing workloads
- Automate compliance reporting
- Enforce organisational governance at admission time
What’s Next?
Section titled “What’s Next?”Next Lab: Lab 04 — Compliance Automation
In the next lab, you will automate Kubernetes compliance assessments by integrating CIS Benchmark checks, policy validation, image scanning, configuration analysis, policy reports, evidence collection, CI/CD security gates, compliance dashboards, and scheduled assessment workflows.