AWS basics · Lesson 2 · 35 min

IAM: users, groups & policies

Every single AWS request is checked by IAM (Identity and Access Management) before anything happens: who is asking, and does a policy say they may do this, to this thing? Get IAM right and a leaked key or a clumsy command can only do a little damage. Get it wrong and one mistake can delete everything.

You will learn

  • Users, groups, roles and policies, and how they fit together
  • Reading a policy: Effect, Action, Resource
  • How AWS decides: default deny, allow, and explicit deny wins
  • Access keys, named profiles and --profile
  • Least privilege: writing your own policy and testing it

The four building blocks

ThingWhat it isLinux cousin
UserA person (or a program) with long-lived credentials: a console password and/or access keysan account in /etc/passwd
GroupA bag of users. Attach policies to the group, and every member gets themwheel / sudo
RoleAn identity with no password or keys. Someone or something "puts it on" and gets temporary credentials. EC2 servers, Lambda functions and people from other accounts use rolesa bit like sudo -u
PolicyA JSON document listing what is allowed or denied. Attached to a user, group or role/etc/sudoers rules

Reading a policy

{
  "Version": "2012-10-17",                       # always this date: it's the policy language version
  "Statement": [
    {
      "Effect": "Allow",                         # or "Deny"
      "Action": ["s3:GetObject", "s3:PutObject"], # service:Operation, wildcards allowed: "s3:*"
      "Resource": "arn:aws:s3:::cht-notes-123456789012/*"   # which things (ARNs)
    }
  ]
}

AWS evaluates every request the same way:

  1. Start at deny. Nothing is allowed unless something says so (the "implicit deny").
  2. If any attached policy has a matching Allow, it's allowed…
  3. …unless any policy has a matching Deny. An explicit deny always wins.

AWS ships hundreds of ready-made AWS managed policies (ReadOnlyAccess, AmazonS3ReadOnlyAccess, AdministratorAccess…). They're handy, but broad. For real work you write customer managed policies that allow exactly what's needed. That's least privilege.

Users, groups and keys from the CLI

aws iam create-group --group-name readers
aws iam attach-group-policy --group-name readers \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
aws iam create-user --user-name alex
aws iam add-user-to-group --user-name alex --group-name readers
aws iam create-access-key --user-name alex        # the secret is shown ONCE: save it now

Put permissions on groups, not on each user. When Alex changes jobs, you move Alex to another group instead of hunting through a pile of policies.

Profiles: more than one identity on one computer

aws configure wrote a [default] profile. Add others with --profile:

aws configure --profile alex                        # the same four questions
aws configure set region us-east-1 --profile alex   # or set one value at a time
aws s3 ls --profile alex                            # this one command as alex
export AWS_PROFILE=alex                             # the whole shell as alex
unset AWS_PROFILE                                   # back to default
~/.aws/credentials
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[alex]
aws_access_key_id = AKIAI22QSPKMUTFG3PVC
aws_secret_access_key = PsOzGjF25qJawoXRdf4XwGo2JAaCg09mfDA8NzOr

Profiles are how you test permissions honestly: run the command as the user you're giving access to, not as your all-powerful admin.

Roles: no keys on servers

A web server that reads from S3 needs permissions. Never copy access keys onto it. Give the server a role instead (through an instance profile). The server picks up short-lived credentials automatically, and AWS rotates them for you. A role has a trust policy saying who may use it:

{ "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" }
aws iam create-role --role-name web-server --assume-role-policy-document file://policies/ec2-trust.json
aws iam attach-role-policy --role-name web-server --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam create-instance-profile --instance-profile-name web-server
aws iam add-role-to-instance-profile --instance-profile-name web-server --role-name web-server

Then launch servers with --iam-instance-profile Name=web-server. People can use roles too: AWS IAM Identity Center signs you in through your browser with temporary credentials, which is what most companies use instead of access keys.

Keys leak. Plan for it.

Give each person their own user (never share one), turn on MFA, prefer roles and temporary credentials over access keys, and delete keys nobody uses: aws iam list-access-keys, aws iam delete-access-key. A user can have at most two keys, so you can make a new one, switch to it, then delete the old one.

Practice: a read-only helper, then a custom policy 🔐

You're signed in as sandbox-admin. There's a bucket called cht-notes-123456789012 with some notes in it. Create a user who can read things but not change them, prove it, then grant exactly one extra permission.

Quick check

1. A user's group allows s3:*, but another attached policy has "Effect": "Deny", "Action": "s3:DeleteObject". Can the user delete objects?

2. A web server needs to read files from S3. What's the right way to give it permission?

3. What is "least privilege"?

Finished the missions and the quiz? Mark it done to track your progress.