Ravindra BagaleCourses & study guides मराठी

Chapter 39: Terraform Provisioners Secrets and Sensitive Values

39.2 sensitive values — hide from logs, protect state

Story. A Netflix-style Jenkins log once printed a database password because a plan showed every attribute. Marking a variable or output sensitive = true makes Terraform show it as (sensitive value) in plan and apply output. It does not encrypt anything. The real value is still in state, so the encrypted, access-controlled S3 backend from Chapter 34 is what really protects it.

TF_VAR_ db_password variable sensitive plan shows (sensitive) state plain text S3 encrypted + IAM
sensitive hides values in output; state still holds them, so protect the backend.
variable "db_password" {
  type      = string
  sensitive = true
}

resource "aws_db_instance" "app" {
  identifier          = "badge-dev-db"
  engine              = "mysql"
  instance_class      = "db.t3.micro"
  allocated_storage   = 20
  username            = "badgeadmin"
  password            = var.db_password
  skip_final_snapshot = true
}

# supply it without writing it in a file
read -s TF_VAR_db_password && export TF_VAR_db_password
terraform plan

What each line does

  • sensitive = true — Redacts this variable wherever Terraform prints it.
  • password = var.db_password — Passes the secret to RDS; the plan shows it as sensitive.
  • skip_final_snapshot = true — Lets the lab database be destroyed without leaving a snapshot; never use in prod.
  • read -s TF_VAR_db_password && export TF_VAR_db_password — Reads the password without echoing it and exposes it to Terraform as the variable.
  • terraform plan — Plan picks up TF_VAR_db_password automatically.

When it is green.

      + password = (sensitive value)
      + username = "badgeadmin"
Plan: 1 to add, 0 to change, 0 to destroy.

When it is red.

$ git log -p | grep password
+db_password = "Summer2026!"

Fix. A tfvars file with a real password was committed. Rotate the password now, remove the file from Git history with your team's process, and add *.tfvars to .gitignore.

What: every term in plain English

  • sensitive = true — Hides a variable or output value in plan and apply output.
  • (sensitive value) — What Terraform prints in place of a hidden value.
  • nonsensitive() — A function that removes the sensitive mark. Use only on values you have proven are safe.
  • terraform output -raw — Prints one output value in clear text, for scripts.
  • TF_VAR_name — An environment variable that sets var.name without writing it in a file.
  • ephemeral — Newer Terraform feature for values that are never written to state or plan files.
  • write-only argument — An argument, such as password_wo, that is sent to AWS but never stored in state.

Example 1: Hide a variable in the plan

At a Bharti Airtel project, a Jenkins log printed a database password from a plan. sensitive = true would have hidden it.

  1. Declare a sensitive variable.
  2. Use it in a resource.
  3. Plan with the value from TF_VAR.
variable "db_password" {
  type      = string
  sensitive = true
}

resource "terraform_data" "demo" {
  input = var.db_password
}
export TF_VAR_db_password='S3cure-Lab-Only'
terraform plan | grep input

Output

+ input  = (sensitive value)

What it shows: The value is hidden on screen and in Jenkins logs. It still sits in state, so state must stay private.

Example 2: See that outputs need the mark too

Terraform refuses to print an output built from a sensitive value unless you mark that output sensitive. That error protects you.

  1. Add an output without the mark.
  2. Plan and read the error.
  3. Add sensitive = true.
output "db_password" {
  value     = var.db_password
  sensitive = true
}
terraform apply -auto-approve | tail -2
terraform output
terraform output -raw db_password; echo

Output

Outputs:
db_password = <sensitive>
db_password = <sensitive>
S3cure-Lab-Only

What it shows: Normal output hides it; -raw prints it for a script that really needs it. Never run -raw in a shared log.

Example 3: Find the secret in state anyway

sensitive is a screen feature, not encryption. Prove it so you protect state properly.

  1. Search the state for the value.
terraform state pull | grep -c 'S3cure-Lab-Only'

Output

1

What it shows: The value is in state. Protect state with an encrypted, private S3 backend and tight IAM access.

Example 4: Keep the secret out of state with a write-only argument

