-1

I'm working on adding a IAM policy, but my terraform code fails with the below error because some attributes are determined only after an apply, I don't want to run multiple apply commands, How can I fix this? Does converting default_policies to map(object(list)) fix this issue?

Code:

locals {
  default_policies = toset([
    "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess",
    "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
    "arn:aws:iam::aws:policy/AmazonS3FullAccess",
    "arn:aws:iam::aws:policy/AmazonEC2FullAccess",
    "${aws_iam_policy.assume_prod_policy.arn}"
  ])
}

data "aws_iam_policy_document" "assume_prod_policy_document" {
  statement {
    actions   = ["sts:AssumeRole"]
    effect    = "Allow"
    resources = ["arn:aws:iam::${local.account_id}:role/${var.prod_role}"]
  }
}

resource "aws_iam_policy" "assume_prod_policy" {
  name   = "amp_assume_ecr_prod_policy"
  policy = data.aws_iam_policy_document.assume_prod_policy_document.json

}

# Attach policy
resource "aws_iam_role_policy_attachment" "ga_policy_data" {
  for_each   = local.default_policies
  policy_arn = each.value
  role       = aws_iam_role.xxx.name
}

Error:

 Error: Invalid for_each argument
│
│   on main.tf line 74, in resource "aws_iam_role_policy_attachment" "ga_policy_data":
│   74:   for_each   = local.default_policies
│     ├────────────────
│     │ local.default_policies is set of string with 5 elements
│
│ The "for_each" set includes values derived from resource attributes that cannot be
│ determined until apply, and so Terraform cannot determine the full set of keys that
│ will identify the instances of this resource.
│
│ When working with unknown values in for_each, it's better to use a map value where
│ the keys are defined statically in your configuration and where only the values
│ contain apply-time results.
│
│ Alternatively, you could use the -target planning option to first apply only the
│ resources that the for_each value depends on, and then apply a second time to fully
│ converge.

1 Answer 1

3

If you refactor your local variable to a map(string) with keys that will be known prior to apply and values that you actually use in the resource then it should function as expected with no other necessary modifications:

locals {
  default_policies = {
    "EC2ContainerRegistryFullAccess" = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess",
    "EKSWorkerNodePolicy"            = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
    "S3FullAccess"                   = "arn:aws:iam::aws:policy/AmazonS3FullAccess",
    "EC2FullAccess"                  = "arn:aws:iam::aws:policy/AmazonEC2FullAccess",
    "Prod"                           = aws_iam_policy.assume_prod_policy.arn
  }
}

There are alternative solutions here, but they would all require more refactoring than the above solution.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.