IAM
IAM (Identity and Access Management) is the security spine of AWS. Identities (users, roles, services) get permissions through policies. The model is “deny by default” — nothing works until you explicitly allow it.
Users, roles, policies, least privilege
EXAMPLE
# 1) Concepts
# - Principal : who is making the request (user, role, service)
# - Action : what they're trying to do (s3:GetObject, ec2:RunInstances)
# - Resource : on which thing (an ARN)
# - Condition : optional filters (region, IP, MFA)
# 2) Policy JSON structure
cat > read-bucket.json <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadProductImages",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::product-images",
"arn:aws:s3:::product-images/*"
],
"Condition": {
"StringEquals": { "aws:RequestedRegion": "us-east-1" }
}
}
]
}
JSON
# 3) Create a role for an EC2 instance (and give it the policy)
aws iam create-role --role-name product-reader \
--assume-role-policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Principal":{"Service":"ec2.amazonaws.com"},
"Action":"sts:AssumeRole"
}]
}'
aws iam put-role-policy --role-name product-reader \
--policy-name s3-read --policy-document file://read-bucket.json
aws iam create-instance-profile --instance-profile-name product-reader-profile
aws iam add-role-to-instance-profile --role-name product-reader \
--instance-profile-name product-reader-profile
# Then launch EC2 with --iam-instance-profile Name=product-reader-profile
# 4) Roles for SERVICES (Lambda, EKS, ECS) — same pattern, different Service principal
# Service principals: lambda.amazonaws.com, ecs-tasks.amazonaws.com, eks.amazonaws.com
# 5) Cross-account assume-role — the safe way to share
# Account A creates a role with trust policy: { Principal: { AWS: 'arn:aws:iam::B:root' } }
# User in B: aws sts assume-role --role-arn arn:aws:iam::A:role/X --role-session-name s
# 6) GitHub Actions ↔ AWS via OIDC (no long-lived secrets)
# Trust policy on the role:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::123456789012: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:*" }
}
}]
}
# GitHub Actions workflow:
# - uses: aws-actions/configure-aws-credentials@v4
# with:
# role-to-assume: arn:aws:iam::123:role/gh-deploy
# aws-region: us-east-1
# 7) Least-privilege checklist
# • Start from minimal policy, add as needed (NOT */* and refine later)
# • Use IAM Access Analyzer to identify unused permissions
# • Use IAM Roles, not IAM Users with access keys, wherever possible
# • Add MFA condition for sensitive actions:
# "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
# • Use Conditions to restrict regions, source IPs, tags
# 8) Auditing
# aws iam list-attached-user-policies --user-name alice
# aws iam list-roles | jq '.Roles[].RoleName'
# aws iam generate-credential-report
# aws iam get-credential-report --output text --query Content | base64 -d
# CloudTrail logs every API call — point a SIEM at it.
# 9) AVOID
# • Access keys in code / repos — use roles
# • */* policies (FullAccess) for humans — at least split by service
# • Long-lived users — prefer SSO / OIDC / federated roles
# • Hard-coded ARNs in your app — pass via env / Parameter Store
# • Shared admin user accounts — every human has their own identity
Why it matters
Roles + STS + OIDC kill long-lived credentials. A workflow that assumes a role lives 15 minutes; a leaked access key lives forever. Bias every architecture decision toward temporary, scoped credentials.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Identity & Access Management — users, groups, roles, policies. # Root account: enable MFA, then NEVER use again.Try it Yourself »
Exercise
IAM lets services assume permissions via…
Five letters.
Discussion
Loading…