【入門編】TerraformでAWS IAMポリシーの「JSON記述地獄」から脱出する:jsonencode関数とaws_iam_policy_documentデータソースの使い分け – インフラ構成管理(IaC)活用バイブル

エンジニアの皆さん、こんにちは。インフラの深淵を覗き込み、IaC(Infrastructure as Code)の美学を追求し続ける皆さんに、今日は「TerraformのIAMポリシー地獄」を終わらせるための極意を伝授します。

TerraformでAWSを構築する際、誰もが一度は遭遇する「JSON記述地獄」。あの息苦しいヒアドキュメントから解放され、堅牢で可読性の高いポリシーを構築する方法を、現場の視点から解説します。

—

1. なぜ「生のJSON文字列」を書いてはいけないのか

Terraformのコード内でヒアドキュメント(`<

  • 静的解析が効かない: 構文ミスがあってもTerraformのPlanを実行するまで気づけません。
  • Diffがゴミになる: ポリシーの一部を変更した際、JSON全体が巨大なブロックとして扱われ、どこが変わったのか人間の目では追えなくなります。
  • DRY原則の崩壊: 共通のActionやResourceを再利用できず、コピペの山が生まれます。
  • これらは、インフラエンジニアとしての「美意識」に反しますし、何より事故の温床です。

    —

    2. aws_iam_policy_document で「型安全」を手に入れる

    Terraformには、ポリシーをJSONではなく「HCL(HashiCorp Configuration Language)」として記述するための強力なデータソース `aws_iam_policy_document` が用意されています。

    これを使うと、ポリシーの各要素(Effect, Action, Resource)が独立した属性として扱われます。

    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/”]
    }
    }

    構築時には json プロパティを参照するだけ
    resource “aws_iam_policy” “policy” {
    name = “my-s3-policy”
    policy = data.aws_iam_policy_document.s3_access.json
    }

    ここが凄い:
    記述がHCLになるため、IDEの補完が効きますし、文法エラーがあれば `terraform validate` で即座に弾いてくれます。

    —

    3. 高度なテクニック:動的生成と jsonencode の融合

    現場の複雑な要件では、「環境によって許可するIPを変えたい」「条件によってStatementを動的に追加したい」といったことが発生します。ここで `jsonencode` と `dynamic` ブロックを使いこなすと、コードの質が一段階引き上がります。

    例えば、複数の条件をループで回してStatementを構築する例です:

    locals {
    # 動的な設定値をマップで定義
    allowed_buckets = [“bucket-a”, “bucket-b”]
    }

    data “aws_iam_policy_document” “dynamic_policy” {
    dynamic “statement” {
    for_each = local.allowed_buckets
    content {
    actions = [“s3:PutObject”]
    resources = [“arn:aws:s3:::${statement.value}/”]
    }
    }
    }

    さらに、複雑な設定をJSONとして別途管理したい場合や、一部の値をコード内で計算したい場合は `jsonencode` を活用します。

    JSON構造をコード内で安全に生成
    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 }
    }
    }
    ]
    })
    }

    `jsonencode` は、HCLのマップやリストを自動的に正しいJSON構文へ変換してくれます。これを使うと、JSONのカンマ忘れやクォーテーションのミスから永遠に解放されます。

    —

    4. リファクタリングの極意:Diffを小さく保つ

    ポリシー変更時のDiff精度を上げるための最も重要なルールは、「Statementの最小化とSid(Statement ID)の付与」です。

    1. Sidを必ず書く: TerraformのPlan結果で「どこが変更されたか」が一目で分かるようになります。
    2. 大きなポリシーは分割する: 1つのポリシーに100行も書かない。`aws_iam_policy_document` の `source_policy_documents` 引数を使って、小さな部品(読み取り権限、書き込み権限など)を組み合わせる設計にしましょう。

    —

    最後に:Hello Worldからのステップアップ

    これから始める方は、まずは既存のヒアドキュメントで書かれたポリシーを、`aws_iam_policy_document` に書き換えることから始めてみてください。

    手順:
    1. `terraform plan` を実行し、現状のJSONを確認する。
    2. その構造を `data “aws_iam_policy_document”` に移し替える。
    3. `terraform plan` を実行し、「差分が出ないこと」を確認する。(これが最強の動作確認です)

    この作業を繰り返すだけで、あなたのTerraformコードは驚くほど堅牢になり、インフラ構築のスピードが加速します。

    「面倒な作業を、コードの力で優雅に解決する」。それが私たちSREの流儀です。ぜひ今日から取り入れてみてください。何か詰まったら、いつでもまた聞きに来てくださいね。一緒に最高のインフラを創り上げましょう。

    タイトルとURLをコピーしました