Ask a platform team where their production database password lives and the answer is usually "in the secrets manager". Ask where else it lives and the honest answer is often "in the Terraform state file, in plaintext, readable by anyone with access to the state bucket". That was the default for years: a secret read through a data source or set on a resource ended up in both plan and state16.
What changed
| Version | Feature | What it does |
|---|---|---|
| 1.10 | Ephemeral values and resources | Fetch or generate values during a run without persisting them in plan or state14 |
| 1.11 | Write-only arguments | Pass ephemeral values to managed resources; never stored in plan or state2 |
Together they close the gap: a secret can be read from a secrets manager ephemerally and handed to a resource through a write-only argument, without ever landing in state23. There is one catch. Because Terraform never stores the value, it can't detect when it changes. Write-only arguments are paired with a version argument that you increment to trigger an update, and only the version is stored2. Support also depends on each provider, resource by resource35.
"Sensitive" hides a value from your screen. "Ephemeral" and "write-only" keep it out of the file. Only the second protects you if the state bucket leaks.
1. Find the exposure
- Inventory every state file and who can read it, including CI service accounts and old backends nobody uses.
- Search state for secret-bearing attributes: passwords, private keys, tokens, connection strings.
- List data sources that read from secrets managers; each one is copying a secret into state today.
- Treat any secret that has ever been in state as potentially exposed to everyone with state access.
2. Upgrade the toolchain
- Move to Terraform 1.11 or later so both features are available2.
- Upgrade providers and check their documentation for ephemeral resources and write-only arguments on the resources you use.
- If you run OpenTofu, check its equivalent features and version support separately; the choice is covered in OpenTofu or Terraform.
3. Migrate resource by resource
- Replace secret-reading data sources with ephemeral resources where the provider offers them.
- Switch resources to write-only arguments for passwords and keys, with a version argument for rotation.
- Rotate the secret as part of the migration. Moving to write-only stops future storage; it doesn't undo past exposure.
- Better still, let the platform generate and manage the secret itself, such as a managed database credential stored in the cloud's secrets manager, so Terraform never handles it.
- Update shared modules first, using the patterns in Terraform module design, so every consumer benefits.
4. Harden state anyway
- Encrypt state at rest with customer-managed keys and restrict decrypt permissions.
- Limit state read access to the pipelines that need it; humans rarely do.
- Enable versioning and access logging on the state backend, and alert on unusual reads.
- Keep plan files out of CI artefacts and logs, or apply the same controls to them.
5. Keep it from regressing
- Add a policy check in CI that flags secret-bearing attributes set through normal arguments, and secret-reading data sources.
- Document the rotation process using version arguments, so it's routine rather than tribal knowledge.
- Include state access in access reviews and in your SOC 2 evidence; it is often the broadest secret access in the company.
How I can help
I review and redesign infrastructure-as-code estates for security and maintainability, including secrets handling, state architecture and module standards. As a fractional CTO I can own that roadmap. Or analyse your challenge and bring the result to a call.
- 1Terraform 1.10 improves handling secrets in state with ephemeral valuesHashiCorp · Nov 2024
- 2
- 3Manage sensitive data in your configurationHashiCorp developer documentation
- 4Ephemerality in resourcesHashiCorp developer documentation
- 5Write-only arguments (Plugin Framework)HashiCorp developer documentation
- 6Terraform 1.10 ephemeral valuesInfoQ · Nov 2024