SOPS + Age a Perfect Twin Brothers for Cost Effective Secret Management in Git

SOPS + Age a Perfect Twin Brothers for Cost Effective Secret Management in Git

When I moved to my current company, I was shocked and a bit irritated by the current condition in the infrastructure side. The infrastructure was not well-organized and documented, there is no Infrastructure as Code (IaC) that I love so much.

I started to introduce and initiate the IaC, and in the process I found that I need to manage the secrets. At first, I want to use GCP Secret Manager / GCP KMS, like what I know in AWS, we can use AWS Parameter Store / AWS KMS to do encryption and storing secrets but it’s not cost effective at current scale and condition, we faced.

Racking my brain, when I on the progress of initiating and migrating some of our live Infrastructure to IaC, I found problem that I need to store secrets in git. reading here and there, I stumpled to sops, that well integrated with terragrunt. As terragrunt have sops_decrypt_file built in function. The later question that race in my mind is, what next tools I can use for the encryption part. As I mentioned, obiviously I will skip AWS KMS, GCP KMS, and Hashicorp Vault, since they need additional cost. So what left is gpg or age. Quick comparison, gpg is a bit complex and age is simple, easy to use, and maybe less computing resources needed, my opinionated hypothesis (not yet proven by data), as I stumbled As I found Age vs GPG #432. Other than that we don’t need beautiful exchange feature in GPG like what terraform aws provider does in pgp_key with keybase.io. So here its goes, I choose sops with age for the secrets data encryption before storing it in git.

Notes
I use macOS, so the command and the way I do it, maybe different with other OS. but you can refer to the official document for other OS.

In this chance, I will focus on how to integreate sops with age to encrypt data then we can store it in git, and decrypt it when we need it.

  1. First we need to install sops and age

bash

brew install sops
brew install age
  1. Check if the installation is successful

bash

$ sops --version
Example Output
sops 3.8.1 (latest)

bash

age --version
Example Output
v1.1.1

bash

age-keygen --version
Example Output
v1.1.1
  1. After that, we need to generate age key pair, and let us check the content

bash

age-keygen -o keys.txt
Example Output
Public key: age19z2w4gkykg5naumux8l50anh8veav5sk0wl4lmjx9gjggmrc74uq3w92uv

bash

cat keys.txt
Example Output

txt

# created: 2024-02-07T19:44:54+07:00
# public key: age19z2w4gkykg5naumux8l50anh8veav5sk0wl4lmjx9gjggmrc74uq3w92uv
AGE-SECRET-KEY-1Y0HRFPHJMKEFQ2249ZR3LZMJ295J5W3VE9QYDTASWW7H9JT9LTAS2QQ88N

As you see the key pair will be :

  • The Public key is age19z2w4gkykg5naumux8l50anh8veav5sk0wl4lmjx9gjggmrc74uq3w92uv

  • The Private key is AGE-SECRET-KEY-1Y0HRFPHJMKEFQ2249ZR3LZMJ295J5W3VE9QYDTASWW7H9JT9LTAS2QQ88N

Warning
Please keep the private key in a safe place, as it’s the only way to decrypt the data encrypted with the public key.
  1. Configure SOPS to use Age

bash

# configure sops to use our private key ~/keys.txt
export SOPS_AGE_KEY_FILE=~/keys.txt
# configure sops to use our public key / recipient
export SOPS_AGE_RECIPIENTS=age19z2w4gkykg5naumux8l50anh8veav5sk0wl4lmjx9gjggmrc74uq3w92uv
  1. Now we can start to encrypt the data with SOPS and Age

lets say we have a file secrets.yaml with the following content

yaml

secrets:
  db:
    username: admin
    password: Str0nGP@ssw0rd
  api:
    key: 1234567890987654321

we can encrypt the file with the following command

bash

sops --encrypt secrets.yaml > secrets.enc.yaml
  1. Check the encrypted file

bash

cat secrets.enc.yaml
Example Output

yaml

secrets:
  db:
    username: ENC[AES256_GCM,data:02kaPac=,iv:1Ixg5HTyMs/lIAAD1CPKB/DMQ9dGFB/zjtkCcn+j2ZA=,tag:2sBjBrxTZF4hXvxOAwnUOg==,type:str]
    password: ENC[AES256_GCM,data:LftsUgh3Kr3hbF4UZkE=,iv:UCNXF47VD2szy9WEd4X5rUbvJTlxh8WaK16W5f9FYBc=,tag:TTlY83P1qllLrq1OjgJxlg==,type:str]
  api:
    key: ENC[AES256_GCM,data:j930xJxvTMS0EG4WDu5teC2p8A==,iv:TgRwnGI3uFBWXpmhkyhqZW2t83isJ+zNH6CB0OH8dLk=,tag:y1KioWxIj4LJJ3v7utEIAQ==,type:int]
sops:
  kms: []
  gcp_kms: []
  azure_kv: []
  hc_vault: []
  age:
    - recipient: age19z2w4gkykg5naumux8l50anh8veav5sk0wl4lmjx9gjggmrc74uq3w92uv
      enc: |
        -----BEGIN AGE ENCRYPTED FILE-----
        YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSdmtQV0lxN3V5dStReXVW
        dk9pZWJHYkwzMzhKYkZVRW1vQXZvMUtnWEdvCmZCbUJTZWlOZlRVeVlKclFGNFZB
        U2NRS0F3NFItTjNMMDY0M2pKM1pTVTgKLS0tIGljSEpLRGo5UTVrK3czaWI2OVA1
        OVJHRURsNzlHZFVoclRoZDVveEIzS1EKR/XGuFj8VybQf9u89vZGutiPzwT6uGXj
        OYDPP13fyrZxlNi+1O+QcJ+JRYhPQKON1SpAXHR4etVUXRGWDalXMQ==
        -----END AGE ENCRYPTED FILE-----        
  lastmodified: "2024-02-07T12:58:57Z"
  mac: ENC[AES256_GCM,data:5jMI76oTnUxgEUCWKpYjSbendNgWrNaolftrUWyH9gpDq86VYAL0tGF2sh7sM6qLOVQomcpwtpYjtmZxXgwojmi2jxzKbBMreAr9Dhip1LmYpRc/BMQw4aDufIfUPBPN3b2IQaVI98lyLJJYPnYUuuCJBDLVoZ2QrRYLKhmGoVk=,iv:X4uHt5nafPOt2NR0CU6OF7MXVyIMDnxwQo6dNSqJ+S8=,tag:RflCmG239NWtZQgAy65P8w==,type:str]
  pgp: []
  unencrypted_suffix: _unencrypted
  version: 3.8.1
  1. Next we can try to decrypt the file

bash

sops --decrypt secrets.enc.yaml > secrets.test.yaml
Example Output

yaml

secrets:
  db:
    username: admin
    password: Str0nGP@ssw0rd
  api:
    key: 1234567890987654321
  1. Now we can commit the secrets.enc.yaml to git, and when we need to decrypt it, we can use the sops command to decrypt it.

In this post, I have shown how to integrate sops with age to encrypt data then we can store it in git, and decrypt it when we need it. This is a cost effective way to manage secrets in git, and it’s easy to use. As far as I know, this sops and age is well integrated with terragrunt, and argocd using helm-secrets. So it’s a good choice for managing secrets in git for your Infrastructure as Code (IaC), GitOps with ArgoCD, and maybe other use cases.

  1. https://github.com/getsops/sops

  2. https://github.com/FiloSottile/age

  3. https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#sops_decrypt_file

  4. https://github.com/jkroepke/helm-secrets/wiki/ArgoCD-Integration#using-age-1

Related Content