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

Support for IAM "Role Chaining" #22728

Open dkujawski opened 2 years ago

dkujawski commented 2 years ago

Community Note

Description

Support a list of IAM roles to be assumed where currently only a single IAM role is allowed. When a list of IAM roles is encountered, assume the roles in the order that they are listed.

New or Affected Resource(s)

The provider

Potential Terraform Configuration

provider "aws" {
  region = "us-west-2"

  assume_role {
    role_arn_chain = [
      "arn:aws:iam:01234567890:role/origin",
      "arn:aws:iam:01234567890:role/role_a",
      "arn:aws:iam:01234567890:role/role_b",
      "arn:aws:iam:01234567890:role/role_c"
    ]
  }
}

An alternate implementation:

provider "aws" {
  region = "us-west-2"

  assume_role {
    role_arn       = "arn:aws:iam:01234567890:role/role_origin"
    role_arn_chain = [
      "arn:aws:iam:01234567890:role/role_a",
      "arn:aws:iam:01234567890:role/role_b",
      "arn:aws:iam:01234567890:role/role_c"
    ]
  }
}

References

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html

jbg commented 2 years ago

Neither of the proposed implementations would support using external_id for arbitrary roles in the chain.

Why not just remove the restriction that there is at most one assume_role block? That seems cleaner:

provider "aws" {
  region = "us-west-2"

  assume_role {
    role_arn = "arn:aws:iam:01234567890:role/origin"
  }

  assume_role {
    role_arn = "arn:aws:iam:2389472384:role/role_a"
    external_id = "foo"
  }

  assume_role {
    role_arn = "arn:aws:iam:2389472384:role/role_b"
  }
}
gdavison commented 2 years ago

Hi @dkujawski, this looks like an interesting idea. As @jbg notes above, we will need more than just the role ARNs for each role. Each role can potentially define the full set of parameters defined by the assume_role block.

The bulk of the work will have to be done in https://github.com/hashicorp/aws-sdk-go-base.

djotanov commented 2 years ago

Or:

provider "aws" {
  region = "us-west-2"

  assume_roles = [
    {
      role_arn = "arn:aws:iam:01234567890:role/origin"
    },
    {
      role_arn = "arn:aws:iam:2389472384:role/role_a"
      external_id = "foo"
    },
    {
      role_arn = "arn:aws:iam:2389472384:role/role_b"
    }
]
jbg commented 2 years ago

The block approach has the advantage of being directly backward-compatible with existing configurations that just assume a single role, and being consistent with the rest of the terraform ecosystem (lists of arbitrary objects are not really common in resources, repeated blocks are far more typical).

mbamber commented 2 years ago

Out of interest, would the block approach have a consistent order?

JHeilCoveo commented 1 year ago

Out of interest, would the block approach have a consistent order?

If it isn't consistent a simple fix would be to add an order property and sort them according to that field.

jack-parsons-bjss commented 7 months ago

Did a format get agreed upon? Perhaps a separate argument for a source_provider with a full provider block for each step of the chain?

ustulation commented 6 months ago

This is also useful in CD Pipelines. The pipeline "machine" can assume a role in target account A0 to deploy to it, but that target account might need to setup peering with another account A1. A1 allows A0 to assume a role in A1 to set up peering. That way anyone logged into A0 with appropriate role/creds can deploy to A0 as well as assume the role in A1 to setup peering. When the pipeline needs to do the same it will need to assume A0 role to deploy to A0 and then assume A1 after assuming A0 to also do peering. Currently this is not possible in terraform.

As a workaround we either use on-the-fly generated aws-config to set up this chain OR ask A1 to additionally allow the pipeline account to assume that peering role in it (ie. in addition to allowing A0). The former is messy and the latter is an OK compromise but now every such A1 account needs to give perms to both, the corresponding A0 account (to allow whoever is logged into A0 locally to conveniently run terraform apply) and the pipeline account (for automated deployments) to assume the peering role in A1.

mikedizon commented 2 months ago

any movement on this?