How to attach multiple IAM policies to IAM roles using Terraform?

Adding another option, which is similar to the excepted answer but instead of:

policy_arn = "${var.iam_policy_arn[count.index]}"

You can use the element function:

policy_arn = "${element(var.iam_policy_arn,count.index)}"

I think that in some cases (like a project with a large amount of code) this could be more readable.


Did you try something like this:

resource "aws_iam_role" "iam_role_name" {
  name = "iam_role_name"
}

resource "aws_iam_role_policy_attachment" "mgd_pol_1" {
  name       = "mgd_pol_attach_name"
  role       = "${aws_iam_role.iam_role_name.name}"
  policy_arn = "${aws_iam_policy.mgd_pol_1.arn}"
}

resource "aws_iam_role_policy_attachment" "mgd_pol_2" {
  name       = "mgd_pol_attach_name"
  role       = "${aws_iam_role.iam_role_name.name}"
  policy_arn = "${aws_iam_policy.mgd_pol_2.arn}"
}

For Terraform versions >= 0.12 the cleanest way to add multiple policies is probably something like this:

resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
  for_each = toset([
    "arn:aws:iam::aws:policy/AmazonEC2FullAccess", 
    "arn:aws:iam::aws:policy/AmazonS3FullAccess"
  ])

  role       = var.iam_role_name
  policy_arn = each.value
}

As described in Pranshu Verma's answer, the list of policies can also be put into a variable.

Using for_each in favor of count has the advantage, that insertions to the list are properly recognized by terraform so that it would really only add one policy, while with count all policies after the insertion would be changed (this is described in detail in this blog post)


Thanks Krishna Kumar R for the hint.

A little more polished answer I reached from your answer.

# Define policy ARNs as list
variable "iam_policy_arn" {
  description = "IAM Policy to be attached to role"
  type = "list"
}

# Then parse through the list using count
resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
  role       = "${var.iam_role_name}"
  count      = "${length(var.iam_policy_arn)}"
  policy_arn = "${var.iam_policy_arn[count.index]}"
}

And finally the list of policies should be specified in *.tfvars file or in command line using -var, for example:

iam_policy_arn = [ "arn:aws:iam::aws:policy/AmazonEC2FullAccess", "arn:aws:iam::aws:policy/AmazonS3FullAccess"]