Managing Vault Configuration with Terraform
The Terraform Vault provider wraps the Vault API and gives you two things: a way to codify Vault configuration itself, and a way to pull secrets from Vault into other Terraform runs. Before HashiCorp, Ken provisioned new AWS accounts at a car insurance company. With IaC and peer-reviewed HCL configs, that process went from a month down to a few hours.
“it allows for a peer review.” — Ken Keller
Version-controlling Vault policies and namespaces the same way you version-control application code is the payoff. A config change goes through a pull request before it touches production.
The Secret Leakage Problem in Plan Files and State
When secrets appear in a Terraform configuration, they spread. terraform show -json against a saved plan file shows the database admin password in clear text in terraform show JSON (17:33). After terraform apply, that same password lands in terraform.tfstate. One secret in the config becomes the same secret in up to three files on disk.
Terraform marks values as “sensitive” in the terminal display, but that label only controls what the CLI prints. The saved plan file and the state file store them unmasked.
Ephemeral Values: Write-Only Attributes and Ephemeral Resources
The fix starts with bumping the Vault provider from version 4.8 to version 5 and running terraform init -upgrade. Two constructs become available: data_json_write_only replaces the normal data_json attribute on vault_kv_secret_v2, and an ephemeral "vault_kv_secret_v2" block reads the secret only during execution, writing nothing to state or plan.
Because write-only values are never stored, Terraform cannot detect when the underlying secret changes. A companion data_json_write_only_version attribute handles that. As Ken put it:
“that’s the purpose of the versions here.” — Ken Keller
Increment the integer, and Terraform sees the resource as changed on the next apply.
Verifying Secrets Are Gone from Plan and State
After the provider upgrade and config changes, terraform plan shows that attributes are now hidden rather than masked as sensitive. Running terraform plan -out then terraform show -json | jq confirms null values in plan and state after ephemeral upgrade (26:47): data_json_write_only is null, and password_write_only is null. Neither value travels into the output file.
terraform apply then updates only the two modified resources. Querying the state file with jq shows the same result: both fields are null. The secret exists in Vault, not on disk.
Notable Quotes
it allows for a peer review. Ken Keller · ▶ 5:00
Terraform doesn’t know you’ve changed it Ken Keller · ▶ 24:53
that’s the purpose of the versions here. Ken Keller · ▶ 22:05
Key Takeaways
- Secrets set via the Vault provider leak into Terraform plan files and state in clear text without ephemeral values.
- Vault provider v5 and Terraform 1.11 add write-only attributes and ephemeral resources that stay out of plan and state.
- Write-only fields need a companion version attribute so Terraform detects when the secret has changed.