Skip to content
DevOps AI ToolKit
Newsletter
All prompts
AI for Terraform Difficulty: Advanced ClaudeChatGPTCursor

Terraform Vault Provider Secrets Integration Prompt

Inject HashiCorp Vault secrets into Terraform via data sources and ephemeral resources without persisting plaintext to state.

Target user
Platform and security engineers wiring Vault into Terraform pipelines
Difficulty
Advanced
Tools
Claude, ChatGPT, Cursor

The prompt

You are a senior platform engineer hardening how Terraform consumes secrets from HashiCorp Vault. Assume Terraform >= 1.10 and the `hashicorp/vault` provider >= 4.3. Your job is to eliminate plaintext secrets from state and plan artifacts while keeping the workflow non-interactive in CI.

Work through these steps in order:

1. Authenticate the provider without a hardcoded token. Prefer AppRole (`role_id` + `secret_id`) for CI runners or JWT/OIDC (`jwt` auth) for pipeline identity federation (e.g. GitHub Actions OIDC). Configure `auth_login` blocks on the `vault` provider, never a static `token = "s.xxxx"`.

2. Classify every secret read. For KV v2 use `data "vault_kv_secret_v2"`; for dynamic backends (database, AWS STS) use the matching data source. Flag which reads land in state: ANY `data "vault_generic_secret"` or `data "vault_kv_secret_v2"` persists the full secret payload into `terraform.tfstate` in cleartext. Treat that as a DESTRUCTIVE exposure.

3. Convert state-persisting reads to Terraform 1.10+ `ephemeral "vault_kv_secret_v2"` blocks where the secret only feeds a `write-only` argument or a provider config. Ephemeral values never enter state or plan. Show the migration diff.

4. Mark every derived attribute `sensitive = true` in outputs and locals so nothing leaks in CLI output or CI logs.

5. Address lease and TTL lifecycle: dynamic secrets have leases. Warn that `terraform destroy` does NOT always revoke leases, and re-running apply can generate new dynamic credentials while old leases still live. Recommend `vault lease revoke -prefix` cleanup and short `max_ttl`.

6. Call out DESTRUCTIVE operations explicitly: writing secrets to state, committing state to a non-encrypted backend, revoking a lease still in use by running workloads, and rotating a `secret_id` that active runners depend on.

Deliver: provider auth config, the ephemeral vs data-source decision table, migrated HCL, and a state-hygiene checklist.

Input template:
```
Vault address: <https://vault.example.com>
Auth method: <approle | jwt/oidc>
Secret engines in use: <kv-v2 path, database, aws, ...>
Terraform version: <1.10.x>
Backend + encryption: <s3+sse-kms | tfc | ...>
Secrets consumed and their sinks: <secret -> where it is used>
```

Run this prompt with AI

Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.

Why this prompt works

Terraform’s biggest secrets footgun is that a data source read is stored verbatim in state. Engineers assume data "vault_kv_secret_v2" is “read-only and safe,” but the retrieved value is serialized into terraform.tfstate and into the plan file. This prompt forces a per-secret classification and pushes state-persisting reads toward Terraform 1.10+ ephemeral resources, which are evaluated at runtime and never serialized. It also treats lease lifecycle as a first-class concern rather than an afterthought.

How to use it

Fill in the input template with your Vault address, auth method, and a map of every secret to its sink (provider config, resource argument, output). Paste it into Claude or Cursor. Ask the model to produce (1) the provider auth_login block, (2) a decision table of ephemeral vs data source per secret, and (3) the migrated HCL. Then run the state-hygiene checklist against your existing configuration before applying.

Useful commands

# Authenticate a CI runner with AppRole and export a scoped token
export VAULT_ADDR=https://vault.example.com
VAULT_TOKEN=$(vault write -field=token auth/approle/login \
  role_id="$VAULT_ROLE_ID" secret_id="$VAULT_SECRET_ID")
export VAULT_TOKEN

# Inspect what a data source would persist BEFORE applying
terraform plan -out=tfplan
terraform show -json tfplan | jq '.planned_values.root_module.resources[].values' | less

# Detect plaintext secrets already sitting in state
terraform state pull | jq '.resources[] | select(.type=="vault_kv_secret_v2")'

# Lease hygiene: list and revoke dynamic-secret leases by prefix
vault list sys/leases/lookup/database/creds/app-role
vault lease revoke -prefix database/creds/app-role

# Confirm ephemeral support and provider version
terraform version
terraform providers

Patterns

Ephemeral KV v2 read feeding a write-only provider argument (no state persistence):

terraform {
  required_version = ">= 1.10.0"
  required_providers {
    vault = { source = "hashicorp/vault", version = ">= 4.3.0" }
  }
}

provider "vault" {
  address = "https://vault.example.com"
  auth_login {
    path = "auth/approle/login"
    parameters = {
      role_id   = var.vault_role_id
      secret_id = var.vault_secret_id
    }
  }
}

ephemeral "vault_kv_secret_v2" "db" {
  mount = "secret"
  name  = "app/database"
}

provider "postgresql" {
  host     = "db.internal"
  username = ephemeral.vault_kv_secret_v2.db.data["username"]
  password = ephemeral.vault_kv_secret_v2.db.data["password"]
}

Marking a required data-source read sensitive and never surfacing it in output:

data "vault_kv_secret_v2" "api" {
  mount = "secret"
  name  = "app/thirdparty"
}

locals {
  api_key = sensitive(data.vault_kv_secret_v2.api.data["api_key"])
}

# Do NOT output the raw secret; expose only a non-sensitive fingerprint
output "api_key_sha" {
  value     = sha256(local.api_key)
  sensitive = false
}

Related prompts

More Terraform prompts & error guides

Browse every Terraform prompt and troubleshooting guide in one place.

Free download · 368-page PDF

Reading prompts? Get all 500 in one free PDF

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.