IAM (Identity and Access Management) controls who can do what in AWS. Getting it wrong means either security breaches or blocked deployments. This guide covers what DevOps engineers need.
Core Concepts
| Concept | What It Is | Example |
|---|---|---|
| User | A person or application | alice, ci-bot |
| Group | Collection of users | developers, admins |
| Role | Temporary credentials for services/users | ec2-s3-access, lambda-execution |
| Policy | JSON document defining permissions | Allow S3 read on specific bucket |
Rule of thumb: Use roles, not users. Users are for humans; roles are for everything else.
Policy Structure
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Read",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "10.0.0.0/8"
}
}
}
]
}| Field | Purpose |
|---|---|
Effect | Allow or Deny |
Action | AWS API actions (e.g., s3:GetObject) |
Resource | ARNs of resources this applies to |
Condition | Optional: IP, time, MFA, tags |
Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Least Privilege Principle
Start with zero permissions, add only what is needed:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:eu-west-1:123456789:repository/my-app"
},
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}This CI role can only pull images from one specific ECR repository.
Common Role Patterns
EC2 Instance Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::app-assets/*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:eu-west-1:123456789:secret:app/*"
}
]
}CI/CD Role (GitHub Actions OIDC)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:ListClusters"
],
"Resource": "arn:aws:eks:eu-west-1:123456789:cluster/production"
}
]
}Trust policy (allow GitHub Actions to assume the role):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"
}
}
}
]
}Terraform IAM
# Role
resource "aws_iam_role" "app" {
name = "app-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
})
}
# Policy
resource "aws_iam_role_policy" "app_s3" {
name = "app-s3-access"
role = aws_iam_role.app.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["s3:GetObject", "s3:PutObject"]
Resource = "${aws_s3_bucket.assets.arn}/*"
}]
})
}
# Instance profile
resource "aws_iam_instance_profile" "app" {
name = "app-profile"
role = aws_iam_role.app.name
}Get weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →IAM Best Practices
| Practice | Why |
|---|---|
| Use roles, not access keys | Keys can leak; roles are temporary |
| Enable MFA for humans | Prevents credential theft |
| Use OIDC for CI/CD | No long-lived credentials |
| Tag everything | Track who created what |
| Review with IAM Access Analyzer | Find overly permissive policies |
| Use permission boundaries | Limit what roles can grant |
| Separate accounts per environment | Blast radius reduction |
Debugging IAM
# Who am I?
aws sts get-caller-identity
# Simulate a policy
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789:role/app-role \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::my-bucket/file.txt
# Check recent access
aws iam generate-service-last-accessed-details \
--arn arn:aws:iam::123456789:role/app-roleWhat's Next?
Our Terraform for Beginners course covers AWS IAM automation with Terraform across 15 hands-on lessons. First lesson is free. -e ---
Ready to go deeper? Explore our hands-on DevOps courses — practical labs covering Docker, Ansible, Terraform, and more.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Quality vs Safety in Engineering
Quality and safety are not the same thing in software engineering. Learn when to prioritize safety over quality, how to build guardrails without slowing.
Ansible Inventory: Static and Dynamic
Master Ansible inventory in INI and YAML formats. Learn host groups, variables, dynamic inventory plugins for AWS and Azure, and patterns for scaling.
Terraform Workspaces for Environments
Use Terraform workspaces for dev, staging, and production. Practical patterns, trade-offs, and best practices for multi-env IaC.
Backstage Developer Portal Guide
Spotify Backstage is the most popular open-source developer portal. Learn how to set it up, create software templates, build a service catalog, and integrate.
Backstage Software Catalog Setup
Backstage's software catalog gives you a single inventory of all services, APIs, and infrastructure. Learn how to register components, define system models.
Bash Scripting for DevOps
Essential Bash scripting skills for DevOps engineers. Variables, conditionals, loops, functions, error handling, and practical automation scripts for daily.
Explore topics
Browse more articles on the topics covered here.