Terraform Advanced — Security Exercises
Practice security hardening for Terraform.
Exercise 1 — Sensitive Variable
Task: Declare a variable for a database password that won’t appear in plan output.
Answer
variable "db_password" {
type = string
description = "Database master password"
sensitive = true
}
Pass it via environment variable:
export TF_VAR_db_password="my-secret-pass"
terraform apply
Exercise 2 — OPA Policy
Task: Write a Rego policy that denies EC2 instances without encrypted root volumes.
Answer
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
block := resource.change.after.root_block_device[_]
not block.encrypted
msg := sprintf("Instance '%s' must have encrypted root volume",
[resource.name])
}
Exercise 3 — Dynamic Secrets
Task: Write Terraform config to read a database password from AWS Secrets Manager instead of hardcoding it.
Answer
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "prod/database/password"
}
resource "aws_db_instance" "main" {
engine = "postgres"
username = "admin"
password = data.aws_secretsmanager_secret_version.db_password.secret_string
}
Chapter Summary
- Mark sensitive variables with
sensitive = true - Use Secrets Manager or Vault — never hardcode secrets
- Vault provides dynamic, short-lived credentials
- Sentinel (TF Cloud) or OPA/Conftest (open source) for policy enforcement
- Apply least-privilege IAM — use
iamliveto discover minimal permissions - Always encrypt state at rest and in transit