sops-secrets-operator

repository·master·Indexed 19 days ago

https://github.com/isindir/sops-secrets-operator

A Kubernetes operator that enables managing Kubernetes Secrets using SOPS-encrypted files. It allows users to store encrypted secrets in Git (GitOps) and automatically decrypt and instantiate them as Kubernetes Secrets within a cluster. It supports multiple decryption providers, including AWS KMS, GCP KMS, Azure KeyVault, age, and GPG.

Tokens
7.6K
Snippets
27
Records
35
Agent score
67%

What's inside sops-secrets-operator

  1. What is the sops-secrets-operator?

    master

    The sops-secrets-operator is a Kubernetes operator that manages Kubernetes Secret resources created from user-defined SopsSecret Custom Resources (CRs).

    It is inspired by Bitnami SealedSecrets and sops. A single SopsSecret CR can define multiple Kubernetes Secret resources. It supports managing secrets with annotations and labels, making them compatible with tools like the Jenkins Kubernetes Credentials Provider Plugin.

    Key benefits include:

    • Integration with GitOps workflows (e.g., Flux CD).
    • Ability to store encrypted files in Git using sops for AWS, GCP, Azure, or on-prem clusters.
    • Simplified management of encrypted files in version control.
  2. Migrate SopsSecret from v1alpha1 to v1alpha3

    master

    When upgrading from v1alpha1 to v1alpha3, several breaking changes in the schema must be addressed in your SopsSecret manifest:

    1. apiVersion: Change from isindir.github.com/v1alpha1 to isindir.github.com/v1alpha3.
    2. Field Renaming: secret_templates becomes secretTemplates.
    3. Data Field: The data field within template elements changes to stringData.
    4. Encryption Suffix: The sops encryption command must use a different --encrypted-suffix to match the new schema (e.g., from _templates to Templates).
    # v1alpha1 example
    apiVersion: isindir.github.com/v1alpha1
    kind: SopsSecret
    spec:
      secret_templates:
        - name: my-secret
          data:
            key: value
    
    # v1alpha3 example
    apiVersion: isindir.github.com/v1alpha3
    kind: SopsSecret
    spec:
      secretTemplates:
        - name: my-secret
          stringData:
            key: value
  3. Create and encrypt a SopsSecret Custom Resource

    master

    A SopsSecret resource defines one or more Kubernetes secrets.

    1. Define the SopsSecret

    Create a YAML file (e.g., jenkins-secrets.yaml) following the isindir.github.com/v1alpha3 API version. You can define secretTemplates which include labels, annotations, stringData, and data.

    2. Encrypt the file using sops

    Use the sops CLI to encrypt your file for your chosen provider:

    AWS KMS:

    sops encrypt --kms 'arn:aws:kms:<region>:<account>:alias/<key-alias-name>' --encrypted-suffix='Templates' jenkins-secrets.yaml > jenkins-secrets.enc.yaml

    GCP KMS:

    sops encrypt --gcp-kms 'projects/<project-name>/locations/<location>/keyRings/<keyring-name>/cryptoKeys/<key-name>' --encrypted-suffix='Templates' jenkins-secrets.yaml > jenkins-secrets.enc.yaml

    Azure Key Vault:

    sops encrypt --azure-kv 'https://<vault-url>/keys/<key-name>/<key-version>' --encrypted-suffix='Templates' jenkins-secrets.yaml > jenkins-secrets.enc.yaml

    PGP:

    sops encrypt --pgp '<pgp-finger-print>' --encrypted-suffix='Templates' jenkins-secrets.yaml > jenkins-secrets.enc.yaml

    Note: Using --encrypted-suffix='Templates' is recommended to ensure the resulting file is compatible with Kubernetes. Using --encrypted-regex should be done with caution as it may result in files inapplicable to the cluster.

    apiVersion: isindir.github.com/v1alpha3
    kind: SopsSecret
    metadata:
      name: example-sopssecret
    spec:
      suspend: false
      secretTemplates:
        - name: jenkins-secret
          labels:
            "jenkins.io/credentials-type": "usernamePassword"
          stringData:
            username: myUsername
            password: 'Pa$$word'
  4. Configure Azure Key Vault for the operator

    master

    To use Azure Key Vault, you must create a KeyVault, a Key, and a Service Principal with encryption/decryption permissions. You can provide credentials in two ways:

    Option 1: Direct login info in values.yaml

    azure:
      enabled: true
      tenantId: <YOUR_TENANT_ID>
      clientId: <YOUR_CLIENT_ID>
      clientSecret: '<YOUR_CLIENT_SECRET>'

    Option 2: Use a pre-existing Kubernetes Secret

    1. Create a Kubernetes secret containing the credentials:
    kind: Secret
    apiVersion: v1
    metadata:
      name: azure-sp-credentials
    type: Opaque
    stringData:
      clientId: <YOUR_CLIENT_ID>
      tenantId: <YOUR_TENANT_ID>
      clientSecret: '<YOUR_CLIENT_SECRET>'
    1. Reference the secret in your values.yaml:
    azure:
      enabled: true
      existingSecret: azure-sp-credentials
    1. Apply the secret and install the chart:
    kubectl create namespace sops
    kubectl apply -n sops -f azure_secret.yaml
    
    helm repo add sops https://isindir.github.io/sops-secrets-operator/
    helm upgrade --install sops sops/sops-secrets-operator --namespace sops -f azure_values.yaml
  5. Encrypt secrets using generated PGP keys

    master

    Once PGP keys are generated, you can use them to encrypt your secret files. You must first source the keys-env file to set up the necessary environment variables (such as $FP) for the sops command.

    1. Source the environment file:
      source ./keys-env
    2. Use sops to encrypt a file. For example, to encrypt a sample configuration:
      sops encrypt -p $FP --encrypted-suffix='Templates' ../../config/samples/isindir_v1alpha3_sopssecret.yaml > example-secrets.enc.yaml

    Security Note: The generated keys.tar.gz, 1.yaml, and 2.yaml files are highly sensitive and must be treated as secrets themselves.

    source ./keys-env
    sops encrypt -p $FP --encrypted-suffix='Templates' ../../config/samples/isindir_v1alpha3_sopssecret.yaml > example-secrets.enc.yaml
  6. Generate PGP keys for sops-secrets-operator

    master

    To use PGP keys with the sops-secrets-operator, you can generate a set of keys using a Docker container to ensure a consistent environment. This process produces the necessary configuration and Kubernetes manifests to allow the operator to decrypt secrets within your cluster.

    1. Run an Ubuntu container and mount your current directory to /tmp/scripts:
      docker run --rm -v $( pwd ):/tmp/scripts -ti ubuntu:24.04 bash
    2. Inside the container, navigate to the scripts directory and run the installation and build commands:
      cd /tmp/scripts
      ./install.sh
      make

    Generated Files:

    • keys.tar.gz: Contains the GPG configuration used for encryption/decryption.
    • 1.yaml and 2.yaml: Kubernetes manifests that must be applied to the same namespace where sops-secrets-operator is deployed via Helm.
    docker run --rm -v $( pwd ):/tmp/scripts -ti ubuntu:24.04 bash
    
    # Inside the container:
    cd /tmp/scripts
    ./install.sh
    make
  7. Build, install, and run the operator locally

    master

    Use the provided Makefile targets to manage the operator lifecycle during development:

    • make all: Builds and tests the project.
    • make install: Installs the Custom Resource Definitions (CRDs) into your Kubernetes cluster.
    • make run: Runs the controller locally.

    After running the controller, you can apply your encrypted SopsSecret manifests using kubectl apply.

    # build and test
    make all
    
    # installs crds
    make install
    
    # run controller locally
    make run
    kubectl apply -f qqq.jenkins-secrets.enc.yaml
  8. Upgrade SopsSecret API without downtime

    master

    Since sops-secrets-operator does not provide a Conversion Webhook Service, you can perform zero-downtime upgrades between SopsSecret API versions by manually managing the Custom Resource Definition (CRD) versions and scaling down the operator during the transition.

    High-level Upgrade Strategy:

    1. Prepare the CRD: Modify the existing CRD to support multiple versions (e.g., adding v1alpha3 while keeping v1alpha1 as the storage version).
    2. Pause the Operator: Scale the operator deployment to 0 replicas to prevent it from interfering with resource updates.
    3. Migrate Resources: Prepare the new version of your SopsSecret objects (e.g., updating apiVersion, field names, and encryption suffixes).
    4. Update CRD to New Storage Version: Patch the CRD so the new version becomes the storage: true version.
    5. Apply Changes: Apply the new SopsSecret objects and the patched CRD.
    6. Resume Operator: Upgrade the operator via Helm and scale it back up. The new operator version will automatically refresh the secrets to the new format.
  9. Install the sops-secrets-operator via Helm

    master

    To deploy the sops-secrets-operator on a Kubernetes cluster, follow these steps to create the namespace, apply the Custom Resource Definitions (CRDs), add the Helm repository, and install the chart. You must provide a custom values.yaml to configure access to your chosen Cloud KMS (AWS, GCP, Azure, etc.).

    $ kubectl create namespace sops
    
    $ kubectl apply -f deploy/crds/isindir_v1alpha1_sopssecret_crd.yaml
    
    $ helm repo add sops https://isindir.github.io/sops-secrets-operator/
    
    $ helm upgrade --install sops sops/sops-secrets-operator \
      --namespace sops -f custom.values.yaml