How to store secrets in public repositories
Is it possible in a secure way? The answer is yes!
We all feel this pain sooner or later: you are working hard on your git repository. For whatever reason, you change the PC but you still want to work on your project.
So you download the repo using git clone
. You’re ready to go, but then you’re stuck because you don’t remember the secrets that you put in your .gitignore
file.
Luckily now there’s a solution for that. And it’s called git-crypt.
Git-crypt will encrypt your secrets before pushing your changes on your remote branch, and it decrypts them when you download from it. So after you set it up, everything is completely transparent. You will forget to have secrets in your repo!
Bootstrap
To start with it, you need to install it. On Mac you can run the following command in the terminal after you installed the package manager brew
brew install git-crypt
Then, you need to go to your public repository where you want to put secrets. And initialize git-crypt
cd <YOUR_REPO_PATH>
git-crypt init
Add secrets
Now you need to add the .gitattribute
file in the repository’s root folder. In this file, you declare the files and folders you want to keep secret.
This is an example of .gitattribute
file
# Make the file .env secret
.env filter=git-crypt diff=git-crypt
# Make all files that ends with .key secret
*.key filter=git-crypt diff=git-crypt
# Make all the files contained in secretdir folder secret
secretdir/** filter=git-crypt diff=git-crypt
After you created the .gitattribute
file, you can put the secrets in the place you have just declared. If you put the files before the .gitattribute
, your secrets won’t be encrypted!
Before committing anything, you can have a confirmation that files will be encrypted using git-crypt status
command
# Show whether files are encrypted or not
git-crypt status
# Show encrypted files only
git-crypt status -e
# Show unencrypted files only
git-crypt status -u
If a file was previously there, it won’t be encrypted. You need to run the command git-crypt status -f
. I repeat myself: if you’re using this command, it means the file was already in your repo in cleartext.
So you need to rotate the secrets that are in that files. Otherwise, it’s very easy for an attacker to see the secrets just by looking at previous commits.
Now you can commit and push. You’ll see only some encrypted binary files in your public repository! You’re able to see them locally.
Moving the symmetric key to another device
So good so far… But if you clone the repository elsewhere, you will download the encrypted files. So how can we decrypt the files again?
To answer this question we need to reveal some magic. git-crypt
decrypt files using a symmetric key.
During the initialization with git-crypt init
, it created the symmetric key and he put it in <YOUR_REPO_PATH>/.git-crypt/keys/default
.
You can easily export it with this command
git-crypt export-key /path/to/keyfile
with this key you are able to decrypt also on your other devices. So keep it secure.
To decrypt a repository protected with git-crypt
you can use the command
git-crypt unlock /path/to/keyfile
Using GPG keys
I know what you’re thinking: “Come on… I have 30+ repositories. I can’t store and move the keys for every repo! There should be an easier way to handle them.”. There is, indeed!
You can use your GPG key to unlock your repository. If you don’t have one, you can follow the Github guide to create the GPG key.
All you need to do is to allow your GPG key to decrypt the repository
# From now on, you're able to unlock using <YOUR_GPG_KEY>
git-crypt add-gpg-user <YOUR_GPG_KEY_ID>
To find your GPG key, you can use the following command. I’m assuming you have already installed GnuPG
gpg --list-secret-keys --keyid-format=long
Then, if you clone your repo elsewhere, you can unlock it with
git-crypt unlock
git-crypt will be smart enough to look into your machine for the GPG key. If it finds it, it will decrypt everything!
How the GPG mode works
… But how does it work? I assume you don’t like magic.
When you write
git-crypt add-gpg-user <YOUR_GPG_KEY_ID>
git-crypt
will encrypt the symmetric key using your public GPG key, and it will commit into your repo in .git-crypt/keys/default/0
folder.
Then, when you write
git-crypt unlock
git-crypt
will find your GPG key in your Mac, it will decrypt the symmetric key that it saved in .git-crypt/keys/default/0
using your private GPG key. Finally, it will decrypt the secrets using the symmetric key just decrypted.
I hope I helped you to find a good way to manage the secrets in your repositories. I’m extensively using it both in my hobby projects and at work. I’m so happy with it that I wanted to share it with you.
See you!
Do you like my content?
Help me creating other stuff like this!
Keeping up to date is essential
Get the latest news by email