Secrets Management with SOPS and AWS KMS

If you’re a developer, chances are you know that you should never store application secrets in source control. Even if your repository is private, it’s still best practice to not store them there. But where do we put them? How do we manage secrets, especially if we work on a team? Where can we store application secrets in a way that the team can easily access them but they are still secure? Well, I believe by using SOPS and AWS KMS we can easily protect our secrets while making them easier to access for our team members.

What is SOPS?

Well…, according to the official repo:

sops is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP.”

https://github.com/mozilla/sops

So what does that mean exactly? Here’s how I define it. It’s a command line tool that lets you encrypt your files before committing them to version control. So that’s a step in the right direction with solving our problem, but what do we do about the encryption key? In order for our team to be able to decrypt our files, we need some way of sharing the encryption key, but that kind of puts us back at square one, now doesn’t it? This is where AWS KMS comes into play.

What is AWS KMS

AWS KMS logoAWS KMS is a service from Amazon Web Services that allows you to use cryptographic keys in order to encrypt data. The beauty of it is that you never get access to the actual key. Instead you have an ARN that points to the key. And that ARN is controlled with AWS IAM permissions, so you can easily revoke access to it if you ever need to, without needing to generate a new key. You could also create separate keys for different things if you need to be more granular with who can access what. I’ll also mention here that AWS KMS keys are not free. You can learn more about their pricing here.

Using SOPS and AWS KMS

Let’s get SOPS and AWS KMS set up so we can use them to encrypt and decrypt files. Then we’ll look at how we can use this to manage application secrets in our development workflow.

Install and Configure the AWS CLI

First of all, I’m assuming you’ve created an AWS account. If not, you’ll need to go ahead and do that before getting started here.

Then, you’ll need to install the AWS CLI on your system. You can find instructions here in order to do this. Then you can follow these instructions to configure the CLI with your IAM user. There are also other options for authenticating which can be found here, if you’d prefer to do one of those rather than using your IAM user. Now let’s create our KMS key.

Create an AWS KMS Key

In the AWS dashboard search for KMS and click on “Key Management Service”. This will take you to the KMS page where you can click “Create Key”.

AWS KMS Key creation screen recording
Quick example of how to create an AWS KMS key in the AWS console

You can learn more about the different options you have here, but we’re going to choose “symmetric” and “encrypt and decrypt” and click “next”. The next screen will allow you to name your key, add a description and tags, which can be helpful for tracking billing. For step 3, you will be able to choose admins that are allowed to administer the new key and also choose if admins should be allowed to delete it. Once keys are deleted, any data encrypted with them cannot be decrypted, so be careful when deleting keys!

Next, in step 4 you choose which users or roles are allowed to actually use the key for encrypting/decrypting data. Finally, you can review all of the settings and create your AWS KMS key. After creating your key, copy it’s “ARN”… you will need this later.

Alternatively, you can also create AWS KMS keys from the command line with the AWS CLI.

aws kms create-key --description "Your Key Description"

Install SOPS

Now lets get SOPS installed. If you’re on a mac you can install it with Homebrew.

brew install sops

If you’re using Linux or Windows, you will need to do your own research to see how to install SOPS. I haven’t installed it on either of those systems yet, so I don’t have links to instructions that I’ve verified. I’m sure a quick Google search or visit to ChatGPT will be all the help you need though. 😉

To make sure SOPS is installed you can run sops --version in the terminal and it should print out a version number for you. Now we’re ready to try encrypting our secrets with SOPS and AWS KMS! How EXCITING!

Encrypting and Decrypting Files

In your code editor, create a .example.env file and add a key/value pair. For example:

api_key=some_api_key

Now in the command line, make sure you’re in the same directory as your .example.env file. Run the following command:

sops -e --in-place --kms your_aws_kms_arn_here .example.env

Take a look in your .example.env file and you will notice a lot has changed. You can still see api_key, but the value assigned to it has been encrypted. You’ll also notice that SOPS added a bunch of other information. Now, that this file is encrypted, it is something you could comfortably push to source control knowing that your application secrets are safe. And if you needed to view the values again you can run the following command to decrypt your file.

sops -d --in-place --kms your_aws_kms_arn_here .example.env

SOPS and AWS KMS development workflow

So this is all well and good, but how would you use this in your day to day? What would an actual encryption/decryption workflow look like? Well, it could look something like this:

  • create a .example.env file with the application secrets
  • create a copy of that file by running cp .example.env .env
  • Now you can use sops to encrypt your .example.env with the command shown above. This is the file that will be committed to source control.
  • This leaves you with your unencrypted .env file, which should not be committed to source control. You can use this for local development, and be sure to add it to your .gitignore file.

And in the future, if you need to modify values in your .example.env file, you can do the following:

  • decrypt .example.env
  • make your changes.
  • run cp .example.env .env again to copy your changes over to your local .env file
  • re-encrypt .example.env

I hope that workflow makes sense to you. I’m sure it’s not the only way to go about encrypting your secrets, and as I continue to experiment with this I may come back here and make some updates regarding how my workflow might have changed or been improved. But for now, it’s an approach that I’ve been using in my own projects and I think it’s been working well.

Now before you go, I’ll show you some things I have done to make this workflow even easier to use.

Improving Our Workflow

The first improvement we can make is saving our AWS KMS key ARN as an environment variable. Run export AWS_KMS_KEY=your_key_here and that will save it as an environment variable. You can also add it to your .bashrc or .zshrc file to make sure it persists across sessions.

Next, we can create a Makefile. If you’re not familiar with Makefiles, I’m not going to go into great detail here, but I encourage you to do some of your own research. In regards to what we’re doing here, a Makefile can give you an easier way to run the sops commands, since they are a bit verbose. Here’s an example of what your Makefile could look like:

.PHONY: encrypt decrypt

encrypt: sops_encrypt
decrypt: sops_decrypt

sops_encrypt: 
	@sops -e --in-place --kms ${AWS_KMS_KEY} .example.env

sops_decrypt: 
	@sops -d --in-place --kms ${AWS_KMS_KEY} .example.env

And now running make encrypt or make decrypt will make it easier to run the sops commands.

Further Learning

If you’re interested in learning more about SOPS, there’s of course the repo I linked above. That repo links to a useful YouTube video which gives a good overview of SOPS. I also came across this article as well, which was an interesting read and it dives into a bit more detail for the other key options you can use with SOPS (KMS isn’t the only option!).

And so there you have it, the most glamorous side of web development! Jokes aside, keeping your application secrets secure is a serious topic, and it requires the attention of all developers. There’s no “one big thing” that we can do to prevent the next data leak. We need to be constantly vigilant with all of the small things. So I hope this tutorial about SOPS and AWS KMS gave you some ideas on how you can secure your application secrets. Or at the very least, I hope it encourages you to think about this very important topic maybe a little bit more than you did before. Happy coding!