Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicraMarcin/5492be75551d2e3c3259b7d61fb22cce to your computer and use it in GitHub Desktop.
Save nicraMarcin/5492be75551d2e3c3259b7d61fb22cce to your computer and use it in GitHub Desktop.
Helm + Sealed secrets
I had a bit of trouble figuring out how to use bitnami's [sealed secrets](https://github.com/bitnami-labs/sealed-secrets) with [helm](https://helm.sh)
Here's a definition of done to help you see what I was trying to achieve.
**Definition of done**
- Single secret available for a release in a namespace, listing all secret variables
- Regular helm workflow, with no extra kubeseal commands for developers
- Encrypted secrets clearly visible in git
- Sealedsecret managed by helm
After much suffering, here's what I came up with. A pre-commit hook that creates the single sealedsecret in my chart.
It took me a while, so I thought I should share in case someone can improve it.
app/templates/sealedsecret.yml ->
```yml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: {{ include "app.fullname" . }}
labels:
...
spec:
encryptedData:
{{- range $key, $val := .Values.secret }}
{{ $key }}: {{ $val | quote }}
{{- end }}
```
./env/ci.values.yml ->
```yml
...
env:
...
NODE_ENV: production
AWS_BUCKET: xyz
```
./env/ci.secrets.yml ->
```yml
...
AWS_ACCESS_KEY_ID: abc123
AWS_SECRET_ACCESS_KEY: xyz
```
Pre-commit hook ->
```bash
#!/bin/bash
# use bash, as echo -n does not work in #!/bin/sh
# dependencies
# - yq : read secrets.yml
# - kubeseal : encrypt secrets with kubernetes cluster sealed secrets public key
set -e
encrypt() {
# the full name of the app - {release}-{chart} or just {release}
fullname="YOUR APP FULL NAME"
# the top level yaml key for secrets in the values.yml file
secret_prefix="secret"
# the name and namespace of the sealed secrets controller after installation to the cluster
controller_name="sealed-secrets"
controller_namespace="default"
# find namespace specific values and secrets files, and a temporary file for storing intermediate values
namespace=${1}
secrets_file=${GIT_DIR:-$PWD}/env/${namespace}.secrets.yml
values_file=${GIT_DIR:-$PWD}/env/${namespace}.values.yml
tmp_secret_file=${GIT_DIR:-$PWD}/env/tmpsecretfile
if [[ ! -f "$secrets_file" ]]; then
echo "No secrets to encrypt in $secrets. Skipping..."
return
fi
# get all secret key names
keys=$(yq r -j $secrets_file | jq -r 'keys[]')
# count keys, and strip whitespace
nkeys=$(wc -w <<<$keys | sed 's/ //g')
echo "Encrypting $nkeys secrets from $secrets..."
# we will write each key to the values file
for key in $keys; do
# echo with -n to file first, otherwise you might have a trailing new line in your decrypted value
echo -n $(yq r $secrets_file $key) >${tmp_secret_file}
# --name should match the name of the sealedsecret (data-platform.fullname from _helpers.tpl)
encrypted=$(kubeseal --raw --name=${fullname} --namespace=${namespace} --from-file=${tmp_secret_file} --controller-name=${controller_name} --controller-namespace=${controller_namespace})
rm ${tmp_secret_file}
# write the secret to the values file
yq w -i $values_file "$secret_prefix.$key" $encrypted
done
echo "Successfully wrote ciphertext to $values."
}
encrypt ci
encrypt qa
encrypt prod
git add env
```
The folder structure is as follows:
app/templates/sealedsecret.yml
env/ci.values.yml
env/ci.secrets.yml
After running `git commit`, the `env/ci.values.yml` file is now as follows
```yml
env:
...
NODE_ENV: production
AWS_BUCKET: xyz
secret:
AWS_ACCESS_KEY_ID: ...encrypted data
AWS_SECRET_ACCESS_KEY: ...encrypted data
```
Make sure to add env/*.secrets.yml to your .gitignore!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment