Secrets, sensitive and ephemeral values

Terraform · Expert · 12 min

State has historically held every secret in plain text; modern Terraform can avoid that.

sensitive = true on variables and outputs, and sensitive attributes in provider schemas, only redact display: plans and logs show (sensitive value), but the value is still written to state and to saved plan files. So state and plan files must be treated as secrets: encrypted storage, tight access, no uploading plan files to public CI artifacts.

Newer features keep values out of artifacts entirely:

  • Ephemeral variables and outputs (ephemeral = true, 1.10+): available during the run, never persisted in state or plan. They can only flow into places that accept ephemeral values.
  • Ephemeral resources (ephemeral "aws_secretsmanager_secret_version" "db" {...}): fetch a secret or a temporary credential for the duration of the run, e.g. to configure a provider, without saving it.
  • Write-only arguments (1.11+): resource arguments like password_wo (with a companion password_wo_version to signal changes) that are sent to the API but never stored. Support depends on the provider and resource.

Other options: have the service generate and own the secret (RDS manage_master_user_password = true stores it in Secrets Manager), or pass references (an ARN) rather than values.

Avoid random_password resources whose result lands in state, unless state is protected accordingly. OpenTofu additionally offers client-side state encryption.

Example

variable "db_password" {
  type      = string
  sensitive = true
  ephemeral = true                 # never stored in state or plan
}

ephemeral "aws_secretsmanager_secret_version" "api_key" {
  secret_id = "prod/api-key"       # read during the run only
}

resource "aws_db_instance" "main" {
  identifier          = "shop-prod"
  engine              = "postgres"
  instance_class      = "db.t4g.medium"
  allocated_storage   = 50
  username            = "shop"
  password_wo         = var.db_password   # write-only: sent, not stored
  password_wo_version = 2                 # bump to rotate
}
# State records password_wo_version, never the password itself.

Remember

  • sensitive hides output but values still land in state and plans
  • ephemeral variables/resources are never persisted
  • Write-only arguments send secrets without storing them; bump the version to change

Watch out for

  • Believing sensitive = true keeps a password out of the state file.

Check yourself

  1. Which feature keeps a database password out of the state file entirely?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.hashicorp.com/terraform/language/state/sensitive-data