Newer AWS provider versions offer write-only arguments such as password_wo on aws_db_instance. The value goes to AWS and never into state.

  1. Use an ephemeral random password.
  2. Pass it to password_wo with a version number.
  3. Plan and search state after apply.
ephemeral "random_password" "db" {
  length  = 20
  special = false
}

resource "aws_db_instance" "app" {
  identifier          = "badge-lab-db"
  engine              = "postgres"
  instance_class      = "db.t4g.micro"
  allocated_storage   = 20
  username            = "app"
  password_wo         = ephemeral.random_password.db.result
  password_wo_version = 1
  skip_final_snapshot = true
}
terraform plan | grep -E "password_wo|Plan"

Output

      + password_wo         = (write-only attribute)
      + password_wo_version = 1
Plan: 1 to add, 0 to change, 0 to destroy.

What it shows: This needs Terraform 1.11 or newer and a recent AWS provider. Raise password_wo_version to rotate the password. The RDS instance costs money, so plan only unless you will destroy it soon.

Example 5: Pass the secret from Jenkins credentials, masked

At a Mphasis client, the pipeline took the database password from Jenkins credentials. Jenkins masks it in the console, and Terraform hides it in the plan. Two layers of protection.

  1. Store the password in Jenkins as a Secret text credential named db-password.
  2. Wrap the Terraform steps in withCredentials.
  3. Run the job and read the console.
stage('Plan') {
  steps {
    withCredentials([string(credentialsId: 'db-password', variable: 'TF_VAR_db_password')]) {
      sh 'terraform plan -input=false -no-color'
    }
  }
}

Output

[Pipeline] withCredentials
Masking supported pattern matches of $TF_VAR_db_password
[Pipeline] sh
+ terraform plan -input=false -no-color
      + input  = (sensitive value)
Plan: 1 to add, 0 to change, 0 to destroy.

What it shows: Even if a script echoed the value by mistake, Jenkins would print four stars in place of it.

Command cheat sheet

Command What it does When to use it
export TF_​VAR_​db_​password=... Sets a variable from the environment Keep secrets out of files
terraform output Shows outputs with sensitive ones hidden Normal use
terraform output -​raw NAME Prints one value in clear Scripts only
terraform output -​json JSON with sensitive values shown Careful, scripts only
terraform state pull | grep VALUE Checks if a value is in state Prove the risk
unset TF_​VAR_​db_​password Removes the variable After the session

Verify: did it work?

  1. Hidden in plan

    terraform plan | grep -c "sensitive value"
    

    Output

    1
    
  2. Output hidden

    terraform output db_password
    

    Output

    <sensitive>
    

When it is red 1

Error: Output refers to sensitive values

Cause. An output uses a sensitive value but is not marked sensitive.

Fix, step by step

  1. Add sensitive = true to the output.
  2. Or remove the output if no one needs it.

When it is red 2

Password visible in Jenkins console log

Cause. Someone ran terraform output -json or -raw in the pipeline.

Fix, step by step

  1. Remove that step.
  2. Rotate the password now.
  3. Use Jenkins credentials masking for any script that needs it.

When it is red 3

Error: Unsupported argument "password_wo"

Cause. Your AWS provider or Terraform version is too old.

Fix, step by step

  1. Run terraform version.
  2. Upgrade to Terraform 1.11 and a recent provider.
  3. Run init -upgrade.

Cleanup

terraform destroy -auto-approve
unset TF_VAR_db_password

Ravindra Bagale's Tip

Treat sensitive as curtains, not a lock. The lock is a private, encrypted state bucket.

Practice tasks

Easy Hide it

Why: Use sensitive.

What to do: Mark a variable and plan.

How:
  1. Use TF_VAR.

Check: (sensitive value).

Easy Output

Why: Fix the error.

What to do: Create an output and mark it sensitive.

How:
  1. Read the error first.

Check: Output hidden.

Medium Find in state

Why: See the risk.

What to do: grep state for the value.

How:
  1. Use state pull.

Check: Count 1.

Medium Write-only

Why: Keep it out of state.

What to do: Plan an RDS with password_wo.

