Study guide

9.3 Vault, Ephemeral Values, and Write-Only Arguments

HashiCorp Certified: Terraform Associate 004

Track your progress as you read

Finished sections get a check mark.

1 Introduction & Exam Overview

1.1 Current Exam Facts 1.2 Format, Delivery, Retakes, and Recertification 1.3 004 Changes, Terraform 1.12, and Study Plan

2 Infrastructure as Code with Terraform

2.1 What Infrastructure as Code Is 2.2 Advantages of IaC Patterns 2.3 Multi-Cloud, Hybrid, and Service-Agnostic Workflows

3 Terraform Fundamentals: Providers & State

3.1 Install and Version Terraform Providers 3.2 How Terraform Uses Providers 3.3 Configuration with Multiple Providers 3.4 How Terraform Uses and Manages State

4 Core Terraform Workflow: Init & Validate

4.1 The Terraform Write–Plan–Apply Workflow 4.2 Initialize a Working Directory 4.3 Validate a Configuration

5 Plan, Apply, Destroy, and Formatting

5.1 Generate and Review an Execution Plan 5.2 Apply Changes to Infrastructure 5.3 Destroy Terraform-Managed Infrastructure 5.4 Formatting and Style Adjustments

6 Resources, Data Sources, and References

6.1 Resource Blocks vs Data Blocks 6.2 Resource Attributes and Cross-Resource References 6.3 Resource Addressing and Interpolation Patterns

7 Variables, Outputs, and Complex Types

7.1 Input Variables, tfvars, and Precedence 7.2 Output Values 7.3 Complex Types: list, map, object, tuple, set

8 Dynamic Configuration and Dependencies

8.1 Expressions, count, for_each, and dynamic Blocks 8.2 Built-in Functions 8.3 Dependencies, depends_on, and Lifecycle Rules

9 Conditions, Secrets, and Sensitive Data

9.1 Custom Conditions: validation, precondition, postcondition, check 9.2 Sensitive Data Handling 9.3 Vault, Ephemeral Values, and Write-Only Arguments

10 Terraform Modules

10.1 How Terraform Sources Modules 10.2 Variable Scope within Modules 10.3 Using Modules in Configuration 10.4 Managing Module Versions

11 Terraform State Management

11.1 The Local Backend 11.2 State Locking 11.3 Remote State and the backend Block 11.4 Resource Drift and State Operations

12 Maintain Infrastructure with Terraform

12.1 Import Existing Infrastructure 12.2 Inspect State with the CLI 12.3 Verbose Logging and Diagnostics

13 HCP Terraform

13.1 Create Infrastructure with HCP Terraform 13.2 Collaboration and Governance Features 13.3 Workspaces and Projects 13.4 HCP Terraform Integrations

9.3 Vault, Ephemeral Values, and Write-Only Arguments

Key Takeaways Explain This Topic AI

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:

Feature First Terraform version On the 004 / 1.12 exam?

  • sensitive on variables and outputs 0.15 Yes — section 9.2
  • ephemeral argument on variables and child-module outputs; ephemeral resource block 1.10 Yes
  • Write-only arguments on managed resources 1.11 Yes
  • Product version tested 1.12 Yes
  • Vault as the secrets-manager pattern

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

Manage Vault with Terraform — hashicorp/vault provider creates policies, auth methods, mounts, and KV secrets as code.

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:

Construct Syntax Persisted?

Ephemeral variable variable "api_token" { ephemeral = true } No

Ephemeral child-module output output "session_token" { ephemeral = true } No. Illegal on a root-module output.

Ephemeral resource ephemeral "random_password" "db" { ... } No. Address is ephemeral.TYPE.NAME .

Write-only argument password_wo = ... on a managed resource The 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:

Open — the provider obtains the secret (Vault: get a lease and return the secret).

Renew — if the run lasts longer than the remote TTL, the provider renews (Vault: lease renewal API).

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 ( 1 → 2 ) 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):

ephemeral "random_password" generates a password — not stored.

A managed secret resource accepts it on a write-only argument ( secret_string_wo ) — payload not stored; version is.

ephemeral "aws_secretsmanager_secret_version" (or ephemeral "vault_kv_secret_v2" ) reads the secret back for this run — not stored.

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