Skip to main content

Sealed Secrets

Kubernetes Secrets are managed using the tool Sealed Secrets. Sealed Secrets allows you to define your Secrets locally, encrypt them and turn them into a SealedSecret resource. A SealedSecret resource is safe to store in any (public) repository. A deployed SealedSecret resource can be decrypted only by a controller running in the cluster and nobody else (not even the original author) is able to obtain the original Secret from the SealedSecret.

Prerequisites

To be able to use Sealed Secrets, it is required to install kubeseal.

Kubeseal is a local client running on your host that you will use to encrypt any Kubernetes Secrets locally and turn them into SealedSecret resources. If you are using VSCode, it is highly adviced to install the Kubeseal extension to ease operations.

Usage

Sealed Secrets employs asymmetric encryption. In this reference repository, we use a static (private) key to ensure that our secrets persist across the lifecycle of a (local) cluster. Using the key generated by the Sealed Secrets controller would render our Sealed Secrets unusable if a new cluster with a Sealed Secrets controller is created.

Important Note for "Real Environments", especially production environments

In environments outside this reference repository, especially production environments, never use the static-key.yaml. Always exclude it and allow the Sealed Secrets controller to generate a key automatically.

The static key is located in infrastructure/sealed-secrets/overlays/local/static-key/static-key.yaml. In the same folder the public portion is included as well. You can use this key to generate a Sealed Secret resource:

kubeseal --cert infrastructure/sealed-secrets/overlays/local/static-key/pub.key --controller-namespace sealed-secrets -n default -f secret.yaml -w sealed.yaml

This command outputs a Sealed Secret resource based on your secret.yaml in a file named sealed.yaml.

Generating new static keys

For any other overlays, you could use the same static key by just copying the static-key folder to the relevant overlay and referring to it in the kustomization.yaml. If for any reason you need to generate a new static key, or use a dedicated static key for an overlay, you can follow the next steps:

Export some variables:

export PRIVATEKEY="priv.key"
export PUBLICKEY="pub.key"
export NAMESPACE="sealed-secrets"
export SECRETNAME="static-key"

Generate keys:

openssl req -x509 -days 365 -nodes -newkey rsa:4096 -keyout "$PRIVATEKEY" -out "$PUBLICKEY" -subj "/CN=sealed-secret/O=sealed-secret"

Write the keys to a Kubernetes secret:

kubectl -n "$NAMESPACE" create secret tls "$SECRETNAME" --cert="$PUBLICKEY" --key="$PRIVATEKEY" --dry-run=client -o yaml | yq e '.metadata.labels["sealedsecrets.bitnami.com/sealed-secrets-key"] = "active"' - > static-key.yaml && rm priv.key

Use the static-key.yaml as resource in the relevant overlay / kustomization.yaml. The logs of the Sealed Secrets controller should display that you are using the static key:

time=2025-04-01T14:44:07.065Z level=INFO msg="registered private key" secretname=static-key

Ensure that you also copy the generated pub.key in the repo, as this key should be used to encrypt secrets by generating Sealed Secrets resources.