For all the good things that come with AWS, simplicity is not always one of them.

The permissions attached to an IAM Role come from it’s Policies. And of course there is more than one way to do this.

Using inline IAM policies

I’ve never been a fan of inline policies. They’re easy to set up in the AWS console and then you would generally forget about them.

Inline policies also hinder reusability, and in case you want to change a rule for a number of users/roles you will have to change it on all the inline policies.

Regardless, I promise I will not judge if you give in to the laziness and use this:

resource "aws_iam_role_policy" "my_inline_policy" {
  name = "all_the_ec2"
  role = aws_iam_role.my_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = ["ec2:*"]
        Effect   = "Allow"
        Resource = "*"
      }
    ]
  })
}

If you need to attach more than one policy to a role, you only have to copy paste the above block and edit to your heart desire.

Using attached IAM policies

Attached policies need a tiny bit more code to write up, but they can be easily reused and modified and show up all together in a nice, auditable list.

Here’s an example:

resource "aws_iam_policy" "my_policy" {
  name        = "all_the_ec2"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = ["ec2:*"]
        Effect   = "Allow"
        Resource = "*"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "attachment" {
  role       = aws_iam_role.my_role.name
  policy_arn = aws_iam_policy.my_policy.arn
}

Attaching multiple policies with for_each

If you have defined a number of aws_iam_policy(s), you can attach all the policies you need to a role, or a user, or a group with this neat Terraform trick:

resource "aws_iam_role_policy_attachment" "attachment" {
  for_each = toset([
    aws_iam_policy.my_first_policy.arn,
    aws_iam_policy.my_other_policy.arn,

     # Works with AWS Provided policies too!
    "arn:aws:iam::aws:policy/AmazonS3FullAccess"
  ])
  
  role       = aws_iam_role.my_role.name
  policy_arn = each.value
}