Manage sensitive data in your configuration
Terraform may require access to sensitive data, such as cloud provider credentials, API tokens, and other secrets to provision your infrastructure. If you add secret values directly to your configuration, Terraform stores those secrets in its state and plan files. Learn about the different options for securing sensitive data in your configuration, and the tradeoffs of each approach.
Background
Terraform state and plan files contain detailed information about your infrastructure, including resource attributes and metadata that can contain sensitive values, such as initial database passwords or API tokens.
If you are developing with Terraform locally, Terraform stores your state in a plaintext file, which includes any secret values you defined in your configuration. Treat your state file as sensitive data by excluding it from Git workflows and following our recommendations tosecure your state file.
You can also configure Terraform to store your state and plan files in aremote location. When you configure Terraform to use remote state storage, it only holds state in memory when actively using it. You can encrypt your state at rest, but the encryption method depends on your specific backend. For example, HCP Terraform automatically encrypts state at rest and protects it with TLS in transit.
Requirements
The following requirements are tied to specific blocks and arguments you can use to handle sensitive values in your Terraform configuration:
- Use Terraform 0.15 or later to add the
sensitiveargument tovariableandoutputblocks - Use Terraform 1.10 or later to add the
ephemeralargument to variables and child module outputs, or add theephemeralblock - Use Terraform 1.11 or later to use a write-only argument on a managed resource
Each provider defines any availableephemeral blocks and write-only arguments on their managed resources. Reference theTerraform registry to learn more about what your provider supports.
Determine how to handle your sensitive data
To decide how to handle sensitive values in your configuration, start by determining whether you want to hide values from the Terraform CLI and HCP Terraform UI, or prevent Terraform from storing those values entirely.
You can add thesensitive argument tovariable oroutput blocks so that Terraform redacts those values from CLI output and in the HCP Terraform UI. Terraform also treats any expressions that reference a sensitive variable or output as inherently sensitive. Refer toHide sensitive variables and outputs for instructions on hiding sensitive data in variables and outputs.
Ephemeral values are available at runtime, but Terraform omits them from state and plan files entirely. Terraform provides four ways to define ephemeral values in your configuration:
- The
ephemeralargument on variables and child module outputs - The
ephemeralblock - A write-only argument on a managed resource
For more information about ephemeral values and their restrictions, refer toOmit values from state and plan files.
You can also add both theephemeral andsensitive arguments tovariable and child moduleoutput blocks to prevent Terraform from storing their values. Doing so redacts those values in the Terraform CLI and HCP Terraform UI. Learn more abouthiding values in the CLI without storing them.
Hide sensitive variables and outputs
Hands-on: Try theProtect Sensitive Input Variables tutorial.
Use thesensitive argument onvariable andoutput blocks when you want to redact those values from Terraform CLI log output and the HCP Terraform UI. Terraform also treats any expressions that reference a sensitive variable or output as inherently sensitive.
Add thesensitive argument tovariable blocks that contain sensitive data:
variable "database_password" { description= "Password for the database instance" type= string sensitive= true}You can also addsensitive tooutput blocks that contain sensitive data:
output "connection_string" { description= "Database connection string" value= "postgresql://${var.db_username}:${var.database_password}@${aws_db_instance.main.endpoint}/mydb" sensitive= true}Terraform then redacts sensitive variables and outputs in the operation log of the Terraform CLI. For example, theconnection_string output is redacted in the following apply summary:
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Outputs:connection_string = (sensitive value)Terraform also automatically treats any expression that references a sensitive variable or output as sensitive. In the following example, thepassword argument references the sensitivevar.database_password in another resource:
resource "aws_db_instance" "main" { identifier= "my-database" engine= "postgres" username= var.db_username password= var.database_password}Terraform redacts thepassword argument from themain resource in plan and apply operations:
# aws_db_instance.main will be created+ resource "aws_db_instance" "main" { + password = (sensitive value) + username = "admin" }Terraform stores values with thesensitive argument in both state and plan files, and anyone who can access those files can access your sensitive values. Additionally, if you use theterraform output CLI command with the-json or-raw flags, Terraform displays sensitive variables and outputs in plain text.
If you do not want to store the values of your sensitive variables and outputs, refer toOmit values from state and plan files. If you have sensitive values in your state and plan files, we recommendsecuring your state.
Hide values without storing them
You can add thesensitive argument to variables and child module outputs that have theephemeral argument to combine their benefits. The followingdatabase_password variable is omitted from state and plan files, and the value is redacted in the Terraform CLI and the HCP Terraform UI:
variable "database_password" { description= "Password for the database instance" type= string sensitive= true ephemeral= true}To learn more about theephemeral argument, refer toOmit values from state and plan files.
Omit values from state and plan files
Ephemeral values are available at the run time of an operation, but Terraform omits them from state and plan files. Because Terraform does not store ephemeral values, you must capture any generated values you want to preserve in another resource or output in your configuration.
You can use the following methods ways to define ephemeral values in your configuration:
- The
ephemeralargument on variables and child module outputs - The
ephemeralblock - Awrite-only argument on a managed resource
Terraform restricts where you can reference ephemeral values in your configuration. You can only refer to ephemeral values in the following contexts:
- In the
localsblock - In
variableblocks with theephemeralargument - Inchild module
outputblocks with theephemeralargument - In a managed resourcewrite-only argument
- The
ephemeralblock - Configuringproviders in the
providerblock - Inprovisioner andconnection blocks
Add theephemeral argument to a variable or output
Set theephemeral argument totrue in avariable block containing temporary sensitive data to omit that value from state and plan files:
variable "api_token" { description= "Short-lived API token for provider authentication" type= string sensitive= true ephemeral= true}You can reference avariable block with theephemeral argument in otherephemeral contexts. For example, you can use theapi_token variable in aprovider block to configure a provider:
provider "example" { api_token= var.api_token}You can also add theephemeral argument in theoutput block in child modules to pass data between modules without persisting that data to state or plan files. You cannot add theephemeral argument to outputs in the root module.
output "session_token" { value= ephemeral.auth_provider.main.token ephemeral= true sensitive= true}Passing output values between child modules and the root module is useful for managing credentials, tokens, and other temporary values that you do not want to store in state.
You can also add thesensitive argument tovariable andoutput blocks to hide their values in the CLI and HCP Terraform UI. Learn more aboutusing theephemeral argument alongside thesensitive argument.
Use theephemeral block
Theephemeral block declares a temporary ephemeral resource that only exists during the current Terraform operation. Terraform does not store ephemeral resources in state or plan files, making them ideal for managing sensitive or temporary data that you do not want to persist, such as temporary passwords or connections to other systems. Each provider defines any available ephemeral resources. Reference theTerraform registry to learn more about what your provider supports.
For example, you can use therandom_password ephemeral resource to generate a temporary password:
ephemeral "random_password" "db_password" { length= 16 override_special= "!#$%&*()-_=+[]{}<>:?"}You can only reference anephemeral block in other ephemeral contexts, such as a write-only argument in a managed resource. Write-only arguments let you securely pass temporary values to managed resources during an operation without persisting those resource values. For example, you can reference thedb_password in thepassword_wo write-only argument:
#...ephemeral "random_password" "db_password" { length= 16 override_special= "!#$%&*()-_=+[]{}<>:?"}resource "aws_db_instance" "example" { instance_class= "db.t3.micro" allocated_storage= "5" engine= "postgres" username= "example" skip_final_snapshot= true publicly_accessible= true db_subnet_group_name= aws_db_subnet_group.example.name password_wo= ephemeral.random_password.db_password.result password_wo_version= 1}Neither write-only arguments norephemeral blocks persist outside of the current Terraform run. This ensures that theephemeral.random_password.db_password.result value is completely omitted from state and plan files.
Terraform does not store the generated value ofephemeral.random_password.db_password.result, but you can capture it in another resource to ensure the value is not lost. For an example of generating, storing, retrieving, and using an ephemeral password, refer towrite-only arguments.
To learn about ephemeral resources, refer to theephemeral block reference.
Use write-only arguments
Write-only arguments let you securely pass temporary values to Terraform's managed resources during an operation without persisting those values to state or plan files. Each provider defines any available write-only arguments on their managed resources. Reference theTerraform registry to learn more about what your provider supports.
Write-only arguments typically end with_wo and have corresponding_wo_version arguments. For example, theaws_db_instance has apassword_wo write-only argument:
resource "aws_db_instance" "main" { instance_class= "db.t3.micro" allocated_storage= "20" engine= "postgres" username= "admin" skip_final_snapshot= true password_wo= ephemeral.random_password.db_password.result password_wo_version= 1}During a Terraform operation, theaws provider uses thepassword_wo value to create the database instance, and then Terraform discards that value without storing it in the plan or state file. To learn more about write-only arguments, including how to update them with versions and store their values, refer towrite-only arguments.
State security best practices
If you store sensitive values in a state file, we recommend implementing additional security measures to keep your state safe:
- Store your state remotely
- Encrypt your state at rest
- Use access controls to limit who has access to your state
- Use audit logs to track state access over time
Storing your state remotely can provide better security by letting you encrypt your state when it's at rest. For example, the following backends support state encryption:
- HCP Terraform encrypts state at rest, lets yousupply your own encryption keys, and protects state with TLS in transit
- TheS3 backend can encrypt state at rest if you enable the
encryptoption, and protects state with TLS in transit - The GCS backend supports usingcustomer-supplied orcustomer-managed encryption keys