Terraform — Implementing Automated IAM User Permission Assignment

Tony Fu
5 min readOct 3, 2023

Using Terraform to automate general tasks offers several advantages. It accelerates response times to user requests, minimizes configuration errors, and maintains version control tracking.

Step 1 — Create a child directory for further development. I’ve found that the -chdir option is helpful if you want to separate your subproject with Terraform.

Execute the following command to initialize a working directory containing Terraform configuration files:

terraform -chdir=AWS-RBAC-UserPermissionAssignment init

After running this command, you will receive a successful initialization message welcoming you to work with Terraform.

Step 2 — Create a HCL file to define the policy and associate it with a user.

//create a test user
resource "aws_iam_user" "terraform-user-1" {
name = "terraform-ec2-user-1"
path = "/"

tags = {
tag-key = "terraform-ec2-user-1"
}
}

//Create a Policy
resource "aws_iam_policy" "custom-ec2-create" {
name = "custom-ec2-create"
path = "/"
description = "Assign to user who need manage ec2"

# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:*",
]
Effect = "Allow"
Resource = "*"
},
]
})
}

//Attaches a Managed IAM Policy to an IAM user
resource "aws_iam_user_policy_attachment" "ec2-attachment" {
user = "terraform-ec2-user-1"
policy_arn = "arn:aws:iam::4444xxxxxx03:policy/custom-ec2-create"
}

Once you’ve placed all the HCL files under the AWS-RBAC-UserPermissionAssignment directory, run terraform plan by executing the command terraform -chdir=AWS-RBAC-UserPermissionAssignment plan. This will validate whether the resources you’ve created are correct or not.

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create

Terraform will perform the following actions:

# aws_iam_policy.custom-ec2-create will be created
+ resource "aws_iam_policy" "custom-ec2-create" {
+ arn = (known after apply)
+ description = "Assign to user who need manage ec2"
+ id = (known after apply)
+ name = "custom-ec2-create"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "ec2:*",
]
+ Effect = "Allow"
+ Resource = "*"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}

# aws_iam_user.terraform-user-1 will be created
+ resource "aws_iam_user" "terraform-user-1" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "terraform-ec2-user-1"
+ path = "/"
+ tags = {
+ "tag-key" = "terraform-ec2-user-1"
}
+ tags_all = {
+ "tag-key" = "terraform-ec2-user-1"
}
+ unique_id = (known after apply)
}

# aws_iam_user_policy_attachment.ec2-attachment will be created
+ resource "aws_iam_user_policy_attachment" "ec2-attachment" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::4444xxxxxx03:policy/custom-ec2-create"
+ user = "terraform-ec2-user-1"
}

Plan: 3 to add, 0 to change, 0 to destroy.

───────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform apply" now.

Step 3 — Apply the changes using Terraform with the command terraform -chdir=AWS-RBAC-UserPermissionAssignment apply. This will synchronize the configuration with AWS. The HCL file you executed will create the user and policy, and then assign the policy to the new user.



Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# aws_iam_user.terraform-user-1 will be created
+ resource "aws_iam_user" "terraform-user-1" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "terraform-ec2-user-1"
+ path = "/"
+ tags = {
+ "tag-key" = "terraform-ec2-user-1"
}
+ tags_all = {
+ "tag-key" = "terraform-ec2-user-1"
}
+ unique_id = (known after apply)
}

# aws_iam_policy.custom-ec2-create will be created
+ resource "aws_iam_policy" "custom-ec2-create" {
+ arn = (known after apply)
+ description = "Assign to user who need manage ec2"
+ id = (known after apply)
+ name = "custom-ec2-create"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "ec2:*",
]
+ Effect = "Allow"
+ Resource = "*"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}

# aws_iam_user_policy_attachment.ec2-attachment will be created
+ resource "aws_iam_user_policy_attachment" "ec2-attachment" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::4444xxxxxx03:policy/custom-ec2-create"
+ user = "terraform-ec2-user-1"
}

Plan: 3 to add, 0 to change, 0 to destroy.

aws_iam_user.terraform-user-1: Creating...
aws_iam_policy.custom-ec2-create: Creating...
aws_iam_user_policy_attachment.ec2-attachment: Creating...
aws_iam_user.terraform-user-1: Creation complete after 1s [id=terraform-ec2-user-1]
aws_iam_policy.custom-ec2-create: Creation complete after 2s [id=arn:aws:iam::4444xxxxxx03:policy/custom-ec2-create]
aws_iam_user_policy_attachment.ec2-attachment: Creation complete after 1s [id=terraform-ec2-user-1-20231002183919589600000001]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

After the apply is completed, you will receive details about the resources, such as the user ID, which will be something like terraform-ec2-user-1, and the policy’s Amazon Resource Name (ARN), which will be in the format arn:aws:iam::4444xxxxxx03:policy/custom-ec2-create.

Step 4 — Use the “output” module to review which policy is assigned to the existing user.

The output HCL file, created under the same directory as “output.tf,” validates which policy is assigned to the user.

output "terraform-user-1" {
description = "Policy with the user"
value = aws_iam_user_policy_attachment.ec2-attachment.user
}

Execute the following command to apply the change again to get the output:

terraform -chdir=AWS-RBAC-UserPermissionAssignment apply

After creating the outputs, execute the command below to query all of them:

terraform -chdir=AWS-RBAC-UserPermissionAssignment output

As a result, the output you get is about the output “terraform-user-1” with the value of “terraform-ec2-user-1.”

Wrapping up, terraform provides developers, network administrators, and system administrators with a streamlined approach to managing their infrastructure through code. It not only simplifies infrastructure management but also offers significant advantages in terms of time and efficiency.

--

--

Tony Fu

Extensive experience as network engineer and cybersecurity engineer, interest in automation, simplifying architecture, and innovating with new technologies.