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.arnCustom 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.
Never miss a story from us, subscribe to our newsletter