Skip to content
Learni
View all tutorials
Sécurité Cloud

How to Configure Advanced IAM with Terraform on AWS in 2026

18 minADVANCED
Lire en français

Introduction

Identity and Access Management (IAM) is critical for securing cloud environments. With AWS and Terraform, you can automate the creation of roles, users, and policies with granular control. This advanced tutorial guides you step-by-step toward a production-ready configuration including conditions, permission boundaries, and automatic rotation.

Prerequisites

  • AWS CLI configured with credentials
  • Terraform 1.9+
  • Solid knowledge of HCL and AWS IAM
  • AWS account with administrator rights

Initializing the Terraform Project

main.tf
terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.80"
    }
  }
}

provider "aws" {
  region = "eu-west-3"
}

This block initializes Terraform and the AWS provider. It ensures reproducibility and uses the latest stable provider version to support new IAM features.

Creating a Secure IAM User

iam_user.tf
resource "aws_iam_user" "app_user" {
  name = "app-service-user"
  path = "/service/"

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

resource "aws_iam_access_key" "app_user_key" {
  user = aws_iam_user.app_user.name
}

Creates a dedicated IAM user with a specific path. The access key is generated but should be stored via AWS Secrets Manager in production.

IAM Policy with Advanced Conditions

iam_policy.tf
resource "aws_iam_policy" "restricted_s3_policy" {
  name        = "RestrictedS3Access"
  description = "Accès S3 avec conditions IP et MFA"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Action = ["s3:GetObject", "s3:PutObject"]
      Resource = "arn:aws:s3:::my-secure-bucket/*"
      Condition = {
        IpAddress = { "aws:SourceIp" = ["10.0.0.0/8"] }
        Bool = { "aws:MultiFactorAuthPresent" = "true" }
      }
    }]
  })
}

This conditional policy restricts access by IP and requires MFA. IAM conditions provide an additional critical security layer in production.

Attaching the Policy to the User

iam_attachment.tf
resource "aws_iam_user_policy_attachment" "app_user_attach" {
  user       = aws_iam_user.app_user.name
  policy_arn = aws_iam_policy.restricted_s3_policy.arn
}

The attachment links the conditional policy to the user. Always use attachments rather than inline policies for better traceability.

IAM Role with Permission Boundary

iam_role.tf
resource "aws_iam_role" "lambda_execution_role" {
  name = "LambdaSecureRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
    }]
  })

  permissions_boundary = aws_iam_policy.restricted_s3_policy.arn
}

The role includes a permission boundary that limits maximum permissions even if an overly permissive policy is accidentally attached.

Best Practices

  • Always use permission boundaries on roles
  • Prefer IAM conditions (IP, MFA, tags) over overly broad policies
  • Store credentials via Secrets Manager instead of plaintext
  • Enable CloudTrail logging on all IAM actions
  • Apply the principle of least privilege with quarterly reviews

Common Mistakes to Avoid

  • Omitting conditions on policies allowing bypass
  • Using excessive wildcards (*) in resources
  • Not versioning Terraform policies
  • Ignoring access key rotation
  • Attaching policies directly to users instead of roles

Further Reading

Deepen your IAM management with our expert training at Learni Group.