Terraform Sensitive Variables | Brainboard Blog

Terraform Sensitive Variables

Chafik Belhaoues September 16, 2025
Expert reviewed
Terraform Sensitive Variables
Terraform Sensitive VariablesMaster the art of handling sensitive data in Terraform with best practices for secure infrastructure managementDevOpsChafik Belhaoues2025-09-16T00:00:00.000Z12 minutesintermediateguidedevelopers, DevOps engineers, cloud architects
12 min read
Level: intermediate
Type: guide

Terraform sensitive variables: your shield against data exposure

Have you ever accidentally committed your database password to GitHub? If you just felt a chill run down your spine, you’re not alone. We’ve all been there, frantically trying to rotate credentials after realizing our mistake. That’s where Terraform sensitive variables come to the rescue, acting like a security guard for your infrastructure secrets.

What are sensitive variables in Terraform?

Think of sensitive variables as Terraform’s way of putting a blindfold on certain pieces of information. When you mark a variable as sensitive, you’re essentially telling Terraform, “Hey, this is top-secret stuff – handle with care!” These variables contain confidential data like passwords, API keys, connection strings, or any information you wouldn’t want displayed in logs or terminal outputs.

Regular variables in Terraform are like open books – anyone with access to your state files or console output can read them. But sensitive variables? They’re more like those diary entries you wrote with invisible ink as a kid. They exist, they work, but Terraform makes sure they stay hidden from prying eyes.

Why sensitivity matters in infrastructure as code

Let me paint you a picture. You’re working on a team project, and your Terraform configuration manages a production database. Without sensitive variables, every time someone runs terraform plan or terraform apply, your database password might appear in the console output. Now imagine that output gets copied to a CI/CD log, shared in a Slack channel for debugging, or worse – screenshot and posted on Stack Overflow when asking for help.

Security breaches often happen not through sophisticated hacking attempts but through simple oversights. A leaked API key here, an exposed database password there – these small mistakes can snowball into massive security incidents. By using sensitive variables, you’re adding an essential layer of protection to your infrastructure code.

How to declare sensitive variables in Terraform

Creating a sensitive variable is surprisingly straightforward. You simply add the sensitive = true argument to your variable declaration. Here’s how it looks in practice:

variable "database_password" {
  description = "The password for the RDS instance"
  type        = string
  sensitive   = true
}

variable "api_secret_key" {
  description = "Secret key for external API authentication"
  type        = string
  sensitive   = true
  default     = "" # Not recommended for sensitive data
}

You can also mark outputs as sensitive when you need to pass secret values between modules:

output "connection_string" {
  value     = "postgresql://${var.username}:${var.database_password}@${aws_db_instance.main.endpoint}/mydb"
  sensitive = true
}

Best practices for managing sensitive data

Use environment variables or secret management tools

Never, and I mean never, hardcode sensitive values directly in your Terraform files. Instead, use environment variables:

export TF_VAR_database_password="super-secret-password"
terraform apply

Or better yet, integrate with secret management tools like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. These tools are like having a professional bodyguard for your secrets.

Leverage terraform.tfvars files (with caution)

If you must use .tfvars files for sensitive data, ensure they’re never committed to version control. Add them to your .gitignore file immediately:

*.tfvars
!example.tfvars

Implement proper state file security

Remember that sensitive values still end up in your state file in plain text. It’s like locking your front door but leaving the window open. Always encrypt your state files at rest and use remote backends with proper access controls:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-lock"
  }
}

Common pitfalls and how to avoid them

The string interpolation trap

Here’s something that might surprise you: when you use sensitive variables in string interpolation, the entire result becomes sensitive. It’s like adding a drop of food coloring to water – the whole thing changes:

locals {
  # This entire string becomes sensitive
  connection_url = "mysql://${var.username}:${var.sensitive_password}@localhost/mydb"
}

Debugging challenges

Sensitive variables can make debugging trickier since Terraform replaces their values with (sensitive) in outputs. It’s like trying to solve a puzzle with some pieces hidden. When debugging, you might need to temporarily remove the sensitive flag, but remember to add it back before committing your code.

