Three Simple Rules for Storing Secrets in Git

Jesse Swidler
Udacity Eng & Data
Published in
4 min readNov 5, 2018

--

I’ve been thinking about my growing collection of secret keys and how to manage them. We use LastPass at Udacity, which is an okay way to share keys or passwords with a specific group of people. But, it also leaves a whole lot to be desired if you are talking about things like RSA keys, or if you must integrate a build system with your secrets. Updating your keys can become a serious pain.

This pain grows the more secrets you have. Many of us understand this pain because we know we must not check our secrets into Git. I am not the first person to come to the conclusion that this advice is not always practical. Source control is an incredibly useful way to store a large number of changing files, which is exactly what you need sometimes.

There are a number of tools to help you put secrets into Git in a safe way. I’ve created an app that makes the process very simple, which is important to keep your keys safe! But no matter which tool you use, I have three simple rules if you are going to put your keys into a Git repo.

I wrote LockGit to make securing your secrets in Git as simple as possible. If you are looking for a solution to put encrypted secrets in a Git repo, why not check it out?

1. Separate applications and configuration

Repos with secrets are the exception, not the rule

You can never really take something out of Git. Therefore, it is important to consider the long term implications of putting a secret into source control before you do. Applications should not be shipped with hard coded secrets. Test code can use ephemeral deployments which generate new keys on the fly.

But, specific persistent deployments of services will often require secret keys, and those who manage those deployments may want to keep those keys in a safe backup location. This might include the keys for the production and staging environment. If your code repo is highly coupled to a specific deployment by design, then it makes sense to store your keys in it.

Within these types of deployment specific repos, it should still be clear to you which files have secrets in it. Do not put the secrets in code files themselves, load them from configuration files. You should also be thinking about how you will rotate keys if they expire or are leaked.

2. Use private repos and encryption

Working with others is important, but don’t trust more than you need to

Your first level of protection is access control on the Git repo. If the repo is public, anyone will be able to get the encrypted files, and may see it as a challenge to try and break the encryption. With strong encryption, this might be no easy task, but why risk things? If the repo is private, there is at least a legal threat to people leaking the files in it. Also, in the event there is mistake and a secret is pushed to Git, the limited access will reduce your exposure while you rotate your keys.

Access control on the Git repo will help to ensure easier transitions when people leave the team. If someone leaves and secrets are rotated, they will not be able to get the new secrets even if they still possess the encryption key. Some tools allow for multiple users with different decryption keys, but I think that overcomplicates the problem. For me, it is enough to be able to change the encryption key when needed.

3. Use .gitignore and a simple naming scheme

Never check in secrets unencrypted; consistency is the key to avoiding mistakes

Depending on your secrets, you might be able to target all your keys with one or more simple file extensions, such as .pem and .key. If that is the case, you can add **/*.pem and **/*.key to your .gitignore file, which will make it much harder to accidentally check those files into Git.

If file extensions are not entirely convenient, it is best to use some other naming scheme for consistency in your repo. For instance, maybe some YAML files have secrets and some do not. You could require by convention that all files with secrets contain the text _key in the filename. Then, you can add **/*_key* to .gitignore, and files like helm_key.yml will be ignored, but helm_config.yml will not be.

Following these conventions will be important to avoiding mistakes.

Final thoughts:

Having to work with secrets is always a little bit risky, but it’s even more dangerous when your secrets are in the same folder as things you push upstream. Remember to check your commits very closely before pushing. If there is no reason for you to have the plaintext files around, you can remove them from the filesystem once they are stored in an encrypted vault.

Please check out LockGit if the idea of using Git to store your secrets is something you are interested in. I promise you won’t be disappointed!

Ready to Learn More?

Check out Udacity’s full catalog

Follow Us

For more from the engineers and data scientists building Udacity, follow us here on Medium.

Interested in joining us @udacity? See our current opportunities.

--

--