Git Crypt

· 589 words · 3 minutes read source-control tutorial

Secret management is an issue that everyone runs into at some point and there are many solutions to it depending on your use case. A few examples of secrets management tools are Hashicorp Vault, Ansible Vault, and AWS Secrets Manager, but there are many more. Git Crypt is one more way of managing secrets, it’s similar to ansible vault in that you have encrypted file(s) which contain your secrets, whats different about git crypt is that it’s encrypting/decrypting the files automatically on git commits, pulls, etc.

I think the best way to explain this is to show it in action, so first lets install it which requires compiling from source, I’ll be doing this in CentOS, for other operating systems see their installation instructions in the repo.

sudo yum install gcc-c++ openssl-devel openssl
git clone https://github.com/AGWA/git-crypt.git
cd git-crypt
make
sudo make install
# To install to a custom location:
# sudo make install PREFIX=<location>

# This should validate that it's installed correctly
git-crypt --version

At this point if you don’t already have a PGP keypair you’ll need to make one. This will be used to decrypt the secrets.

sudo yum install gnupg # this is probably already installed but just in case
gpg2 --gen-key
# Select RSA and RSA
# Set your desired keysize, I generally go as large as possible but it's not necessary
# How long the key should be valid
# Fill in details on the key (name, email, comment)
# Setup password
# Test the key replacing the email address with yours
gpg2 --fingerprint j.doe@example.com

Great now that you’ve got a key to encrypt your secrets with. From here you’ll need to initialize your project to use git crypt. Go into the repo you want to encrypt one or more files in and run the following commands:

[root@ea87476a980e go2-api]# git-crypt init
Generating key...
[root@ea87476a980e go2-api]# git-crypt add-gpg-user j.doe@example.com
[master b447e9f] Add 1 git-crypt collaborator
 2 files changed, 4 insertions(+)
 create mode 100644 .git-crypt/.gitattributes
 create mode 100644 .git-crypt/keys/default/0/4EF294CAE1C984410BA37EFD71ACD015B22B1987.gpg
[root@ea87476a980e go2-api]# git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#   (use "git push" to publish your local commits)
#
nothing to commit, working directory clean

At this point you’re ready to setup a .gitattributes file to tell git-crypt what to encrypt, here’s an example:

secretfile filter=git-crypt diff=git-crypt
*secrets* filter=git-crypt diff=git-crypt

Any file with “secrets” in it’s name or called “secretfile” will be encrypted. So lets commit a file that will get encrypted now that the git attributes file has been committed. You can commit the file and validate that it works by running git-crypt lock once you do that you should see it’s been encrypted if everything’s right. At this point you can push it and it’ll be encrypted on the server. To unlock the file(s) again simply run git-crypt unlock. Needless to say this file is going to be impossible to automerge any merge conflicts, you’ll have to manually resolve any merge conflicts to encrypted files. The easiest way would to be have two copies of the repo, decrypt the files side by side and perform a diff doing the correct merge.

So why would you use this? I don’t use it in any public repos but for internal repos at work I encrypt various secrets like kubernetes secrets, vault password files for ansible, and other similar situations. Then when someone new joins they simply generate a PGP key, provide someone with access to the secrets already with their public key and that user can give them access.