Tag: Sealed Secrets

  • Using Sealed Secrets with ArgoCD and Helm Charts

    When managing Kubernetes applications with ArgoCD and Helm, securing sensitive data such as passwords, API keys, and other secrets is crucial. Bitnami Sealed Secrets provides a powerful way to encrypt secrets that can be safely stored in Git and used within your ArgoCD and Helm workflows.

    This guide will cover how to integrate Sealed Secrets with ArgoCD and Helm to securely manage secrets in your values.yaml files for Helm charts.

    Overview

    ArgoCD allows you to deploy and manage applications in Kubernetes using GitOps principles, where the desired state of your applications is stored in Git repositories. Helm, on the other hand, is a package manager for Kubernetes that simplifies application deployment through reusable templates (Helm charts).

    Bitnami Sealed Secrets provides a way to encrypt your Kubernetes secrets using a public key, which can only be decrypted by the Sealed Secrets controller running in your Kubernetes cluster. This allows you to safely store and version-control encrypted secrets.

    1. Prerequisites

    Before you begin, ensure you have the following set up:

    1. Kubernetes Cluster: A running Kubernetes cluster.
    2. ArgoCD: Installed and configured in your Kubernetes cluster.
    3. Helm: Installed on your local machine.
    4. Sealed Secrets: The Sealed Secrets controller installed in your Kubernetes cluster.
    5. kubeseal: The Sealed Secrets CLI tool installed on your local machine.

    2. Setting Up Sealed Secrets

    If you haven’t already installed the Sealed Secrets controller, follow these steps:

    Install the Sealed Secrets Controller

    Using Helm:

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm install sealed-secrets-controller bitnami/sealed-secrets

    Or using kubectl:

    kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.20.2/controller.yaml

    3. Encrypting Helm Values Using Sealed Secrets

    In this section, we’ll demonstrate how to encrypt sensitive values in a Helm values.yaml file using Sealed Secrets, ensuring they are securely managed and version-controlled.

    Step 1: Identify Sensitive Data in values.yaml

    Suppose you have a Helm chart with a values.yaml file that contains sensitive information:

    # values.yaml
    database:
      username: admin
      password: my-secret-password  # Sensitive data
      host: db.example.com

    Step 2: Create a Kubernetes Secret Manifest

    First, create a Kubernetes Secret manifest for the sensitive data:

    # my-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-database-secret
      namespace: default
    type: Opaque
    data:
      password: bXktc2VjcmV0LXBhc3N3b3Jk  # base64 encoded 'my-secret-password'

    Step 3: Encrypt the Secret Using kubeseal

    Use the kubeseal CLI to encrypt the secret using the public key from the Sealed Secrets controller:

    kubeseal --format yaml < my-secret.yaml > my-sealedsecret.yaml

    This command generates a SealedSecret resource that is safe to store in your Git repository:

    # my-sealedsecret.yaml
    apiVersion: bitnami.com/v1alpha1
    kind: SealedSecret
    metadata:
      name: my-database-secret
      namespace: default
    spec:
      encryptedData:
        password: AgA7SyR4l5URRXg...  # Encrypted data

    Step 4: Modify the Helm Chart to Use the SealedSecret

    In your Helm chart, modify the values.yaml file to reference the Kubernetes Secret instead of directly embedding sensitive values:

    # values.yaml
    database:
      username: admin
      secretName: my-database-secret
      host: db.example.com

    In the deployment.yaml template of your Helm chart, reference the secret:

    # templates/deployment.yaml
    env:
      - name: DB_USERNAME
        value: {{ .Values.database.username }}
      - name: DB_PASSWORD
        valueFrom:
          secretKeyRef:
            name: {{ .Values.database.secretName }}
            key: password

    This approach keeps the sensitive data out of the values.yaml file, instead storing it securely in a SealedSecret.

    Step 5: Apply the SealedSecret to Your Kubernetes Cluster

    Apply the SealedSecret to your cluster:

    kubectl apply -f my-sealedsecret.yaml

    The Sealed Secrets controller will decrypt the SealedSecret and create the corresponding Kubernetes Secret.

    4. Deploying the Helm Chart with ArgoCD

    Step 1: Create an ArgoCD Application

    You can create an ArgoCD application either via the ArgoCD UI or using the argocd CLI. Here’s how to do it with the CLI:

    argocd app create my-app \
      --repo https://github.com/your-org/your-repo.git \
      --path helm/my-app \
      --dest-server https://kubernetes.default.svc \
      --dest-namespace default

    In this command:

    • --repo: The URL of the Git repository where your Helm chart is stored.
    • --path: The path to the Helm chart within the repository.
    • --dest-server: The Kubernetes API server.
    • --dest-namespace: The namespace where the application will be deployed.

    Step 2: Sync the Application

    Once the ArgoCD application is created, ArgoCD will monitor the Git repository for changes and automatically synchronize the Kubernetes cluster with the desired state.

    • Auto-Sync: If auto-sync is enabled, ArgoCD will automatically deploy the application whenever changes are detected in the Git repository.
    • Manual Sync: You can manually trigger a sync using the ArgoCD UI or CLI:
      argocd app sync my-app

    5. Example: Encrypting and Using Multiple Secrets

    In more complex scenarios, you might have multiple sensitive values to encrypt. Here’s how you can manage multiple secrets:

    Step 1: Create Multiple Kubernetes Secrets

    # db-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-secret
      namespace: default
    type: Opaque
    data:
      username: YWRtaW4= # base64 encoded 'admin'
      password: c2VjcmV0cGFzcw== # base64 encoded 'secretpass'
    
    # api-key-secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: api-key-secret
      namespace: default
    type: Opaque
    data:
      apiKey: c2VjcmV0YXBpa2V5 # base64 encoded 'secretapikey'

    Step 2: Encrypt the Secrets Using kubeseal

    Encrypt each secret using kubeseal:

    kubeseal --format yaml < db-secret.yaml > db-sealedsecret.yaml
    kubeseal --format yaml < api-key-secret.yaml > api-key-sealedsecret.yaml

    Step 3: Apply the SealedSecrets

    Apply the SealedSecrets to your Kubernetes cluster:

    kubectl apply -f db-sealedsecret.yaml
    kubectl apply -f api-key-sealedsecret.yaml

    Step 4: Reference Secrets in Helm Values

    Modify your Helm values.yaml file to reference these secrets:

    # values.yaml
    database:
      secretName: db-secret
    api:
      secretName: api-key-secret

    In your Helm chart templates, use the secrets:

    # templates/deployment.yaml
    env:
      - name: DB_USERNAME
        valueFrom:
          secretKeyRef:
            name: {{ .Values.database.secretName }}
            key: username
      - name: DB_PASSWORD
        valueFrom:
          secretKeyRef:
            name: {{ .Values.database.secretName }}
            key: password
      - name: API_KEY
        valueFrom:
          secretKeyRef:
            name: {{ .Values.api.secretName }}
            key: apiKey

    6. Best Practices

    • Environment-Specific Secrets: Use different SealedSecrets for different environments (e.g., staging, production). Encrypt and store these separately.
    • Backup and Rotation: Regularly back up the SealedSecrets and rotate the keys used by the Sealed Secrets controller.
    • Audit and Monitor: Enable logging and monitoring in your Kubernetes cluster to track the use of SealedSecrets.

    When creating a Kubernetes Secret, the data must be base64 encoded before you can encrypt it with Sealed Secrets. This is because Kubernetes Secrets expect the values to be base64 encoded, and Sealed Secrets operates on the same principle since it wraps around Kubernetes Secrets.

    Why Base64 Encoding?

    Kubernetes Secrets require data to be stored as base64-encoded strings. This encoding is necessary because it allows binary data (like certificates, keys, or complex strings) to be stored as plain text in YAML files.

    Steps for Using Sealed Secrets with Base64 Encoding

    Here’s how you typically work with base64 encoding in the context of Sealed Secrets:

    1. Base64 Encode Your Secret Data

    Before creating a Kubernetes Secret, you need to base64 encode your sensitive data. For example, if your secret is a password like my-password, you would encode it:

    echo -n 'my-password' | base64

    This command outputs the base64-encoded version of my-password:

    bXktcGFzc3dvcmQ=

    2. Create the Kubernetes Secret Manifest

    Create a Kubernetes Secret YAML file with the base64-encoded value:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
      namespace: default
    type: Opaque
    data:
      password: bXktcGFzc3dvcmQ=  # base64 encoded 'my-password'

    3. Encrypt the Secret Using kubeseal

    Once the Kubernetes Secret manifest is ready, encrypt it using the kubeseal command:

    kubeseal --format yaml < my-secret.yaml > my-sealedsecret.yaml

    This command creates a SealedSecret, which can safely be committed to version control.

    4. Apply the SealedSecret

    Finally, apply the SealedSecret to your Kubernetes cluster:

    kubectl apply -f my-sealedsecret.yaml

    The Sealed Secrets controller in your cluster will decrypt the SealedSecret and create the corresponding Kubernetes Secret with the base64-encoded data.

    Summary

    • Base64 Encoding: You must base64 encode your secret data before creating a Kubernetes Secret manifest because Kubernetes expects the data to be in this format.
    • Encrypting with Sealed Secrets: After creating the Kubernetes Secret manifest with base64-encoded data, use Sealed Secrets to encrypt the entire manifest.
    • Applying SealedSecrets: The Sealed Secrets controller will decrypt the SealedSecret and create the Kubernetes Secret with the correctly encoded data.

    Conclusion

    By combining ArgoCD, Helm, and Sealed Secrets, you can securely manage and deploy Kubernetes applications in a GitOps workflow. Sealed Secrets ensure that sensitive data remains encrypted and safe, even when stored in a version control system, while Helm provides the flexibility to manage complex applications. Following the steps outlined in this guide, you can confidently manage secrets in your Kubernetes deployments, ensuring both security and efficiency.

  • Bitnami Sealed Secrets

    Bitnami Sealed Secrets is a Kubernetes operator that allows you to encrypt your Kubernetes secrets and store them safely in a version control system, such as Git. Sealed Secrets uses a combination of public and private key cryptography to ensure that your secrets can only be decrypted by the Sealed Secrets controller running in your Kubernetes cluster.

    This guide will provide an overview of Bitnami Sealed Secrets, how it works, and walk through three detailed examples to help you get started.

    Overview of Bitnami Sealed Secrets

    Sealed Secrets is a tool designed to solve the problem of managing secrets securely in Kubernetes. Unlike Kubernetes Secrets, which are base64 encoded but not encrypted, Sealed Secrets encrypt the data using a public key. The encrypted secrets can be safely stored in a Git repository. Only the Sealed Secrets controller, which holds the private key, can decrypt these secrets and apply them to your Kubernetes cluster.

    Key Concepts

    • SealedSecret CRD: A custom resource definition (CRD) that represents an encrypted secret. This resource is safe to commit to version control.
    • Sealed Secrets Controller: A Kubernetes controller that runs in your cluster and is responsible for decrypting SealedSecrets and creating the corresponding Kubernetes Secrets.
    • Public/Private Key Pair: The Sealed Secrets controller generates a public/private key pair. The public key is used to encrypt secrets, while the private key, held by the controller, is used to decrypt them.

    Installation

    To use Sealed Secrets, you need to install the Sealed Secrets controller in your Kubernetes cluster and set up the kubeseal CLI tool.

    Step 1: Install Sealed Secrets Controller

    Install the Sealed Secrets controller in your Kubernetes cluster using Helm:

    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm install sealed-secrets-controller bitnami/sealed-secrets

    Alternatively, you can install it using kubectl:

    kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.20.2/controller.yaml

    Step 2: Install kubeseal CLI

    The kubeseal CLI tool is used to encrypt your Kubernetes secrets using the public key from the Sealed Secrets controller.

    • macOS:
      brew install kubeseal
    • Linux:
      wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.20.2/kubeseal-linux-amd64 -O kubeseal
      chmod +x kubeseal
      sudo mv kubeseal /usr/local/bin/
    • Windows:
      Download the kubeseal.exe binary from the releases page.

    How Sealed Secrets Work

    1. Create a Kubernetes Secret: Define your secret using a Kubernetes Secret manifest.
    2. Encrypt the Secret with kubeseal: Use the kubeseal CLI to encrypt the secret using the Sealed Secrets public key.
    3. Apply the SealedSecret: The encrypted secret is stored as a SealedSecret resource in your cluster.
    4. Decryption and Creation of Kubernetes Secret: The Sealed Secrets controller decrypts the SealedSecret and creates the corresponding Kubernetes Secret.

    Example 1: Basic Sealed Secret

    Step 1: Create a Kubernetes Secret

    Start by creating a Kubernetes Secret manifest. For example, let’s create a secret that contains a database password.

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-db-secret
      namespace: default
    type: Opaque
    data:
      password: cGFzc3dvcmQ= # base64 encoded 'password'

    Step 2: Encrypt the Secret Using kubeseal

    Use the kubeseal command to encrypt the secret:

    kubectl create secret generic my-db-secret --dry-run=client --from-literal=password=password -o yaml > my-db-secret.yaml
    
    kubeseal --format yaml < my-db-secret.yaml > my-db-sealedsecret.yaml

    This command will create a SealedSecret manifest file (my-db-sealedsecret.yaml), which is safe to store in a Git repository.

    Step 3: Apply the SealedSecret

    Apply the SealedSecret manifest to your Kubernetes cluster:

    kubectl apply -f my-db-sealedsecret.yaml

    The Sealed Secrets controller will decrypt the sealed secret and create a Kubernetes Secret in the cluster.

    Example 2: Environment-Specific Sealed Secrets

    Step 1: Create Environment-Specific Secrets

    Create separate Kubernetes Secrets for different environments (e.g., development, staging, production).

    For the staging environment:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-db-secret
      namespace: staging
    type: Opaque
    data:
      password: c3RhZ2luZy1wYXNzd29yZA== # base64 encoded 'staging-password'

    For the production environment:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-db-secret
      namespace: production
    type: Opaque
    data:
      password: cHJvZHVjdGlvbi1wYXNzd29yZA== # base64 encoded 'production-password'

    Step 2: Encrypt Each Secret

    Encrypt each secret using kubeseal:

    For staging:

    kubeseal --format yaml < my-db-secret-staging.yaml > my-db-sealedsecret-staging.yaml

    For production:

    kubeseal --format yaml < my-db-secret-production.yaml > my-db-sealedsecret-production.yaml

    Step 3: Apply the SealedSecrets

    Apply the SealedSecrets to the respective namespaces:

    kubectl apply -f my-db-sealedsecret-staging.yaml
    kubectl apply -f my-db-sealedsecret-production.yaml

    The Sealed Secrets controller will create the Kubernetes Secrets in the appropriate environments.

    Example 3: Using SOPS and Sealed Secrets Together

    SOPS (Secret Operations) is a tool used to encrypt files (including Kubernetes secrets) before committing them to a repository. You can use SOPS in conjunction with Sealed Secrets to add another layer of encryption.

    Step 1: Create a Secret and Encrypt with SOPS

    First, create a Kubernetes Secret and encrypt it with SOPS:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-sops-secret
      namespace: default
    type: Opaque
    data:
      password: cGFzc3dvcmQ= # base64 encoded 'password'

    Encrypt this file using SOPS:

    sops --encrypt --kms arn:aws:kms:your-region:your-account-id:key/your-kms-key-id my-sops-secret.yaml > my-sops-secret.enc.yaml

    Step 2: Decrypt and Seal with kubeseal

    Before applying the secret to Kubernetes, decrypt it with SOPS and then seal it with kubeseal:

    sops --decrypt my-sops-secret.enc.yaml | kubeseal --format yaml > my-sops-sealedsecret.yaml

    Step 3: Apply the SealedSecret

    Apply the SealedSecret to your Kubernetes cluster:

    kubectl apply -f my-sops-sealedsecret.yaml

    This approach adds an extra layer of security by encrypting the secret file with SOPS before sealing it with Sealed Secrets.

    Best Practices for Using Sealed Secrets

    1. Key Rotation: Regularly rotate the Sealed Secrets controller’s keys to minimize the risk of key compromise. This can be done by re-installing the Sealed Secrets controller, which generates a new key pair.
    2. Environment-Specific Secrets: Use different secrets for different environments to avoid leaking sensitive data from one environment to another. Encrypt these secrets separately for each environment.
    3. Audit and Monitoring: Implement logging and monitoring to track the creation, modification, and access to secrets. This helps in detecting unauthorized access or misuse.
    4. Backups: Regularly back up your SealedSecrets and the Sealed Secrets controller’s private key. This ensures that you can recover your secrets in case of a disaster.
    5. Automated Workflows: Integrate Sealed Secrets into your CI/CD pipelines to automate the encryption, decryption, and deployment of secrets as part of your workflow.
    6. Secure the Sealed Secrets Controller: Ensure that the Sealed Secrets controller is running in a secure environment with limited access, as it holds the private key necessary for decrypting secrets.

    Conclusion

    Bitnami Sealed Secrets is an essential tool for securely managing secrets in Kubernetes, especially in GitOps workflows where secrets are stored in version control systems. By following the detailed examples and best practices provided in this guide, you can securely manage secrets across different environments, integrate Sealed Secrets with other tools like SOPS, and ensure that your Kubernetes applications are both secure and scalable.