Add helm chart for observing secrets

This commit adds helm chart for observing changes to a kubernetes
secret. This is done with a cron job. The cron job updates a
configurable deployment annotation with a checksum of the secret.
This way, when the secret changes, the pod in the deployment is
automatically restarted to pick up the changes.

Change-Id: I1a1a1b78ec1c6752747ea2a115ecea9caffdfb66
Story: 2007361
Task: 42932
Signed-off-by: Jerry Sun <jerry.sun@windriver.com>
This commit is contained in:
Jerry Sun 2021-08-11 16:13:56 -04:00
parent 4e77c25a20
commit 638dc8f924
7 changed files with 204 additions and 0 deletions

View File

@ -0,0 +1,10 @@
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
apiVersion: v1
appVersion: "1.0"
description: A Helm chart to update a deployment annotation if a secret changes
name: secret-observer
version: 0.1.0

View File

@ -0,0 +1,23 @@
{{/*
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
*/}}
{{- if .Values.clusterRole.create }}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: secret-observer-cr
labels:
app: secret-observer
release: "{{ .Release.Name }}"
rules:
- apiGroups: ["apps"]
resources:
- deployments
verbs:
- patch
{{- end -}}

View File

@ -0,0 +1,24 @@
{{/*
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
*/}}
{{- if .Values.clusterRoleBinding.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
release: "{{ .Release.Name }}"
name: secret-observer-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: secret-observer-cr
subjects:
- kind: ServiceAccount
name: secret-observer
namespace: {{ .Values.namespace }}
{{- end -}}

View File

@ -0,0 +1,27 @@
{{/*
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: secret-observer-bin
namespace: {{ .Values.namespace }}
data:
update-secret-sha.sh: |
#!/bin/sh
set -ex
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
SECRET_SHA=$(sha256sum /home/$1 | awk '{print $1}')
curl -sS -H "Authorization: Bearer $KUBE_TOKEN" \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
--request PATCH -H "Accept: application/json" \
-H "Content-Type: application/strategic-merge-patch+json" \
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/apis/apps/v1/namespaces/{{ .Values.namespace }}/deployments/$2 \
--data '{"spec":{"template":{"metadata":{"annotations":{"'$3'": "'$SECRET_SHA'"}}}}}';

View File

@ -0,0 +1,66 @@
{{/*
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
*/}}
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: secret-observer-cron-job
namespace: {{ .Values.namespace }}
spec:
schedule: "{{ .Values.cronSchedule }}"
successfulJobsHistoryLimit: {{ .Values.jobs.successfulHistoryLimit }}
failedJobsHistoryLimit: {{ .Values.jobs.failedHistoryLimit }}
concurrencyPolicy: Forbid
startingDeadlineSeconds: {{ .Values.jobs.startingDeadlineSeconds }}
jobTemplate:
spec:
template:
spec:
serviceAccountName: secret-observer
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 12 }}
{{- end }}
containers:
- name: secret-observer-cron-container
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
command:
- /bin/sh
- -c
- |
{{- range .Values.observedSecrets }}
/tmp/update-secret-sha.sh "{{ .secretName }}-{{ .deploymentToRestart }}/{{ .filename }}" {{ .deploymentToRestart }} "{{ .secretName }}sha"
{{- end }}
stdin: true
tty: true
volumeMounts:
{{- range .Values.observedSecrets }}
- mountPath: "/home/{{ .secretName }}-{{ .deploymentToRestart }}"
name: mounted-{{ .secretName | replace "." "-" }}-{{ .deploymentToRestart | replace "." "-" }}-{{ .filename | replace "." "-" }}
{{- end }}
- name: pod-tmp
mountPath: /tmp
- name: secret-observer-bin
mountPath: /tmp/update-secret-sha.sh
subPath: update-secret-sha.sh
readOnly: true
restartPolicy: OnFailure
imagePullSecrets:
- name: default-registry-key
volumes:
{{- range .Values.observedSecrets }}
- name: mounted-{{ .secretName | replace "." "-" }}-{{ .deploymentToRestart | replace "." "-" }}-{{ .filename | replace "." "-" }}
secret:
secretName: {{ .secretName }}
{{- end }}
- name: pod-tmp
emptyDir: {}
- name: secret-observer-bin
configMap:
name: secret-observer-bin
defaultMode: 0555

View File

@ -0,0 +1,18 @@
{{/*
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
*/}}
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
release: "{{ .Release.Name }}"
name: secret-observer
namespace: {{ .Values.namespace }}
imagePullSecrets:
- name: default-registry-key
{{- end -}}

View File

@ -0,0 +1,36 @@
#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
image: docker.io/curlimages/curl
imageTag: 7.77.0
namespace: default
clusterRoleBinding:
create: true
clusterRole:
create: true
serviceAccount:
create: true
cronSchedule: "0 1 * * *"
nodeSelector:
node-role.kubernetes.io/master: ""
jobs:
startingDeadlineSeconds: 200
successfulHistoryLimit: 3
failedHistoryLimit: 1
observedSecrets:
# the name of the secret to observe
# - secretName: "overrideMe"
# the name of the file within the secret to observe
# filename: "overrideMe"
# the deployment to restart if a change in the secret is detected
# deploymentToRestart: "overrideMe"