The DevOps Jedi

Taking the cloud by storm one line of code at a time....

How I Protect Secrets In Terraform Configurations

2023-01-213 min readDarren Johnson

I have already touched on the importance of Terraform state in a previous post, but I wanted to expand on this from a security perspective.

Let’s get this out the way now, Terraform stores secrets in its state file in plain text! There I said it.

So how do I protect against secrets being revealed that could allow an attacker to compromise my systems? Well, I use a defence in depth strategy in a number of ways.

The state file is never local on my machine, so there is no danger of leaving it behind after applying some code. I store it securely in an Azure storage account and it is never checked into source control.

I never store secrets in my code. If a secret is required as part of a configuration, I store it in a key vault and reference it as a data source. This means even if you do gain access to a copy of my code you would require access to my key vault in order to retrieve the secrets. I use an access policy on my key vault that controls who can access it.

If the secret cannot be retrieved from a key vault because it is required before Terraform initialises, I store it as an environment variable that is specific to the command line session I am running. I use a PowerShell wrapper script to set the variable by pulling it from guess what, yes a key vault! I authenticate and set the variable before running terraform init, then as soon as I close the console the variables are cleared.

Finally, and this is a key one for me, I don’t ever use the -out=FILE option when running terraform plan. This goes against a lot of advice out there as by using a plan file you can guarantee that what is in your plan is what will be applied. However there is a key problem with this approach and the file in that it can be decoded and all the secrets are available in plain text locally!

Before I continue, it’s worth mentioning that a good while ago Terraform was updated so sensitive values are no longer shown on the cli when running terraform plan which is great. However, this is not the case for the plan file.

To prove this for yourself, try running the following commands for a configuration that contains secrets:

terraform plan -out=myplanfile
terraform show -json ./myplanfile >>planfiledecoded.json

If you then inspect the contents of plan file, you will see everything listed in plain text locally. What’s worse is that some people check the plan file into their source control to ensure their CI/CD pipeline deploys exactly what is expected without realising how easily this can be decoded.

Key Takeaway: Never add secrets to your code in plain text, always reference them from a key vault or similar solution. Be aware of what data is checked into source control as once secrets are checked in they will need to be changed immediately to prevent being hacked.