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
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
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
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
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
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.