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
}