Managing IAM users manually in AWS is fine... until it's not.
Once your team grows, clicking around the console becomes pain + chaos.
So, I built a Terraform-Based IAM User management system where:
- Users come from a CSV file
- Groups and memberships are auto assigned
- Everything is reproducible, version-controlled, and scalable
Overview
This demo shows how to manage:
- IAM Users
- IAM Groups
- Group Memberships
using Terraform with a CSV file as the single source of truth.
Instead of manually creating users, you just update a CSV -> run
terraform apply-> done.
Prerequisites:
Make sure you have:
- AWS CLI configured (
aws configure) - Terraform v1.0+
- IAM permissions to create users & groups
- An S3 bucket for remote Terraform state
Quick Start
Create S3 Backend Bucket
terraform {
backend "s3" {
bucket = "my-aws-terraform-state-bucket-amit-123"
key = "Day-16/terraform/terraform.tfstate"
region = "us-east-1"
}
}
Initialize Terraform
terraform init
Review Changes
terraform plan
Apply Configuration
terraform apply -auto-approve
Project File Structure
Day16/terraform
├── backend.tf # S3 backend configuration
├── provider.tf # AWS provider setup
├── versions.tf # Terraform & provider versions
├── main.tf # IAM users + CSV parsing
├── groups.tf # Groups and memberships
├── users.csv # User data source
└── README.md # Project overview
How it Works (Step-by-Step)
Step 1: Read Users from CSV
Terraform reads the CSV file and converts it into structured data:
# Read users from CSV
locals {
users = csvdecode(file("users.csv"))
}
Step 2: Create IAM Users
Each user is created dynamically using for_each.
Username format: {first_initial}{lastname}
(eg:- Michael Scott -> mscott)
# Create IAM users
resource "aws_iam_user" "users" {
for_each = { for user in local.users : user.first_name => user }
name = lower("${substr(each.value.first_name, 0, 1)}${each.value.last_name}")
path = "/users/"
tags = {
"DisplayName" = "${each.value.first_name} ${each.value.last_name}"
"Department" = each.value.department
"JobTitle" = each.value.job_title
}
}
Step 3: Enable Console Access
Each user gets console access and is forced to reset password on first login:
# Create IAM user login profile (password)
resource "aws_iam_user_login_profile" "users" {
for_each = aws_iam_user.users
user = each.value.name
password_reset_required = true
lifecycle {
ignore_changes = [
password_length,
password_reset_required,
]
}
}
Step 4: Create Groups & Memberships
Groups are created once, and memberships are assigned dynamically.
Example: Education group
# Create IAM Groups
resource "aws_iam_group" "education" {
name = "Education"
path = "/groups/"
}
resource "aws_iam_group" "managers" {
name = "Managers"
path = "/groups/"
}
resource "aws_iam_group" "engineers" {
name = "Engineers"
path = "/groups/"
}
Terraform Outputs:
After apply, you can check:
terraform output account_id
terraform output user_names
terraform output user_passwords # sensitive
Useful for verification and automation.
Users List (Sample)
first_name,last_name,department,job_title
Michael,Scott,Education,Regional Manager
Dwight,Schrute,Sales,Assistant to the Regional Manager
Jim,Halpert,Sales,Sales Representative
Pam,Beesly,Reception,Receptionist
Ryan,Howard,Temps,Temp
Andy,Bernard,Sales,Sales Representative
Robert,California,Corporate,CEO
Stanley,Hudson,Sales,Sales Representative
Kevin,Malone,Accounting,Accountant
Angela,Martin,Accounting,Accountant
Oscar,Martinez,Accounting,Accountant
Phyllis,Vance,Sales,Sales Representative
Toby,Flenderson,HR,HR Representative
Kelly,Kapoor,Customer Service,Customer Service Representative
Darryl,Philbin,Warehouse,Warehouse Foreman
Creed,Bratton,Quality Assurance,Quality Assurance
Meredith,Palmer,Supplier Relations,Supplier Relations
Erin,Hannon,Reception,Receptionist
Gabe,Lewis,Corporate,Coordinating Director of Emerging Regions
Jan,Levinson,Corporate,Vice President of Northeast Sales
David,Wallace,Corporate,CFO
Holly,Flax,HR,HR Representative
Charles,Miner,Corporate,Vice President of the Northeast Region
Jo,Bennett,Corporate,CEO of Sabre
Clark,Green,Sales,Sales Representative
Pete,Miller,Customer Service,Customer Service Representative
Cleanup
To remove all created resources:
terraform destroy
Warning: This will delete all users, groups, and memberships.
Troubleshooting:
Error: Backend Access Denied
Check your AWS credentials:
aws sts get-caller-identity
Error: User Already Exists
Import existing user into state:
terraform import aws_iam_user.users[\"Michael\"] mscott
Or delete the existing user:
aws iam delete-login-profile --user-name mscott
aws iam delete-user --user-name mscott
Resources:
-Terraform AWS Provider Docs
-AWS IAM Best Practices
-Terraform Functions
Success!
Your AWS IAM infrastructure is now managed as code. You can:
- Add new users by editing the CSV
- Modify group memberships by changing user attributes
- Version control all changes
- Replicate this setup across multiple AWS accounts
- Happy Terraforming! 🚀
Reference:
>> Connect With Me
If you enjoyed this post or want to follow my #30DaysOfAWSTerraformChallenge journey, feel free to connect with me here:
💼 LinkedIn: Amit Kushwaha
🐙 GitHub: Amit Kushwaha
📝 Hashnode / Amit Kushwaha
🐦 Twitter/X: Amit Kushwaha

Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.