Keeping Terraform Cloud/Enterprise Provider Credentials Secure

Yulei Liu
HashiCorp Solutions Engineering Blog
5 min readDec 15, 2021
Keeping credentials sensitive

The Problem

As one of the most popular infrastructure as code tools, Terraform helps in configuring, provisioning, and managing the infrastructure across 400+ providers. To authenticate to a cloud service’s API, Terraform needs credentials and a provider plugin to customized to work with that service. The credentials used by Terraform are generally privileged so that Terraform can create/update/destroy resources. However, I find one of the biggest challenges most users have is keeping those credentials completely secure at every phase of a user’s process.

There are several methods I’ll explain below, but the final purpose of this article is to introduce a pair of tools that will help you proactively prevent credentials from being exposed, and also catch when a credential is exposed or not marked as sensitive in Terraform.

Methods for Providing Credentials to Terraform Providers

Credentials can be provided to Terraform in several ways. I’ll cover the most common here, using AWS as an example:

Hardcoded:

Hardcoding credentials risks secrets leakage, whoever gets access to your config files will be able to use it. This is bad in almost any instance.

Terraform variable:

This method is an improvement to hardcoding secrets, since the values of Terraform variables don’t have to be stored in the code. They can be configured in Terraform Cloud as shown below:

Providing Terraform variable values via Terraform Cloud GUI

However, this method has its own risks. Because the credentials are provided as Terraform variables, their values are accessible by Terraform code, for example:

Terraform output that prints out Terraform variables

Terraform variables can be further secured by marking Terraform variables as sensitive, but it still relies on the practitioner and administrators to enforce good coding practices (be very careful with nonsensitive function).

Environment variable:

Environment variables are more secure than Terraform variables, as they can not be referenced by any Terraform code. Environment variables also have fixed names per provider, which makes it easy to be identified.

Then…

IAM roles/Instance profiles

You can also run Terraform CLI on the cloud and use predefined IAM roles. There is no credential involved, but this will only work within the cloud where Terraform is deployed — you can’t use AWS IAM roles to provision on Google Cloud, or vice versa. For people with multiple providers, they still need to find a way manage credentials for other providers.

Ensuring Credentials Are Marked “Sensitive”

Terraform Cloud/Enterprise provides a means for users to store their credentials as a Terraform or environment variable, which can be marked as sensitive. Sensitive variables are encrypted and not readable by any user.

Based on the discussion above, providing provider credentials via environment variables is perhaps the most widely used and most secure way, but it still relies on Terraform Cloud/Enterprise admins to mark those variables that could contain secrets as sensitive. Below is an example of a not-so-secure environment variable:

tfcvar-sec is an open source tool that will scan Terraform and environment variables configured in Terraform Cloud/Enterprise, and reports if there is any variable that may contain secrets but hasn’t been marked as sensitive.

Credentials provided to Terraform providers via environment variables have a fixed key, which makes it easy for tfcvar-sec to identify. Environment variables identified by tfcvar-sec will be printed in red.

Credentials provided to Terraform providers via Terraform variables are harder to identify, as the variable names could be anything. tfcvar-sec will do a best effort guess based on the name of the variable. Identified Terraform variables will be printed in yellow.

Terraform variable values can also be provided as environment variables, e.g. TF_VAR_varname. Those will be printed in yellow as well.

Below is an example output:

tfcvar-sec

Installation

tfcvar-sec is written in golang. It doesn’t have any external dependencies. You can just download, unzip, and copy the binary to system PATH.

Usage

tfcvar-sec only works with Terraform Cloud for now. You need a Terraform Cloud token which will be used by tfcvar-sec to find all organizations, workspaces, and variables. Here’s what usage looks like:

TFE_TOKEN=YOUR.atlasv1.TFE_TOKEN tfcvar-sec scan

or

tfcvar-sec scan -token YOUR.atlasv1.TFE_TOKEN

tfcvar-sec will read Terraform Cloud credentials files if no tokens are provided via CLI or environment variable. This is $HOME/.terraform.d/credentials.tfrc.json by default. Take a look:

tfcvar-sec scan

Retrospective vs Preventative

tfcvar-sec is a nice tool that can help you find the insecure variables. You can schedule it whenever you feel necessary. However, it doesn’t matter how often you schedule tfcvar-sec, there is always a window between creation and scheduled scan, during which the variables are not secure, and thus have the risk of leaking.

Wouldn’t it be nice if there was a tool that could prevent creation of insecure variables in the first place? Terraform Cloud does have a governance engine that does exactly that: Sentinel policy as code. There are many out of box Sentinel policies that can be used to govern Terraform code during the plan phase as a preventative measure. Below is a Sentinel policy that is equivalent to tfcvar-sec.

You can use this policy set, which comes with several best practices for Terraform Cloud. Below is an example screenshot:

Being able to prevent insecure variables from been created is a good way to keep your Terraform Cloud secure, but it requires that you manage Terraform Cloud using the Terraform Cloud/Enterprise provider. Sentinel doesn’t stop Terraform Cloud users from creating insecure variables manually.

Conclusion

The combination of reactive (tfcvar-sec) and proactive (Sentinel policy as code) will help you keep provider credentials safe and secure.

--

--