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.
What you will learn
- Read and write IAM policies across clouds
- Explain role assumption and trust
- Compute effective permissions (intersection + explicit deny)
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).
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.
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.
Mental model
A theater backstage pass
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.
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.
Examples
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 sessionaws sts assume-role --role-arn arn:aws:iam::991100000000:role/Deploy --role-session-name build-123Trust pins the exact OIDC subject; the role's permissions policies then scope what Deploy may do — least privilege starts at the trust.
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.
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.
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).
Common issues
AssumeRole fails with AccessDeniedTrust policy excludes the caller or condition fails
Verify the caller passes the trust (principal, MFA, OIDC sub) and has sts:AssumeRole permission.
Role can do nothing after assumingPermission policies empty or the effective ceiling is an SCP
Attach least-privilege permission policies and review the SCP chain.
Explicit deny blocks a needed actionA resource policy or SCP has too-broad a deny
Isolate the deny to the specific condition/resource and re-validate.
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.
Interview checkpoint
Hands-on lab
- 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
Quick quiz
Which wins if an allow and an explicit deny both cover an action?
A role's trust policy controls who may assume the role.