How:
  1. Plan only.

Check: write-only attribute.

Easy Say it in two lines

Why: If you can say it simply, you understand it.

What to do: Write two short lines about this lesson for a fresher.

How:
  1. Write the problem it solves.
  2. Write the one command or file you use.
  3. Read it aloud.

Check: A fresher understands it without a question.

Easy Start a safe lab folder

Why: Practice needs a throwaway place.

What to do: Make a new folder with versions.tf and a random_pet resource, so no AWS cost.

How:
  1. mkdir tf-lab and cd into it.
  2. Add the hashicorp/random provider and one random_pet.
  3. Run terraform init and terraform apply.

Check: Apply complete! with 1 added.

Medium Break it on purpose

Why: You must know the red output by face.

What to do: Cause one error from the red part of this lesson and fix it.

How:
  1. Follow one red section.
  2. Copy the exact message to your notes.
  3. Write the fix in one line.

Check: You fixed it without searching the web.

Medium Run it twice

Why: A second run must be quiet.

What to do: Run the same plan two times with no edits.

How:
  1. Run terraform plan.
  2. Run it again.
  3. Explain any change it still shows.

Check: The second plan says No changes, or you can explain each line.

Medium Write a runbook page

Why: At 2 a.m. nobody remembers flags.

What to do: Write a one-page runbook for this lesson.

How:
  1. Title, when to use, exact commands, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Run it from a pipeline

Why: Real teams run Terraform from CI, not from laptops.

What to do: Run the main command of this lesson inside a GitHub Actions or Jenkins job.

How:
  1. Add a job with hashicorp/setup-terraform or a Terraform Docker image.
  2. Give it AWS access through an IAM role, never a key in the file.
  3. Run init, then the command from this lesson.

Check: The job log shows the same output you saw on your laptop.

Medium Check the cost

Why: Labs left running cost real money.

What to do: Find what this lesson would cost per day if you forgot to destroy it.

How:
  1. Open the AWS Pricing Calculator.
  2. Add each resource from your plan.
  3. Write the daily cost in your notes.

Check: You know the daily cost and you ran terraform destroy.

Hard Draw the flow top to bottom

Why: A drawing shows the order of work.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at your code, go through plan and state, end at AWS.
  2. Mark where each command reads or writes.

Check: Each box matches a real step you ran.

Hard Explain it like an interview

Why: Interviewers want real stories.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command, and one error you hit.

Check: Your answer has a real command and a real error message.

Homework: try at home

Try at home

List every place a secret could leak in a Terraform pipeline: code, tfvars, plan output, state, logs, and how to close each one.

Recap

  • sensitive hides values on screen and in logs.
  • Outputs built from secrets must be sensitive too.
  • State still stores sensitive values in clear text.
  • Write-only and ephemeral values stay out of state.
  • Use TF_VAR and never commit tfvars with secrets.

FAQ

Does sensitive encrypt anything?

No. It only hides values in output.

Is plan.out safe to share?

No. A saved plan file can contain secrets.

How do apps get the secret?

From Secrets Manager at runtime, as the next lesson shows.

Can I use nonsensitive on a password?

No. Use it only on values you have proven are not secret, such as a length.

Is TF_VAR safe in Jenkins?

Use withCredentials so Jenkins masks the value in logs.

Interview questions

  1. What does sensitive = true do?

    Hides the value in plan, apply and output, not in state.

  2. How do you keep a password out of state?

    Write-only arguments and ephemeral resources in newer Terraform.

  3. Why must outputs be marked sensitive?

    Terraform refuses to print a sensitive-derived output unmarked.

  4. How do you pass a secret without a file?

    TF_VAR environment variables from a secret store.

  5. Is a saved plan file safe?

    No, it can include sensitive values.

Quick quiz

Q1. Is a sensitive value in state?

Yes, unless write-only or ephemeral

Q2. Env var for var.db_password?

TF_VAR_db_password

Q3. Output flag that prints clear text?

-raw

Q4. Minimum Terraform for write-only?

1.11

Q5. Shown in plan for hidden values?

(sensitive value)

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards