Let’s face it, managing secrets in software projects can be as thrilling as being stabbed in the eye. Yet, it’s a necessary evil that we all have to deal with.

Problem: we have a set of a developers and set of infrastructure that all needs to share secrets. Would like to minimize infrastructure and keep cognitive load to a minimum so we can focus on writing code. Sure you’ve got AWS Secrets Manager and Hashicorp Vault for the heavy lifting, but that’s like using a tractor to crack a nut. And then there’s the keep-all-your-secrets-in-github-action-ENVs which leads to “push-and-pray” mentality (https://dagger.io/ talks on CI/CD are awesome). Not exactly the pinnacle of security or convenience, right?

Enter SOPS, the cool kid on the block that encrypts your files without the bullshit (You know it’s cool cos it’s the latest in a long line of tech abandoned by Mozilla). But setting it up? Still sucks. This post is about how github-to-sops helps.

Enter github-to-sops

So, in anger after n-th secrets-management-sucks process I wrote github-to-sops. It’s a fun Python script that turns GitHub into world’s only successful key distribution mechanism (remember keybase?).

Approach: Use yaml in git for secret storage/sync, github identities and pre-existing ssh keys. SOPS makes it easy to encrypt same data N times where N=|developer ssh public keys| + |server ssh public keys|. During decryption SOPS will transparently loop through the N encrypted copies until it finds one it can decrypt with the private ssh key.

Algorithm:

  1. Query a github repo to get a list of developers. Alternatively one can pass github usernames with --github-users and avoid GITHUB_TOKEN auth drama.
  2. Fetch their SSH public keys from github
  3. Optinally fetch SSH public keys for any servers that one wants to deploy to
  4. Convert their ssh keys into age keys which are suitable for SOPS.
  5. Write converted keys along with comments as to what they belong to into .sops.yaml file that tells SOPS how to encrypt/decrypt secrets

Now every secret is encrypted once per every person/server that needs to decrypt it. Each of those devs can now decrypt the secrets by converting their ssh private key into age key.

SOPS is a joy to use once it’s configured in a productive fashion. It took me a long time to figure out how to use SOPS well, so I wrote a script :)

Here’s how you get started

Let’s setup SOPS so all devs within chatcraft.org can decrypt the openai key:

github-to-sops --github-url https://github.com/tarasglek/chatcraft.org --key-types ssh-ed25519 --format sops > .sops.yaml

Devs use their ssh key to access secrets

Lets extract our secret in a way that’s useful for automation

export SOPS_AGE_KEY=$(ssh-to-age -private-key < ~/.ssh/id_ed25519)
sops -d keys.enc.yaml

There is also a way that’s useful for automation:

sops --extract '["secrets"]["OPENAI_API_KEY"]' -d keys.enc.yaml

Last but not least: sops -i secrets.env.yaml is convenient for interactive editing.

Update(rotate) keys

Suppose you decided you don’t to give access to all devs within project or maybe you want to pull any updated keys from github.

github-to-sops --inplace-edit .sops.yaml --github-users tarasglek,rjwignar
sops updatekeys -y keys.enc.yaml

What’s the Big Deal?

  • Quick Setup: Share your secrets easily, using github infra!
  • Choose Your Flavor: Need authorized_keys for easy ssh logins? You got it.
  • Convenient: Grab keys from your local checkout or a github url. github-to-sops doesn’t judge.
  • Pretty: With handy comments re key origin in your .sops.yaml, rotating keys is no longer a treasure hunt.

Wrapping Up

github-to-sops is my secret weapon against the drudgery of secret management. It’s all about getting you back to doing what you love—writing code. So give it a whirl, and take back your dev time from the clutches of secret management purgatory.