version: 1
id: policy-kyverno-basics
title: Apply Kyverno Baseline Policies
summary: Author and apply Kyverno ClusterPolicies on a live k3d cluster that require app labels and block :latest images.
difficulty: intermediate
estimatedMinutes: 40
prerequisites: [kubernetes-rbac, kubernetes-deploy]
image: alpine/k8s:1.31.4
shell: /bin/bash
runtime:
  type: k3d
  addons: [kyverno]
setup:
  - "mkdir -p /workspace/policy /workspace/docs"
  - "printf 'Ticket: payments cluster needs admission baselines.\\nRequire app label; block image tags ending in :latest.\\nApply with kubectl — Kyverno is already installed.\\n' > /workspace/policy/TICKET.md"
  - "kubectl wait --for=condition=established crd/clusterpolicies.kyverno.io --timeout=120s"
tasks:
  - id: require-labels
    title: Require app labels
    description: 'Create /workspace/policy/require-labels.yaml with kind: ClusterPolicy, metadata.name require-app-label, and a validate rule that requires metadata.labels.app (or app.kubernetes.io/name). Set validationFailureAction to Enforce. Apply it with kubectl apply -f.'
    hints:
      - 'Tip code KYN_LABEL: baseline ClusterPolicy should validate that metadata.labels.app exists.'
      - 'Tip code KYN_ENFORCE: set validationFailureAction: Enforce for prod baselines.'
      - 'kubectl apply -f /workspace/policy/require-labels.yaml'
    checks:
      - type: file
        name: ClusterPolicy kind
        path: /workspace/policy/require-labels.yaml
        value: "kind: ClusterPolicy"
      - type: file
        name: Policy named
        path: /workspace/policy/require-labels.yaml
        value: require-app-label
      - type: file
        name: Mentions app label
        path: /workspace/policy/require-labels.yaml
        value: app
      - type: command
        name: Mentions validation
        command: "grep -Eqi 'validat|validation' /workspace/policy/require-labels.yaml"
      - type: command
        name: Mentions enforce
        command: "grep -Eqi 'enforce' /workspace/policy/require-labels.yaml"
      - type: kubernetes
        name: Policy applied
        command: kubectl get clusterpolicy require-app-label
  - id: block-latest
    title: Block latest tags
    description: 'Create /workspace/policy/block-latest.yaml with kind: ClusterPolicy, metadata.name block-latest-tag, that denies images containing :latest. Apply it. Write /workspace/docs/POLICY.md with headings Labels and Images. Write /workspace/policy/STATUS.txt containing KYVERNO_OK.'
    hints:
      - 'Tip code NO_LATEST_TAG: admission should deny container images tagged :latest.'
      - 'POLICY.md should be scannable with Labels and Images headings.'
      - 'STATUS.txt should include KYVERNO_OK.'
    checks:
      - type: file
        name: Block-latest policy present
        path: /workspace/policy/block-latest.yaml
        value: "kind: ClusterPolicy"
      - type: file
        name: Block-latest named
        path: /workspace/policy/block-latest.yaml
        value: block-latest-tag
      - type: file
        name: Mentions latest tag
        path: /workspace/policy/block-latest.yaml
        value: ":latest"
      - type: command
        name: Mentions image or containers
        command: "grep -Eqi 'image|containers' /workspace/policy/block-latest.yaml"
      - type: kubernetes
        name: Block-latest applied
        command: kubectl get clusterpolicy block-latest-tag
      - type: file
        name: Labels section present
        path: /workspace/docs/POLICY.md
        value: Labels
      - type: file
        name: Images section present
        path: /workspace/docs/POLICY.md
        value: Images
      - type: file
        name: Kyverno status ok
        path: /workspace/policy/STATUS.txt
        value: KYVERNO_OK
limits: {cpus: "1.0", memory: 768m, pids: 256, timeout: 3600, network: true}
