apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-deployment-owner spec: validationFailureAction: Audit background: false rules: - name: check-pod-owner-is-replicaset-from-deployment skipBackgroundRequests: true match: any: - resources: kinds: - Pod exclude: any: - resources: namespaces: - kube-system - kyverno - cert-manager - monitoring - argocd - traefik-system context: - name: ownerReplicaSet apiCall: method: GET urlPath: "/apis/apps/v1/namespaces/{{request.namespace}}/replicasets/{{request.object.metadata.ownerReferences[0].name}}" jmesPath: "@" preconditions: all: - key: "{{ request.object.metadata.ownerReferences || `[]` | [?kind=='ReplicaSet'] | length(@) }}" operator: GreaterThanOrEquals value: 1 validate: allowExistingViolations: true message: "Pods must be created through a Deployment resource." deny: conditions: any: - key: "{{ownerReplicaSet.metadata.ownerReferences[0].kind}}" operator: NotEquals value: Deployment - name: deny-pods-without-replicaset-owner match: any: - resources: kinds: - Pod exclude: any: - resources: namespaces: - kube-system - kyverno - cert-manager - monitoring - argocd - traefik-system skipBackgroundRequests: true validate: allowExistingViolations: true message: "Direct pod creation is not allowed. Pods must come from a Deployment managed by ArgoCD." deny: conditions: all: - key: "{{ request.object.metadata.ownerReferences || `[]` | [?kind=='ReplicaSet'] | length(@) }}" operator: LessThan value: 1