Security management in a fine-grained manner is a critical component to deploy the enterprise application successfully. Terraform enables us to manage any resource on the cloud service by using the declarative language, HCL. If you are a software engineer providing any service on AWS like me, Terraform gives us the excellent capability and saves us time for sure. I have found a tiny tip to be shared here about the Terraform usage setting the IAM policy. This article aims to explain the use of aws_iam_role_policy
and its potential limitations from the practical viewpoint.
Limitation of aws_iam_role_policy
We used aws_iam_role_policy
to set the specific IAM policy to a role. It’s the most straightforward and easy way to attach a policy to the role you are managing. But there is a caveat to be noted. The resource can only create inline policy, which is not designed to be shared by multiple roles afterward.
Looking at the following list, you can notice that the policy attached to my-role
does not have any name specified. Even if the policy is sufficiently general to be used by other roles, we have no way with aws_iam_role_policy
.
resource "aws_iam_role" "my-role" {
name = "my-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "my-policy" {
name = "my-policy"
role = "${aws_iam_role.my-role.id}"
# This policy is exclusively available by my-role.
policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::my-bucket"
]
}
]
}
EOF
Standalone policy with aws_iam_policy
Here comes the aws_iam_policy
and aws_iam_role_policy_attachment
resources. aws_iam_policy
is a resource to create a standalone IAM policy. It’s almost the same as what aws_iam_role_policy
does, but it does not attach the policy with any IAM entity such as users, roles, and groups. The policy is isolated and does not affect unless it is attached to the existing IAM entity. aws_iam_role_policy_attachment
does that as the name implied. You can attach the existing policy to the existing IAM role. That indicates we can reuse the policy by attaching it to several roles.
resource "aws_iam_policy" "my-policy" {
name = "my-policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::my-bucket"
]
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "my-policy-attach" {
role = "${aws_iam_role.my-role.name}"
policy_arn = "${aws_iam_policy.my-policy.arn}"
}
If you have another role named my-role-2
, you can attach the my-policy
again with the following code’s call.
resource "aws_iam_role_policy_attachment" "my-policy-attach-2" {
role = "${aws_iam_role.my-role-2.name}"
policy_arn = "${aws_iam_policy.my-policy.arn}"
}
That’s a handy way to reuse the existing policy component and be less error-prone because we can avoid rewriting the same policy repeatedly.
WARNING
We have another resource that has a very similar name,
aws_iam_policy_attachment
. But we should be careful of the usage of this resource because it attaches the policy exclusively. Across the entire AWS account, only one IAM entity (i.e., users/roles/groups) can be declared by aws_iam_policy_attachement
. That limitation is counterintuitive. Using aws_iam_role_policy_attachment
will prevent us from wasting time digging deeper into what’s going on when facing an issue.