DEV Community

Cover image for Using 'dynamic' block to generate IAM policy statements in Terraform
Arpan
Arpan

Posted on • Edited on

7 1

Using 'dynamic' block to generate IAM policy statements in Terraform

Terraform has a cool resource block called the 'dynamic' block that allows generating multiple nested blocks for a resource.

This tutorial will show you how to generate multiple IAM policy statements using this dynamic block.

In this example we have a list of AWS Principals that we want to allow access to our bucket named dev-to-multi-account-bucket.

# variables.tf
variable "aws_accounts" {
  type        = map(list(string))
  description = "A map of lists of AWS Principals"
  default     = {
    "mgmt" = ["arn:aws:iam::123456789876:root"]
    "prod" = ["arn:aws:iam::098765432123:root"]
  }
}
Enter fullscreen mode Exit fullscreen mode
# bucket_policy.tf
resource "aws_s3_bucket_policy" "cross_account_policy" {
    bucket = "dev-to-multi-account-bucket"
    policy = data.aws_iam_policy_document.allow_access_from_another_account.json
}

# dynamic policy statement block for each account specified
data "aws_iam_policy_document" "allow_access_from_another_account" {
    dynamic "statement" {
        for_each = var.aws_accounts
        content {
            actions   = ["s3:*"]
            resources = [
                "arn:aws:s3:::dev-to-multi-account-bucket/${statement.key}*",
                ]
            principals {
                type = "AWS"
                identifiers = "${flatten(statement.value)}"
            } 
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Explaination

So what's really happening here? Let's look at the aws_iam_policy_document.allow_access_from_another_account "data" resource block.

We are leveraging the dynamic block within this resource to iterate through the aws_accounts variable. This generates multiple statements inside the policy allowing us to rely on the variable's length.

The variable statement has two important attributes: key and value. These allow you to target the respective section of the key-value map.

We can access these attributes through the statement variable. Terraform automatically assigns this variable name from the dynamic block's configuration. In this case, it's named statement.

After running terraform plan, we see a plan that looks something like this:

  # aws_s3_bucket_policy.cross_account_policy will be created
  + resource "aws_s3_bucket_policy" "cross_account_policy" {
      + bucket = "dev-to-multi-account-bucket"
      + id     = (known after apply)
      + policy = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "s3:*"
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::123456789876:root"
                        }
                      + Resource  = [
                          + "arn:aws:s3:::dev-to-multi-account-bucket/mgmt*",
                        ]
                      + Sid       = ""
                    },
                  + {
                      + Action    = "s3:*"
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::098765432123:root"
                        }
                      + Resource  = [
                          + "arn:aws:s3:::dev-to-multi-account-bucket/prod*",
                        ]
                      + Sid       = ""
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
    }
Enter fullscreen mode Exit fullscreen mode

Nice!

Find more about dynamic blocks in Terraform's official documentation page.

Heroku

Deliver your unique apps, your own way.

Heroku tackles the toil — patching and upgrading, 24/7 ops and security, build systems, failovers, and more. Stay focused on building great data-driven applications.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay