1. 概要
bcrypt— パスワードのBcryptハッシュを生成rsadecrypt— RSA秘密鍵でデータを復号- セキュリティ上の注意点
Terraformの暗号関数は、初期パスワードのハッシュ化やEC2インスタンスの初期パスワード取得などの限定的な用途に使います。機密データの扱いには十分な注意が必要です。
2. bcrypt — Bcryptハッシュを生成
bcrypt(string, cost)は文字列のBcryptハッシュを返します。costはハッシュのコスト(デフォルト10)で、高いほど計算が重くなります。
# terraform consoleで確認
> bcrypt("my-password")
"$2a$10$..." # 実行のたびに異なるソルトが生成される
Grafanaの初期パスワードをBcryptで設定する
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "environment" {
description = "環境名"
type = string
default = "dev"
}
variable "grafana_admin_password" {
description = "Grafana管理者パスワード"
type = string
sensitive = true
}
locals {
# パスワードのBcryptハッシュを生成(Grafanaのenv変数に渡す形式)
grafana_password_hash = bcrypt(var.grafana_admin_password)
}
# ECSタスク定義のenv変数としてBcryptハッシュを渡す
resource "aws_ecs_task_definition" "grafana" {
family = "${var.environment}-grafana"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_execution.arn
container_definitions = jsonencode([{
name = "grafana"
image = "grafana/grafana:latest"
environment = [
{
name = "GF_SECURITY_ADMIN_PASSWORD__FILE"
value = "/dev/stdin"
},
{
# Bcryptハッシュ形式で渡す(平文パスワードを避ける)
name = "GF_SECURITY_ADMIN_PASSWORD"
value = local.grafana_password_hash
}
]
portMappings = [{
containerPort = 3000
protocol = "tcp"
}]
}])
tags = {
Name = "${var.environment}-grafana"
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_iam_role" "ecs_execution" {
name = "${var.environment}-ecs-execution"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "ecs-tasks.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
tags = {
Name = "${var.environment}-ecs-execution"
Environment = var.environment
ManagedBy = "terraform"
}
}
注意:
bcrypt()は実行のたびに異なるソルトが生成されるため、planのたびに差分が発生します。lifecycle { ignore_changes = [container_definitions] }で管理するか、外部でハッシュを生成して変数で渡す方法を検討してください。
3. rsadecrypt — RSA秘密鍵で復号
rsadecrypt(ciphertext, privatekey)はRSA秘密鍵でBase64エンコードされた暗号文を復号します。主にEC2 Windowsインスタンスの初期パスワード取得に使います。
data "aws_instance" "windows" {
instance_id = "i-1234567890abcdef0"
}
# Windowsインスタンスの初期パスワードを取得
data "aws_ec2_instance_password_data" "windows" {
instance_id = data.aws_instance.windows.id
}
locals {
# RSA秘密鍵で暗号化されたパスワードを復号
windows_password = rsadecrypt(
data.aws_ec2_instance_password_data.windows.encrypted_password,
file("${path.module}/ec2-key.pem")
)
}
output "windows_password" {
value = local.windows_password
sensitive = true # sensitiveで出力を隠す
}
4. セキュリティ上の注意点
bcrypt()やrsadecrypt()で扱う値はtfstateに平文で記録されます。
- tfstateの暗号化を有効にすること(S3バックエンドの場合はSSE)
- tfstateへのアクセス権限を最小限に制限すること
sensitive = trueをoutputやvariableに設定すること
5. 関連記事
- sensitive変数の使い方 — 機密値の安全な扱い方
- base64encode / md5 / sha256 / uuid — ハッシュ関数
- backend — stateファイルの保存場所 — stateの暗号化設定
6. まとめ
bcrypt(str, cost)— Bcryptハッシュを生成。Grafanaなどの初期パスワード設定に使うrsadecrypt(cipher, key)— RSA秘密鍵で復号。WindowsのEC2初期パスワード取得に使うbcrypt()は実行のたびに値が変わるためdriftが発生する。ignore_changesか外部ハッシュを検討- 暗号関数で扱う値はtfstateに記録されるためstateの暗号化が必須
動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/bcrypt