9.3 Vault, Ephemeral Values, and Write-Only Arguments

Key Takeaways

  • HashiCorp Vault is the exam's recommended secrets manager: authenticate the Vault provider with VAULT_ADDR and VAULT_TOKEN, and prefer reading secrets at runtime instead of committing them
  • Ephemeral values (Terraform 1.10+, current on the 1.12 exam) exist for the run only — Terraform omits them from state and plan files
  • Write-only arguments (Terraform 1.11+) such as password_wo are sent to the provider and discarded; they are not stored in state. A companion _wo_version argument is stored so you can force an update
  • Ephemeral values may only flow to other ephemeral destinations, write-only arguments, locals, provider configuration, or provisioner/connection blocks — not to ordinary resource arguments or root outputs
  • The 004 update summary explicitly adds ephemeral values and write-only arguments to sensitive-data objective 4h
Last updated: August 2026

9.3 Vault, Ephemeral Values, and Write-Only Arguments

Quick Answer: Vault is HashiCorp's recommended secrets manager for Terraform. On Terraform 1.12, ephemeral values (1.10+) and write-only arguments (1.11+) are the 004-new way to keep a secret out of state and plan files. sensitive only hid it. Ephemeral values may flow only to other ephemeral or write-only destinations. Write-only args such as password_wo are discarded after the provider uses them; you bump password_wo_version (which is stored) when you intend a new secret.

Objective 4h continues here. The 004 content update explicitly lists ephemeral values and write-only arguments next to Vault. Official pages on the 1.12 line: Manage sensitive data, ephemeral block, write-only arguments, and HashiCorp's Vault + Terraform tutorials.

Version pins the exam expects you not to invert:

FeatureFirst Terraform versionOn the 004 / 1.12 exam?
sensitive on variables and outputs0.15Yes — section 9.2
ephemeral argument on variables and child-module outputs; ephemeral resource block1.10Yes
Write-only arguments on managed resources1.11Yes
Product version tested1.12Yes

Vault as the secrets-manager pattern

004 wording is "including secrets management with Vault." Two complementary patterns appear in HashiCorp's own tutorials:

  1. Manage Vault with Terraformhashicorp/vault provider creates policies, auth methods, mounts, and KV secrets as code.
  2. Consume secrets from Vault during a Terraform run — so the password never lives in .tf, .tfvars, or (with ephemeral / write-only) in state.

Configure the provider from the environment, not from a committed file. Official tutorial language is strong: specify target-server information with VAULT_ADDR and VAULT_TOKEN.

terraform {
  required_providers {
    vault = {
      source  = "hashicorp/vault"
      version = "~> 5.0.0"
    }
  }
}

provider "vault" {
  # address and token come from VAULT_ADDR and VAULT_TOKEN
}

Vault provider 5.0.0+ documents ephemeral resources and write-only arguments. HashiCorp's Enterprise-codify tutorial writes a KV v2 secret with data_json_wo / data_json_wo_version so the payload is not written to state or shown in the plan, then reads it back with ephemeral "vault_kv_secret_v2" and feeds password_wo on a database connection. That is the picture 4h wants: Vault holds the secret; Terraform borrows it for the run.

You can also keep Terraform out of the secret entirely: a provisioner, a cloud-init template, or the application fetches from Vault at boot. Exam-correct either way: do not persist the secret in Terraform state if you can avoid it, and do not commit Vault tokens.

Four ephemeral constructs on Terraform 1.12

HashiCorp's manage-sensitive-data page groups them as the ways you omit values from state and plan:

ConstructSyntaxPersisted?
Ephemeral variablevariable "api_token" { ephemeral = true }No
Ephemeral child-module outputoutput "session_token" { ephemeral = true }No. Illegal on a root-module output.
Ephemeral resourceephemeral "random_password" "db" { ... }No. Address is ephemeral.TYPE.NAME.
Write-only argumentpassword_wo = ... on a managed resourceThe argument value is not stored. A sibling _wo_version usually is.

You can set both sensitive = true and ephemeral = true on a variable or child output. Then the value is omitted from artifacts and redacted in the CLI/UI.

Because Terraform does not store an ephemeral value, capture anything you must keep in another system — Vault, AWS Secrets Manager, Azure Key Vault — during the same run. If you generate ephemeral.random_password.db.result and never write it to a secret store or a write-only API, the password exists only in memory for that operation and is gone when the run ends.

Ephemeral resources: open, renew, close

An ephemeral block is not a managed resource and not a data source. Terraform does not put it in state. It has its own lifecycle, which the 1.12 docs spell with a Vault lease as the example:

  1. Open — the provider obtains the secret (Vault: get a lease and return the secret).
  2. Renew — if the run lasts longer than the remote TTL, the provider renews (Vault: lease renewal API).
  3. Close — after dependent providers finish this run phase, Terraform closes the object (Vault: end the lease so credentials are revoked immediately).
