# Kyverno ClusterPolicies: Image scanning, Pod security, and admission control --- # Policy 1: Require non-root containers apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-non-root namespace: kyverno spec: validationFailureAction: audit # audit first, then change to enforce rules: - name: check-runAsNonRoot match: any: - resources: kinds: - Pod selector: matchLabels: pod-security.kubernetes.io/enforce: "!privileged" validate: message: "Container must not run as root" pattern: spec: containers: - securityContext: runAsNonRoot: true --- # Policy 2: Drop all Linux capabilities, add only required ones apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-dropped-caps namespace: kyverno spec: validationFailureAction: audit rules: - name: drop-all-capabilities match: any: - resources: kinds: - Pod selector: matchLabels: pod-security.kubernetes.io/enforce: "!privileged" validate: message: "All Linux capabilities must be dropped" pattern: spec: containers: - securityContext: capabilities: drop: - ALL --- # Policy 3: Require image tags (no 'latest') apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-latest-tag namespace: kyverno spec: validationFailureAction: audit # Change to enforce after testing rules: - name: disallow-latest match: any: - resources: kinds: - Pod - Deployment - StatefulSet - DaemonSet - Job validate: message: "Image tag 'latest' is not allowed. Use explicit version tags." pattern: spec: =(template): spec: containers: - image: "!*:latest" =(initContainers): - image: "!*:latest" --- # Policy 4: Restrict images to trusted registries apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: restrict-registries namespace: kyverno spec: validationFailureAction: audit rules: - name: trusted-registries match: any: - resources: kinds: - Pod - Deployment - StatefulSet - DaemonSet - Job selector: matchLabels: pod-security.kubernetes.io/enforce: "!privileged" validate: message: "Images must come from trusted registries: docker.io, ghcr.io, quay.io, k8s.gcr.io, registry.k8s.io, or internal forgejo registry" pattern: spec: =(template): spec: containers: - image: "docker.io/* | ghcr.io/* | quay.io/* | k8s.gcr.io/* | registry.k8s.io/* | forgejo.riotpiao.com/* | *" --- # Policy 5: Require read-only root filesystem (audit only, exceptions for apps that need writes) apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-readonly-filesystem namespace: kyverno spec: validationFailureAction: audit rules: - name: check-readOnlyRootFilesystem match: any: - resources: kinds: - Pod selector: matchLabels: pod-security.kubernetes.io/enforce: "!privileged" validate: message: "Root filesystem should be read-only for defense-in-depth" pattern: spec: containers: - securityContext: readOnlyRootFilesystem: true --- # Policy 6: Require resource requests and limits (prevent resource starvation) apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-resource-limits namespace: kyverno spec: validationFailureAction: audit rules: - name: check-resources match: any: - resources: kinds: - Pod - Deployment - StatefulSet - DaemonSet excludeResources: namespaceSelector: matchLabels: kubernetes.io/metadata.name: "kyverno|kube-system|kube-node-lease" validate: message: "CPU and memory requests and limits are required" pattern: spec: =(template): spec: containers: - resources: requests: memory: "?*" cpu: "?*" limits: memory: "?*" cpu: "?*" --- # Policy 7: Require securityContext on all containers apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-security-context namespace: kyverno spec: validationFailureAction: audit rules: - name: check-securityContext match: any: - resources: kinds: - Pod selector: matchLabels: pod-security.kubernetes.io/enforce: "!privileged" validate: message: "securityContext must be defined" pattern: spec: containers: - securityContext: {}