Managing AWS IAM Roles and Policies Using Terraform
Learn how to create and manage AWS IAM roles, policies, and users using Terraform for secure access management
Managing AWS IAM Roles and Policies Using Terraform
AWS Identity and Access Management (IAM) is crucial for securing your AWS infrastructure. This guide demonstrates how to manage IAM resources using Terraform, ensuring consistent and version-controlled access management.
Video Tutorial
Learn more about managing AWS IAM with Terraform in this comprehensive video tutorial:
Prerequisites
- AWS CLI installed and configured
- Terraform installed (version 1.0.0 or later)
- Basic understanding of AWS IAM concepts
- Text editor of your choice
Project Structure
iam-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Setting Up the Provider
Create main.tf
:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = var.aws_region
}
# IAM User
resource "aws_iam_user" "developer" {
name = "developer-${var.environment}"
path = "/users/"
tags = {
Environment = var.environment
Role = "Developer"
}
}
# IAM Group
resource "aws_iam_group" "developers" {
name = "developers-${var.environment}"
path = "/groups/"
}
# Group Membership
resource "aws_iam_user_group_membership" "developer_group" {
user = aws_iam_user.developer.name
groups = [aws_iam_group.developers.name]
}
# IAM Role for EC2
resource "aws_iam_role" "ec2_role" {
name = "ec2-role-${var.environment}"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
tags = {
Environment = var.environment
}
}
# S3 Access Policy
resource "aws_iam_policy" "s3_access" {
name = "s3-access-${var.environment}"
description = "Policy for S3 bucket access"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
]
Resource = [
"arn:aws:s3:::${var.bucket_name}",
"arn:aws:s3:::${var.bucket_name}/*"
]
}
]
})
}
# Attach policy to role
resource "aws_iam_role_policy_attachment" "s3_access" {
policy_arn = aws_iam_policy.s3_access.arn
role = aws_iam_role.ec2_role.name
}
# Instance Profile
resource "aws_iam_instance_profile" "ec2_profile" {
name = "ec2-profile-${var.environment}"
role = aws_iam_role.ec2_role.name
}
# Developer Group Policy
resource "aws_iam_group_policy" "developer_policy" {
name = "developer-policy-${var.environment}"
group = aws_iam_group.developers.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"ec2:Describe*",
"s3:List*",
"s3:Get*"
]
Resource = "*"
}
]
})
}
# Password Policy
resource "aws_iam_account_password_policy" "strict" {
minimum_password_length = 12
require_lowercase_characters = true
require_uppercase_characters = true
require_numbers = true
require_symbols = true
allow_users_to_change_password = true
password_reuse_prevention = 24
max_password_age = 90
}
Variables Configuration
Create variables.tf
:
variable "aws_region" {
description = "AWS region"
type = string
default = "us-west-2"
}
variable "environment" {
description = "Environment name"
type = string
default = "dev"
}
variable "bucket_name" {
description = "Name of the S3 bucket to grant access to"
type = string
}
Output Configuration
Create outputs.tf
:
output "iam_user_arn" {
description = "ARN of the created IAM user"
value = aws_iam_user.developer.arn
}
output "iam_role_arn" {
description = "ARN of the created IAM role"
value = aws_iam_role.ec2_role.arn
}
output "instance_profile_arn" {
description = "ARN of the created instance profile"
value = aws_iam_instance_profile.ec2_profile.arn
}
Best Practices
-
Principle of Least Privilege
- Grant minimum necessary permissions
- Use specific resource ARNs instead of wildcards
- Regularly review and audit permissions
-
Security
- Implement strong password policies
- Enable MFA for IAM users
- Rotate access keys regularly
-
Organization
- Use consistent naming conventions
- Tag resources appropriately
- Document policy decisions
Common IAM Patterns
1. Cross-Account Access
resource "aws_iam_role" "cross_account" {
name = "cross-account-access"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::ACCOUNT-ID:root"
}
}
]
})
}
2. Service-Linked Roles
resource "aws_iam_service_linked_role" "es" {
aws_service_name = "es.amazonaws.com"
}
3. Custom Policy with Conditions
resource "aws_iam_policy" "restricted_access" {
name = "restricted-access"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject"]
Resource = "*"
Condition = {
IpAddress = {
"aws:SourceIp": ["10.0.0.0/8"]
}
}
}
]
})
}
Deployment Steps
- Initialize Terraform:
terraform init
- Create
terraform.tfvars
:
aws_region = "us-west-2"
environment = "dev"
bucket_name = "my-application-bucket"
- Review the plan:
terraform plan
- Apply the configuration:
terraform apply
Security Considerations
-
Access Key Management
- Don’t create access keys using Terraform
- Manage access keys manually through AWS Console
- Implement key rotation policies
-
Policy Versioning
- Keep policy documents in version control
- Document policy changes
- Use policy variables for reusability
-
Monitoring and Auditing
- Enable AWS CloudTrail
- Set up alerts for policy changes
- Regular security reviews
Cleanup
Remove the IAM resources when no longer needed:
terraform destroy
Troubleshooting
-
Policy Validation Errors
- Check JSON syntax
- Verify action names
- Confirm resource ARNs
-
Role Trust Issues
- Verify assume role policies
- Check principal formatting
- Confirm account IDs
-
Permission Issues
- Review effective permissions
- Check policy attachments
- Verify group memberships
Conclusion
You’ve learned how to set up and manage AWS IAM using Terraform. This setup provides:
- Consistent access management
- Version-controlled policies
- Reproducible IAM configurations
- Secure access patterns
Remember to:
- Follow security best practices
- Regularly review and update policies
- Document your IAM structure
- Maintain proper access controls