apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: tls-activation spec: validationFailureAction: Audit background: true rules: - name: tls-containers match: any: - resources: kinds: - Secret operations: - CREATE - UPDATE preconditions: all: - key: '{{ length(certs) }}' operator: GreaterThan value: 0 context: - name: certs variable: jmesPath: sort_by(items(request.object.data || `{}`, 'key', 'value')[?value != '' && (contains(`["tls.crt", "ca.crt", "ssl.cert"]`, key) || contains(base64_decode(value), '-----BEGIN CERTIFICATE-----'))], &key) - name: pods apiCall: urlPath: /api/v1/namespaces/{{ request.object.metadata.namespace }}/pods jmesPath: 'items[?status.phase != `"Succeeded"` && status.phase != `"Failed"` && (spec.volumes[?secret.secretName == ''{{ request.object.metadata.name }}'' || contains(projected.sources[].secret.name || `[]`, ''{{ request.object.metadata.name }}'')] || spec.[containers, initContainers][][?env[].valueFrom.secretKeyRef[?name == ''{{ request.object.metadata.name }}''] || envFrom[].secretRef[?name == ''{{ request.object.metadata.name }}'']])].{metadata: {name: metadata.name, ownerReferences: metadata.ownerReferences, annotations: {"certificates.quorate.internal/activation": metadata.annotations."certificates.quorate.internal/activation"}}, spec: {volumes: spec.volumes, containers: spec.containers[].{name: name, volumeMounts: volumeMounts, env: env[].valueFrom.secretKeyRef, envFrom: envFrom[].secretRef}, initContainers: spec.initContainers[].{name: name, volumeMounts: volumeMounts, env: env[].valueFrom.secretKeyRef, envFrom: envFrom[].secretRef}}}' - name: deployments apiCall: urlPath: /apis/apps/v1/namespaces/{{ request.object.metadata.namespace }}/deployments jmesPath: items[?spec.paused != `true`].metadata.name - name: replicas apiCall: urlPath: /apis/apps/v1/namespaces/{{ request.object.metadata.namespace }}/replicasets jmesPath: items[?metadata.ownerReferences[?kind == 'Deployment' && contains(`{{ deployments }}`, name)]].metadata.name - name: daemonsets apiCall: urlPath: /apis/apps/v1/namespaces/{{ request.object.metadata.namespace }}/daemonsets jmesPath: items[?spec.updateStrategy.type != 'OnDelete'].metadata.name - name: statefulsets apiCall: urlPath: /apis/apps/v1/namespaces/{{ request.object.metadata.namespace }}/statefulsets jmesPath: items[?spec.updateStrategy.type != 'OnDelete' && (spec.updateStrategy.rollingUpdate.partition || `0`) == `0`].metadata.name validate: message: TLS consumers need an eligible rollout controller or an explicit native reload mechanism. foreach: - list: pods context: - name: tlsVolumes variable: jmesPath: element0.spec.volumes[?secret.secretName == '{{ request.object.metadata.name }}' || contains(projected.sources[].secret.name || `[]`, '{{ request.object.metadata.name }}')].name default: [] - name: activation variable: jmesPath: parse_json(element0.metadata.annotations."certificates.quorate.internal/activation" || '{}') - name: rollout variable: jmesPath: length(element0.metadata.ownerReferences[?(kind == 'ReplicaSet' && contains(`{{ replicas }}`, name)) || (kind == 'DaemonSet' && contains(`{{ daemonsets }}`, name)) || (kind == 'StatefulSet' && contains(`{{ statefulsets }}`, name))] || `[]`) > `0` foreach: - list: element.spec.[containers, initContainers][] preconditions: all: - key: '{{ rollout }}' operator: Equals value: false any: - key: '{{ element.volumeMounts[].name || `[]` }}' operator: AnyIn value: '{{ tlsVolumes }}' - key: '{{ element.env[].name || `[]` }}' operator: AnyIn value: - '{{ request.object.metadata.name }}' - key: '{{ element.envFrom[].name || `[]` }}' operator: AnyIn value: - '{{ request.object.metadata.name }}' deny: conditions: all: - key: '{{ activation."{{ element.name }}" || `""` }}' operator: AnyNotIn value: - native - controller message: Pod {{ element0.metadata.name }}, container {{ element.name }} has no automatic certificate activation path.