Terraform nested loops for creating principals in data json policy [aws]

I’m trying to create repositories with cross-account policies. With the repositories that need only one role per account it works fine with the following piece of code:

#X-Account Policy for the repositories
data "aws_iam_policy_document" "components_policy" {
  statement {
    sid    = "AllowPushPull"
    effect = "Allow"

    actions = [
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage",
      "ecr:CompleteLayerUpload",
      "ecr:GetDownloadUrlForLayer",
      "ecr:InitiateLayerUpload",
      "ecr:PutImage",
      "ecr:UploadLayerPart"
    ]

    principals {
      type = "AWS"
      identifiers = [
        for account_id in var.whitelisting :
          "arn:aws:iam::${account_id}:role/eks-node-role"
      ]
    }
  }
}

The problem arises when I try to whitelist 3 roles for account. I’ve tried the following but it doesn’t work:

#X-Account Policy for the repositories
data "aws_iam_policy_document" "components_policy" {
  statement {
    sid    = "AllowPushPull"
    effect = "Allow"

    actions = [
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage",
      "ecr:CompleteLayerUpload",
      "ecr:GetDownloadUrlForLayer",
      "ecr:InitiateLayerUpload",
      "ecr:PutImage",
      "ecr:UploadLayerPart"
    ]

    principals {
      type = "AWS"
      identifiers = [
        for account_id in var.whitelisting :
          <<EOF
                "arn:aws:iam::${account_id}:role/eks-node-role-1",
                "arn:aws:iam::${account_id}:role/eks-node-role-2",
                "arn:aws:iam::${account_id}:role/eks-node-role-3"
            EOF
      ]
    }
  }
}

Nested for loops are not possible so I’m currently looking at dynamic blocks but so far I’m unable to grasp whether I can get to do this through them. Any help would be appreciated, thank you.

>Solution :

The here-document feature you are using (the <<EOF to EOF) is going to generate a big string, not a list of array elements. That’s going to end up with an incorrect format for your values.

I haven’t tested this, but try the following:

identifiers = flatten([
        for account_id in var.whitelisting :
                ["arn:aws:iam::${account_id}:role/eks-node-role-1",
                "arn:aws:iam::${account_id}:role/eks-node-role-2",
                "arn:aws:iam::${account_id}:role/eks-node-role-3"]
             
      ])

The above will create a list of lists, and then use the Terraform flatten function to turn that into a single list of values appropriate for the IAM identifiers property.

Leave a Reply