LearnAWS
AWS02. Governance & Identity·EXPERT·8 min read

4. Identity & Access Management

Identity & Access Management

TL;DR

  • Effective IAM permissions are the intersection of every applicable layer — SCP, permission boundary, identity policy, resource policy, session policy — not the union. An explicit Deny in any layer overrides an Allow everywhere else.
  • ABAC (tag-based policies) replaces linear RBAC sprawl (one role per team per environment) with a small, stable policy set, at the cost of requiring enforced tagging discipline.
  • Permission boundaries cap what a self-service-created role can ever do; SCPs cap what an entire OU/account can ever do. Neither grants access on its own.
  • STS AssumeRole with short-lived credentials is the default mechanism for cross-account access, human federation, and workload identity — long-lived IAM user access keys are a legacy pattern and a standing finding in any security review.
  • The policy simulator is necessary but not sufficient: it does not always fully model nested SCP/boundary/session-policy interactions, so production-adjacent testing in non-prod is still required.

Core Concepts

Policy evaluation: intersection, not union

A common misconception treats permissions as additive: “the role has this policy, so it can do this.” Effective permissions are the intersection of every layer that applies to a given request: SCPs at the OU level, permission boundaries on the role, the identity policy itself, any resource policy on the target, and session policies if the credentials were assumed via STS. Missing one layer in the mental model produces either over-granted access or an “Access Denied” that looks like a bug but is correct behavior from a forgotten layer. Evaluation order, at a high level: an explicit Deny in any applicable policy wins outright; absent an explicit Deny, an explicit Allow in any layer is required, and if no layer allows the action, the implicit default is Deny.

IAM identity policies

The base unit: a policy attached to a user, group, or role defining which actions a principal can take on which resources, under which conditions (Condition blocks — source IP, MFA presence, tag matches, time of day). Scales fine for a small number of stable roles. Breaks down once dozens of teams each want a slightly-different-but-mostly-the-same role, producing policy sprawl that becomes its own maintenance burden and audit liability.

ABAC (attribute-based access control)

The scalable alternative to policy-per-team RBAC. Principals are tagged (via IAM Identity Center attributes or STS session tags) and resources are tagged, and a small number of policies grant access based on tag matches — e.g., aws:PrincipalTag/team equals aws:ResourceTag/team. This can collapse hundreds of explicit RBAC roles into a handful of ABAC policies. The trade-off is structural: ABAC only works if tagging is enforced (via SCPs requiring tags on resource creation, or tag policies in Organizations); without that enforcement, the model silently breaks the first time a resource is created without the expected tag.

Permission boundaries

A different problem than ABAC/RBAC: safely delegating iam:CreateRole/iam:CreatePolicy to a team without opening a path to privilege escalation. A permission boundary sets a hard ceiling on a role — no identity policy attached to that role, regardless of who attaches it or when, can exceed the boundary’s permissions. This is what makes self-service IAM role creation (for CI/CD pipelines, application workloads) safe to delegate to platform or application teams.

SCPs (Service Control Policies)

Operate one level above individual accounts, at the OU or account level within AWS Organizations. SCPs never grant permissions — they only restrict the maximum available permissions for every principal in scope, including the root user of member accounts. A role can have a permissive identity policy and still be blocked entirely by an SCP at the OU level.

Resource policies

Attached to the target resource, not the principal — bucket policies, KMS key policies, Lambda resource policies, SQS/SNS policies. These are how cross-account access is actually authorized: an identity policy in Account A alone cannot grant access to a resource in Account B without either a matching resource policy on that resource, or a role in Account B that Account A’s principal can assume.

Session policies

The least-understood layer. When a role is assumed via STS, an inline session policy can be passed that further restricts — never expands — what that specific session can do relative to what the role’s identity policy allows. Useful for handing out narrowly-scoped, single-purpose temporary credentials derived from a broader role, without creating a new role for every scope variation.

IAM Identity Center and Federation

The mechanism for human access without per-account IAM users: a single identity provider (SAML/OIDC), permission sets defined centrally, mapped to roles in target accounts and assumed via STS behind the scenes at login. A design where humans hold long-lived IAM user access keys is a standing finding in a security review, not an acceptable baseline.

STS (Security Token Service)

The underlying mechanism for nearly everything above: short-lived, automatically-expiring credentials issued via AssumeRole (and variants like AssumeRoleWithWebIdentity, AssumeRoleWithSAML). Used for cross-account access, federated human login, and workload identity (IRSA in EKS, OIDC federation from GitHub Actions/GitLab CI). Any service-to-service integration still relying on long-lived access keys instead of STS-issued temporary credentials is the first item to flag in a modern IAM review.