ephemeral "random_password" "db_password" {
  length           = 16
  override_special = "!#$%&*()-_=+[]{}<>:?"
}

resource "aws_db_instance" "example" {
  instance_class      = "db.t3.micro"
  allocated_storage   = 5
  engine              = "postgres"
  username            = "example"
  skip_final_snapshot = true
  password_wo         = ephemeral.random_password.db_password.result
  password_wo_version = 1
}

Reference form is ephemeral.TYPE.LABEL. Ephemeral resources participate in the dependency graph like resources and data sources. If an argument is unknown until apply, Terraform defers opening that ephemeral resource until apply.

They accept count, for_each (mutually exclusive), depends_on, provider, and lifecycle precondition / postcondition. They do not take provisioners of their own; they are the temporary handle.

Restriction: ephemeral only flows to ephemeral or write-only destinations

This is the 4h graph rule. Official allow-list for referring to an ephemeral value:

  • Another ephemeral resource block
  • A variable with ephemeral = true
  • A child-module output with ephemeral = true
  • A managed-resource write-only argument
  • A locals block (that local then also becomes ephemeral and is not stored)
  • A provider block (for example a short-lived API token)
  • provisioner and connection blocks

If you write password = ephemeral.random_password.db.result on an ordinary (not write-only) argument, plan fails. If you export an ephemeral value from the root module as a normal output, plan fails. Root outputs are state. Child-module ephemeral outputs exist so a child can hand a token to the parent without writing it to the child's state.

An expression that references an ephemeral variable becomes ephemeral. Sensitivity is a redaction taint; ephemeral is a persistence taint. They stack.

Write-only arguments

Write-only arguments are provider schema, not a new Terraform block. Providers mark them in the Registry. By convention they end in _wo and travel with a _wo_version:

  • aws_db_instance.password_wo + password_wo_version
  • aws_secretsmanager_secret_version.secret_string_wo + secret_string_wo_version
  • azurerm_key_vault_secret.value_wo + value_wo_version
  • vault_kv_secret_v2.data_json_wo + data_json_wo_version

During the operation Terraform sends the _wo value to the provider. The provider uses it to create or update the remote object. Terraform then discards it. It is not in the plan file and not in state.

Unlike ephemeral variables, write-only arguments accept both ephemeral and non-ephemeral values. You can write password_wo = "literal". HashiCorp still recommends feeding them from an ephemeral resource so the literal never sits in .tf.

Because the value is not stored, Terraform cannot diff it and cannot know it changed. Official consequence: Terraform sends write-only arguments to the provider on every operation. The _wo_version argument is stored. Increment it (12) when you intend a rotation; Terraform sees the version change, tells the provider, and the provider applies the new _wo value. Implementation details are provider-specific — read the Registry — but the exam-level model is: version in state, secret not in state.

The 004 pattern: generate, store in a manager, read back, write once

HashiCorp's write-only page shows the full loop with AWS Secrets Manager (Azure Key Vault is the sibling example; Vault's tutorial is the same shape):

  1. ephemeral "random_password" generates a password — not stored.
  2. A managed secret resource accepts it on a write-only argument (secret_string_wo) — payload not stored; version is.
  3. ephemeral "aws_secretsmanager_secret_version" (or ephemeral "vault_kv_secret_v2") reads the secret back for this run — not stored.
  4. aws_db_instance.password_wo consumes that read — not stored. password_wo_version tracks rotation.

If step 3 depends on an id that is unknown during plan, Terraform defers the ephemeral read until apply so it does not invent a false plan.

That loop is how 004 wants you to talk about Vault, AWS Secrets Manager, or Azure Key Vault: the manager is the system of record; Terraform's artifacts never keep the bytes.

004 traps for Vault, ephemeral, and write-only

  • sensitive = true is not ephemeral. It still lands in state.
  • ephemeral = true is illegal on a root output. Child-module outputs only.
  • You cannot assign an ephemeral value to an ordinary managed argument. Use a write-only argument or another ephemeral sink.
  • Write-only ≠ encrypted-in-state. It is absent from state.
  • Bump _wo_version to rotate. Editing only password_wo may not produce a plan you can see, because Terraform cannot diff a value it does not store.
  • Vault tokens belong in VAULT_TOKEN, not in git.
  • 004 added ephemeral values and write-only arguments to 4h. An answer that stops at sensitive = true is answering the 003 half of the objective.
Loading diagram...
Ephemeral secret path versus sensitive-in-state
Test Your Knowledge

On Terraform 1.12, what is the defining behavior of an ephemeral value?

A
B
C
D
Test Your Knowledge

Why do providers pair a write-only argument such as password_wo with a password_wo_version argument?

A
B
C
D
Test Your Knowledge

Where may a Terraform 1.12 configuration legally reference an ephemeral variable or an ephemeral resource attribute?

A
B
C
D