Hide secrets in Terraform
Infrastructure as Code (IaC) is the new buzzword in the city. DevOps Engineers have become crazy and are writing code to launch their infrastructure on the cloud. Terraform has just pushed that craziness to the next level. This tool has become very famous for building, changing, and versioning infrastructure. In fact, it has been the safest and the most efficient way of managing large infrastructure.
You write code for your infrastructure, right? You push the code to a git repo, don’t you? How do you manage your secret files there? You don’t, seriously? Your terraform project may have a lot of secret files like terraform.tfstate, private keys, and other secret files, you never want to be exposed. You may use S3 bucket as your state storage. But what about other files for which you prefer git repo to S3 bucket? Okay. In this blog post, we will learn how we can hide our secret files in a git repo.
I was highly fascinated when I found
To install git-crypt and gpg on MacOS, we can use homebrew. The commands are simple:
$ brew install git-crypt $ brew install gnupg
And for Ubuntu, we can run the following commands:
$ sudo apt update $ sudo apt install git-crypt gnupg -y
Generate a new GPG key
If we don’t have a GPG key, it is high time we should generate it.
$ gpg --full-generate-key
We will be asked to choose some options at the prompt. Let’s choose by keeping this in mind: GPG key should use RSA with a key size of 4096 bits.
After a successful GPG key generation, we will export our public key to a keyserver. A
$ gpg --list-secret-keys --keyid-format LONG
This command will show us something like this on terminal:
/Users/username/.gnupg/pubring.kbx --------------------------------- sec rsa4096/<key ID> <Generation Date> [<Expiry Date>] <Public key fingerprint> uid [ultimate] <Full Name> <Email Address> ssb rsa4096/<Some Secret> <Generation Date> [E]
Let’s grab the key ID and export it to the keyserver using this command:
$ gpg --keyserver https://pgp.mit.edu/ --send-keys <key ID>
Hide our secrets
To hide secrets in any git repository, we need to enter into the repo from the terminal. Now we have to configure git-crypt here:
$ git-crypt init $ git-crypt add-gpg-user --trusted <email address>
But how will we specify the files we need to encrypt? Like a
.gitignore file, we have to create a
.gitattributes file in the parent directory of the repo and specify the files need to be encrypted. For a Terraform project, this file can look like below:
# files need to be encrypted # format: file_name filter=git-crypt diff=git-crypt id_rsa filter=git-crypt diff=git-crypt *.pem filter=git-crypt diff=git-crypt *.tfstate filter=git-crypt diff=git-crypt # never encrypt .gitattributes file .gitattributes !filter !diff
If we want to encrypt any specific file of any specific folder, then we can create
* filter=git-crypt diff=git-crypt .gitattributes !filter !diff
Whatever the way is, we need to make sure that we are not adding these files
$ git add -A $ git-crypt status -e
All is well! Right? We can commit and push the changes:
$ git commit -m "using git-crypt for encryption" $ git push <upstream> <branch>
We can check on the Web UI of the upstream and confirm.
Add our teammate
It’s damn easy. We can grab our teammate’s public key from keyserver or key file.
$ gpg --keyserver pgp.mit.edu --recv-key <teammate's key ID> # Or $ gpg --import /path/to/public/key/file
Now like before, we can add this key using his/her email address:
$ git-crypt add-gpg-user --trusted <teammate's email address>
Decrypt encrypted files
Normally, all files remain decrypted in the local repository. But after cloning a repository for the first time, we need to decrypt files with GPG:
$ git-crypt unlock
There is another project: git-secret. It can be used for the same purpose. For encrypting inline secrets, we can use