AWS Terraform IAM User Management

Published: (December 15, 2025 at 01:43 AM EST)
4 min read
Source: Dev.to

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.

Back to Blog

Related posts

Read more »

AWS Modulo 3: Lambda con Go

Compilé para Linux sin Salir de mi Mac y Costó $0.06 Serie: AWS Zero to Architect - Módulo 3 Tiempo de lectura: 20 minutos Tiempo de implementación: 120 minuto...