IAM
Intermediate 15 min read IAM

Roles and Policies

The mechanics of authorization

Roles are identities you assume; policies are the rules that say what roles can do. Trust relationships, policy structure, effective permissions and the deny rule are the mechanics of every authorization decision.

rolepolicytrust policyassume roleeffective permissionsdeny
Before we start

What you will learn

  • Read and write IAM policies across clouds
  • Explain role assumption and trust
  • Compute effective permissions (intersection + explicit deny)
In 60 seconds

A role is an identity you temporarily assume; its trust policy says who may assume it; its permissions policy says what it can do after. Effective permission = intersection of all applicable allows, minus explicit denies (deny always wins).

Introduction

What is this?

AWS IAM roles: attach a trust policy (who can AssumeRole) and permission policies; assume via STS. Azure: Azure RBAC roles bind role definitions to a scope; managed identity gets a role assignment. GCP: IAM member gets a role binding at the project/org level (roles define permissions). Policies are JSON (AWS) or declarative definitions (Azure RBAC, GCP roles). Effective access on AWS = union of identity policies + resource policies, intersected with SCPs, minus explicit Deny. Azure has deny assignments and Policy deny effects; GCP has organization policy constraints separately.

Motivation

Why do you need it?

  • Role assumption is how cross-account, cross-cloud and CI access works.
  • The deny rule (explicit deny beats allow) is the safety valve for incident cuts.
  • Effective-permission reasoning is table stakes for debugging access.
  • Least privilege is expressed in policies, not vibes.
Think about it

Mental model

Imagine

A theater backstage pass

Think of

A role

The pass (role) is valid for a time, names whom it's for (trust), and lists allowed areas (permissions). You don't ask 'can Bob go anywhere?' but 'what's on Bob's pass today?' — and management can revoke passes instantly with an explicit no-backstage rule.

Mechanics

How it works

  • AWS: create role → trust policy (Principal + Action sts:AssumeRole) → permissions policy; STS issues temp credentials.
  • Azure: define or use a built-in role (Owner/Contributor/Reader), assign at scope; deny assignments override.
  • GCP: role (viewer/editor/owner or custom) bound to member at org/folder/project; org-policy constraints separate.
  • SCPs (AWS Organizations) set the ceiling — effective permission = intersection of SCP and IAM.
  • Explicit Deny anywhere (IAM, SCP, resource policy, deny assignment) blocks the action.

Effective permission computation.

Identity policies
Resource policies
SCP / policy ceiling
Intersection + explicit deny
Allow or Deny
Hands-on

Examples

A cross-account role trust + permission policy

A cross-account role trust + permission policy
// Trust policy: only the CI org's OIDC role in account 9911 may assume
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::991100000000:oidc-provider/oidc.example.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": { "StringEquals": { "oidc.example.com:sub": "repo:acme/app:ref:refs/heads/main" } }
}]
}
# Assume and cap the session
aws sts assume-role --role-arn arn:aws:iam::991100000000:role/Deploy --role-session-name build-123

Trust pins the exact OIDC subject; the role's permissions policies then scope what Deploy may do — least privilege starts at the trust.

Real world

In production

  • CI assumes an OIDC federated role per repo+branch to deploy, so a PR fork can't deploy prod.
  • A security team uses an explicit deny SCP on root user action `iam:DeleteUser` to protect break-glass.
  • Azure: managed identity on App Service gets a Reader+contributor-bounded role at RG scope.
Guidelines

Best practices

  • Least privilege: grant narrowly, expand with evidence, audit quarterly.
  • Scope allow lists by conditions (IP, MFA, OIDC subject, resource tags).
  • Prefer service-scoped roles over per-user Admin/Owner.
  • Store policies as code and review in CI before apply.
Watch out

Common mistakes

  • One giant 'everything admin' role reused everywhere.
  • Trust policy too wide (anyone can assume).
  • Misplacing denies in SCPs vs IAM — deny the resource you didn't mean.
  • Not testing a policy before rollout (the 'deny everything' surprise).
Root cause analysis

Common issues

Error
AssumeRole fails with AccessDenied
Root cause

Trust policy excludes the caller or condition fails

Fix

Verify the caller passes the trust (principal, MFA, OIDC sub) and has sts:AssumeRole permission.

Error
Role can do nothing after assuming
Root cause

Permission policies empty or the effective ceiling is an SCP

Fix

Attach least-privilege permission policies and review the SCP chain.

Error
Explicit deny blocks a needed action
Root cause

A resource policy or SCP has too-broad a deny

Fix

Isolate the deny to the specific condition/resource and re-validate.

When things break

Debugging tips

  • Denied? Trace the layers: identity policy, resource policy, SCP, deny assignment, condition.
  • Use simulated effective policy tools (policy simulator, Effective NSG/LB/RBAC views).
  • A policy that 'should work' but fails usually has a condition or resource ARN mismatch.
  • Check request-time context: MFA, source IP, session tag.
Interviews

Interview checkpoint

Practice

Hands-on lab

Write and Simulate a Policy
30 min · intermediate
In progress
Objectives
  • Author a least-privilege policy for S3 reads
  • Use the AWS policy simulator to validate
  • Model the equivalent GCP/Azure policy

Write and Simulate a Policy

30 min · intermediate

0/4 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Which wins if an allow and an explicit deny both cover an action?

2

A role's trust policy controls who may assume the role.

Go deeper

Official documentation