Quickstart: Bitnami Sealed Secrets

Quickstart: Bitnami Sealed Secrets

Overview

In this post, I’ll go through the process of…

  • Downloading and installing kubeseal in a regular *nix environment.
  • Installing the cluster-side controller with helm.
  • Backing up and restoring processes / commands.
  • Enumerating useful commands.

Get familiar with these links:

This guide could be referencing an older version of these tools by the time you read it. Before you begin, see what newer versions you could use. See the releases page. The helm chart slightly lags behind.

Assumptions

  • You’re installing on kubernetes version >=1.9.0.
  • You’re running these commands in a *nix environment.

Installing Components

Client

wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.9.6/kubeseal-linux-amd64 -O kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal && rm kubeseal

Server

Heads up:

  • The helm chart will install and maintain the needed CRDs.
  • The controller will work fine in any workspace. In this example, we’re putting it in its own namespace.
  1. Create the sealed-secrets namespace (and label it - good for custom Network Policies):
kubectl create namespace sealed-secrets && \
kubectl label namespace sealed-secrets name=sealed-secrets
  1. Run the install command:
# install
helm install --name sealed-secrets --namespace sealed-secrets --set rbac.pspEnabled=true stable/sealed-secrets --version 1.6.1
  1. Download the public key that was generated by the controller:
kubeseal --fetch-cert --controller-name=sealed-secrets --controller-namespace=sealed-secrets > ~/kubeseal.pem
  1. Create an alias to automatically pass this certificate to the kubeseal command:
alias kubeseal='kubeseal --cert ~/kubeseal.pem'

Now you can create encrypted secrets. Additional chart commands:

# upgrade
helm upgrade sealed-secrets --set rbac.pspEnabled=true stable/sealed-secrets --version 1.6.1
# delete
helm del --purge sealed-secrets
# delete the CRDs -deleting/purging the chart will not delete these resources:
kubectl delete customresourcedefinitions.apiextensions.k8s.io sealedsecrets.bitnami.com

Creating Encrypted Secrets

In these examples, we’re using kustomize which is built into recent versions of kubectl (via kubectl apply -k). You don’t have to use kubectl apply -k ~/secrets to perform these actions (instead of kubectl apply -f ~/secrets), but it makes managing these secrets and quick restores so much easier.

mkdir -p ~/secrets && touch ~/secrets/kustomization.yaml
Nginx-Ingress Basic Auth

Where ~/secrets/kustomization.yaml contains something like:

resources:
- auth-nginx.json
# - auth-app-password

Run command (you can copy and paste the whole block):

 export SS_NAME='auth-nginx' \
 SS_NAMESPACE='default' \
 SS_USERNAME='nginx-auth' \
 SS_PASSWORD='nginx-password' && \
kubectl create secret generic "$SS_NAME" --dry-run -o yaml --from-literal auth=$(htpasswd -nb "$SS_USERNAME" "$SS_PASSWORD") > ~/secrets/unencrypted-secret.yaml && \
kubeseal <~/secrets/unencrypted-secret.yaml >~/secrets/$SS_NAME.json && \
rm ~/secrets/unencrypted-secret.yaml && \
kubectl kustomize ~/secrets/ && \
kubectl apply -k ~/secrets/ && \
unset SS_NAME SS_NAMESPACE SS_USERNAME SS_PASSWORD

You should see output like this:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: auth-nginx
  namespace: default
