Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

IAM policies: who may do what

After this lesson: I can read a policy and say whether a call is allowed.

55 min lessonNo commands

Who decides which door opens?

An IAM policy is the written list of what a person or a program may do in a cloud account. Reading one correctly is how you stop a leak before it happens, and how you fix an "access denied" error.

A student card works the same way. It opens the library door but not the staff room, because somebody wrote down which doors each card may open.

By the end of this lesson

Note

I can read a policy and say whether a call is allowed.

Key words

WordWhat it meansExample
Policya document that lists what may and may not be done
Statementone rule inside a policy
Effectwhether a statement allows or denies
Actionthe call being mades3:GetObject
Resourcethe thing the call is made on
Least privilegegiving only the access a job needs

The cells students fill in are left blank in this preview.

A policy is a list of statements

A policy is a JSON document. It has a Version and a list called Statement. Each statement says three things: the effect, the action and the resource.

The effect is Allow or Deny. The action is the call, such as s3:GetObject, which reads one file. The resource is what the call is made on, named by a long text called an ARN. These policies are invented. Nothing here needs an account.

Try it: read a policy

Code: python
policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": ["s3:GetObject", "s3:PutObject"],
            "Resource": "arn:aws:s3:::photos-demo/*",
        },
        {
            "Effect": "Deny",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::photos-demo/private/*",
        },
    ],
}

for statement in policy["Statement"]:
    print(statement["Effect"], statement["Action"], statement["Resource"])
# Change "Deny" to "Allow". The program still reads it. Does the meaning change?

A star matches any run of characters

Writing every file name would take for ever. So a pattern may hold a star. A star matches any run of characters, including none at all.

The resource "arn:aws:s3:::photos-demo/" matches every object in that bucket. The action "s3:" matches every S3 call. A pattern with no star must match the text exactly.

Worked example: which texts a pattern matches

PatternTextMatches?
s3:*s3:GetObjectYes
s3:*sqs:SendMessageNo, it does not start with s3:
s3:Get*s3:GetObjectYes
s3:Get*s3:PutObjectNo
photos/*photos/Yes, the star matches nothing
*.jpgcat.jpgYes
s3:GetObjects3:GetObjectAclNo, no star, so exact

The cells students fill in are left blank in this preview.

A deny always wins

To decide one call, find every statement whose action and resource both match it. Then apply three rules.

If any matching statement says Deny, the call is refused. This is an explicit deny, and it wins over every Allow. If none denies but one allows, the call is allowed. If nothing matches, the call is refused anyway. That is an implicit deny.

Worked example: three calls on the photos policy

CallStatements that matchResult
s3:GetObject on photos-demo/cat.jpgAllow onlyAllowed
s3:GetObject on photos-demo/private/id.jpgAllow and DenyRefused: explicit deny wins
sqs:SendMessage on a queueNoneRefused: implicit deny

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think a call is allowed unless a policy forbids it. It is the other way round. A call is refused unless a statement allows it, and a Deny beats any Allow.

Try it: three rules in code

Code: python
matched = ["Allow", "Deny"]

if "Deny" in matched:
    result = "refused: explicit deny"
elif "Allow" in matched:
    result = "allowed"
else:
    result = "refused: implicit deny"
print(result)
# Change matched to ["Allow"], then to []. What does each print?

Give the least that works

A photo site needs to read and add photos. It does not need to delete them or touch the queues. So its policy names only those two actions, on only that bucket.

This is least privilege. If the site is ever misused, the damage stops at what the policy allowed.

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.