Sealing Your Secrets

First, let’s delete the database-credentials Secret resource that was created with Kustomize earlier in this module and deployed to the octank namespace in the cluster. After this operation, the only Secret that should exist in that namespace will be that of the token generated by Kubernetes for the default service account associated with the octank namespace.

kubectl delete secret database-credentials -n octank
kubectl get secret -n octank

Output:


NAME                  TYPE                                  DATA   AGE
default-token-gv8nr   kubernetes.io/service-account-token   3      2d23h

Now, create the Secret and SealedSecret YAML manifests with Kubectl, Kustomize and Kubeseal.

cd ~/environment/secrets
kubectl kustomize . > secret.yaml
kubeseal --format=yaml < secret.yaml > sealed-secret.yaml

An alternative approach is to fetch the public key from the controller and use it offline to seal your Secrets

kubeseal --fetch-cert > public-key-cert.pem
kubeseal --cert=public-key-cert.pem --format=yaml < secret.yaml > sealed-secret.yaml

View the contents of the regular Secret and the corresponding SealedSecret with the following commands:

cat secret.yaml 
cat sealed-secret.yaml 

Output of secret.yaml :


apiVersion: v1
data:
  password: VHJ1NXROMCE=
  username: YWRtaW4=
kind: Secret
metadata:
  name: database-credentials
  namespace: octank
type: Opaque

Output of sealed-secret.yaml:


apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: database-credentials
  namespace: octank
spec:
  encryptedData:
    password: AgB3s2m3c2wzDmfyFXPgZWzXG2Ad2s2DF5K8H4Z . . .
    username: AgAHJTiY9kEQCgFw90i3H1mKPRkGKFr85wDCDxU . . .
  template:
    metadata:
      creationTimestamp: null
      name: database-credentials
      namespace: octank
    type: Opaque
status: {}

Note that the keys in the original Secret, namely, username and password, are not encrypted in the SealedSecret; only their values. You may change the names of these keys, if necessary, in the SealedSecret YAML file and still be able to deploy it successfully to the cluster. However, you cannot change the name and namespace of the SealedSecret. The SealedSecret and Secret must have the same namespace and name

Now, deploy the SealedSecret to your cluster:

kubectl apply -f sealed-secret.yaml 

Looking at the logs of the contoller, you can see that it picks up the SealedSecret custom resource that was just deployed, unseals it to create a regular Secret.

kubectl logs sealed-secrets-controller-84fcdcd5fd-9qb5j -n kube-system

Output:


2020/03/07 22:11:20 Starting sealed-secrets controller version: v0.9.8
2020/03/07 22:11:20 Searching for existing private keys
2020/03/07 22:11:23 New key written to kube-system/sealed-secrets-key8d8z2
2020/03/07 22:11:23 Certificate is 
-----BEGIN CERTIFICATE-----
MIIErTCCApWgAwIBAgIQJsQQhEXabaLWTUIzkH+EeDANBgkqhkiG9w0BAQsFADAA
MB4XDTIwMDMwNzIyMTEyM1oXDTMwMDMwNTIyMTEyM1owADCCAiIwDQYJKoZIhvcN
. . . . .
Se0Lk6ZACjiFqNMdL/VkSG2pYkjdFg64KZzDLad7lBrB3tOtCW8xG5T8jZuzDewB
65pXxa+MvFjnfukUE3LfC1xM17pPjRQmJ5YgcQCXsTorFXHIw21t3mF6EZfuZgpJ
XA==
-----END CERTIFICATE-----

2020/03/07 22:11:23 HTTP server serving on :8080
2020/03/07 22:27:15 Updating octank/database-credentials
2020/03/07 22:27:15 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"octank", Name:"database-credentials", UID:"cc4d3675-60c2-11ea-a6b7-0e57dc790b09", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"6403704", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully

Verfiy that the database-credentials Secret unsealed from the SealedSecret was deployed by the controller to the octank namespace.

kubectl get Secret database-credentials -n octank

NAME                   TYPE     DATA   AGE
database-credentials   Opaque   2      4m18s

Redeploy the pod that reads from the above Secret and verfiy that the keys have been exposed as environment variables with the correct literal values.

kubectl delete pod pod-variable -n octank
kubectl apply -f pod-variable.yaml 
kubectl logs pod-variable -n octank

Output:


DATABASE_USER = admin
DATABASE_PASSWROD = Tru5tN0!

The YAML file, sealed-secret.yaml, that pertains to the SealedSecret is safe to be stored in a Git repository along with YAML manifests pertaining to other Kubernetes resources such as DaemonSets, Deployments, ConfigMaps etc. deployed in the cluster. You can then use a GitOps workflow to manage the deployment of these resources to your cluster. The YAML file, secret.yaml, that pertains to the Secret may be deleted becaue it is never used in any subsequent workflows.