Everyone Can Learn Program
中文 Start learning
Specialty · Cloud and SRELesson 3 of 5Free to read

IAM and least privilege · Cloud and Reliability

Who is allowed to do what in a cloud account?

Course contents

Why you need it

Cloud accounts are controlled by permission policies. A policy that's too broad turns one leaked key or one bug into access to everything: every bucket, every database, every bill. Least privilege, giving each app exactly what it needs and nothing more, is one of the most effective security habits there is, and it starts with reading policies correctly.

The intuition

A policy is a list of statements. Each says: for these actions on these resources, Allow (or Deny). Wildcards are common: s3:Get*, photos/*.

policy = [
    {"effect": "Allow", "actions": ["s3:GetObject", "s3:PutObject"], "resources": ["shop-photos/*"]},
    {"effect": "Deny",  "actions": ["s3:*"],                         "resources": ["shop-photos/private/*"]},
]

Evaluation works like AWS IAM, simplified:

  1. Find the statements that match both the action and the resource.
  2. If any matching statement is a Deny → denied. An explicit deny always wins.
  3. Otherwise, if any is an Allow → allowed.
  4. Otherwise → denied. Nothing is allowed unless something allows it (implicit deny).

Least privilege in practice: list what the app really does (read photos, upload photos) and allow only those actions on only those resources. "actions": ["*"], "resources": ["*"] is the opposite.

Definition

Policy

A list of statements that allow or deny actions on resources.

Explicit deny

A matching Deny statement. It overrides every Allow.

Least privilege

Granting only the actions and resources a job needs, nothing more.

Examples

fnmatch matches * and ? the same way IAM patterns do.

import fnmatch

print(fnmatch.fnmatchcase("s3:GetObject", "s3:Get*"))
print(fnmatch.fnmatchcase("s3:PutObject", "s3:Get*"))
print(fnmatch.fnmatchcase("shop-photos/cats/1.jpg", "shop-photos/*"))
print(fnmatch.fnmatchcase("shop-photos", "shop-photos/*"))
Output
True
False
True
False
Step by step
  1. L3
    • matches any characters: Object.
    True
  2. L5
    • also crosses / here, so everything under the folder matches.
    True
  3. L6The pattern needs a / after the name, so the bucket itself doesn't match.False

Allow, deny, and nothing

Try it yourself

An explicit deny beats an allow; no match means no.

import fnmatch

def matches(patterns, value):
    return any(fnmatch.fnmatchcase(value, p) for p in patterns)

def allowed(policy, action, resource):
    hits = [s for s in policy if matches(s["actions"], action) and matches(s["resources"], resource)]
    if any(s["effect"] == "Deny" for s in hits):
        return False
    return any(s["effect"] == "Allow" for s in hits)

policy = [
    {"effect": "Allow", "actions": ["s3:GetObject", "s3:PutObject"], "resources": ["shop-photos/*"]},
    {"effect": "Deny", "actions": ["s3:*"], "resources": ["shop-photos/private/*"]},
]

print(allowed(policy, "s3:GetObject", "shop-photos/cat.jpg"))
print(allowed(policy, "s3:GetObject", "shop-photos/private/id.png"))
print(allowed(policy, "s3:DeleteObject", "shop-photos/cat.jpg"))
Output
True
False
False
Step by step
  1. L7Statements matching both the action and the resource.
  2. L8Any matching deny wins.
  3. L18Both statements match; the Deny wins.False
  4. L19Nothing allows deleting: implicit deny.False

Common mistakes

"*" on "*"

An app with full access turns any bug or leaked key into a full account takeover. List the actions it really uses.

Expecting Allow to beat Deny

An explicit Deny always wins, wherever it comes from. That's how guardrails like "never delete backups" work.

Long-lived keys

Access keys that never expire leak eventually. Prefer roles with short-lived credentials, and rotate any key that must exist.

Quick quiz

1. One statement allows `s3:*` on `logs/*`; another denies `s3:DeleteObject` on `logs/*`. Can the app delete `logs/a.txt`?

  1. ANo: the explicit deny wins
  2. BYes: s3:* allows it
  3. CIt depends on the order of the statements
Show the answer

Answer: A

Order doesn't matter. Any matching Deny overrides every Allow.

2. A policy only allows `s3:GetObject`. What happens on `s3:PutObject`?

  1. ADenied: nothing allows it
  2. BAllowed: nothing denies it
  3. CAn error in the policy
Show the answer

Answer: A

Implicit deny: anything not allowed is refused.

Practice

3 exercises in three steps: predict what a program prints, change a program to meet a new requirement, then write one from scratch. Your code runs in the browser and is checked the moment you submit.

  1. PredictDecide each request

    Type exactly what this prints.

  2. ModifyLeast privilege

    The photo app only needs to read and upload files under shop-photos/uploads/. Its policy allows everything. Replace POLICY with one that allows exactly s3:GetObject and s3:PutObject on shop-photos/uploads/*.

  3. WriteEvaluate a policy

    Write allowed(policy, action, resource) yourself. Each statement has "effect" ("Allow" or "Deny"), "actions" and "resources" (lists of patterns with * and ?). Rules:

    1. a statement applies if any action pattern matches action and any resource pattern matches resource
    2. any applying Deny → False
    3. else any applying Allow → True
    4. else False

    Use fnmatch.fnmatchcase(value, pattern) for matching.

Practise this lesson

Open the interactive lesson to edit and run these examples and solve the exercises with instant feedback. Free to start, no sign-up.

Interactive lessons open in order. If you have not done the earlier ones yet, you start at the course map.

Terms in this lesson

TermChineseDefinition
IAM身份与访问管理Identity and access management: who may do what in a cloud account.
Least privilege最小权限Only the permissions a job needs.
Implicit deny隐式拒绝Anything not explicitly allowed is refused.