terraform-provider-aws icon indicating copy to clipboard operation
terraform-provider-aws copied to clipboard

Reason for deprecating aws_iam_role.managed_policy_arns

Open sylr opened this issue 1 year ago • 6 comments

Description

Hi,

As a pretty extensive user of AWS IAM roles, deprecating aws_iam_role.managed_policy_arns in favor of a new aws_iam_role_policy_attachments_exclusive resource is going to have a non negligible and unwanted impact on my Terraform Cloud bill.

I'd like an explanation for this change.

Regards.

References

No response

Would you like to implement a fix?

None

sylr avatar Oct 17 '24 13:10 sylr

Community Note

Voting for Prioritization

  • Please vote on this issue by adding a 👍 reaction to the original post to help the community and maintainers prioritize this request.
  • Please see our prioritization guide for information on how we prioritize.
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request.

Volunteering to Work on This Issue

  • If you are interested in working on this issue, please leave a comment.
  • If this would be your first contribution, please review the contribution guide.

github-actions[bot] avatar Oct 17 '24 13:10 github-actions[bot]

#22336

alexbacchin avatar Oct 18 '24 06:10 alexbacchin

#22336

I don't see how this relates. aws_iam_role.managed_policy_arns vs aws_iam_role_policy_attachments_exclusive should just be an implementation detail, I see no need to force all of the consumers to invest heavily in changing their IaC.

IgorMilavec avatar Oct 18 '24 07:10 IgorMilavec

Not sure what you mean by the Terraform Cloud bill, but this change is very annoying and the reasoning behind it doesn't seem clear to me either 😞

mimozell avatar Oct 18 '24 13:10 mimozell

Seems like it is related to: https://github.com/hashicorp/terraform-provider-aws/pull/39718, https://github.com/hashicorp/terraform-provider-aws/issues/39376, https://github.com/hashicorp/terraform-provider-aws/pull/39204

And the easiest to read is here: https://github.com/hashicorp/terraform-provider-aws/blob/main/docs/design-decisions/exclusive-relationship-management-resources.md

mimozell avatar Oct 18 '24 13:10 mimozell

Not sure what you mean by the Terraform Cloud bill

Terraform Cloud bills you per number of resources managed.

Moving relations from attributes to dedicated resources increases your bill.

sylr avatar Oct 18 '24 14:10 sylr

Hey @sylr - thanks for your question. The short answer is to reduce the scope of responsibility for the aws_iam_role resource.

Arguments like managed_policy_arns or inline_policy force a single resource to manage the lifecycle of other related resources. This can lead to partially successful apply operations, which introduces with another set of failure modes to handle. In general this is a pattern we're attempting to move away from, as documented in the proposal for exclusive relationship management resources linked above.

We understand that migrating arguments on such a foundational resource will require a non-trivial amount of effort, which is why we don't have imminent plans to remove the argument. A relevant section from the proposal:

Due to the popularity of the resources in this section, argument deprecations are likely to be "soft" deprecations where removal will not happen for several major releases, or until tooling is available to limit the amount of manual changes required to migrate to the preferred pattern. Despite this long removal window, a soft deprecation is still helpful for maintainers to reference when making best practice recommendations to the community.

We have no plans to remove this argument in the next major version, so you can continue using the existing argument without any changes to your TFC resource count. Hopefully this helps to describe our thinking with this change!

jar-b avatar Oct 21 '24 16:10 jar-b

Thank you @jar-b for your comment. I understand the reasoning/principles behind this.

Since this attribute is "deprecated", it will be slated for removal some time in the future even if it's not the next major release so the concern regarding a multiplicative effect on our RUM will still exist.

As a result of RUM, we are already trying to migrate away from using resources like aws_iam_role_policy_attachment where possible and this is yet another roadblock in our attempt to reduce our RUM.

I am aware that this is not directly related to the provider itself, but it's a big concern on our end as customers of HCP Terraform.

lawliet89 avatar Jan 08 '25 08:01 lawliet89

Moving my issue here, as it was marked duplicated

This deprecation is also causing an issue for us, without suitable alternative:

The problem

Removing the managed_policy_arns from aws_iam_role will result in having to explicitly configure dependencies in terraform, rather than relying on implicit dependencies.

