Sensitive Variables: Protecting Secrets in Terraform
Scenario
Your configuration needs a database password and an API key. You must ensure these values are never shown in CLI output or plan logs. You also need to understand that sensitive = true masks values in output but does NOT encrypt the state file.
- Declare a variable with sensitive = true.
- Pass the sensitive value via TF_VAR_ environment variable.
- Create a sensitive output.
- Observe that the value is masked as (sensitive value).
- Understand the security limitation: values are still in the state file in plain text.
Additional Context
sensitive = true on a variable prevents Terraform from showing the value in CLI plan/apply output. It also prevents the value from being used in resource names (Terraform errors if you try). If you mark a variable sensitive, any output that references it must also be marked sensitive.
Best practices: Never store secrets in .tfvars committed to Git. Use environment variables, a secrets manager (AWS Secrets Manager, HashiCorp Vault), or HCP Terraform's encrypted variable storage.
variables.tf
variable "db_password" {
description = "Database password — will be masked in all output."
type = string
sensitive = true # ← VALUE IS MASKED IN CLI OUTPUT
}
variable "api_key" {
description = "External API key."
type = string
sensitive = true
default = "default-key-for-dev"
}
variable "aws_region" { type = string; default = "us-east-1" }main.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" { region = var.aws_region }
# Store the secret in SSM Parameter Store (SecureString type)
resource "aws_ssm_parameter" "db_password" {
name = "/myapp/db-password"
type = "SecureString" # encrypted at rest by AWS
value = var.db_password # this value is sensitive
tags = { ManagedBy = "terraform" }
}
resource "aws_ssm_parameter" "api_key" {
name = "/myapp/api-key"
type = "SecureString"
value = var.api_key
tags = { ManagedBy = "terraform" }
}outputs.tf
# Outputs that reference sensitive values MUST also be sensitive
output "db_param_name" { value = aws_ssm_parameter.db_password.name }
output "db_param_arn" { value = aws_ssm_parameter.db_password.arn; sensitive = true }
output "api_key_name" { value = aws_ssm_parameter.api_key.name }Workflow Commands
# Pass sensitive values via environment variables (NEVER commit to Git)
export TF_VAR_db_password="SuperSecret123!"
terraform init && terraform apply
# Plan shows: db_password = (sensitive value)
# The actual value is NEVER printed
# Force view the sensitive output
terraform output -raw db_param_arn
# WARNING: State file contains secrets in plain text
terraform state pull | grep -i "SecureString"
unset TF_VAR_db_password
terraform destroy + resource "aws_ssm_parameter" "db_password" {
+ name = "/myapp/db-password"
+ type = "SecureString"
+ value = (sensitive value) ← masked!
}