spec:
  encryptedData:
    auth: AgA9+HbNP0d1ta3zHgzh1GDDSM9YgWKv7IMecDyddpWLccJOYSpR/xVjYL9lug/d7fvOrG6WTsjOnQF+MLGaOcFMUzXlzE/qV5+6OXiYPvwoeDbp1JNTlPDgOCNKvr3wvJz/FjE4aZE+e9SxeiUPBAt80j1iDbApPNUHIdcmXp2AtZ8k0U+3EDQ4xAfSYL60d76SbubCb5gIo8O/y4JFN8AD83Y7/BnNaDbeJMMBlOe1Poi69KckHTS9jhF09Xf5XB8fX+bl+6zdDmTuAQaM1qoW3NC6aLuroEBdRX6kLH7d8jQa+z6KD/Vf3T27e9eapCjvtcJHbS9a2BLyEW/P7c/Y6Ciy8hAcEORMOUNe3cYXLwTHkj5RqxBGVTRCA5lRskOFUKOGZsLjM5vpG5c7or9/WKcLSoMOBqqwhmDt92/VItmBidfLNSefwcUZWVfYQXZfCov98C+/dVkFFKkybWzS+hJI28tuEnP4Qm4kqrR/AFKKLdHQRPTjuX/rSPof01r/kOczJAAMlXyngOrsBC9/8zEA1qO6pFtV2BTu/KwoQHgaadNDk1nK3XKsZjsPcwXAGePlEZEMo7SdbYjUC88fCIcyDwAGrIY2cEbVr0LXGuLUewx38xae5GmaThahuwPahU7KBfFLDNcKOSVK9zJIPwX+gou3AMWhUIlRhwvLKQLT2Y9Tz5mipYrvuNpi5m3YXceE6gnB6o2CUl17ul20hkGa1X1UOAyBD5lNmmuQyk1fGiNpPGB4DKPxZLe4g/o=
  template:
    metadata:
      creationTimestamp: null
      name: auth-nginx
      namespace: default
status: {}
Creating a Secret Containing Key/Value Pair(s)

Where ~/secrets/kustomization.yaml contains something like:

resources:
# - auth-nginx.json
- auth-app-password.json
 export SS_NAME='auth-app-password' \
 SS_NAMESPACE='default' \
 SS_KEY='app-username' \
 SS_PASSWORD='app-password' && \
kubectl create secret generic "$SS_NAME" --dry-run -o yaml --from-literal $SS_KEY="$SS_PASSWORD" > ~/secrets/unencrypted-secret.yaml && \
kubeseal <~/secrets/unencrypted-secret.yaml >~/secrets/$SS_NAME.json && \
rm ~/secrets/unencrypted-secret.yaml && \
kubectl kustomize ~/secrets/ && \
kubectl apply -k ~/secrets/ && \
unset SS_NAME SS_NAMESPACE SS_KEY SS_PASSWORD

(You can chain --from-literal parameters back-to-back-to-back (etc) to add multiple keys/values to this single secret)

You should see output like this:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: auth-app-password
  namespace: default
spec:
  encryptedData:
    app-username: AgCMQSUYop1XzRuCHoaLUAuAWYGRWZl4aM01juJE+wkBlXckPJ7U1zfCqo7z+3EH/eBStvuCoQ5F1ny6Y3C2jgihkgBtL8EhsE2tCKpQCfcaPWxBHFAMzTxiF76ZFOooa+XrKnuX0sImdAT3+KQISxCdMWTQt6VAb6rTxX1r4k9ESqq8WBpAotjBPfC1KMC/Gkp8pX5mQXXQgxD/YPtv0gV7g8c2PPBnYqFnCLs7iI7VkLsZ6pezmyKR4OG7XPQFNDPVPhWgf/3I7Ny3Wj3zPqkAXyBnKklCtksBDt6yFaleLG5Jl6ZnmOVvZuQBz3ZwuMbiT62XHyMUexlBRHiohrsVBqFo7mpgliNGrLTXiO+RrFrdZQ9WtYz3RB5SRGvBV7cbWvybUDFKeBRql7tkJpLXCArUBG6sshYXIpqsPfgQ2CjEeRkmsVE1slmLbEtv7+WNZgizylGlvV5AHPy3kJl5Dkh42JHF9ZEK3FEW4VYPGf2yacqoa8Rmf1B9zR4MavkxF2WOmKNyeCBhUjCaqEGDc66dvZ6XKKk6G2SVFwl0GSsAJ5scsGesNkV5HC3PBxACTF0IPP/V81BGJLl6U4lr8+mEoYnShZtu7r7Fq1sL/h01q3Z8WTZPDV8WufxCFPQeNxW6DjFgA0p7rbvUtzBVZjZEqqHpffa3TswCXSO6mvdRHVusDVnO0eGlq2DUZXmLmfX6KypS06hXZn8=
  template:
    metadata:
      creationTimestamp: null
      name: auth-app-password
      namespace: default
status: {}

Backup / Restore

Backing Up Your Keys

To create a kubernetes secret that contains the public and private key for the sealed-secrets certificate authority, run this command:

