Mastering IAM with Terraform: Comparing Heredoc, jsonencode(), and aws_iam_policy_document


When managing AWS Identity and Access Management (IAM) policies with Terraform, choosing the proper method to define and render policy documents can significantly affect readability, maintainability, and validation. Three popular approaches are:

  • Heredoc syntax with inline JSON

  • jsonencode() function

  • aws_iam_policy_document data source

This post compares these methods, discusses their pros and cons, and provides practical examples to help you choose the most suitable option for your use case.


1. Heredoc Syntax with Inline JSON

 Use Case

Quick prototyping or when working with pre-existing IAM JSON files.

 Example


resource "aws_iam_policy" "inline_heredoc" {

  name        = "heredoc-example"

  description = "IAM Policy using heredoc"

  policy = <<EOF

{

  "Version": "2012-10-17",

  "Statement": [{

    "Effect": "Allow",

    "Action": "s3:ListBucket",

    "Resource": "arn:aws:s3:::example-bucket"

  }]

}

EOF

}


 Pros

  • Mirrors AWS IAM JSON directly

  • Fast to implement

  • Easy to copy/paste from existing policies

 Cons

  • No Terraform validation

  • High risk of syntax errors

  • Not DRY: no variable interpolation or reusability.


2. jsonencode() Function

 Use Case

When you need dynamic values and prefer working with Terraform-native structures.

 Example


resource "aws_iam_policy" "jsonencoded" {

  name        = "jsonencode-example"

  description = "IAM Policy using jsonencode"

  policy      = jsonencode({

    Version = "2012-10-17",

    Statement = [

      {

        Effect   = "Allow",

        Action   = ["s3:GetObject"],

        Resource = "arn:aws:s3:::example-bucket/*"

      }

    ]

  })

}


Pros

  • Validates the structure at the Terraform plan time

  • Supports interpolation and conditionals

  • Cleaner and more readable for developers

 Cons

  • Nested JSON can get verbose

  • Harder to align with IAM JSON documentation

  • Not as readable for non-developers


3. aws_iam_policy_document Data Source

Use Case

Best for complex policies, dynamic values, modular infrastructure, and DRY principles.

 Example


data "aws_iam_policy_document" "example" {

  statement {

    actions   = ["s3:PutObject"]

    resources = ["arn:aws:s3:::example-bucket/*"]

    effect    = "Allow"

  }

}


resource "aws_iam_policy" "structured" {

  name   = "structured-policy"

  policy = data.aws_iam_policy_document.example.json

}


 Pros

  • Highly modular and dynamic

  • Prevents invalid configurations

  • Easy to read and debug

  • Recommended for production environments

 Cons

  • Slightly more verbose

  • More learning curve for new Terraform users


Comparison Table.

Comparison of Terraform Methods for Defining IAM Policies

  1. Heredoc

    • Human Readable:  Yes

    • Terraform Validation:  No

    • Supports Interpolation:  No

    • Best for Dynamic Policies:  No

    • Recommended for Production:  No

  2. jsonencode()

    • Human Readable:  Moderate

    • Terraform Validation:  Yes

    • Supports Interpolation: Yes

    • Best for Dynamic Policies:  Yes

    • Recommended for Production:  Maybe

  3. aws_iam_policy_document

    • Human Readable:  Yes

    • Terraform Validation:  Yes

    • Supports Interpolation:  Yes

    • Best for Dynamic Policies:  Yes

    • Recommended for Production:  Yes


Conclusion: Choose What Fits Your Context

  • Use Heredoc if you're just pasting in JSON from AWS docs for a quick test.

  • Use jsonencode() if you're comfortable with HCL and want dynamic values.

  • Use aws_iam_policy_document when building production-grade, scalable IAM policies with reusability and validation.

You can manage IAM policies at any scale with Terraform by mastering these three approaches.


Comments

Popular posts from this blog

Podcast - How to Obfuscate Code and Protect Your Intellectual Property (IP) Across PHP, JavaScript, Node.js, React, Java, .NET, Android, and iOS Apps

YouTube Channel

Follow us on X