RBAC vs ABAC

Aspect RBAC (explicit roles) ABAC (tag-based)
Policy count One (or more) per team/environment/resource combination Small, stable set independent of team count
Scaling Linear growth with teams × environments; becomes sprawl Scales to any number of teams without new policies
Prerequisite None beyond role design Enforced, disciplined tagging on principals and resources
Failure mode Policy sprawl, drift, hard-to-audit duplication Silent access breakage if tags are missing or wrong
Best fit Small number of stable, well-understood roles Large or fast-growing number of teams/environments

Permission Boundary vs SCP

Aspect Permission Boundary SCP
Scope Attached to a single IAM user/role Applied at OU or account level in Organizations
Applies to That one principal Every principal in the account(s)/OU, including root
Purpose Cap self-service-created roles to prevent privilege escalation Cap the maximum permissions available across an account/OU
Grants access? No — ceiling only No — ceiling only
Typical owner Platform team delegating iam:CreateRole Central cloud governance / security team

Command / Configuration Reference

// Permission boundary attached at role creation — caps max permissions regardless of later policy attachments
{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "s3:*", "Resource": "arn:aws:s3:::team-a-*" },
    { "Effect": "Deny", "Action": "iam:*", "Resource": "*" }
  ]
}
// ABAC policy: allow access only when principal tag matches resource tag
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "*",
    "Condition": {
      "StringEquals": { "aws:ResourceTag/team": "${aws:PrincipalTag/team}" }
    }
  }]
}
# Assume a cross-account role via STS, returns short-lived credentials
aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/partner-access \
  --role-session-name lambda-session

# Simulate whether a principal can perform an action (necessary but not sufficient check)
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::111111111111:role/app-role \
  --action-names s3:GetObject \
  --resource-arns arn:aws:s3:::example-bucket/*
# SCP attached at OU level (Organizations) — restricts, never grants
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Deny",
    "Action": "iam:CreateUser",
    "Resource": "*"
  }]
}

Common Pitfalls

  • Pitfall: Treating permissions as additive across policy types. Why: Effective access is the intersection of all applicable layers, and an explicit Deny anywhere overrides an Allow everywhere. Fix: Evaluate SCP, boundary, identity policy, resource policy, and session policy together before predicting an outcome.
  • Pitfall: Granting iam:PassRole too broadly. Why: It lets a principal hand its own (or a more privileged) role to a service, enabling effective privilege escalation. Fix: Scope iam:PassRole to specific role ARNs and pair it with iam:PassedToService conditions.
  • Pitfall: Long-lived IAM user access keys for service accounts. Why: Keys stored in config files or CI secrets outlive the person who created them and are rarely rotated. Fix: Replace with STS AssumeRole, IRSA, or OIDC federation for workload identity.
  • Pitfall: Adopting ABAC without enforcing tag governance. Why: The model depends entirely on consistent tagging; a resource created without the expected tag silently loses or gains access. Fix: Enforce required tags via SCPs or tag policies at resource-creation time, not after the fact.
  • Pitfall: Trusting the policy simulator as the final check before a production IAM change. Why: It does not always fully model nested SCP, permission boundary, and session policy interactions in complex scenarios. Fix: Test the actual access path in a non-production account before shipping.

Interview Questions

  • “Explain the policy evaluation order, including where a permission boundary and an SCP each sit in that logic.” — tests whether the intersection model (versus additive) is genuinely understood.
  • “Design an access model for 40 application teams across dev/staging/prod without creating 120 explicit IAM roles.” — tests whether ABAC is reached for, and whether the tagging-discipline trade-off is acknowledged.
  • “A role has an identity policy allowing an action, but a bucket policy explicitly denies it. What happens, and why?” — tests whether explicit-Deny precedence is understood at a mechanism level, not just as a rule of thumb.
  • “A GitHub Actions pipeline needs to deploy to three AWS accounts. Walk through the identity design with zero long-lived secrets.” — tests OIDC federation and STS AssumeRole understanding end to end.
  • “A team wants to self-service create IAM roles for their own CI/CD. How do you make that safe?” — tests whether permission boundaries are understood as the mechanism, not just a name.
🔒 Locked
Sign in and unlock the full syllabus to keep reading.
Sign in to continue
Knowledge check
5 scenario questions on this topic
Take the quiz →
Related in 02. Governance & Identity
3. Enterprise Landing Zone
EXPERT