Revisando opciones para mantener los secretos seguros en un flujo de GitOps estuve jugando con Sealed Secrets de Bitnami. Hoy, al igual que ya te conté como hacerlo con SOPS, te comparto mis pruebas con esta otra solución.
Instalar kubeseal
Lo primero que necesitas hacer es instalar la herramienta kubeseal en tu máquina local:
# Install the kubeseal CLI
brew install kubeseal
Instalar sealed secrets en el clúster
En este ejemplo estoy utilizando Flux, pero puede ser cualquier otro operador de GitOps:
# Add the source for sealed secrets
flux create source helm sealed-secrets \
--interval=1h \
--url=https://bitnami-labs.github.io/sealed-secrets \
--export > ./clusters/$AKS_NAME/sources/sealed-secrets.yaml
# Create a helm release for sealed secrets
flux create helmrelease sealed-secrets \
--interval=1h \
--release-name=sealed-secrets-controller \
--target-namespace=flux-system \
--source=HelmRepository/sealed-secrets \
--chart=sealed-secrets \
--chart-version=">=1.15.0-0" \
--crds=CreateReplace \
--export > ./clusters/$CLUSTER_NAME/apps/sealed-secrets.yaml
# Push changes
git add -A && git commit -m "Add sealed secrets demo"
git push
# check helm releases
flux get helmreleases -n flux-system --watch
Una vez que ha finalizado la instalación, se habrá generado una clave con la que tú podrás cifrar y el clúster descifrar tus secretos. Para recuperar la clave pública puedes utilizar el siguiente comando:
# At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and persists the private and public keys
# as Kubernetes secrets in the flux-system namespace.
# You can retrieve the public key with:
kubeseal --fetch-cert \
--controller-name=sealed-secrets-controller \
--controller-namespace=flux-system \
> pub-sealed-secrets.pem
Ahora ya tienes todo lo necesario para poder cifrar y descifrar los secretos en tu clúster.
Prueba con secretos
Para comprobar que funciona correctamente, he creado un par de secretos de la siguiente forma:
# Create a secret for the backend
cat > ./tour-of-heroes-secured-secrets/base/backend/secret.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: sqlserver-connection-string
type: Opaque
stringData:
password: Server=prod-tour-of-heroes-sql,1433;Initial Catalog=heroes;Persist Security Info=False;User ID=sa;Password=YourStrong!Passw0rd;
EOF
# Create a secret for the db
cat > ./tour-of-heroes-secured-secrets/base/db/secret.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: mssql
type: Opaque
stringData:
SA_PASSWORD: YourStrong!Passw0rd
EOF
Después los cifro con la clave pública que me he descargado anteriormente:
# Encrypt the secrets with kubeseal
kubeseal --scope cluster-wide --format=yaml --cert=pub-sealed-secrets.pem \
< tour-of-heroes-secured-secrets/base/backend/secret.yaml > tour-of-heroes-secured-secrets/base/backend/secret-sealed.yaml
# Remove the unencrypted secret
rm tour-of-heroes-secured-secrets/base/backend/secret.yaml
kubeseal --scope cluster-wide --format=yaml --cert=pub-sealed-secrets.pem \
< tour-of-heroes-secured-secrets/base/db/secret.yaml > tour-of-heroes-secured-secrets/base/db/secret-sealed.yaml
# Remove the unencrypted secret
rm tour-of-heroes-secured-secrets/base/db/secret.yaml
Como ves, además de cifrar el contenido debo eliminar el secreto en plano, ya que de no ser así todo esto no tendría sentido 😙
Por otro lado, como estoy usando Kustomize para el plantillado de mi aplicación, necesito añadir los dos nuevos archivos llamados secret-sealed.yaml a sus respectivos kustomization.yaml, para que los tenga en cuenta durante el despliegue.
Publico los cambios y espero a que se desplieguen en el clúster:
# Push changes
git add -A && git commit -m "Add secrets-seaed files"
git push
# Check the deployment
flux get kustomizations -n tour-of-heroes --watch
k get all -n prod-tour-of-heroes
Para comprobar que los secretos se han creado correctamente puedes revisar su contenido, descodificándolos con este comando:
kubectl get secret <SECRET_NAME> -n <NAMESPACE> -o jsonpath="{.data.<FIELD_NAME>}" | base64 --decode
¡Saludos!