Skip to content

Sealed Secrets

The SealedSecrets controller solves the problem of storing Kubernetes secret data securely by encrypting the configurations. It can only be decrypted by sealed secret controller running in cluster.

Architecture

SealedSecrets is composed of two Kubernetes components:

  • Controller: A cluster-side component for data decryption.
  • Kubeseal: A client-side utility for data encryption. It uses asymmetric cryptography methods for data encryption and kubeconfig to communicate with the cluster.

Pre-Requisites

You need to have kubeseal installed on your local machine. You can get the latest release from Sealed Secret Releases.

Usage

Create K8s sealed secret

Lets create a sample k8s secret that will be used for MySQL:

  1. Create the secret as a normal Kubernetes secret resource:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secrets
      namespace: gabbar-dev
    data:
      # base64 encoded "root"
      USERNAME: cm9vdA==
      # base64 encoded "@mysqlpassword"
      USER_PASSWORD: QG15c3FscGFzc3dvcmQ=
      # base64 encoded "test-database"
      DATABASE: dGVzdC1kYXRhYmFzZQ==
    
  2. Save it in a file named secret-mysql.yaml. This file should not be pushed to source control as it is easily de-codable.

  3. Install kubeseal and your kubeconfig should be pointing to your SAAP cluster

  4. Sealed secrets controller is running in stakater-sealed-secrets namespace and sealed secrets service name is sealed-secrets, so you need to run:

    kubeseal --controller-name=sealed-secrets --controller-namespace=stakater-sealed-secrets --format yaml < SECRET_FILE 
    

    where:

    • SECRET_FILE: the name of the YAML file containing the k8s secret
    • SEALED_SECRET: the name of the YAML file that will contain the sealed secret
  5. Add and commit this sealed secret to source control

  6. Remove the original secret

For Dynamic Test Environment

To use secrets in dynamic test environments (for PR environment), you need to seal secret with cluster-wide scope so that it can be decrypted by any namespace. Since PR namespaces are dynamic and tied to the lifecycle of PR, cluster-wide scope make sure that it can be decrypted by dynamic namespaces.

To create a sealed secret in Dynamic Test Environments:

  1. Generate a SealedSecret resource:

    kubeseal --controller-name=sealed-secrets --controller-namespace=stakater-sealed-secrets --format yaml --scope cluster-wide < secret-mysql.yaml 
    

    This will generate sealedsecret resource output:

    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      annotations:
        sealedsecrets.bitnami.com/cluster-wide: "true"
      creationTimestamp: null
      name: mysql-secrets
    spec:
      encryptedData:
        DATABASE: AgBLmwvAw...
        USER_PASSWORD: AgCkxffaV...
        USERNAME: AgAkGib0a...
      template:
        metadata:
          annotations:
            sealedsecrets.bitnami.com/cluster-wide: "true"
          creationTimestamp: null
          name: mysql-secrets
    
  2. Add a sealedSecret block in the Helm values present in deploy/values.yaml in your application repository and copy/paste the key values from the resource:

      sealedSecret:
        enabled: true
        annotations:
          sealedsecrets.bitnami.com/cluster-wide: "true"
        files:
        - name: mysql-secrets
          encryptedData:
            DATABASE: AgBLmwvAw...
            USER_PASSWORD: AgCkxffaV...
            USERNAME: AgAkGib0a...
    

For Dev Environment

To generate sealedsecrets for dev environment:

  1. Run the following command:

    kubeseal --controller-name=sealed-secrets --controller-namespace=stakater-sealed-secrets --format yaml  < secret-mysql.yaml 
    

    This will generate sealedsecret resource output:

    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      creationTimestamp: null
      name: mysql-secrets
      namespace: gabbar-dev
    spec:
      encryptedData:
        DATABASE: AgBLmwvAw...
        USER_PASSWORD: AgCkxffaV...
        USERNAME: AgAkGib0a...
      template:
        metadata:
          creationTimestamp: null
          name: mysql-secrets
          namespace: gabbar-dev
    
  2. Add a sealedSecret block in the Helm values present in <tenant>/<application>/<env>/values.yaml in the GitOps-config repository and copy/paste key values from the generated output:

      sealedSecret:
        enabled: true
        annotations: ""
        files:
        - name: mysql-secrets
          encryptedData:
            DATABASE: AgBLmwvAw...
            USER_PASSWORD: AgCkxffaV...
            USERNAME: AgAkGib0a...
    

Consuming Secret in Application using Environment Variables

When consuming the sealed secret in the application using environment variables, you need to add the env: field in the values file, for example if you want to use environment variables from above MySQL secret, in values file, replace:

  env: []

with:

  env:
  - name: MYSQL_USERNAME
    valueFrom:
      secretKeyRef:
        name: mysql-secrets
        key: USERNAME
  - name: MYSQL_PASSWORD
    valueFrom:
      secretKeyRef:
        name: mysql-secrets
        key: USER_PASSWORD

Copyright © 2023 Stakater AB – Change cookie settings