# if needed, update the name of secret here
kubectl -n misc get secret sealed-secrets-key7mxb6 -o yaml > ~/sealed-secrets.keys
cat ~/sealed-secrets.keys
# NEVER actually a secret like this in an unencrypted form like I'm doing here
apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVyVENDQXBXZ0F3SUJBZ0lRVkhmNGJ1QSs3dDB1WmxNYyt3YlZMREFOQmdrcWhraUc5dzBCQVFzRkFEQUEKTUI0WERURTVNVEl3T0RJd01qRXlNRm9YRFRJNU1USXdOVEl3TWpFeU1Gb3dBRENDQWlJd0RRWUpLb1pJaHZjTgpBUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBTHBrWDdoN0xMbE1TQUMxWU5OU2x3RWNmdzQyVVVrVDRjZTJqM1N4CjZmbllUanlZd0tEWUc5OTU5dFJWdTZyZFlLZEJVMnQ4dndCQTRjK0EzN0luNWJYQkNlbklQa2dLcWZsRngrZVMKNjlkMnpyZnAwaEQ2T0NPUHBhaktyeU5SS0tUWHQ4ZDdRZTcvM3M1L2hWNzhFTmVuNzdYdWFTU25ieXN0c2hocQowN0hjY2o0ZURBRWN4M0lKSkxPWmsvUDgrai9oekRXc25zWkFwNDZZNCtIa1ZyS0JsQzBPVHcvOGM5K2JzQjQ0Cm9IcFBFM2lhVXIzRE5kSEhFcjI4c3AwZkJUajhQL1VselJ5azJYcWw2SWZTL0pwWEJydVJ3d2JYc0FwRjJxWTcKaVY4TjNjZXNnOWNBc1liRFZ2NVFIS1FMVkQ5Q0xUQVRnbW1yU056UmlReS9sSVVwZ3VYT2xlN3BTbFhyRiswbwpVczVnTkRiQmpoYUhHTTBMeDFBKzV2M29DKzdTMGYrQ1llWHFraExGMTdWNHpLRVRQY1Bxd3Ezc2J0RUl5VWZECmR2VWo0OXBpbHp5UVlxMlMwYSt1US9nNFc2VDAvbHFwcmN1RXRXMVJoMXUvRmpmbXpGY081TGI4a1JrN3lZREEKZFpPbEVIbEs3QXVpdEN6YnRtbTZIQzk0dUkxREZTUWFkK0RGbitBOFVDVkRqb1FVbTFubFB0ai9jQ3dRUm1ZSQpIWW5IY2lVd3lJWFFkV1phdVplWGRtamd2MlZIM1FGSTk3TEdId1RRL3l5QmljVFZZTUJKbW1icDZ6NWg3OUNsCjhkR1BHMW1zY0ZCa3dWNUlNcml6NHJ0R3pmQysrN0tFU2RhOXhqSGRQbEVHdVJVMlpoNWZodGNZbGZrTk9rQVQKVTJRWkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lBQVRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwRwpDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQ0FLQTZlNzRMZ1hjUU5CYTdCaXhzTXhlb2NscHNvYklhU1VYUlNJcEFVCmVleTJ5dVFqeVl3ei9RYys5N0hXM3ZoNWdSNGlQN2NHVE15MndoK003L2pPb2tFRlR4T2VQUE5hNXRZQlByczkKTVQremZqUEpsbGdySVRvajhYZGU5R09Ea2xsVmRuVHMrUmNmTDNGOVN6Q2t6VEp3NWp2UFZVbmpjb0FpM0F0dwpNTi9laHJkbmhTdHNxVjZTV0U0amJpRkU3NVZqL1MzNkFEZmU2SDYvWExQKzNsa1hvM2k5eUJoS21rUTFpSU5nClhhWXdDOXZmOE5YVFNlWVM5M3NFOFl1NnFPcUJpTzBBQWRvTzhLMThsc0k4RFRWakFSWkhRanhhS3pOWGdnQnkKdTN5QUtyQ3VvWHEzaUdLdnQrZmtXbWgwSUJkSGRzMDc4L1JOVDB5NDlZR2RaNXhjOUtLQVc1N2c0YThQVWVOMwo3WHhzK2ZMUkZ5NE9YM2R4ekMyRVA0TFZ0L3llOFlWbTBqMS82bVNGNmZpY3IzMkY4RVRLWGZuVUxjRDhnYWFkCkRWREhmUWJqeGRISkxOL3ExQmkxNm8zcGV6R01zOTAzb1BOMUhsV3pOM2V0NEk0b2dic0M0U2pwcmN5RWlySmsKc1BvVGtKdll4OERtMEZhcWwxR0tJTDlETUxHQ0MvVmpUU1BRN2JxTXFsWEpHWFY4NmlDYS9aM1k2R2JQbklLbQpiQ0hyMGtsRzNjN1FhWld1dlZLRkNCS25ZYlZScE5LY2dpMGpWNW9IMFBwcWtJMmJxOVF5bFVWMkVTTGZPR2p2CjNoQ1VpOE5nUVViejlCR3EyaXNaSmdod2k2R3BUR0JLNzZzZlF2cHF2UndPMXhnVGxUdytVc2k5b3JYUW5hNTUKdWc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKSndJQkFBS0NBZ0VBdW1SZnVIc3N1VXhJQUxWZzAxS1hBUngvRGpaUlNSUGh4N2FQZExIcCtkaE9QSmpBCm9OZ2IzM24yMUZXN3F0MWdwMEZUYTN5L0FFRGh6NERmc2lmbHRjRUo2Y2crU0FxcCtVWEg1NUxyMTNiT3QrblMKRVBvNEk0K2xxTXF2STFFb3BOZTN4M3RCN3YvZXpuK0ZYdndRMTZmdnRlNXBKS2R2S3kyeUdHclRzZHh5UGg0TQpBUnpIY2dra3M1bVQ4L3o2UCtITU5heWV4a0NuanBqajRlUldzb0dVTFE1UEQveHozNXV3SGppZ2VrOFRlSnBTCnZjTTEwY2NTdmJ5eW5SOEZPUHcvOVNYTkhLVFplcVhvaDlMOG1sY0d1NUhEQnRld0NrWGFwanVKWHczZHg2eUQKMXdDeGhzTlcvbEFjcEF0VVAwSXRNQk9DYWF0STNOR0pETCtVaFNtQzVjNlY3dWxLVmVzWDdTaFN6bUEwTnNHTwpGb2NZelF2SFVEN20vZWdMN3RMUi80Smg1ZXFTRXNYWHRYak1vUk05dytyQ3JleHUwUWpKUjhOMjlTUGoybUtYClBKQmlyWkxScjY1RCtEaGJwUFQrV3FtdHk0UzFiVkdIVzc4V04rYk1WdzdrdHZ5UkdUdkpnTUIxazZVUWVVcnMKQzZLMExOdTJhYm9jTDNpNGpVTVZKQnAzNE1XZjREeFFKVU9PaEJTYldlVSsyUDl3TEJCR1pnZ2RpY2R5SlRESQpoZEIxWmxxNWw1ZDJhT0MvWlVmZEFVajNzc1lmQk5EL0xJR0p4TlZnd0VtYVp1bnJQbUh2MEtYeDBZOGJXYXh3ClVHVEJYa2d5dUxQaXUwYk44TDc3c29SSjFyM0dNZDArVVFhNUZUWm1IbCtHMXhpVitRMDZRQk5UWkJrQ0F3RUEKQVFLQ0FnQXNHeHhiZHlvNkhzYmJCQkNKY1AyeWtaK3ZLVU5LMjUyTnVMRnhsN2dhR3dsSVpZMFBncFAxNmRKeQpwR2JvSThKL1VZSC82V0Q1R21GVXpOWWlQamFwTDZpODNWbC9pcVoyQ2dFbjF5aGZzQWx5azYzVnZxQVNLaWUxCkxXRU1KbVJMdlpBTGNDdEY5dDR1Vnhha1IxbGs3cVJXbExma3FJb3gyWHBQTk5nck9sTCtSL1huUFh3a2krMVgKWW53VVBFU3JZUzhGZEhlTnlqYmNFMm01Um1NTmtvUVJ0VlVZSDFEOEZNYzBING81NXdSZ2dZUWF5MXFzN1VLTwpDMXpvdVRKdkxhR2t6UEVnV2hIc1o5NENaZmJJUHRlbEF2VDNaWXFPbzhEOW5SRUFvVE5kMElEU0c2UG1rOHErCkd3N3I4cEpZOWJ2anFIb3Zyd3hxMUZwdDNkZXkwMGFYWHNxSkNhUkZReEp3OERYVU5YSEwxTW13clBXalI5azYKMDNqN2QzeUFBSlg3TDNqbmdNdk50Ulp2WXZlYWQzT0ZsK3FlMDFLWjhBNU5wa1JlVk80TkpYKzBoSENGRHBnZgprV2JkVGRGSGQvZDlRdVhCSGhRcXZWalhSVGc0OGpkVkFWYUJDMkNBRFpWUzAwc3pZNzd0ZVllMFZwYkhIL2c3CnU3RjM2MXhyYU1oZlA3MzNvajRWZnpzSVJGNHk1UWhjUER5eG1oaE5lZFdGeWtpQ1NzbmM4UWFDRnVTMUl5aTEKbDZvQldobm1xK2NaWWhua3FEUWlhSE5ZY085RkxxOVJ6UGtxYldPOVdLN0YvNGlSQ1EycjZidFpRa3QwZlZodgpMcVBDNVduNTY0cDRLdGRwMUgvb0hZYm9hNlJDOHVQVGgySjVFbXpkanBKbUxMUEZRUUtDQVFFQTdXaHFLdDhZCmFGVVhuMlpXU2NLVFNYMWRrRVZzS0s1bDdxSkw0Zi9NOXRCemxtZlAyejVscTVjdzVMVkY2aEt1QmN6RnFVelMKY0F6NHlvV3M5anMrRytHWW5kSE5wOUVKUUlGZHdxVGpMT2dJWHdIYVpteFd4MjhvalprYjUwczBrUG03NWtnVgo3T1gxTHFZcHZuUm4vTVBGOC9wRnY5MXJFeDZOdzk1bTBLdWtnNktBUWlQZTIxZTZkZWRhbHp5RmN1U1VqZnRhCjN1bC9ONEFkMHB2bFpkRUdMZWFqQzV0N1lPNE1ycm52UVUvZlcxeDNRdTJvYkZjSTJnMDY0QjMrd3NBNEkxOW4KTkx6QUxyUWFvV1dqQnpkTUpxdFduR0hjVnI4cExJY2tMaHlYem9HUnBaRzJrdk1tTkxFZVpvRjhqOUNnZVVtSwpKT0dJQTR1d1QvcytGUUtDQVFFQXlQMHdFKzg3RUs5RTZObmVJM1FZVFh5RndOLzdyTENGN084WGtQQXdWeDRzCkhSVm9KcVJYMzVQVllvMUQ0MlRnNk9UTEYyVTlDL21QMUhxMlFzelhDTnhqSHhZNG9RcHo3NVFwNFhxRjBEN2wKN05Wa0IwQVJza3JQcXh3eVJjN2ZnYW1NU20xeHI3Tm5ieHEveWJhVDc5YWVNOHY1QlpYakJINVBjMGg4dFM5VQowZCs0eGxrSlBiZEg5UVNodm9FRlAxZEZHWk5zMk5vRFBzN2ZTak8zZWN0QXhXcklFY3ZyUGZsYTl3Rms0ekg0ClV5WnowVXI0QnBIY3VQckcrR05KY09rR2RmSStReTFrTFZyRVg5TkpnckllTEF2WDBPRVVVY1pKdi9hYXRXOUQKRHVraFlHanhydXd4WjNZdjRHTXpIQ05xMUdEUlF4dUQ3b3RKKzlXUzlRS0NBUUEzZGVNSGJPSzR6TmdkNXJ4VgpzdHpSbURYWlZENTJLbmVwamNTSVlVZXlpUFBYdVJ5M3JSWDNSZlNvR1NqaUM4Y1hsOFM5VGpNQzlpVFF1dld5CitCZ0VUMmxseFBOME5zTWdqSmdvdG5oVHIwajFXT3Q2YmVpLzRsbm82bEc0Y0xzdyt3WklQNkxQbXREeU91TVoKbVB3SjhubzJDc3RzalA5TWtpQ3dGeTZScE9kajBQeUJkdnZDNWZXclFZYktPZHM3QWVjcVhBUFllMWU2MFhVbQpGRUU4emQzUnIwVjdtckR4N2VxTWp1Y3pyTU1UQnNEZG84TnF1OUpYaml1bzI1aitTZ1ZUVGlCQUU3QVp1UDFYCm92UzQ1TlFuWEhONVNPcytZSjN2eHdwT3MyTkxYTDEzbmxpMmI1TUhVREUzNVJ3Q1JNeVlTUE82dGUwZVZ1MnoKWVpBWkFvSUJBRng0WUU1TG1wa3Fpa0czT3dTRXZVbXBLTUI4VElZL0VON1pnYllsUzVoSlFYS0FEdEw0ZVpWYgpwcWtZNVVzUmRvaXYrdUJncTUxK3pEV3QzMzBNVVVLNllzQkNzUHNtbkFCMTRtN2l0LzMvY2psc1ZBRWg4UUplCmVQejRsQWlhRFNyU25zRC9hWGEweTduS1RNSzVSWWJxN3c1Vm9kUjRDV0pmMnAzbms3aW9kaFc1SUlIaEpPZEkKRThzZXZtdXZZSUtyM0JiUVJSdmY4ZTVMcjErc081WEZkWjllYVg0R204eC9sT0pmdWRMdGdwcCs3bm8wUzdoNgpFMXJueGZNeGV2Qi94WUV1V29iOXMwRktxVjZORHgwYVpkZE4rNVVXZVFyR2Q5ZmgxWHYwSEo0WGxFdU8vT0xGCnVGVXBndzF4bG1vendVckU0SUpIZm9PWmdnaGpVcUVDZ2dFQVVMQVZ2Rmh2Njd2N2FNdEd6amQya0JrUDM5ZFUKTGFVbUtxUWFtcW0vdE8vcTZIeSsrNUY0RHg3WkorcklmaXdJKzAzZFhOVjI3SEhxeHl4QVI4QkhQWWRpVFB2SQpPSDNBYkEwR2VnMHQ5WUJvN2NrWitlMUJNMlJWbitjU0xZNDNSNzdFdHVhL2JKUHdid2pySEhVYkc1VXJCT0w0ClpoQzhBakVPNjlUU21pQ3ZiMnYzTWpwaXBPK3BBdkFlVkFQWnpjYVpLWS9yOGxDY2dHY1BEb2hPZmtpUGdjMVEKa3RoNWxjejV5c1k5WGJCOXVBdUtSYU1oRjJ4M3BGNHA0YTlyNWVIU1J4TWdpRVZGQVI2cmVpTkowVmoxbTJ3cApYbG1iZExhTkdSc0E2QjJtbG5palVrUGNqTjB0M3MrMUtEN3dITHZvZmUxMTNjZkdYNUV6ejg3d0JnPT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K
kind: Secret
metadata:
  creationTimestamp: "2019-12-08T20:21:20Z"
  generateName: sealed-secrets-key
  labels:
    sealedsecrets.bitnami.com/sealed-secrets-key: active
  name: sealed-secrets-keychpxh
  namespace: sealed-secrets
  resourceVersion: "19778822"
  selfLink: /api/v1/namespaces/sealed-secrets/secrets/sealed-secrets-keychpxh
  uid: 7aad3a63-061a-4b65-ac1c-7df4fc80e596
