Handling Sensitive Values in Terraform

🔐 Real-World Use Case: Secrets That Shouldn’t Leak

Imagine this: you’re building an AKS cluster, provisioning Key Vault secrets, and injecting them into Kubernetes secrets or application settings. You deal with:

      • Client secrets
      • Database passwords
      • API tokens
      • Certificates or private keys

Now imagine someone running terraform apply in a CI/CD pipeline—and your secret values show up in terminal output or Terraform Cloud logs. This isn’t just bad hygiene—it’s a serious security risk.


🚨 Problem: Terraform is Transparent by Default

Terraform is designed to be declarative and audit-friendly. That means all attributes, even sensitive ones, are stored in state and shown during plan/apply—unless you explicitly prevent that.

✅ Part 1: Use sensitive = true to Suppress Output

You can flag any variable or output as sensitive to avoid accidental visibility in CLI or plan output.

Example: Marking an Output as Sensitive

resource "azurerm_key_vault_secret" "db_pass" {
  name         = "db-password"
  value        = var.db_password
  key_vault_id = azurerm_key_vault.main.id
}

output "db_password" {
  value     = azurerm_key_vault_secret.db_pass.value
  sensitive = true
}

Terraform now shows:

Outputs:

db_password = (sensitive value)

🔁 Sensitive Variables in Modules

Sensitivity propagates downstream. When a variable is marked sensitive, its value cannot be printed by any output unless you explicitly mark that output as sensitive too.

variable "db_password" {
  type      = string
  sensitive = true
}

If you try to output it without marking the output as sensitive, Terraform throws an error.

🧩 Edge Cases and Gotchas

      • Concatenating a sensitive value into a string still makes the entire string sensitive.
      • Sensitive values are still stored in plaintext in the state file unless protected externally.
      • Don’t use sensitive values in resource names, tags, or keys—those are never masked.

📘 Thumb Rules for Using sensitive

Scenario Recommendation
Return a password or token Use sensitive = true in output
Pass secrets into a module Mark variable as sensitive = true
Prevent secret exposure in logs Use sensitive + mask logs
Protect the state file Use remote backend + encryption + RBAC
Debugging with sensitive values Temporarily unset sensitive, then reapply it
Note:
sensitive hides values from CLI and logs—but does not stop them from being stored in Terraform state.
Anyone with state access can still read the raw values unless encryption or remote state protection is in place.

✅ Part 2: Ephemeral Values – Terraform 1.10+

Starting in Terraform 1.10, HashiCorp introduced ephemeral blocks—used to retrieve or generate values during the apply phase that are never written to state or plan files.

Example: Fetch a Secret Ephemerally

ephemeral "aws_secretsmanager_secret_version" "db_secret" {
  secret_id = "arn:aws:secretsmanager:eu-west-1:xxxx:secret:db-password"
}

locals {
  credentials = jsondecode(ephemeral.aws_secretsmanager_secret_version.db_secret.secret_string)
}

The credentials will be available only during terraform apply, used locally (e.g., to configure a provider or provision a resource), but not stored in state or visible in plan.

New in Terraform 1.10:
Use the ephemeral block to safely use secrets at runtime—without storing them. Ideal for passwords, tokens, and anything transient or sensitive.

Final Thoughts

Terraform gives you layered tools to handle secrets:

    • sensitive for output/log masking
    • ephemeral for no-storage runtime use

Use them together for a strong security posture. Protect state storage. Use RBAC and encryption. And always assume that what’s not explicitly protected—can be leaked.

 

Leave a comment