Git Crypt

Protect secrets with git-crypt

How can I protect sensitive data of my git projects such as API tokens or credentials to access databases?

Often vaulting tools are used that require a lot of effort to manage and maintenance, which is not justified for smaller contexts or private projects

In this article I will show you how to use git-crypt to securely keep your application secrets in source code repositories.

1. The common problem with secrets 😕

Many applications need keys or credentials to function, such as access keys to use an S3 bucket.

To deploy these applications on private or public kubernetes infrastructure many organizations adopt the gitops strategy using ArgoCD. This requires that all the manifests required for an application be available in a git repository, including secrets that may contain sensitive information.

Using a private repository is seem like a good solution, but it is also risky. It is easy to forget in a private repository secrets and then later decide to make this repository public, accidentally revealing your secrets, or forget to clean the git history.

Using a vault or a secret manager is often the recommended solution, but for small projects it is onerous and they are not easy tools to implement. Some of these often work only for x86 architectures.

2. Shepherd’s Solution 🐑

Git-crypt could solve some of these problems, with each push your secrets are encrypted on the git repository and with each pull they are decrypted.

2.1 Install git-crypt

There are instructions for Linux, Mac, and Windows on the git-crypt install page Git-crypt is a client available for Linux, Mac, and Windows. In this article explains how to install and usage it on Ubuntu distro:

$ apt install git-crypt

2.2 Create a new repository

$ mkdir myapp && cd myapp
$ git init
$ echo "Hello World!" > README.md
$ git add .
$ git commit -m "First commit"
$ git remote add origin https://github.com/<username>/myapp.git
$ git push -u origin main

2.3 Setup git-crypt

$ git-crypt init
Generating key...

This command generates a symmetric key for this repository, you can copy this key and use it in other repositories. By default, git-crypt stores the generated key in the file .git/git-crypt/keys/default, this is the key that can decrypt all encrypted files in the repository.

Using the file called .gitattributes, it is possible to add metadata to files and folders to indicate which ones we want to encrypt. Since we are starting from a new repository in this example, we must create an empty .gitattributes file and use this syntax:

# Files to encrypt
filename  attr1=value1 attr2=value2
folder/** attr1=value1 attr2=value2

To enable encryption of the desired files you need to specify two attributes filter and diff both configured with value “git-crypt”.

# Files to encrypt
s3-credentials  filter=git-crypt diff=git-crypt
secrets/**      filter=git-crypt diff=git-crypt

2.4 Test configuration

Add the newly configured .gitattributes file to our git repository and commit it:

$ git add .gitattributes
$ git commit -m "Add .gitattributes"
$ git push

We can now create the file containing the credentials of an S3 bucket in the repository.

Tip

Before using real values, test the configurations using dummy values

$ cat <<EOF>> s3-credentials 
[default]
aws_access_key_id = <dummy private key>
aws_secret_access_key = <dummy private access key>
EOF

We can check the status of the file before pushing the s3-credentials file into git.

$ git-crypt status
    encrypted: s3-credentials
not encrypted: .gitattributes 

This means that the file will be encrypted when placed in the git repository, so we add the file and commit:

$ git add s3-credentials
$ git commit -m "Add s3-credentials"
$ git push

2.5 Check encryption status

The use of git-crypt is transparent, in fact if you check the file with the cat command, you will notice that locally it is still in plain text, whereas if you try to open it from a browser or by cloning the repository again, the file is encrypted.

$ cat s3-credentials
[default]
aws_access_key_id = <dummy private key>
aws_secret_access_key = <dummy private access key>

$ file s3-credentials
s3-credentials: ASCII text

if you want to check locally what your files would look like after the commit you can run the command:

$ git-crypt lock

$ file s3-credentials
s3-credentials: data 

$ cat s3-credentials 
GITCRYPT	Z�� \�zr��4�6�]"D p<d�vC��j�.:�࡝�h2	nV

2.6 Encrypt files in the existing repository

In an existing repository, it is possible to start using git-crypt but it is really important to delete the commit history of the branch. I have prepared a simple script to clean up the commits once you are sure you have encrypted all the secret files.

$ cat <<EOF>> delete-commit-history.sh
git checkout --orphan temp_branch
git add -A
git commit -m "Initial commit"
git branch -D main
git branch -m main
echo "Launch the last command"
echo "# git push --force origin main"
EOF

$ chmod +x delete-commit-history.sh
$ ./delete-commit-history.sh
NicTore
Written by

NicTore

I’m a Cloud Architect, specialized in designing and implementing infrastructures in Linux-based environments.