Module boundaries

When passing sensitive variables between modules, both the parent and child module need to handle them properly. Think of it as a relay race where each runner must protect the baton:

module "database" {
  source   = "./modules/database"
  password = var.db_password # Parent variable should also be sensitive
}

Advanced techniques for sensitive data handling

Dynamic secret generation

Why store passwords when you can generate them on the fly? Use Terraform’s random_password resource for automatic password generation:

resource "random_password" "db_password" {
  length  = 32
  special = true
}

resource "aws_db_instance" "database" {
  password = random_password.db_password.result
}

Conditional sensitivity

Sometimes you want variables to be sensitive only in certain environments. While Terraform doesn’t support conditional sensitivity directly, you can work around this with creative module design:

variable "environment" {
  type = string
}

variable "password_prod" {
  type      = string
  sensitive = true
}

variable "password_dev" {
  type      = string
  sensitive = false
}

locals {
  actual_password = var.environment == "production" ? var.password_prod : var.password_dev
}

Testing and validation strategies

Testing configurations with sensitive variables requires extra care. You can’t just echo values to verify them anymore. Instead, consider these approaches:

Create smoke tests that verify connectivity without exposing credentials. Use Terraform’s validation blocks to ensure sensitive variables meet your security requirements:

variable "api_key" {
  type      = string
  sensitive = true
  
  validation {
    condition     = length(var.api_key) >= 32
    error_message = "API key must be at least 32 characters long."
  }
}

Integration with CI/CD pipelines

Integrating sensitive variables into your CI/CD pipeline is like teaching your robot assistant to keep secrets. Most CI/CD platforms offer secret management features. For GitHub Actions, you’d use repository secrets:

- name: Terraform Apply
  env:
    TF_VAR_database_password: ${{ secrets.DATABASE_PASSWORD }}
  run: terraform apply -auto-approve

For Jenkins, GitLab CI, or Azure DevOps, similar patterns apply. The key is ensuring secrets never appear in logs or build artifacts.

Conclusion

Handling sensitive variables in Terraform isn’t just about adding sensitive = true to your variable declarations. It’s about building a comprehensive security strategy that protects your infrastructure secrets at every stage of the deployment process. From proper declaration and storage to secure transmission and state management, each step matters.

Remember, security isn’t a destination; it’s a journey. Start by marking your sensitive variables today, implement proper secret management tomorrow, and continuously improve your security posture. Your future self (and your security team) will thank you when you avoid that dreaded security incident.

FAQs

Can I convert an existing variable to sensitive without recreating resources?

Yes, adding sensitive = true to an existing variable won’t trigger resource recreation. It only affects how Terraform displays the value in outputs and logs. However, remember that historical logs might still contain the exposed values from before the change.

Do sensitive variables encrypt data in the state file?

No, sensitive variables don’t encrypt data in the state file. They only prevent values from being displayed in console output and logs. You must implement state file encryption separately using your backend provider’s encryption features.

What happens if I accidentally remove the sensitive flag from a variable?

If you remove the sensitive flag, Terraform will start displaying the value in outputs and logs again. Previous logs won’t retroactively expose the value, but new operations will. Always review your changes carefully before applying them.

Can I use sensitive variables with data sources?

While you can’t mark data source attributes as sensitive directly, you can assign them to sensitive variables or outputs. If a data source retrieves sensitive information, immediately assign it to a sensitive variable for proper handling.

How do I debug issues when sensitive variables hide important information?

For debugging, you can temporarily use Terraform’s debug logging (TF_LOG=DEBUG) which might reveal more information, though sensitive values remain hidden. Alternatively, use targeted outputs with non-sensitive parts of your configuration or implement proper application-level logging that safely records diagnostic information without exposing secrets.

Chafik Belhaoues

Cloud Architect and Former SRE
LinkedIn

Chafik has more than 20 years of experience in the IT industry, including 12 years as a Senior Site Reliability Engineer (SRE) and 8 years as a Cloud Architect. He is the founder of Brainboard, focusing on cloud infrastructure and DevOps automation.

Back to Blog