LAB-04: Meta Arguments (Count, For_Each, Map) => Provision IAM Users, User Groups, Policies, Attachment Policy-User Group
This scenario shows:
- how to create IAM User, User Groups, Permission Policies, Attachment Policy-User Group
- how to use Count, For_Each, Map
Code: https://github.com/omerbsezer/Fast-Terraform/tree/main/labs/iamuser-metaargs-count-for-foreach-map
- You should have a look following lab:
- Create main.tf under count directory and copy the code:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
#####################################################
# User - User Group Attachment (With Index Count)
resource "aws_iam_user_group_membership" "user1_group_attach" {
user = aws_iam_user.user_example[0].name
groups = [
aws_iam_group.admin_group.name,
aws_iam_group.dev_group.name,
]
}
resource "aws_iam_user_group_membership" "user2_group_attach" {
user = aws_iam_user.user_example[1].id
groups = [
aws_iam_group.admin_group.name
]
}
resource "aws_iam_user_group_membership" "user3_group_attach" {
user = aws_iam_user.user_example[2].name
groups = [
aws_iam_group.dev_group.name
]
}
#####################################################
# User Group Definition
resource "aws_iam_group" "admin_group" {
name = "admin_group"
}
resource "aws_iam_group" "dev_group" {
name = "dev_group"
}
#####################################################
# Policy Definition, Policy-Group Attachment
data "aws_iam_policy_document" "admin_policy" {
statement {
effect = "Allow"
actions = ["*"]
resources = ["*"]
}
}
resource "aws_iam_policy" "admin_policy" {
name = "admin-policy"
description = "Admin policy"
policy = data.aws_iam_policy_document.admin_policy.json
}
data "aws_iam_policy_document" "ec2_policy" {
statement {
effect = "Allow"
actions = ["ec2:Describe*"]
resources = ["*"]
}
}
resource "aws_iam_policy" "ec2_policy" {
name = "ec2-policy"
description = "EC2 policy"
policy = data.aws_iam_policy_document.ec2_policy.json
}
#####################################################
# Policy Attachment to the Admin, Dev Group
resource "aws_iam_group_policy_attachment" "admin_group_admin_policy_attach" {
group = aws_iam_group.admin_group.name
policy_arn = aws_iam_policy.admin_policy.arn
}
resource "aws_iam_group_policy_attachment" "dev_group_ec2_policy_attach" {
group = aws_iam_group.dev_group.name
policy_arn = aws_iam_policy.ec2_policy.arn
}
#####################################################
# Username Definition
# With Count
resource "aws_iam_user" "user_example" {
count = length(var.user_names)
name = var.user_names[count.index]
}
# count, use list
variable "user_names" {
description = "IAM usernames"
type = list(string)
default = ["username1_admin_dev", "username2_admin", "username3_dev_ec2"]
}
#####################################################
# With for loop
output "print_the_names" {
value = [for name in var.user_names : name]
}
- Run init command:
terraform init
- Validate file:
terraform validate
- Run plan command:
terraform plan
- Run apply command:
terraform apply
- On AWS > IAM > Users, users are created:
- Click on "username1_admin_dev" to see the policies:
- To see user groups membership:
- Users in the "admin_group":
- EC2 Policy for "username3_dev_ec2":
- Destroy resources:
terraform destroy
- To test "for_each", main.tf under for_each.
- Some differents from previous one:
- not index, with name. e.g. aws_iam_user.user_example["username1_admin_dev"].name
- s3 policy, attachment
- for_each implementation
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
#####################################################
# User - User Group Attachment (With Index Count)
resource "aws_iam_user_group_membership" "user1_group_attach" {
user = aws_iam_user.user_example["username1_admin_dev"].name
groups = [
aws_iam_group.admin_group.name,
aws_iam_group.dev_group.name,
]
}
resource "aws_iam_user_group_membership" "user2_group_attach" {
user = aws_iam_user.user_example["username2_admin"].id
groups = [
aws_iam_group.admin_group.name
]
}
resource "aws_iam_user_group_membership" "user3_group_attach" {
user = aws_iam_user.user_example["username3_dev_s3"].name
groups = [
aws_iam_group.dev_group.name
]
}
#####################################################
# User Group Definition
resource "aws_iam_group" "admin_group" {
name = "admin_group"
}
resource "aws_iam_group" "dev_group" {
name = "dev_group"
}
#####################################################
# Policy Definition, Policy-Group Attachment
data "aws_iam_policy_document" "admin_policy" {
statement {
effect = "Allow"
actions = ["*"]
resources = ["*"]
}
}
resource "aws_iam_policy" "admin_policy" {
name = "admin-policy"
description = "Admin policy"
policy = data.aws_iam_policy_document.admin_policy.json
}
data "aws_iam_policy_document" "s3_policy" {
statement {
effect = "Allow"
actions = ["s3:*"]
resources = [
"arn:aws:s3:::mybucket",
"arn:aws:s3:::mybucket/*"
]
}
}
resource "aws_iam_policy" "s3_policy" {
name = "s3-policy"
description = "S3 policy"
policy = data.aws_iam_policy_document.s3_policy.json
}
#####################################################
# Policy Attachment to the Admin, Dev Group
resource "aws_iam_group_policy_attachment" "admin_group_admin_policy_attach" {
group = aws_iam_group.admin_group.name
policy_arn = aws_iam_policy.admin_policy.arn
}
resource "aws_iam_group_policy_attachment" "dev_group_s3_policy_attach" {
group = aws_iam_group.dev_group.name
policy_arn = aws_iam_policy.s3_policy.arn
}
#####################################################
# With for_each
resource "aws_iam_user" "user_example" {
for_each = var.user_names
name = each.value
}
# for each, use set instead of list
variable "user_names" {
description = "IAM usernames"
type = set(string)
default = ["username1_admin_dev", "username2_admin", "username3_dev_s3"]
}
#####################################################
# With for loop
output "print_the_names" {
value = [for name in var.user_names : name]
}
-
This time, for dev groups, it creates S3 Permission Policy
-
Run init command:
terraform init
- Validate file:
terraform validate
- Run plan command:
terraform plan
- Run apply command:
terraform apply
On AWS, the different from previous example, s3 policy is created:
- Destroy resources:
terraform destroy
- You can also use map to define usernames, following yaml file shows how to use maps
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
#####################################################
# With for_each
resource "aws_iam_user" "example" {
for_each = var.user_names
name = each.value
}
# With Map
variable "user_names" {
description = "map"
type = map(string)
default = {
user1 = "username1"
user2 = "username2"
user3 = "username3"
}
}
# with for loop on map
output "user_with_roles" {
value = [for name, role in var.user_names : "${name} is the ${role}"]
}