IAM
01 / 03

Policies & Permission Boundaries

AWS IAM: Policies & Permission Boundaries

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3ReadOnSpecificBucket",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
      "Sid": "DenyDeleteEverywhere",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteBucket"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowEC2InRegion",
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    },
    {
      "Sid": "AllowResourcesOwnedByUser",
      "Effect": "Allow",
      "Action": "dynamodb:*",
      "Resource": "arn:aws:dynamodb:*:*:table/my-table-${aws:username}"
    }
  ]
}

Common Condition Keys

"Condition": {
  "StringEquals": { "aws:RequestedRegion": "us-east-1" },
  "StringLike": { "s3:prefix": "home/${aws:username}/*" },
  "StringNotEquals": { "aws:PrincipalAccount": "123456789012" },
  "Bool": { "aws:MultiFactorAuthPresent": "true" },
  "NumericLessThan": { "aws:MultiFactorAuthAge": "3600" },
  "IpAddress": { "aws:SourceIp": "203.0.113.0/24" },
  "NotIpAddress": { "aws:SourceIp": "203.0.113.0/24" },
  "ArnEquals": { "aws:PrincipalArn": "arn:aws:iam::123456789012:user/alice" },
  "DateGreaterThan": { "aws:CurrentTime": "2024-01-01T00:00:00Z" }
}

Policy Types

1. Identity-based policies (most common)
   - Attached to users, groups, or roles
   - Managed policies: AWS-managed or customer-managed (reusable)
   - Inline policies: embedded in single identity (avoid — hard to manage)

2. Resource-based policies
   - Attached to resources (S3 bucket policy, SQS, KMS key policy)
   - Grant cross-account access without assuming a role
   - Example: S3 bucket policy allowing specific external account

3. Permission boundaries
   - Maximum permissions a user/role can have
   - Does NOT grant access by itself — must ALSO have identity-based policy
   - Use case: allow devs to create roles but limit what roles they can create

4. Service Control Policies (SCP) — AWS Organizations
   - Applied at Organization/OU/Account level
   - Maximum permissions for ENTIRE account
   - Override nothing at account level — all accounts need both SCP + identity policy

5. Session policies
   - Passed when assuming a role or federating
   - Further restrict temporary credentials

Evaluation order:
  Deny in SCP → explicit Deny in any policy → Allow in all relevant policies

Policy Creation & Management

# Create customer-managed policy
aws iam create-policy   --policy-name S3ReadMyBucket   --policy-document file://policy.json

# Attach to user/group/role
aws iam attach-user-policy   --user-name alice   --policy-arn arn:aws:iam::123456789012:policy/S3ReadMyBucket

# List policies
aws iam list-policies --scope Local   # customer-managed
aws iam list-policies --scope AWS     # AWS-managed
aws iam list-attached-user-policies --user-name alice

# Simulate policy evaluation
aws iam simulate-principal-policy   --policy-source-arn arn:aws:iam::123456789012:user/alice   --action-names s3:GetObject   --resource-arns arn:aws:s3:::my-bucket/file.txt

# IAM Access Analyzer — detect overly permissive policies
aws accessanalyzer create-analyzer   --analyzer-name account-analyzer   --type ACCOUNT

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free