Using for_each with resources that haven't been created yet

Hi,

We are using for_each to create multiple IAM policies/roles. We want to attach these policies to the roles.

As the policies haven’t been created yet we don’t know the ARN. How can we attach multiple policies to the roles in the terraform that doesn’t involve us creating the policies first, updating the terraform then running it again?

Is it possible to use the output of iam_policy in aws_iam_role_policy_attachment?

I realise: policy_arn = each.aws_iam_policy.iam_policy.arn will not work as the arn is not set in the variable

Code below for an example:

resource "aws_iam_policy" "iam_policy" {
  for_each      = var.vars
  name          = each.value.iam_policy_name
  description   = each.value.iam_policy_description
  policy = jsonencode({
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "s3:Get*",
                      "s3:List*"
                    ],
                  "Resource": [
                      "*"
                    ]
              }
          ]
      })
  depends_on = [aws_s3_bucket.s3_bucket]
}

resource "aws_iam_role_policy_attachment" "iam_attachment" {
  for_each    = var.vars
  role             = each.value.iam_role
  policy_arn  = each.aws_iam_policy.iam_policy.arn
}

Hi @vanwoes,

If I’m understanding your goal correctly, it seems like what you are looking for is Chaining for_each between resources.

In your case, that pattern would work like this:

resource "aws_iam_role_policy_attachment" "iam_attachment" {
  for_each = aws_iam_policy.iam_policy

  role        = var.vars[each.key].iam_role
  policy_arn  = each.value.arn
}

It would also be valid to write this a different way without using the chaining pattern:

resource "aws_iam_role_policy_attachment" "iam_attachment" {
  for_each = var.vars

  role        = each.value.iam_role
  policy_arn  = aws_iam_policy.iam_policy[each.key].arn
}

These two have the same general effect, but the first one gives Terraform slightly more information about your intent to have the aws_iam_role_policy_attachment.iam_attachment instances always match the aws_iam_policy.iam_policy instances, and so in less common situations, like using terraform apply -target=... to work around a problem by making a partial plan, Terraform is less likely to run into confusing errors if the two resources get out of sync with one another.

If you just use Terraform in the standard way with argument-less terraform plan/terraform apply then the distinction between these two approaches is unimportant, though.