Protecting secrets in a Git repository

Terraform doesn't provide any built-in way of securing your state file. Neither is there a way to secure only some part of it or even provide encrypted data inside your templates. And it's a shame because sooner or later you will have to use some kind of secrets with your templates: passwords, API keys, and others. If you plan to store your state file in the git repository, it's important to protect it. The easiest solution is to encrypt the whole state file, store the encrypted version in the repository, and distribute the key for decryption with your team members.

You could make this task easier with the help of a tool named terrahelp. Terrahelp is a small CLI written in Go that simplifies the encryption and decryption of your Terraform state files (and not only the state files). It has a nice integration with Vault, yet another HashiCorp tool, this time in order to manage secrets. Don't worry, we won't use Vault, it's rather a complex tool that deserves it's own book.

Note

Starting from version 0.8, Terraform has a built-in support for Vault as a source of data.

Download terrahelp binary from GitHub Releases at https://github.com/opencredo/terrahelp/releases, and make it available in your $PATH. Now you can use the terrahelp encrypt command to encrypt the complete state file like this:

$> terrahelp encrypt -file terraform.tfstate --simple-key AES256Key-32Characters0987654321

After you run it, your terraform.tfstate file will look similar to this:

@terrahelp-encrypted(90EYsi7dEgTqcwN63AePssKjIUF3nqJq4c9hFFnvNQ63eJwL0ZmMZL
8AUmUjsqCpho3af13DKjKTU3vQ8K8qMqgm70ToYBVYki6+8vq7nmPt5MGojhfPclAkrLmiestZ
SsTYVhmDbsykX/4zkCME29...many-more-symbols

The unencrypted version was put in a file named terraform.tfstate.terrahelpbkp for your convenience, in case you forget your encryption key. To avoid creating this file, add the --nobackup option:

$> terrahelp encrypt -file terraform.tfstate --simple-key 
AES256Key-32Characters0987654321 --nobackup

The encrypted state file can be safely stored in a remote repository, only people who know the key (AES256Key-32Characters0987654321) will be able to decrypt it. The workflow for your Terraform procedure is the following:

  1. Pull the latest changes from the remote repository.
  2. Decrypt the state file.
  3. Run the terraform apply command.
  4. Encrypt the state file with the same key.

Many things can go wrong during this process. You could forget to encrypt the file and push the plain text to the repository. You could streamline this workflow by providing a good old Makefile, but it would not completely prevent bad things from happening. It would be much nicer to encrypt and decrypt state file automatically, without any additional actions from the developer who modifies the Terraform templates.

That's where a tool named git-crypt becomes very handy as it implements exactly the mechanism just described. It's stored on GitHub at  https://github.com/AGWA/git-crypt and written in C++. Sadly, there are not ready-to-use packages of git-crypt; we have to compile it ourselves.

Note

If you are a happy owner of Mac, then you can install git-crypt as brew install git-crypt.

Before installing, you should have a C++ compiler (for example, gcc), Make and OpenSSL development files (libssl-dev or openssl-devel package, depending on your Linux distribution) installed. You also need Git newer than 1.7.2. Installation is easy after all requirements are met:

$> git clone https://github.com/AGWA/git-crypt.git
$> cd git-crypt
$> make
$> sudo make install PREFIX=/usr/local

Verify successful installation with git-crypt help command.

Note

The version of git-crypt used for this chapter is 788a6a99f4289745e6bd12fae2ad8014af320a4f. It's a git commit hash.

To configure git-crypt to manage the state file, we need to create a .gitattributes file in out repository with this content:

*.tfstate filter=git-crypt diff=git-crypt
*.tfstate.backup filter=git-crypt diff=git-crypt

Run git-crypt init at the root of Terraform repository. There are two ways you can use git-crypt: with a key shared among your colleagues or by encrypting data with the personal key of each colleague. You should use the second option, but for the purpose of this demonstration, we will stick with the first one. Create somewhere a text file with a key in it (for example, generate it with the ssh-keygen command) and use this file to set up the encryption:

$> git-crypt export-key /path/to/secret/file

Because the git commit history already has state file in it, you need to force encryption the first time you use git-crypt:

$> git-crypt status -f

Now add the changed state file and the backup of it to new commit and push them to your repository: you will note that it's impossible to see its contents on GitLab. If you clone the repository to your machine, the file will also be encrypted until you unlock it:

$> git-crypt unlock /path/to/secret/file

You need to do it just once. After the initial setup, your files will be automatically encrypted when you commit and push them and decrypted when you pull it from the remote repository. No chance for accidental plain text secret data commits! It's the same thing you would do with terrahelp and Makefile, but completely transparent.

Storing both the templates and state files in a git repository works well when you have just a few people working on them. You can always see who changed what in templates and the state of the infrastructure. Git is not the only state file storage supported by Terraform though. There are many other options for remote storage and other full APIs for working with them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.228.40