How it works
The explanation, with examples you can run.
What "sensitive" does and does not do
From the local demo (Terraform 1.5.7):
resource "random_password" "db" { length = 20 special = false} output "db_password" { value = random_password.db.result sensitive = true}$ terraform outputdb_password = <sensitive>file = "./out/dev-known-woodcock.txt" $ terraform output -raw db_password | wc -c 20And in terraform.tfstate, the result attribute of random_password.db held the full 20-character password in plain text. The provider marks that attribute sensitive in its schema, so plans redact it, but redaction is about display only.
Protecting state
- Use a remote backend with encryption at rest (S3 with KMS, for example), versioning, and IAM that limits readers to the roles that run Terraform.
- Never commit
*.tfstateor plan files; add them to.gitignore. Treat CI artefacts containing plans as secrets and expire them quickly. - OpenTofu can encrypt state and plan files client-side (since OpenTofu 1.7), so the storage backend never sees plain text. Terraform relies on backend-side encryption.
Keeping secrets out of state
Recent Terraform versions add two features for this:
- Ephemeral resources (Terraform 1.10+) are read or generated during a run and never persisted: for example, fetching a secret from a secrets manager or generating a password just for this run.
- Write-only arguments (Terraform 1.11+), on resources whose providers support them, accept ephemeral values and are not stored in plan or state. They usually come with a version argument you bump to trigger rotation.
ephemeral "random_password" "db" { length = 24} resource "aws_db_instance" "main" { # ... password_wo = ephemeral.random_password.db.result password_wo_version = 1}Provider support varies; check the resource documentation for _wo arguments.
Often better: do not handle the secret
Many services can own their secrets. RDS can generate and rotate the master password in Secrets Manager (manage_master_user_password = true), so Terraform only ever sees an ARN. Applications then read the secret at runtime with their own IAM role. The secret never appears in Terraform, its state, its plans or its CI logs, and rotation does not need a Terraform run.
Finally, keep secrets out of variable defaults and .tfvars files in Git, and avoid local-exec provisioners that echo them into logs.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.