type: kubernetes.io/tls

Restoring Your Keys

It’s easier to deploy the secret containing public/private keys for sealed-secrets before the controller is installed.

  1. Assuming you followed the backup instructions above, apply this secret:
kubectl create -f ~/sealed-secrets.keys
  1. Install the helm chart/controller as mentioned earlier.
  2. Check the container’s logs to confirm that it loaded the same master secret
kubectl -n sealed-secrets logs sealed-secrets-95c76d5d5-q6xps
2019/12/08 21:33:20 Starting sealed-secrets controller version: v0.9.6+dirty
2019/12/08 21:33:20 Searching for existing private keys
2019/12/08 21:33:20 ----- sealed-secrets-keychpxh
2019/12/08 21:33:20 HTTP server serving on :8080
  1. Apply your various encrypted secrets:
kubectl apply -k ~/secrets

If there are no existing keys for sealed-secrets, it’ll generate new ones. Because we imported our keys before even installing the controller, we preempted first-time key generation.

Useful Commands

Get the base64 encoded secret:

# secret name will vary
kubectl -n sealed-secrets get secret sealed-secrets-keychpxh -o yaml

Get the public key:

kubeseal --fetch-cert --controller-name=sealed-secrets --controller-namespace=sealed-secrets

Decode either base64 encoded key through kubectl:

# secret name will vary
{% raw %}kubectl -n misc get secrets sealed-secrets-keychpxh -o 'go-template={{index .data "tls.crt"}}' | base64 --decode{% endraw %}
# secret name will vary
{% raw %}kubectl -n misc get secrets sealed-secrets-keychpxh -o 'go-template={{index .data "tls.key"}}' | base64 --decode{% endraw %}