This document covers best practices for managing HashiCorp Vault instances with Terraform. In this guide, you will:
- Gain an understanding of key considerations when integrating Vault with Terraform
- Learn to implement configurations that prioritize security and efficiency
- Identify common pitfalls and learn how to avoid them using industry-standard practices
This document assumes familiarity with the foundational concepts of both HashiCorp Vault and Terraform. If you're unfamiliar with the foundational concepts, visit our Vault and Terraform tutorials to get started.
For Terraform Cloud and Enterprise (TFC/E) customers integrating with Vault, we recommend using dynamic provider credentials for Vault when possible. Dynamic provider credentials generate short-lived credentials as needed and eliminate the need for static credentials in your workspace, reducing risk and increasing the security posture of your integration. If you cannot use dynamic credentials, do not hardcode your Vault credentials. Instead, we recommend that you configure the Vault provider with environment variables.
When you use dynamic provider credentials with the Vault provider, do not pass the
namespace arguments into the provider configuration block. The
namespace values are populated by the
TFC_VAULT_NAMESPACE workspace environment variables when you configure dynamic credentials, which Terraform Cloud uses to retrieve a value for the
Terraform Cloud and Enterprise also support Vault-backed dynamic credentials, limiting the requirement to configure dynamic provider credentials with different cloud providers. This lets you centralize your secrets management with Vault while generating short-lived credentials with multiple cloud providers.
When using dynamic credentials with the Vault provider, Terraform Cloud and Enterprise manage the Vault token lifecycle, and therefore, Vault will not create a child token. You cannot use provider arguments for managing the Vault child token (e.g., token_name argument) when dynamic credentials are enabled.
The following are recommendations that you can implement in your environment if you are unable or choose not to use dynamic credentials.
We recommend setting the Vault provider arguments using environment variables to keep your credentials out of your Terraform configuration. This approach increases security by reducing the exposure risk of sensitive credential information commonly associated with hardcoded values or accidental pushes to version control systems. Environment variables can be set using the command line, in a Terraform Cloud workspace, or by CI/CD tooling.
Terraform creates a child token with a limited TTL to reduce the exposure of secrets read by the provider, unless skip_child_token is set to
true. We recommend setting the token_name argument to something descriptive. The
token_name argument (or
VAULT_TOKEN_NAME environment variable) in the Vault provider configuration allows you to set a custom display name for the child token generated by Vault to execute the Terraform run. This is useful for audit logging and simplifying Terraform execution traceability.
We recommend that you use the auth method-specific configurations provided by the Vault provider when using a supported auth method. Examples of these auth method provider arguments include
auth_login_azure, and others. You should only use the generic auth_login provider argument if the provider does not yet support an auth method-specific configuration or if you use a custom authentication engine.
In Vault Enterprise, there are two ways you can specify a Vault namespace for a Vault resource or data source:
- By using Provider Aliasing with multiple Vault provider blocks. This method typically involves a default Vault provider block and one or more additional provider blocks with the configured namespace attribute. Resources and data sources can then specify a namespace by referencing a specific provider alias.
- By using the namespace attribute configured for the resource or data source. This method involves specifying the namespace directly on each resource or data source without needing to specify a namespace via a provider alias. We recommend simplifying the configuration and offering a cleaner alternative to multiple provider blocks. Note that the Vault provider version 3.8.0 introduces a namespace attribute for resources and data sources in the Vault provider.
Avoid reading or writing long-lived static secrets (for example, from the KV secrets engines) whenever possible when interacting with Vault from Terraform. Secrets that are read or written will persist in the Terraform state file and any generated plan files. Mitigate the risk of Vault secrets exposure by following these guidelines:
- Protect the state file using a secure, encrypted backend such as Terraform Cloud Free Tier. You can learn how TFC uses encryption in our system architecture data security documentation.
- Follow the principle of least privilege by limiting read/write access to the state file.
- When interacting with Vault using Terraform, use dynamic secrets engines with short-lived credentials whenever possible.
- Short-lived credentials that persist in a state file greatly reduce the risk of an attack, as the credentials will likely have expired in the event of a compromised state file.
Use the required Vault token capabilities when managing Vault resources. KV secrets engine resources, for example, need only the
update capability, depending on whether the resource exists. KV secrets engine data sources only require the
read capability. However, it is worth noting that if you use drift detection and want to detect changes made to stored KV secrets, you will need the
read capability to create or update.
Terraform can apply policy and governance at scale using infrastructure as code (IaC). When managing a Vault cluster, we recommend using Terraform to manage administration resources such as auth methods, secrets engines, namespaces, and policies. For example, your security team might have specific ACL or Sentinel policies that apply to every Vault namespace. If you add a new Vault namespace to the Terraform configuration, you can rely on Terraform to apply the correct governance policies for that namespace. However, suppose a Vault namespace administrator creates a child namespace directly from the Vault CLI or API. In that case, this new namespace will not be under Terraform management and likely will not have the required governance policies that would have been applied with the Terraform workflow.
One way to prevent this is to restrict certain capabilities that would otherwise allow Vault operators to create or modify resources that Terraform should manage. For example, you can block namespace manipulation with Sentinel policies.
For resources that you have already created outside of the Terraform provisioning workflow, you can import these resources into the Terraform configuration. To learn how to import these resources, visit the usage document Migrate unmanaged Vault namespace to Terraform-managed infrastructure. This document walks you through migrating an unmanaged Vault child namespace to a Terraform managed resource.
In this document, you learned about the best practices for managing your Vault instance with Terraform. To learn more about managing you resources with Terraform, visit the following resources below: