109 lines
4.3 KiB
YAML
109 lines
4.3 KiB
YAML
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: tls-rollout
|
|
spec:
|
|
mutateExistingOnPolicyUpdate: false
|
|
rules:
|
|
- name: deployments
|
|
match: &secretMatch
|
|
any:
|
|
- resources:
|
|
kinds:
|
|
- Secret
|
|
operations:
|
|
- CREATE
|
|
- UPDATE
|
|
context: &certData
|
|
- 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: oldCerts
|
|
variable:
|
|
jmesPath: >-
|
|
sort_by(items(request.oldObject.data || `{}`, 'key', 'value')[?value != '' && (
|
|
contains(`["tls.crt", "ca.crt", "ssl.cert"]`, key) ||
|
|
contains(base64_decode(value), '-----BEGIN CERTIFICATE-----'))], &key)
|
|
preconditions: &changedCert
|
|
all:
|
|
- key: "{{ length(certs) }}"
|
|
operator: GreaterThan
|
|
value: 0
|
|
- key: "{{ to_string(certs) }}"
|
|
operator: NotEquals
|
|
value: "{{ to_string(oldCerts) }}"
|
|
mutate:
|
|
targets:
|
|
- apiVersion: apps/v1
|
|
kind: Deployment
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
context: &consumerData
|
|
- name: tlsVolumes
|
|
variable:
|
|
jmesPath: >-
|
|
target.spec.template.spec.volumes[?
|
|
secret.secretName == '{{ request.object.metadata.name }}' ||
|
|
contains(projected.sources[].secret.name || `[]`, '{{ request.object.metadata.name }}')].name
|
|
default: []
|
|
- name: clients
|
|
variable:
|
|
jmesPath: >-
|
|
target.spec.template.spec.[containers, initContainers][] | [?
|
|
length(volumeMounts[?contains(`{{ tlsVolumes }}`, name)] || `[]`) > `0` ||
|
|
contains(env[].valueFrom.secretKeyRef.name || `[]`, '{{ request.object.metadata.name }}') ||
|
|
contains(envFrom[].secretRef.name || `[]`, '{{ request.object.metadata.name }}')].name
|
|
- name: handlers
|
|
variable:
|
|
jmesPath: >-
|
|
items(parse_json(target.spec.template.metadata.annotations."certificates.quorate.internal/activation" || '{}'), 'name', 'mode')[?
|
|
contains(`["native", "controller"]`, mode)].name
|
|
preconditions: &rolloutTarget
|
|
all:
|
|
- key: "{{ target.metadata.namespace }}"
|
|
operator: Equals
|
|
value: "{{ request.object.metadata.namespace }}"
|
|
- key: "{{ target.spec.paused || `false` }}"
|
|
operator: Equals
|
|
value: false
|
|
- key: "{{ target.spec.updateStrategy.type || 'RollingUpdate' }}"
|
|
operator: Equals
|
|
value: RollingUpdate
|
|
- key: "{{ target.spec.updateStrategy.rollingUpdate.partition || `0` }}"
|
|
operator: Equals
|
|
value: 0
|
|
- key: "{{ clients }}"
|
|
operator: AnyNotIn
|
|
value: "{{ handlers }}"
|
|
patchStrategicMerge: &rolloutPatch
|
|
spec:
|
|
template:
|
|
metadata:
|
|
annotations:
|
|
"certificates.quorate.internal/{{ truncate(sha256(request.object.metadata.name), `32`) }}": "{{ sha256(to_string(certs)) }}"
|
|
- name: daemonsets
|
|
match: *secretMatch
|
|
context: *certData
|
|
preconditions: *changedCert
|
|
mutate:
|
|
targets:
|
|
- apiVersion: apps/v1
|
|
kind: DaemonSet
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
context: *consumerData
|
|
preconditions: *rolloutTarget
|
|
patchStrategicMerge: *rolloutPatch
|
|
- name: statefulsets
|
|
match: *secretMatch
|
|
context: *certData
|
|
preconditions: *changedCert
|
|
mutate:
|
|
targets:
|
|
- apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
context: *consumerData
|
|
preconditions: *rolloutTarget
|
|
patchStrategicMerge: *rolloutPatch
|