Developer Read-Only AWS IAM Group on AWS Cloud with Terraform

One of the first things I do when setting up a Cloud account on AWS for any client is to set up an IAM
group for developers. Most of the time the Developers just need a read-only group that will enable them to access resources but not modify anything. Therefore they need to view logs and easily debug while being restricted not to doing something stupid and accidentally deleting a resource.
Define the Group
Here we define the IAM
group.
resource "aws_iam_group" "developer_read_only_group" {
name = "developer_read_only_group"
}
Attach AWS Managed Policies
Here we attach AWS-managed read-only policies to the previously created IAM
group.
data "aws_iam_policy" "developer_read_only_group_policy" {
for_each = toset(
[
"AmazonCloudWatchEvidentlyReadOnlyAccess",
"AmazonRDSReadOnlyAccess",
"AWSAppRunnerReadOnlyAccess",
"AmazonS3ReadOnlyAccess",
"CloudFrontReadOnlyAccess",
"AWSCodeBuildReadOnlyAccess",
"AWSCodePipeline_ReadOnlyAccess",
"AmazonEC2ReadOnlyAccess",
"IAMReadOnlyAccess"
]
)
name = each.value
}
resource "aws_iam_group_policy_attachment" "developer_read_only_group_policy" {
for_each = data.aws_iam_policy.developer_read_only_group_policy
group = aws_iam_group.developer_read_only_group.name
policy_arn = each.value.arn
Custom Policy
Here we create a custom IAM
policy and attach it to the IAM
group. This is where you can add custom permissions to the policies that are not covered by the AWS-managed ones.
data "aws_iam_policy_document" "custom_general_developer_read_only" {
statement {
effect = "Allow"
actions = [
"s3:ListAllMyBuckets",
"s3:ListBucketMultipartUploads",
"s3:GetAccountPublicAccessBlock",
"s3:GetBucketPublicAccessBlock",
"s3:GetBucketPolicyStatus",
"s3:GetBucketAcl",
"s3:ListAccessPoints"
]
resources = [
"*"
]
}
statement {
effect = "Allow"
actions = [
"acm:ListCertificates",
"cloudfront:GetDistribution",
"cloudfront:GetStreamingDistribution",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudfront:ListCloudFrontOriginAccessIdentities",
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"cloudfront:ListInvalidations"
]
resources = [
"*"
]
}
statement {
effect = "Allow"
actions = [
"logs:DescribeLogGroups",
"logs:FilterLogEvents",
"logs:DescribeLogGroups"
"logs:DescribeLogGroups",
"logs:FilterLogEvents"
]
resources = [
"*"
]
}
statement {
effect = "Allow"
actions = [
"ecs:ListClusters",
"ecs:Describe*",
"ecs:List*",
"ecs:ListContainerInstances",
"ecs:ListTasks",
"ecs:DescribeClusters",
"ecs:DescribeClusters"
]
resources = [
"*"
]
}
statement {
effect = "Allow"
actions = [
"iam:ListAttachedRolePolicies",
"iam:ListRoles",
"iam:ListGroups",
"iam:ListUsers",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole"
]
resources = [
"*"
]
}
}
Here we attach the custom policy to the group.
resource "aws_iam_policy" "custom_general_developer_read_only" {
name = "custom_general_developer_read_only"
path = "/"
description = "Allow "
policy = data.aws_iam_policy_document.custom_general_developer_read_only.json
}
Here we attach the custom policy to the developer_read_only_group
group.
resource "aws_iam_group_policy_attachment" "custom_general_developer_read_only" {
group = aws_iam_group.developer_read_only_group.name
policy_arn = aws_iam_policy.custom_general_developer_read_only.arn
}
User Management
Now that we have all IAM
groups and policies in place we can focus on creating a user and assigning groups to the users.
# Create a User
resource "aws_iam_user" "user_name_created_with_terraform" {
name = "user_name_created_with_terraform"
}
# Group Membership
resource "aws_iam_user_group_membership" "user_name_created_with_terraform" {
user = aws_iam_user.user_name_created_with_terraform.name
groups = [
aws_iam_group.developer_read_only_group.name
]
}
Attach the AWS Change Password Policy
Here we attach the AWS managed change password policy. This will permit the user to change their password.
resource "aws_iam_policy_attachment" "iam_user_change_password_policy_attach" {
name = "iam_user_change_password_policy_attach"
users = [
"aws_username_not_added_by_terraform",
aws_iam_user.user_name_created_with_terraform.name,
]
policy_arn = "arn:aws:iam::aws:policy/IAMUserChangePassword"
}
Conclusion
In this article, I covered how to create a read-only IAM
group with AWS-managed and custom policies, and user management. This is very useful for every Cloud Engineer.