Whilst aws_iam_role_policy_attachments_exclusive can help to keep resources in declarative state (eg someone manually added a new permission manually, it'll be cleaned up), it can't help terraform to apply changes in the correct order.

Example

I have a lambda, and I want to update the code and permissions to read from Dynamo.

Right now: I can just add the IAM policy in the managed_policy_arns section of the IAM role, and be sure that the IAM role will be updated first, then the Lambda code that references the IAM role.

With the proposed deprecation: I'll have to create a new aws_iam_role_policy_attachment, then add a depends_on to my Lambda, referencing the new aws_iam_role_policy_attachment. Without the depends_on block, there might be a case where my Lambda is updated first, and the permission is updated only after, leading to temporary downtime due to insufficient permissions.

AnitaErnszt avatar Jan 13 '25 18:01 AnitaErnszt

Is there a guide on how to perform such a migration? Does it have to be "terraform state rm" followed by "import"? It feels quite cumbersome and insecure.

ei-grad avatar Jan 24 '25 10:01 ei-grad

Is there a guide on how to perform such a migration? Does it have to be "terraform state rm" followed by "import"? It feels quite cumbersome and insecure.

Migration can be done in a single apply with no changes to the attachments. A similar migration has been documented for inline policies in this comment, but I'll cover managed policy attachments below.


To migrate an existing list of managed policy attachments to the standalone resource, an import block (or alternatively a manual import via the Terraform CLI) is required.

Because the managed_policy_arns argument is Optional and Computed (meaning removal of this argument will not trigger deletion of policy attachments, just change it to track as computed only), this step can be accomplished in a single apply.

Here's a small example. The configuration is hidden by default to improve readability:

Show/Hide Configuration

The uncommented configuration below represents the existing state where managed policy attachments are defined directly on the aws_iam_role resource.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {}

data "aws_iam_policy_document" "trust" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

data "aws_iam_policy_document" "test" {
  statement {
    actions = ["s3:ListBucket"]
    resources = [
      "arn:aws:s3:::some-bucket-a",
      "arn:aws:s3:::some-bucket-b",
    ]
  }
}

resource "aws_iam_policy" "test" {
  policy = data.aws_iam_policy_document.test.json
}

resource "aws_iam_role" "test" {
  name               = "jb-test-managed-policy-arns-migration"
  assume_role_policy = data.aws_iam_policy_document.trust.json

  # Remove this when the new standalone resource is added
  managed_policy_arns = [aws_iam_policy.test.arn]
}

### Start of new resources ###
# This can be removed after the apply in which the resource is imported
# import {
#   to = aws_iam_role_policy_attachment.test
#   id = "jb-test-managed-policy-arns-migration/${aws_iam_policy.test.arn}"
# }
#
# resource "aws_iam_role_policy_attachment" "test" {
#   role       = aws_iam_role.test.name
#   policy_arn = aws_iam_policy.test.arn
# }
#
# resource "aws_iam_role_policy_attachments_exclusive" "test" {
#   role_name = aws_iam_role.test.name
#   policy_arns = [
#     aws_iam_role_policy_attachment.test.policy_arn,
#   ]
# }
### End of new resources ###

To covert this to use the standalone aws_iam_role_policy_attachment resource, do the following:

  1. Remove the managed_policy_arns argument.
  2. Uncomment the ### Start of new resources ### section.
  3. terraform apply. There should be 1 resource to import and 1 to add.
% terraform apply -auto-approve
data.aws_iam_policy_document.test: Reading...
data.aws_iam_policy_document.trust: Reading...
data.aws_iam_policy_document.test: Read complete after 0s [id=748695472]
data.aws_iam_policy_document.trust: Read complete after 0s [id=2851119427]
aws_iam_policy.test: Refreshing state... [id=arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role.test: Refreshing state... [id=jb-test-managed-policy-arns-migration]
aws_iam_role_policy_attachment.test: Preparing import... [id=jb-test-managed-policy-arns-migration/arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role_policy_attachment.test: Refreshing state... [id=jb-test-managed-policy-arns-migration-arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_iam_role_policy_attachment.test will be imported
    resource "aws_iam_role_policy_attachment" "test" {
        id         = "jb-test-managed-policy-arns-migration-arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001"
        policy_arn = "arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001"
        role       = "jb-test-managed-policy-arns-migration"
    }

  # aws_iam_role_policy_attachments_exclusive.test will be created
  + resource "aws_iam_role_policy_attachments_exclusive" "test" {
      + policy_arns = [
          + "arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001",
        ]
      + role_name   = "jb-test-managed-policy-arns-migration"
    }

Plan: 1 to import, 1 to add, 0 to change, 0 to destroy.
aws_iam_role_policy_attachment.test: Importing... [id=jb-test-managed-policy-arns-migration/arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role_policy_attachment.test: Import complete [id=jb-test-managed-policy-arns-migration/arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role_policy_attachments_exclusive.test: Creating...
aws_iam_role_policy_attachments_exclusive.test: Creation complete after 0s

Apply complete! Resources: 1 imported, 1 added, 0 changed, 0 destroyed.
  1. After a successful apply, the import block can be removed, and there are no planned changes.
% terraform plan
data.aws_iam_policy_document.trust: Reading...
data.aws_iam_policy_document.test: Reading...
data.aws_iam_policy_document.test: Read complete after 0s [id=748695472]
data.aws_iam_policy_document.trust: Read complete after 0s [id=2851119427]
aws_iam_policy.test: Refreshing state... [id=arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role.test: Refreshing state... [id=jb-test-managed-policy-arns-migration]
aws_iam_role_policy_attachment.test: Refreshing state... [id=jb-test-managed-policy-arns-migration-arn:aws:iam::012345678901:policy/terraform-20250129211402148800000001]
aws_iam_role_policy_attachments_exclusive.test: Refreshing state...

No changes. Your infrastructure matches the configuration.

jar-b avatar Jan 29 '25 21:01 jar-b

I think that the use of managed_policy_arns in IAM policy management was more preferred because it fits better with the IaC philosophy. The biggest problem is that the more projects that use more managed_policy_arns, the more pain are caused in terraform operations. There is no way to quiet certain deprecated items in terraform, and the aws plugin upgrade fills the plan with a lot of deprecations (especially in terraform Cloud!). I know of course how to manually upgrade to aws_iam_role_policy_attachments_exclusive, but it is not a human task. Adding this deprecation in a minor version update without an automated migration tool, or supression method, is in fact such a “breaking” change.

snmatsui avatar Mar 05 '25 10:03 snmatsui

I'd actually argue that the use of aws_iam_role_policy_attachments_exclusive is actually more dangerous from the standpoint of handling role policy attachment than managed_policy_arns, for the simple reason that when you can see the role definition, you know that the effect of it being applied will be to override the managed policies that are set. There is nothing in terraform that mandates where your aws_iam_role_policy_attachments_exclusive resource is placed. It could be in another file, or just off screen, or in a totally different set of terraform to that which manages the role leading to hours of trying to figure out what is messing around with policy attachments.

Obviously it has its place, but the reality is its use introduces a different set of problems that are equally as challenging as the original implementation. Encouraging people to use it as a replacement for managed_policy_arns is, in my opinion, like throwing the baby out with the bathwater.

essjayhch avatar Mar 24 '25 11:03 essjayhch

A major version, version 6.0.0, has been released, but the situation has not changed as the managed_policy_arns have not been removed and are still treated as deprecated.

Should we leave it to claude code to rewrite every managed_policy_arns ? Or should we wait for the "return" of managed_policy_arns?

snmatsui avatar Jun 24 '25 02:06 snmatsui

The managed_policy_arns and inline_policy are safe arguments to use, as they ensure the lifecycle of the IAM capabilities and the IAM role live together. When I use the these blocks I'm confident that the IAM permissions get updated first, then the resource that's using the policy.

This is not the case with aws_iam_role_policy_attachment where engineers have to remember to add a depends_on block, which is easy to forget, and this is leading to incidents.

I understand the desire of wanting to simplify the resource code for the aws_iam_role so it does less, but moving out the capability will significantly increase the risk of incidents and the complexity on the end user side.

AnitaErnszt avatar Oct 01 '25 08:10 AnitaErnszt