エンジニアの皆さん、こんにちは。インフラの深淵を覗き込み、IaC(Infrastructure as Code)の美学を追求し続ける皆さんに、今日は「TerraformのIAMポリシー地獄」を終わらせるための極意を伝授します。
TerraformでAWSを構築する際、誰もが一度は遭遇する「JSON記述地獄」。あの息苦しいヒアドキュメントから解放され、堅牢で可読性の高いポリシーを構築する方法を、現場の視点から解説します。
—
1. なぜ「生のJSON文字列」を書いてはいけないのか
Terraformのコード内でヒアドキュメント(`< これらは、インフラエンジニアとしての「美意識」に反しますし、何より事故の温床です。 — Terraformには、ポリシーをJSONではなく「HCL(HashiCorp Configuration Language)」として記述するための強力なデータソース `aws_iam_policy_document` が用意されています。 これを使うと、ポリシーの各要素(Effect, Action, Resource)が独立した属性として扱われます。 aws_iam_policy_document を使った直感的な記述 構築時には json プロパティを参照するだけ ここが凄い: — 現場の複雑な要件では、「環境によって許可するIPを変えたい」「条件によってStatementを動的に追加したい」といったことが発生します。ここで `jsonencode` と `dynamic` ブロックを使いこなすと、コードの質が一段階引き上がります。 例えば、複数の条件をループで回してStatementを構築する例です: locals { data “aws_iam_policy_document” “dynamic_policy” { さらに、複雑な設定をJSONとして別途管理したい場合や、一部の値をコード内で計算したい場合は `jsonencode` を活用します。 JSON構造をコード内で安全に生成 `jsonencode` は、HCLのマップやリストを自動的に正しいJSON構文へ変換してくれます。これを使うと、JSONのカンマ忘れやクォーテーションのミスから永遠に解放されます。 — ポリシー変更時のDiff精度を上げるための最も重要なルールは、「Statementの最小化とSid(Statement ID)の付与」です。 1. Sidを必ず書く: TerraformのPlan結果で「どこが変更されたか」が一目で分かるようになります。 — これから始める方は、まずは既存のヒアドキュメントで書かれたポリシーを、`aws_iam_policy_document` に書き換えることから始めてみてください。 手順: この作業を繰り返すだけで、あなたのTerraformコードは驚くほど堅牢になり、インフラ構築のスピードが加速します。 「面倒な作業を、コードの力で優雅に解決する」。それが私たちSREの流儀です。ぜひ今日から取り入れてみてください。何か詰まったら、いつでもまた聞きに来てくださいね。一緒に最高のインフラを創り上げましょう。2. aws_iam_policy_document で「型安全」を手に入れる
data “aws_iam_policy_document” “s3_access” {
statement {
sid = “AllowS3Read”
effect = “Allow”
actions = [
“s3:GetObject”,
“s3:ListBucket”
]
resources = [“arn:aws:s3:::my-secure-bucket/”]
}
}
resource “aws_iam_policy” “policy” {
name = “my-s3-policy”
policy = data.aws_iam_policy_document.s3_access.json
}
記述がHCLになるため、IDEの補完が効きますし、文法エラーがあれば `terraform validate` で即座に弾いてくれます。3. 高度なテクニック:動的生成と jsonencode の融合
# 動的な設定値をマップで定義
allowed_buckets = [“bucket-a”, “bucket-b”]
}
dynamic “statement” {
for_each = local.allowed_buckets
content {
actions = [“s3:PutObject”]
resources = [“arn:aws:s3:::${statement.value}/”]
}
}
}
resource “aws_iam_policy” “complex_policy” {
name = “complex-policy”
policy = jsonencode({
Version = “2012-10-17”
Statement = [
{
Effect = “Allow”
Action = “sts:AssumeRole”
Resource = “”
Condition = {
StringEquals = { “aws:PrincipalOrgID” = var.org_id }
}
}
]
})
}4. リファクタリングの極意:Diffを小さく保つ
2. 大きなポリシーは分割する: 1つのポリシーに100行も書かない。`aws_iam_policy_document` の `source_policy_documents` 引数を使って、小さな部品(読み取り権限、書き込み権限など)を組み合わせる設計にしましょう。最後に:Hello Worldからのステップアップ
1. `terraform plan` を実行し、現状のJSONを確認する。
2. その構造を `data “aws_iam_policy_document”` に移し替える。
3. `terraform plan` を実行し、「差分が出ないこと」を確認する。(これが最強の動作確認です)