AWS IAM Skill
Create least-privilege IAM policies and debug access issues.
When to Use
- •Create IAM roles/policies
- •Debug "Access Denied" errors
- •Audit existing permissions
- •Set up cross-account access
- •Configure service roles
Policy Principles
Least Privilege
- •Specific actions, not
* - •Specific resources, not
* - •Add Condition blocks when possible
- •Use managed policies over inline
Policy Structure
json
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DescriptiveName",
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::bucket/path/*",
"Condition": {
"StringEquals": {"aws:PrincipalTag/team": "myteam"}
}
}]
}
Debug Access Denied
1. Identify the Error
bash
# Check CloudTrail for denied requests aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=EventName,AttributeValue=<operation> \ --query 'Events[?contains(CloudTrailEvent, `AccessDenied`)]'
2. Simulate Policy
bash
# Test if policy allows action aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789:role/MyRole \ --action-names s3:GetObject \ --resource-arns arn:aws:s3:::mybucket/mykey
3. Common Causes
| Error | Check | Fix |
|---|---|---|
| Explicit deny | Check SCPs, permission boundaries | Remove deny statement |
| Missing action | Policy doesn't include action | Add specific action |
| Wrong resource | ARN doesn't match | Fix resource ARN pattern |
| Condition failed | Condition block not met | Check tags, VPC, etc. |
Common Patterns
S3 Read-Only
json
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::bucket",
"arn:aws:s3:::bucket/*"
]
}
Lambda Execution Role
json
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
}
EKS Pod Role (IRSA)
json
{
"Effect": "Allow",
"Principal": {"Federated": "arn:aws:iam::ACCOUNT:oidc-provider/OIDC"},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"OIDC:sub": "system:serviceaccount:NAMESPACE:SA_NAME"
}
}
}
Cross-Account Access
json
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::OTHER_ACCOUNT:root"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {"sts:ExternalId": "UNIQUE_ID"}
}
}
Quick Commands
bash
# List attached policies aws iam list-attached-role-policies --role-name MyRole # Get policy document aws iam get-role-policy --role-name MyRole --policy-name MyPolicy # Who can assume this role? aws iam get-role --role-name MyRole --query 'Role.AssumeRolePolicyDocument' # Test credentials aws sts get-caller-identity
Red Flags
- •
"Action": "*"-> Too broad - •
"Resource": "*"-> Too broad - •No
Condition-> Consider adding - •Inline policies -> Use managed policies
- •Long-lived access keys -> Use IAM roles