DEV Community

Cover image for Manage your secrets in Git with SOPS for Kubernetes ☸️
Stack Labs

Manage your secrets in Git with SOPS for Kubernetes ☸️

davinkevin profile image Λ\: Davin Kevin ・3 min read

In previous parts, we see how to manage our secrets in Git and usable by humans and CI. Right now, we will discover how
to integrate it with Kubernetes, and especially with Kubernetes Secrets.

😊 Naive usage

Since the beginning, Alice, Bobby and Devon are using only *.env file to store secrets. They have to use them
in a Kubernetes context, to create a secret named app-secret. The simple (and naive way) to do this is to use
the kubectl application to create the secret from an env files:

This solution is pretty basic and rely on the capacity of the kubectl cli to create secret from an *.env file. The main problem here is the fact we have to generate our secret from the env file. In Kubernetes context, when we have multiple manifests, we like to have the same semantic and organisation, which is simpler to read and debug.

🔒 Sops & YAML

To match the team expectation, Devon will move to a Kubernetes YAML format for secrets instead of relying on *.env files. To do so, he will use the output generated from the previous example and use sops to encrypt it.

The SOPS output is like this:

apiVersion: ENC[AES256_GCM,data:gEA=,iv:2jeZ0y0SEPXZTgrsmYXc7LgPydoPwnKzF4GVqykSw5M=,tag:YzEMrctU19sUIqat+LUFIw==,type:str]
    secret: ENC[AES256_GCM,data:uJIDP3yMdFyW/7bnBAU0MJp07xmF0nlh,iv:ardoVW+p9HLNpaWfXOWrevZFdNJqGJvt00jPbkrr7p4=,tag:mB3wqa7kNE7gZ9J87IboNg==,type:str]
kind: ENC[AES256_GCM,data:tu+OHbXI,iv:QfqZeYOkTPTzJ618gh+/zGWPMDBJfjp+GwM8yBZCD+Y=,tag:XrJfNhmyDhOQNncd/uNvxA==,type:str]
    name: ENC[AES256_GCM,data:X8WMTByIcUrjag==,iv:pQ6xt5DPchrxwXtt98l4mgCixpcpaA2ewST0lAqYY4E=,tag:fqj/1PbzbhjIhRx9Ogitxg==,type:str]
    kms: []
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-06-13T12:21:16Z'
    mac: ENC[AES256_GCM,data:dU1bm2GBwdkqMQqEa+b0EfuMG5BRiiHDxNjB3tvB4JTVxqamQ17A47tzMld93/lZnJWRb4BtDFUI2xHh/5BCpxdI4J67AvWdv91usRgpgh7z7SF4pK4UUVah3WDYd3tvo+VzugvN6b4V+oGZlfJM789dJrTDOjSCAyyaaa/Qfb0=,iv:Cdaet+2Sowq50TDIkDO1RXi4vgaVqe7rYz08PHybAv0=,tag:1aeR/f4NnydiP2Vuuvljvw==,type:str]
    -   created_at: '2020-06-13T12:21:16Z'
        enc: |
            -----BEGIN PGP MESSAGE-----

            -----END PGP MESSAGE-----
        fp: 57E6DA39E907744429FB07871141FE9F63986243
    unencrypted_suffix: _unencrypted
    version: 3.5.0

SOPS is encrypting every value of the previously generated YAML, including kind or apiVersion and This is problematic because the whole team need to be able to read keys, which are not sensible in this Kubernetes secret.

🔏 Encrypt specific keys only

SOPS provides an handy parameter to choose which keys should be encrypted. This could be used directly from the command line sops --encrypt --encrypted-regex '^(data|stringData)$' app-secret.yaml.

DISCLAIMER: For concision, I've removed a part of the generated files. SOPS parameters are included into the YAML and are verbose.

The file looks like this now:

apiVersion: v1
    secret: ENC[AES256_GCM,data:RLfYML8bJ0d5kN0nudgGgJJQIJMHK9MB,iv:6rurG5rErwn2O7PrHVoPjRnkMT5MjenhRmF3Vxh/cVw=,tag:4B5NeHbTmm0yl5VFlA9fww==,type:str]
kind: Secret
    name: app-secret
    kms: []
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-06-13T12:32:40Z'
    mac: ENC[AES256_GCM,data:jl00u8YtegEi3lvuHv70PtI6Zywo8tSDH2DKk2jw+b4yiUGU2y9T82t3bE6ahY1MWy1U6CRK9NYKBS8p5HJqDjH/N21rhQy7k3g4BuzG/CJt2S/xio0KaAwwGXURUtXbHpXLrko22q0cgqCrsr/IFvz65r6WNhji0utSC1FKCPQ=,iv:XoilcDIZR8ir/ySbu+xVGNO0NkEkQr/IlyKXvAyyeyM=,tag:Hraabep8cq85M3OjvjoQBA==,type:str]
    pgp: ... # Removed for concision
    encrypted_regex: ^(data|stringData)$
    version: 3.5.0

We can do better, because SOPS provides us a solution to store configuration required for every secret directly into the .sops.yaml. We can add the key encrypted-regex to simplify the command line. This is helpful when you need to add another secret key in an existing secret.

Every team member can now read and edit Kubernetes secret simply 🎉.

🦊 CI Integration

The CI needs to be adjusted to be able to deploy those manifests. We are using the base described in the previous article.

deploy int:
  - *auth
  - sops -d app-secret.yaml | kubectl apply -f -


If you are using Kubernetes, and you want to manage your secrets in Git, SOPS will be a good match ❤️. You will be able to encrypt only desired value in a YAML file to keep it readable, by a human and other tools working on Kubernetes manifests.

You can find the source code of this article, files and scripts in this GitLab repository.


Editor guide