đ 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 |
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.
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:
-
sensitivefor output/log maskingephemeralfor 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.