AWS Terraform IAM User Management
Source: Dev.to
Introduction
Managing IAM users manually in AWS can quickly become complex, error‑prone, and difficult to scale. As teams grow, you need a repeatable, auditable, and secure way to manage users, groups, permissions, and security controls like MFA. This guide shows how to implement AWS IAM user management using Terraform, driven by a CSV file as the single source of truth.
Advantages of Terraform for IAM
- Centralized and version‑controlled user management
- Easy onboarding and off‑boarding of users
- Consistent security policies across teams
- Reduced manual errors
- Idempotent and auditable changes
Setup Overview
- IAM users created dynamically from a CSV file
- IAM groups for Education, Managers, and Engineers
- Automatic group membership based on user attributes
- Console access with forced password reset
- MFA enforcement across all groups
- Group‑based permission management
The CSV file becomes the single source of truth for identity data.
Load User Data from CSV
locals {
users = csvdecode(file("users.csv")) // List of maps for the data
}
Terraform converts each row into a map, allowing us to loop over users dynamically. Adding or removing users is as simple as editing the CSV.
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
Email = each.value.email
Phone = each.value.phone
}
}
- Usernames are generated automatically (first initial + last name)
- Tags store rich metadata for filtering, auditing, and policies
- No hard‑coding of users
Console Access (Login Profiles)
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_reset_required,
password_length
]
}
}
Enforces a password reset on first login, aligning with security best practices.
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/"
}
Managing permissions at the group level simplifies administration.
Automatic Group Membership
resource "aws_iam_group_membership" "education_members" {
name = "education-group-membership"
group = aws_iam_group.education.name
users = [
for user in aws_iam_user.users : user.name
if user.tags.Department == "Education"
]
}
resource "aws_iam_group_membership" "managers_members" {
name = "managers-group-membership"
group = aws_iam_group.managers.name
users = [
for user in aws_iam_user.users : user.name
if contains(keys(user.tags), "JobTitle") &&
can(regex("Manager|CEO", user.tags.JobTitle))
]
}
resource "aws_iam_group_membership" "engineers_members" {
name = "engineers-group-membership"
group = aws_iam_group.engineers.name
users = [
for user in aws_iam_user.users : user.name
if user.tags.Department == "Engineering"
]
}
This eliminates manual group assignment and ensures accuracy.
MFA Enforcement
Terraform cannot create MFA devices, but it can enforce MFA usage through IAM policies.
resource "aws_iam_policy" "require_mfa" {
name = "Require-MFA"
description = "Deny access unless MFA is enabled"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyAllExceptMFA"
Effect = "Deny"
Action = "*"
Resource = "*"
Condition = {
BoolIfExists = {
"aws:MultiFactorAuthPresent" = "false"
}
}
}
]
})
}
Attach MFA Policy to Groups
resource "aws_iam_group_policy_attachment" "mfa_enforcement" {
for_each = {
education = aws_iam_group.education.name
managers = aws_iam_group.managers.name
engineers = aws_iam_group.engineers.name
}
group = each.value
policy_arn = aws_iam_policy.require_mfa.arn
}
All users in these groups must enable MFA to access AWS.
Permissions via Managed Policies
resource "aws_iam_group_policy_attachment" "education_readonly" {
group = aws_iam_group.education.name
policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}
resource "aws_iam_group_policy_attachment" "managers_admin" {
group = aws_iam_group.managers.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
resource "aws_iam_group_policy_attachment" "engineers_poweruser" {
group = aws_iam_group.engineers.name
policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess"
}
- Education users have read‑only access
- Managers have full administrative access
- Engineers have PowerUser access (manage resources but not IAM)
Additional Useful Data
data "aws_caller_identity" "current" {}
Useful for outputs, debugging, and ensuring Terraform is operating in the correct AWS account.
Summary
- MFA enforced across all users
- Permissions applied via groups, not individual users
- Metadata stored as tags for auditing
- CSV‑driven user lifecycle management
- Infrastructure fully reproducible and auditable
For production environments, consider using AWS IAM Identity Center (SSO) instead of IAM users. This Terraform‑based solution demonstrates how identity can be treated as code, not configuration. By combining CSV‑driven data, dynamic group membership, MFA enforcement, and least‑privilege access, you obtain a scalable and secure IAM architecture suitable for real‑world environments.