Terraform iterate over list

23,889

Given you have the list of account ids, have you tried this?

var "accounts" {
  default = ["123", "456", "789"]
  type = "list"
}

locals {
  accounts_arn = "${formatlist("arn:aws:iam::%s", var.accounts)}"
}

Then in your policy document:

principals {
  type = "AWS"
  identifiers = ["${local.accounts_arn}"]
}

I haven't actually tried it, but can't think of a reason it wouldn't work.

Share:
23,889
Rafael Marques
Author by

Rafael Marques

Updated on June 19, 2021

Comments

  • Rafael Marques
    Rafael Marques almost 3 years

    I would like to replace the 3 indepedent variables (dev_id, prod_id, stage_id), for a single list containing all the three variables, and iterate over them, applying them to the policy.

    Is this something terraform can do?

    data "aws_iam_policy_document" "iam_policy_document_dynamodb" {
      statement {
        effect    = "Allow"
        resources = ["arn:aws:dynamodb:${var.region}:${var.account_id}:table:${var.dynamodb_table_name}"]
    
        actions = [
          "dynamodb:GetItem",
          "dynamodb:PutItem",
          "dynamodb:DeleteItem",
        ]
    
        principals {
          type = "AWS"
    
          identifiers = [
            "arn:aws:iam::${var.dev_id}:root",
            "arn:aws:iam::${var.prod_id}:root",
            "arn:aws:iam::${var.stage_id}:root"
          ]
        }
      }
    }

    I looked into cycles and interpolation, but It seems that 99% of the time the interpolation is done with "count" which only works for the creation of multiple resources (I hope I am not saying a big lie).

    For example, I used

    principals {
       count = "${length(var.list)}"
       identifiers = ["arn:aws:iam::${var.list[count.index]}"]
    }
    

    but that was unsuccessful.

    Is there some way of achieving the final goal of replacing those 3 variables by a single list (or map) and iterate over them?

  • Rafael Marques
    Rafael Marques over 5 years
    This is a very elegant solution, I was not aware of it. It seams to work as expected, but unfortunately I could not verify it yet because I am getting an error with the policies. Instead of reading my environmental variable, upon setting the variables on the command line, it treats it as as a string: I do: terraform plan \ --var list_account_ids=["${DEV_ID}", "${PROD_ID}", "${STAGE_ID}"] and it treats $DEV_ID as the string "$DEV_ID"...
  • Rafael Marques
    Rafael Marques over 5 years
    after correcting the other problems, I managed to run terraform apply with your suggestion (btw, according to the bugs i got its "local" and not "locals"), but now I get a Malformed policy error "aws_s3_bucket.s3_bucket: Error putting S3 policy: MalformedPolicy: Policy has invalid resource".
  • Rafael Marques
    Rafael Marques over 5 years
    typical syntax error. Your answer was great, I will accept it, thank you! @Magd Kudama
  • rahuljain1311
    rahuljain1311 almost 5 years
    This is the coolest thing I have ever done in TF. Thanks @Magd I tried and it worked like charm :)