hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.71k stars 9.07k forks source link

Changing for_each size causes diff with all aws_iam_policy, even unchanged policies #18877

Open sblask opened 3 years ago

sblask commented 3 years ago

Community Note

Terraform CLI and Terraform AWS Provider Version

Terraform 15.0 and AWS 3.36

Affected Resource(s)

Terraform Configuration Files

terraform {}

provider "aws" {
  assume_role {
    role_arn = "arn:aws:iam::XXXXXXXXXXXXXX:role/terraform-admin"
  }
}

locals {
  users = toset([
    "foo",
    "bar",
    "baz",
  ])
}

data "aws_iam_policy_document" "assume_test" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::YYYYYYYYYYYYYYY:root"]
    }
  }
}

resource "aws_iam_role" "instance" {
  for_each = local.users

  assume_role_policy = data.aws_iam_policy_document.assume_test.json
  name               = "sebastian-instance-${each.key}"
}

data "aws_iam_policy_document" "test" {
  for_each = local.users

  statement {
    sid       = "SetRole"
    actions   = ["iam:PassRole"]
    resources = [aws_iam_role.instance[each.key].arn]
  }
}

resource "aws_iam_policy" "test" {
  for_each = local.users

  name   = "sebastian-test=${each.key}"
  policy = data.aws_iam_policy_document.test[each.key].json
}

resource "aws_iam_role" "test" {
  for_each = local.users

  assume_role_policy = data.aws_iam_policy_document.assume_test.json
  name               = "sebastian-test-${each.key}"
}

resource "aws_iam_role_policy_attachment" "test" {
  for_each = local.users

  role       = aws_iam_role.test[each.key].name
  policy_arn = aws_iam_policy.test[each.key].arn
}

Debug Output

https://gist.github.com/sblask/6e24b1b5489f39fc96b181f98282804b

Expected Behavior

When local.users is modified only added/removed user resources should appear in the plan

Actual Behavior

For each user in local.users a aws_iam_policy_document is shown with will be read during apply and a aws_iam_policy with will be updated in-place even though there are no changes to policy.

Steps to Reproduce

Start with

users = toset([
    "foo",
    "bar",
  ])

and run terraform apply

Add "baz" to the list and run terraform plan

YakDriver commented 3 years ago

@sblask This is an interesting diff situation. I agree with you that there should be no update in place if there are no changes. In other words, with we would hope that using foreach would be equivalent to duplicating the configuration for each of the users, which would not cause a diff with the existing users. Off the bat, nothing jumps out why this would happen.

Hopefully we'll have a chance to dig into this before too long. I'll update the title a little so if others are having the issue we can hopefully figure out what's going on.

YakDriver commented 3 years ago

Related #14447 Related #18035

albertorm95 commented 2 years ago

My solution was to stop using the datasource and just generate the json inside the aws_aim_policy, this also might work with a local so you can reuse it

kamatvishal commented 1 year ago

My solution was to stop using the datasource and just generate the json inside the aws_aim_policy, this also might work with a local so you can reuse it

@albertorm95 Can you please post the code that worked for you?

Is there any update on this issue? I am facing the same