Skip to main content

Sensitive Outputs

ทำให้ output ไม่แสดงค่าใน plan/apply log — เหมาะกับ password, API key, credentials

Sensitive Output Block

output "db_password" {
value = random_password.db.result
sensitive = true
}

หลัง apply:

Outputs:

db_password = <sensitive>

ทำไมต้อง Sensitive?

❌ ไม่ระบุ sensitive

$ terraform apply
...
Outputs:
db_password = "myS3cr3tP@ss" # ← เห็นใน log!

ปัญหา:

  • Log ใน CI/CD เห็นได้
  • Terminal history เห็นได้
  • คนอื่นมองข้ามไหล่เห็นได้

✅ ระบุ sensitive

$ terraform apply
...
Outputs:
db_password = <sensitive>

เข้าถึงค่า Sensitive

ค่ายังอยู่ใน state — เรียกผ่าน CLI ได้:

# ดูค่า
terraform output db_password

# Raw value
terraform output -raw db_password

# JSON output (ทุก output รวมถึง sensitive)
terraform output -json

Sensitive Propagation

ถ้าใช้ค่า sensitive ในที่อื่น — Terraform จะ propagate ความ sensitive:

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

resource "random_string" "suffix" {
length = 8
}

# ค่านี้จะ sensitive อัตโนมัติ เพราะใช้ var.db_password
locals {
db_url = "postgres://admin:${var.db_password}@db.example.com/mydb"
}

output "db_url" {
value = local.db_url
sensitive = true # ต้องระบุ — ไม่งั้น Terraform error!
}

ถ้าลืมระบุ sensitive = true:

Error: Output refers to sensitive values

Functions ที่ลบ Sensitive

ถ้าต้องการ "แค่บางส่วน" ของค่า sensitive (เช่น แสดงแค่ 4 ตัวท้ายของ API key):

output "api_key_last4" {
value = "...${substr(var.api_key, -4, -1)}"
sensitive = false # ปลอดภัย เพราะแค่ 4 ตัวท้าย
}

แต่ Terraform จะ error เพราะ var.api_key sensitive

→ ใช้ nonsensitive() function:

output "api_key_last4" {
value = "...${substr(nonsensitive(var.api_key), -4, -1)}"
sensitive = false
}
ใช้ nonsensitive() ด้วยความระวัง

nonsensitive() = เอา sensitive marker ออก → log เห็นค่าได้

ใช้เฉพาะตอนที่ค่าที่ output ไม่ leak secret จริงๆ

Sensitive ≠ Encrypted

Sensitive แค่ "ซ่อนจาก log"
  • ❌ ค่ายังเก็บ plain text ใน state file
  • ❌ ใครเข้าถึง state file ได้ก็เห็นค่า
  • ✅ Sensitive แค่ป้องกัน leak จาก output/log

ถ้าต้องการความปลอดภัยจริง:

  1. Encrypted backend — S3 + KMS encryption
  2. External secret manager — AWS Secrets Manager / Vault
  3. State permissions — IAM ที่จำกัดคนเข้าถึง
# ใช้ AWS Secrets Manager แทนเก็บใน state
data "aws_secretsmanager_secret_version" "db" {
secret_id = "prod/db-password"
}

resource "aws_db_instance" "main" {
password = data.aws_secretsmanager_secret_version.db.secret_string
}

# อย่า output password — ให้ user ไปหาเองที่ Secrets Manager
output "db_secret_arn" {
value = data.aws_secretsmanager_secret_version.db.arn
}

Pattern: Generated Password

# Generate random password
resource "random_password" "db" {
length = 32
special = true
}

# Store in Secrets Manager
resource "aws_secretsmanager_secret" "db_password" {
name = "prod/db-password"
}

resource "aws_secretsmanager_secret_version" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
secret_string = random_password.db.result
}

# Use in RDS
resource "aws_db_instance" "main" {
password = random_password.db.result
}

# Don't output the password — just the ARN
output "db_secret_arn" {
value = aws_secretsmanager_secret.db_password.arn
description = "Fetch password using: aws secretsmanager get-secret-value --secret-id $(terraform output -raw db_secret_arn)"
}

Sensitive Variable + Output

# Input
variable "api_key" {
type = string
sensitive = true
}

# Pass to resource (state stores it)
resource "aws_lambda_function" "api" {
function_name = "api"
environment {
variables = {
API_KEY = var.api_key
}
}
}

# Output reference, not value
output "lambda_arn" {
value = aws_lambda_function.api.arn
}

# ❌ DON'T output the secret
# output "api_key" { value = var.api_key }

ดู Sensitive ใน State (ระวัง)

# ดู state ทั้งหมด (รวม sensitive!)
terraform show

# Pull state ลง local
terraform state pull > state.json

# State file มีค่าจริง — เก็บอย่างระวัง

Best Practices

✅ DO:
- ใช้ sensitive = true กับทุก secret
- ใช้ external secret manager เก็บ secret จริงๆ
- Output แค่ ARN/reference ของ secret ไม่ใช่ค่า
- Encrypt remote backend (S3 + KMS)

❌ DON'T:
- ห้ามใช้ nonsensitive() แบบไม่จำเป็น
- ห้าม output password ใน plain text
- ห้ามคิดว่า sensitive = encrypted (ไม่ใช่)
- ห้าม commit state file

สรุป

  • sensitive = true ซ่อนค่าจาก output/log
  • Sensitive propagate อัตโนมัติเมื่อใช้ในที่อื่น
  • ใช้ nonsensitive() ลบ marker (ระวัง)
  • Sensitive ไม่ใช่ encryption — state ยังเก็บ plain text
  • Production แนะนำใช้ external secret manager (Secrets Manager / Vault)

ต่อไป → Preconditions