Home/Engineer/Cloud/AWS IAM Roles and Policies i…
CloudIntermediateawsiamSecurity

AWS IAM Roles and Policies in Practice — Least Privilege Best Practices

Covers the conceptual differences among IAM users, groups, roles, and policies; how to write JSON policies; applying least privilege; enforcing MFA; and IAM best practices.

Contents
  1. IAM Core Concepts
  2. JSON Policy Structure
  3. Least-Privilege Policy Examples
  4. Creating an EC2 Instance Role
  5. MFA Enforcement Policy
  6. IAM Best-Practices Checklist

IAM Core Concepts

ConceptDescription
UserA real person or a service account
GroupA collection of users — attach policies to the group
RoleTemporary credentials assumed by AWS services such as EC2 and Lambda
PolicyA JSON document of allow/deny rules
Permissions boundaryThe maximum permission scope a role can have

JSON Policy Structure

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3ReadOnly",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
      "Sid": "DenyDeleteEverything",
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "*"
    }
  ]
}

Deny always takes precedence over Allow.


Least-Privilege Policy Examples

EC2 Read-Only

JSON
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "ec2:Describe*",
      "ec2:List*"
    ],
    "Resource": "*"
  }]
}

Full Access to a Specific S3 Bucket Only

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-specific-bucket",
        "arn:aws:s3:::my-specific-bucket/*"
      ]
    }
  ]
}

Creating an EC2 Instance Role

Bash
# Create the role
aws iam create-role \
  --role-name EC2-S3-ReadOnly \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "ec2.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

# Attach the policy
aws iam attach-role-policy \
  --role-name EC2-S3-ReadOnly \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

# Create and attach the instance profile
aws iam create-instance-profile --instance-profile-name EC2-S3-ReadOnly
aws iam add-role-to-instance-profile \
  --instance-profile-name EC2-S3-ReadOnly \
  --role-name EC2-S3-ReadOnly

MFA Enforcement Policy

Block permissions on console access when MFA is not enabled:

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyWithoutMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:GetUser",
        "iam:ListMFADevices",
        "sts:GetSessionToken"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}

IAM Best-Practices Checklist

Bash
# Check root account usage
aws iam get-account-summary | grep RootAccess

# Find users without MFA
aws iam generate-credential-report
aws iam get-credential-report | python3 -c "
import sys, base64, csv, io
data = eval(sys.stdin.read())
report = base64.b64decode(data['Content']).decode()
reader = csv.DictReader(io.StringIO(report))
for row in reader:
    if row['mfa_active'] == 'false' and row['password_enabled'] == 'true':
        print(row['user'])
"

# Access keys unused for 90+ days
aws iam list-users --query 'Users[*].UserName' --output text | \
  xargs -I{} aws iam list-access-keys --user-name {} --query \
  'AccessKeyMetadata[?Status==`Active`].[UserName,AccessKeyId,CreateDate]' \
  --output table
  • Enable MFA on the root account, then do not use it
  • Use roles instead of personal access keys
  • Regularly delete unused credentials
  • Apply account-level guardrails with AWS Organizations SCPs
#aws#iam#Security#role
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)AWS documentation ↗OWASP documentation ↗

Questions & answers

Ask a question about this guide. We'll review and reply.