Home / AWS

AWSHow-toBeginner

AWS IAM basics: users, groups, roles and policies explained with examples you can run

The IAM building blocks in plain terms, how a policy document is read, how roles are assumed, and a small worked example that gives an EC2 instance read access to one S3 bucket without keys.

Deepak Bhardwaj3 min read

Applies toAWS Identity and Access Management, AWS CLI v2

IAM decides who can do what in an AWS account. It feels complicated because there are many policy types, but the basics fit on one page.

The building blocks

Thing What it is Use it for
IAM user A long-lived identity with a password and/or access keys Rarely now: break-glass or legacy tools. People should use IAM Identity Center
Group A set of users that share policies Managing users, if you have them
Role An identity with no permanent credentials, assumed for a time Workloads (EC2, Lambda, ECS), cross-account access, Identity Center users
Policy A JSON document that allows or denies actions on resources Attached to users, groups, roles, or to resources like S3 buckets

Reading a policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadReports",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::acme-reports",
        "arn:aws:s3:::acme-reports/*"
      ]
    }
  ]
}
  • Effect: Allow or Deny.
  • Action: API calls, as service:Operation. Wildcards work (s3:Get*) but be careful.
  • Resource: the ARN(s) the statement applies to. Note ListBucket applies to the bucket ARN and GetObject to the objects (/*).
  • Condition (optional): extra checks such as source IP, tags or MFA.

How AWS decides

  1. Everything starts as denied.
  2. An explicit Allow in an applicable policy can allow it.
  3. An explicit Deny anywhere always wins.
  4. Organisation guardrails (SCPs), permission boundaries and session policies can only reduce what is allowed, never add to it.

So "I attached AdministratorAccess and still get AccessDenied" usually means a Deny somewhere else, often an SCP.

Roles and trust policies

A role has two policies:

  • Trust policy: who may assume it.
  • Permission policies: what it can do once assumed.

Trust policy for EC2:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ec2.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

Worked example: EC2 reads one bucket, no keys

aws iam create-role --role-name app-reports-reader \
  --assume-role-policy-document file://trust-ec2.json

aws iam put-role-policy --role-name app-reports-reader \
  --policy-name read-acme-reports --policy-document file://read-reports.json

aws iam create-instance-profile --instance-profile-name app-reports-reader
aws iam add-role-to-instance-profile --instance-profile-name app-reports-reader --role-name app-reports-reader

aws ec2 associate-iam-instance-profile --instance-id i-0abc1234def567890 \
  --iam-instance-profile Name=app-reports-reader

On the instance:

aws sts get-caller-identity          # shows the assumed role
aws s3 ls s3://acme-reports/

The SDKs and CLI pick up the role credentials automatically from the instance metadata service. No keys on disk.

Tip

Prefer AWS managed policies to start (for example ReadOnlyAccess), then replace them with customer managed policies scoped to your resources. IAM Access Analyzer can generate a least-privilege policy from CloudTrail activity.

Checking what someone can do

aws iam list-attached-role-policies --role-name app-reports-reader
aws iam list-role-policies --role-name app-reports-reader

aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::111111111111:role/app-reports-reader \
  --action-names s3:GetObject s3:PutObject \
  --resource-arns arn:aws:s3:::acme-reports/2026/report.csv \
  --query "EvaluationResults[].[EvalActionName,EvalDecision]" --output table

Beginner mistakes

Mistake Better
Access keys for an app on EC2 Instance profile role
"Action": "*", "Resource": "*" to "make it work" Start from a managed policy, narrow with Access Analyzer
Root user for daily work MFA on root, lock it away, use Identity Center
Sharing one IAM user among people One identity per person through Identity Center

Prevent it next time

  • Turn on MFA for the root user and any remaining IAM users.
  • Run IAM Access Analyzer for unused access and external access findings monthly.
  • Use roles for everything that runs in AWS.