examhub .cc The most efficient path to the most valuable certifications.
Vol. I
In this note ≈ 36 min

Authorization Iam Policies Troubleshooting

7,050 words · ≈ 36 min read

Authorization, IAM policies, and AccessDenied troubleshooting form the operational core of SCS-C02 Domain 4 — the one area where the exam stops asking what a service does and starts asking why a specific API call failed at 3am. Authorization, IAM policies, and AccessDenied troubleshooting are not a single feature but a discipline: the ability to read a policy, predict the outcome of an authorization decision, and decode an AccessDenied error message into the exact missing or conflicting statement. SCS-C02 Task 4.2 — "Design, implement, and troubleshoot authorization for AWS resources" — weights authorization, IAM policies, and AccessDenied troubleshooting heavily because the security engineer is the person teams call when nothing else has worked.

This Specialty-depth guide walks through every authorization, IAM policies, and AccessDenied troubleshooting topic on SCS-C02: the five policy types (managed, inline, identity-based, resource-based, session) and when each is correct; the policy evaluation algorithm where explicit deny always wins; the four mandatory elements (Principal, Action, Resource, Condition) and how each can fail; ABAC versus RBAC trade-offs and when session tags solve scaling problems RBAC cannot; least privilege and separation of duties as design principles; and a deep set of AccessDenied troubleshooting walkthroughs using CloudTrail, IAM Policy Simulator, and IAM Access Advisor. By the end you will be able to look at any authorization, IAM policies, and AccessDenied troubleshooting scenario on SCS-C02 and identify the exact policy layer that needs to change.

What Are Authorization, IAM Policies, and AccessDenied Troubleshooting?

Authorization, IAM policies, and AccessDenied troubleshooting are the security-engineering activities of designing IAM policies that grant the right access, implementing those policies through the correct combination of attachment points (users, groups, roles, resources, sessions, OUs), and diagnosing the precise reason an authenticated principal received an AccessDenied response on a specific API call. Authorization, IAM policies, and AccessDenied troubleshooting span the design phase (write policies that meet least-privilege intent), the implementation phase (attach them at the right layer), and the operations phase (decode CloudTrail entries when something goes wrong). All three are tested on SCS-C02 because security engineers own every phase.

Why Authorization, IAM Policies, and AccessDenied Troubleshooting Dominate Domain 4

Domain 4 carries 16% of the SCS-C02 exam weight, and within Domain 4 the authorization task statement (4.2) shares scope with authentication (4.1). Authorization, IAM policies, and AccessDenied troubleshooting questions are unusually concrete on SCS-C02 — instead of asking which service to choose, they hand you a policy snippet, an SCP, and a CloudTrail event, then ask why the call failed or which single change would make it succeed. You cannot bluff this domain; you have to read JSON.

Where Authorization, IAM Policies, and AccessDenied Troubleshooting Live in the Security Engineer's Workflow

A security engineer typically works authorization, IAM policies, and AccessDenied troubleshooting in three loops: the design loop (developer requests new role, security writes policy, Policy Simulator validates), the audit loop (Access Advisor and Access Analyzer surface unused permissions, security tightens policies), and the incident loop (production AccessDenied alarm, security pulls CloudTrail, identifies the missing layer, fixes within an SLA). All three loops are exam-relevant.

Plain-Language Explanation: Authorization, IAM Policies, and AccessDenied Troubleshooting

Authorization sounds abstract, so three everyday analogies pin it down. Each surfaces a different angle of authorization, IAM policies, and AccessDenied troubleshooting; read all three.

Analogy 1 — The Office Building Door System (Building / Access Control Analogy)

Picture a corporate office building. Each room is an AWS resource; each employee badge is an IAM principal; the badge reader at every door evaluates the authorization decision. Authorization, IAM policies, and AccessDenied troubleshooting in IAM work like the layered access-control system this building uses.

Your employee badge profile is the identity policy — it lists which rooms you may enter. The room sign-in sheet is a resource policy — some rooms additionally require their own approved-visitor list, and even with a master badge you cannot enter unless the room policy includes you (this is cross-account access). The fire marshal's overriding rule is the SCP — a building-wide directive saying "no one enters the server room after 10pm regardless of badge," and that rule beats any positive permission. The temp visitor pass issued at the front desk is a session policy — it can only restrict what your normal badge already grants for that visit; it cannot expand it. The department head's spending limit is a permissions boundary — even if your manager hands you a wider job description, the boundary caps what your role can ever do.

When the door beeps red and refuses you, AccessDenied troubleshooting is the security guard's diagnostic process: they check whether your badge is on the room's approved list (resource policy), whether your badge profile permits this room (identity policy), whether a building-wide rule blocks entry right now (SCP), whether your visitor pass is more restrictive than your badge (session policy), and whether your boundary caps you below your manager's grant (permissions boundary). Five places to look — and an explicit "no entry" sticker on the door (explicit Deny) wins over any "yes" stamp.

Analogy 2 — The Open-Book Exam With Rule Layers (Exam / Rules Analogy)

Imagine a certification exam with five layers of rules governing what you may bring to the test. The exam is the AWS API call; you are the principal; the exam invigilator is the IAM authorization engine.

The national exam board's prohibited list is the SCP — items the board has banned organization-wide that no test centre can override (no phones, no smartwatches, no calculators in the policy exam). The test centre's allowed-items list is the identity policy — what the centre normally permits (paper notes, pencil, water bottle). The specific room's house rules are the resource policy — some rooms additionally allow earplugs or block water bottles. The proctor's day-of restriction is the session policy — the proctor can further restrict your allowed items today even if your badge says otherwise, but cannot grant items the centre prohibits. The invigilator licensing standard is the permissions boundary — the proctor's authority is itself capped by what the licensing body lets proctors do.

When the invigilator stops you at the door (AccessDenied), troubleshooting follows the layered review: check the national prohibited list first (SCP explicit Deny — game over), then the centre's list (identity allow), then the room policy (resource allow for cross-centre attendance), then today's proctor instructions (session policy intersect), then the proctor's own licensing cap (boundary). Five review steps; any single explicit prohibition kills the request.

Analogy 3 — The Hospital Medication Authorization System (Healthcare / Workflow Analogy)

Picture a hospital where a nurse wants to administer a drug to a patient. The nurse is the IAM principal, the drug is the action, the patient room is the resource, and the medication-administration request is the API call. Authorization, IAM policies, and AccessDenied troubleshooting map onto how hospital authorization works.

The nurse's licensure is the identity policy — the state board grants the nurse permission to administer a defined list of drugs. The patient's chart and prescription orders are the resource policy — the patient's chart must list this drug as ordered for this patient; without that order, the drug is not authorized regardless of nurse licensure. The hospital formulary policy is the SCP — drugs the hospital has banned organization-wide (no fentanyl in the maternity ward) override any prescription. The shift supervisor's restriction is a session policy — during a flu outbreak the supervisor restricts what each nurse may administer that shift, narrower than usual. The board of nursing scope-of-practice is the permissions boundary — the nurse's licence itself caps what nursing roles can ever do, regardless of any individual prescription.

When the medication dispensing system refuses the request (AccessDenied), the pharmacist's troubleshooting walkthrough is precise: pull the audit log (CloudTrail), check whether the nurse is licensed for this drug (identity policy), whether the chart has the order (resource policy), whether the hospital has banned it (SCP), whether the supervisor restricted it today (session policy), and whether scope-of-practice caps it (boundary). The audit log is essential for AccessDenied troubleshooting — it records exactly which check failed.

The Five Policy Types Every Security Engineer Must Distinguish

Authorization, IAM policies, and AccessDenied troubleshooting starts with knowing which of five policy types you are reading. Misidentifying the type is the most common cause of authorization design errors on SCS-C02.

Identity-Based Policies — Attached to a Principal

Identity-based policies are JSON documents attached to an IAM user, group, or role. They grant permissions to that identity. The Principal element is implicit (the principal is whoever the policy is attached to). Identity-based policies come in three sub-flavours: AWS-managed (curated by AWS, e.g. AdministratorAccess), customer-managed (your own reusable managed policies), and inline (anonymous, embedded directly in a user/group/role and deleted with it).

Resource-Based Policies — Attached to a Resource

Resource-based policies are JSON attached directly to a resource — S3 bucket policy, KMS key policy, SNS topic policy, SQS queue policy, Lambda resource policy, Secrets Manager secret policy, ECR repository policy, IAM role trust policy. Resource-based policies must include an explicit Principal element (the policy describes who can act on this resource). They are the only mechanism for granting access to anonymous (unauthenticated) principals on services like S3.

Permissions Boundaries — Caps on a Principal

A permissions boundary is a managed policy attached to a user or role that defines the maximum permissions that identity policies can grant. Boundaries grant nothing; they cap. Effective permissions = identity policy ∩ permissions boundary. Boundaries are how a central security team allows developers to create their own roles without enabling privilege escalation.

Service Control Policies (SCPs) — Org-Wide Caps

SCPs are attached to AWS Organizations roots, OUs, or accounts. Like boundaries, SCPs grant nothing — they define the ceiling for principals in affected accounts. SCPs do not apply to the management account (a recurring SCS-C02 trap). Use SCPs to enforce immutable rules: deny region outside approved list, deny disabling CloudTrail/Config/GuardDuty, deny use of root credentials.

Session Policies — Inline at AssumeRole

Session policies are passed inline to sts:AssumeRole, sts:AssumeRoleWithSAML, sts:AssumeRoleWithWebIdentity, or sts:GetFederationToken via the Policy and PolicyArns parameters. The resulting session's effective permissions = role's permissions ∩ session policy. Session policies cannot expand permissions; they only restrict for a specific session. Identity providers commonly inject session policies during federation to scope down a broad role per-user.

Managed vs Inline — A Cross-Cutting Distinction

Managed and inline is orthogonal to identity vs resource. Managed policies have ARNs, are reusable, and have versions (up to five maintained). Inline policies are anonymous, embedded in the entity, and deleted when the entity is. Use managed for shared standards and reusability; use inline for one-off, tightly coupled rules where the policy must always travel with the entity.

Five policy types, two cross-cutting attributes. Identity-based, resource-based, permissions boundary, SCP, session policy — these are the five. Managed vs inline applies to identity-based policies. Effective permissions for an API call are the intersection of all positive grants across applicable layers, with any explicit Deny in any layer being decisive. Memorise this taxonomy before attempting any AccessDenied troubleshooting question on SCS-C02.

Policy Evaluation Logic — The Algorithm

The IAM policy evaluation algorithm is the single most important authorization, IAM policies, and AccessDenied troubleshooting concept on SCS-C02. Internalise it as a flowchart.

Step 1 — Default Deny

Every authorization decision starts at default Deny. Without any policy granting access, the answer is no. New IAM users, fresh accounts, untouched roles — all default to Deny.

Step 2 — Evaluate All Applicable Policies

For a given request, IAM gathers every applicable policy: SCPs of the principal's account chain, the principal's permissions boundary, the principal's identity-based policies (managed and inline), the resource's resource-based policy if any, and any session policy attached to the current session. All are evaluated; none is skipped.

Step 3 — Explicit Deny Wins

If any applicable policy contains an explicit "Effect": "Deny" matching the request's action, resource, and condition, the final decision is Deny. No allow elsewhere can override an explicit Deny. This is the famous "explicit deny beats allow" rule and the basis for SCP-based guardrails.

Step 4 — Check for Explicit Allow

With no explicit Deny, IAM searches for an explicit Allow. The Allow may come from any applicable policy. For same-account access, an Allow on either the identity policy OR the resource policy is sufficient (most services). For cross-account access, the Allow must appear on BOTH the caller's identity policy AND the target's resource policy.

Step 5 — Apply SCP and Boundary Caps

Even with an Allow, the SCP must permit the action (or at least not deny it) and the permissions boundary must permit the action. SCP and boundary act as filters: the action must be allowed by the identity policy AND not denied by SCP AND not denied by boundary AND not denied by session policy.

Step 6 — Final Decision

If all caps pass and an Allow is found with no explicit Deny anywhere, the result is Allow. Otherwise, Deny. The full evaluation produces an authorization decision recorded in CloudTrail when the call is logged.

Cross-Account Twist

For cross-account access, the evaluation runs in both accounts simultaneously. The caller's account evaluates the caller's identity policy + caller's SCP + caller's boundary; the target's account evaluates the target's resource policy + target's SCP. Both accounts must say Allow with no Deny. This is why cross-account AccessDenied troubleshooting requires CloudTrail in both accounts.

Explicit Deny is decisive — no exceptions. An explicit Deny in any single applicable policy (SCP, boundary, identity, resource, session) overrides any number of Allows. This is why the safest guardrails (e.g. "deny disabling CloudTrail") are written as Deny statements in SCPs — there is no way for any combination of permissions to override them. When troubleshooting, always search for explicit Deny first; if found, no other layer matters.

The Four Mandatory Policy Elements — Principal, Action, Resource, Condition

Every IAM policy statement evaluates four elements. All four must match for the statement to apply. AccessDenied troubleshooting often comes down to identifying which element failed to match.

Principal — Who

The Principal element specifies the IAM entity making the request. In identity-based policies the Principal is implicit (the entity the policy is attached to). In resource-based policies, Principal is required and explicit: an account ARN, an IAM user ARN, an IAM role ARN, an AWS service principal (e.g. lambda.amazonaws.com), a SAML provider, a web identity provider, or "*" for anyone. Mismatched Principal — wrong account ID, wrong role name, role recreated with new internal ID — is a top AccessDenied cause.

Action — What

The Action element specifies the API operation. Use "s3:GetObject", "kms:Decrypt", etc. Wildcards are allowed ("s3:Get*", "s3:*"). Mismatched Action — using s3:GetObject when the call is s3:HeadObject, missing kms:Decrypt when the object is encrypted — produces AccessDenied that looks identical to other failures, requiring CloudTrail to identify.

Resource — On What

The Resource element specifies the AWS resource ARN. "arn:aws:s3:::my-bucket/*" matches all objects in my-bucket, but "arn:aws:s3:::my-bucket" matches only the bucket itself (used for ListBucket, not GetObject). The bucket-vs-object ARN distinction is one of the most common AccessDenied troubleshooting traps on S3.

Condition — Under What Circumstances

The Condition element restricts when the statement applies. Conditions evaluate context keys — aws:SourceIp, aws:MultiFactorAuthPresent, aws:RequestedRegion, aws:PrincipalTag/Team, aws:ResourceTag/Project, s3:x-amz-server-side-encryption, etc. Failed Condition is the subtlest AccessDenied cause: the policy looks correct, the call looks correct, but a context key did not match (caller from wrong IP range, request from wrong region, missing MFA, missing required tag).

How Each Element Can Cause AccessDenied

A useful mental check during AccessDenied troubleshooting: walk Principal, Action, Resource, Condition for every applicable policy. Did the Principal match the caller? Did the Action match the API? Did the Resource ARN cover the target? Did all Conditions evaluate true? One missed element kills the Allow.

The Resource-ARN bucket-vs-object trap. arn:aws:s3:::my-bucket and arn:aws:s3:::my-bucket/* are NOT interchangeable. s3:ListBucket requires the bucket ARN (no /*). s3:GetObject, s3:PutObject, s3:DeleteObject require the object ARN (/* or specific key). A policy granting only arn:aws:s3:::my-bucket/* for s3:ListBucket always fails. The CloudTrail event shows AccessDenied even though the Action and Principal look correct — the Resource ARN simply does not cover the call. SCS-C02 will test this exact mismatch repeatedly.

ABAC vs RBAC — Choosing the Authorization Model

ABAC (Attribute-Based Access Control) and RBAC (Role-Based Access Control) are the two authorization models for designing IAM policies at scale. SCS-C02 tests when each is correct.

RBAC — Roles per Job Function

In RBAC, you define a role for each job function (DataEngineer, Auditor, BillingReader) with explicitly scoped resources. Adding a new project means creating new roles or extending existing ones. Adding a new region means editing every affected role. RBAC is simple to start but scales poorly: 100 projects × 5 roles per project = 500 roles to maintain.

ABAC — Tags on Principal Match Tags on Resource

In ABAC, you tag principals (PrincipalTag/Team=Alpha, PrincipalTag/Project=PaymentSvc) and tag resources identically (ResourceTag/Team=Alpha, ResourceTag/Project=PaymentSvc). A single policy says "allow if PrincipalTag/Team equals ResourceTag/Team." Adding a new project means tagging the new resources and the new users — no policy edits. ABAC scales to thousands of resources with one or two policies.

Session Tags — ABAC From Federation

Session tags inject attributes at AssumeRole time, typically by SAML or web-identity IdPs. The IdP includes https://aws.amazon.com/SAML/Attributes/PrincipalTag:Team claims; the role assumes with those tags applied for the session. ABAC plus session tags is the canonical pattern for federated multi-tenant access — every user inherits their organisational team tag without IAM admins managing user lists.

When RBAC Is Still Right

ABAC is not always better. RBAC remains correct for sensitive privileged roles (SecurityAuditor, BreakGlass) where explicit named principals are auditable and stable. ABAC's flexibility becomes a liability when the permission decision must be precise and traceable to a named human. The exam pattern: ABAC for scalable workload access, RBAC for privileged human roles.

Hybrid Patterns

Production environments commonly mix both: ABAC for bulk team-scoped resource access, RBAC for narrow privileged actions, and SCPs as immutable guardrails over both. SCS-C02 scenarios often require recognising that the right answer combines models.

ABAC requires tag governance — without it, ABAC fails silently. The policy "Condition": {"StringEquals": {"aws:ResourceTag/Team": "${aws:PrincipalTag/Team}"}} only works if every resource is correctly tagged AND every principal carries the matching tag. Untagged resources are inaccessible (no match). Mistagged resources are accessible by the wrong team. The security engineer's pre-requisite for ABAC is mandatory tagging policies (SCPs denying resource creation without required tags) plus tag-on-create automation. SCS-C02 questions about ABAC migration almost always include "what must you implement first" — and the answer is tag governance.

Least Privilege and Separation of Duties

Authorization, IAM policies, and AccessDenied troubleshooting design follows two foundational principles. Both are exam-tested directly.

Least Privilege — Grant Only What Is Needed

Least privilege means granting exactly the permissions a principal needs to perform its job and nothing more. Implementation tactics: start from a deny-by-default position, add permissions iteratively driven by Access Advisor data, prefer specific Resource ARNs over "*", prefer specific Action names over "s3:*", add Condition restrictions where possible (region, IP, MFA, encryption-required).

Separation of Duties — No Single Person Has End-to-End Power

Separation of duties means dividing critical workflows so no single principal can complete a sensitive operation alone. Examples: the principal that writes CloudTrail logs cannot delete them; the principal that approves IAM role creation is different from the principal that uses the roles; the principal that defines SCPs is not the principal that authors workload policies. Implement via OU structure, distinct IAM roles per function, and SCPs preventing privileged actions in workload accounts.

Permissions Boundary as Least-Privilege Enforcement

Permissions boundaries are the operational tool for least privilege at scale. Developers create their own roles for self-service Lambda, EC2, ECS — but every role they create must attach a boundary that caps permissions to what is allowed for workload roles (no IAM admin, no Organizations actions, no CloudTrail control). The boundary is the immovable cap.

Least privilege is iterative, not one-shot. Start broad to unblock, then tighten using Access Advisor data over 30-90 days. Access Advisor shows which actions a role has actually used; everything else can be removed. IAM Access Analyzer policy generation automates this — point it at a role with CloudTrail history and it produces a tightened policy. Manual least-privilege design without these tools produces over-permissioned roles.

AccessDenied Troubleshooting — Decoding the Error

When an API call returns AccessDenied, the security engineer's job is to identify the exact policy layer that caused the denial. AccessDenied troubleshooting follows a structured workflow.

Step 1 — Capture the CloudTrail Event

Pull the CloudTrail event for the failed call. The event includes eventName, eventSource, errorCode (AccessDenied, AccessDeniedException, UnauthorizedOperation, InvalidClientTokenId), errorMessage, userIdentity (principal ARN, account, type), sourceIPAddress, requestParameters (the API arguments — bucket, key, role ARN), and resources (target ARNs). Without this event, AccessDenied troubleshooting is guessing.

Step 2 — Read the Error Message Carefully

AccessDenied error messages have improved in 2023-2024 to include the policy type that caused denial. Modern messages say things like "User: arn:... is not authorized to perform: s3:GetObject on resource: arn:... because no resource-based policy allows the s3:GetObject action" or "...with an explicit deny in a service control policy." Read these carefully — they tell you which layer to investigate first.

Step 3 — Check SCP First (Explicit Deny Path)

If the error mentions an explicit deny, check SCPs first. SCPs deny org-wide and override every Allow. Common SCP-deny patterns: action not in approved region, action on root credentials, action on protected services (CloudTrail/Config/GuardDuty disable). Pull the SCPs attached to the principal's account chain (root → OU → account) and search for matching Deny statements.

Step 4 — Check the Identity Policy

Confirm the principal has an identity policy granting the action on the resource. Common gaps: missing the action entirely, action wildcard does not cover the specific call (s3:Get* does not cover s3:ListBucket), Resource ARN scope wrong (object-level vs bucket-level), Condition fails (wrong region, missing MFA, wrong source IP).

Step 5 — Check the Resource Policy (Cross-Account)

For cross-account calls, also verify the target's resource policy. Common gaps: Principal ARN typo, Principal references an old role that was recreated (different internal ID), Action missing kms:Decrypt even though objects are encrypted, Condition requires VPC endpoint when call is from internet.

Step 6 — Check the Permissions Boundary

If the principal has a boundary, verify the action is allowed by the boundary too. Boundaries silently restrict; the principal sees AccessDenied even when the identity policy is correct.

Step 7 — Check Session Policy

If the call is via AssumeRole with a session policy passed in, verify the session policy permits the action. Federated sessions from SAML or OIDC IdPs frequently inject restrictive session policies; a developer with broad role permissions can hit AccessDenied because the IdP narrowed their session.

Step 8 — Verify with Policy Simulator

Re-run the failing call mentally through IAM Policy Simulator — pick the principal, pick the action, set the resource ARN and any context keys (source IP, MFA, region). Simulator's verdict matches what real IAM evaluation would do, and explains which statement allowed or denied.

Modern AccessDenied messages name the policy type — read them. AWS upgraded AccessDenied messages to identify which layer caused the denial: "explicit deny in identity-based policy," "no resource-based policy allows," "implicit deny due to no allow," "explicit deny in a service control policy." This drastically shortens AccessDenied troubleshooting. Older error messages were terse and required guessing; current ones point you at the layer. SCS-C02 questions use both — be ready to interpret either form.

CloudTrail Investigation Patterns for AccessDenied

CloudTrail is the AccessDenied troubleshooting workhorse. Three query patterns recur on SCS-C02.

Pattern 1 — Filter by errorCode

Use errorCode = AccessDenied (or AccessDeniedException, UnauthorizedOperation) in CloudTrail Lake or Athena to enumerate all denied calls in a window. Group by userIdentity.arn and eventName to identify which principals and which APIs are repeatedly failing — the high-frequency pairs are the ones to fix first.

Pattern 2 — Correlate sourceIPAddress

When a call denies with a Condition failure on aws:SourceIp, the CloudTrail event records the actual source IP. Compare against the policy's allowed CIDR — typically the principal is calling from a new VPN endpoint or office network not in the allowlist.

Pattern 3 — Check Trust Policy Failures

AssumeRole denials surface as eventName = AssumeRole with errorCode = AccessDenied. Read the requestParameters.roleArn and requestParameters.externalId. Common causes: caller's account not in the trust policy Principal, ExternalId mismatch, Condition requiring MFA not met, SCP denying sts:AssumeRole.

Pattern 4 — Analyse readOnly Calls

Failed read-only calls (s3:HeadObject, dynamodb:DescribeTable, kms:DescribeKey) often precede the actual workload call. A common debugging trick: a Lambda fails at kms:Decrypt; the CloudTrail trail shows it first failed at kms:DescribeKey, indicating the role is missing both actions, not just kms:Decrypt.

CloudTrail Lake for Multi-Account Queries

For organization-wide AccessDenied troubleshooting, CloudTrail Lake federates events across all member accounts. SQL-style queries return cross-account result sets — invaluable for finding "every AccessDenied for user X across all 50 accounts in the last 24 hours."

CloudTrail data events are off by default — turn them on for AccessDenied troubleshooting. Management events (the default) capture control-plane API calls but skip S3 object reads, DynamoDB GetItem, Lambda Invoke, and similar high-volume data-plane operations. If a developer reports AccessDenied on s3:GetObject and you see no trace in CloudTrail, the cause is missing data event configuration. Enable data events for the relevant resources via the CloudTrail trail or via CloudTrail Lake event data store with a data-event selector. Filter by resource ARN to control cost.

IAM Policy Simulator Workflows

The IAM Policy Simulator is the security engineer's pre-deploy validation tool. SCS-C02 expects familiarity with three workflows.

Workflow 1 — Validate a New Policy Before Attaching

Compose the new identity policy in the Simulator's policy editor. Pick the action and resource you intend to authorize. Run. Verify Allow. Then add a counter-test: pick an action you intend to deny. Verify Deny. This catches over-broad wildcards before they reach production.

Workflow 2 — Reproduce an AccessDenied Reported by a Developer

The developer reports s3:GetObject failing on a specific bucket. In Simulator, pick their role, pick s3:GetObject, paste the bucket ARN. Set context keys to match the real call (source IP, MFA, requested region). Run. The Simulator shows which statement matched and which decision applied — Allow, Implicit Deny, or Explicit Deny. Cross-reference against the suspected policies.

Workflow 3 — Pre-Test Policy Changes Before Org-Wide Rollout

Before changing an SCP that would affect 100 accounts, simulate the new SCP against existing roles' typical actions. The Simulator supports SCP testing with the SCP attached at the account level. Run a battery of common actions to catch unintended denials before deployment.

Simulator Limitations

The Simulator does not evaluate every condition key (some service-specific keys are not supported). It evaluates one principal at a time. It does not simulate cross-account calls fully (you must simulate caller's identity policy and target's resource policy separately). For complex cross-account AccessDenied troubleshooting, Simulator + manual evaluation is the combined approach.

IAM Access Advisor — Finding Unused Permissions

IAM Access Advisor shows when each AWS service was last accessed by a principal. It is the operational tool for least-privilege cleanup.

What Access Advisor Shows

For any IAM user, group, role, or policy, Access Advisor displays each AWS service the entity has permissions for and the timestamp of last access (or "Not accessed in tracking period" — typically 400 days). Newer service-level Action-Last-Accessed information shows when each Action was last called, not just each service.

Workflow — Tighten an Over-Permissioned Role

Open Access Advisor for a role with AdministratorAccess or other broad managed policies. Review services with Not accessed in tracking period. These are candidates for removal. Build a tightened policy listing only services with recent access. Replace the broad policy with the tightened one. Use Policy Simulator to verify nothing breaks.

Combining With Access Analyzer Policy Generation

Access Analyzer policy generation goes further: it reads CloudTrail history for a role and generates a least-privilege policy listing exactly the actions and resources used. Where Access Advisor shows last-access timestamps, Access Analyzer outputs ready-to-attach JSON. The combined workflow: Access Advisor for triage, Access Analyzer for generation, Policy Simulator for validation.

Limitations

Access Advisor data has lag (typically 4 hours). Some services do not report last-accessed at action granularity. Access Advisor does not detect deny-only or condition-restricted actions; it shows what was attempted, not necessarily what was authorized. For comprehensive least-privilege analysis, combine with Access Analyzer unused access findings.

Common Authorization Bugs and Their Fixes

Five recurring authorization, IAM policies, and AccessDenied troubleshooting bug patterns appear repeatedly on SCS-C02. Recognise them by symptom.

Bug 1 — SCP Deny Overrides Local Allow

Symptom: principal has identity policy granting the action, but call denies. CloudTrail error message mentions "explicit deny in service control policy." Cause: SCP at the OU or account level denies the action — region-restriction SCP, no-disable-CloudTrail SCP, or root-credential-block SCP. Fix: confirm the action is intentionally restricted; if not, modify the SCP. The principal cannot override the SCP locally.

Bug 2 — Resource Policy Missing for Cross-Account

Symptom: call from account A to S3 bucket in account B returns AccessDenied. Account A's role has identity policy allowing s3:GetObject. Cause: account B's bucket policy does not list account A's role as a Principal. Cross-account requires both sides. Fix: add a Principal block to the bucket policy granting account A's role the relevant actions, or grant the entire account A as Principal with a Condition.

Bug 3 — Missing Trust Policy for AssumeRole

Symptom: account A calls sts:AssumeRole on a role in account B. CloudTrail shows AccessDenied. Cause: the role's trust policy in account B does not list account A as a trusted Principal. The role's identity policy is irrelevant — trust comes first. Fix: edit the role's trust policy to include account A's ARN (or specific role ARN) as Principal, with appropriate Conditions (aws:PrincipalOrgID, sts:ExternalId, MFA).

Bug 4 — Session Policy Reducing Intent Permissions

Symptom: a federated user's role has broad permissions, but the user gets AccessDenied on actions the role allows. Cause: the IdP injected a restrictive session policy at AssumeRoleWithSAML or AssumeRoleWithWebIdentity time, intersecting the role's permissions down to a smaller subset. Fix: review the IdP's session-policy logic and either expand the session policy or use a different role attachment.

Bug 5 — Permissions Boundary Silent Cap

Symptom: principal's identity policy looks correct, no SCP denies, no resource policy issue, but AccessDenied returns. Cause: a permissions boundary attached to the principal does not include the action. Fix: either modify the boundary to include the action (if intent allows) or accept the cap. The boundary is invisible in many troubleshooting workflows; check it explicitly via aws iam get-user --user-name X or aws iam get-role --role-name X and look at PermissionsBoundary.

Permissions boundaries are silent — they cause AccessDenied invisibly. Many engineers troubleshoot identity policy + SCP + resource policy and miss the boundary entirely because boundaries are attached as a separate field, not a policy attachment. When a "looks-correct" policy still denies, check PermissionsBoundary on the principal. The exam will set up scenarios specifically where the boundary is the answer; if you forget to check it, you will pick wrong.

Cross-Account Authorization — The Two-Sided Decision

Cross-account access requires both sides to permit. This doubles the AccessDenied troubleshooting surface. Authorization, IAM policies, and AccessDenied troubleshooting in cross-account scenarios is a Domain 4 hot zone.

The Caller's Side

The calling account's principal must have an identity policy permitting the action on the cross-account resource. Cross-account ARNs use the target's account ID — the policy must reference arn:aws:s3:::target-account-bucket/* not the caller's bucket. SCPs in the caller's account must not deny the action. The caller's permissions boundary must permit it.

The Target's Side

The target account's resource (S3 bucket, KMS key, IAM role) must have a resource policy allowing the caller. For S3, this is the bucket policy with the caller's role ARN as Principal. For KMS, the key policy must list the caller. For IAM AssumeRole, the trust policy must list the caller. Target-side SCPs must not deny the action — for example, a target-side SCP denying s3:GetObject from outside the org will block calls from accounts outside the organization.

Both Sides Authoritative

Unlike same-account access where one side suffices for many services, cross-account ALWAYS requires both. A common SCS-C02 question: "Why does this Lambda in account A get AccessDenied calling S3 in account B when the Lambda role has the right policy?" — the answer is almost always "bucket policy in account B does not list the Lambda role as Principal."

KMS Cross-Account is Triple-Sided

For KMS-encrypted S3 cross-account, three places must align: caller's IAM policy (allow kms:Decrypt on key ARN), key policy in target account (Principal = caller, Action = kms:Decrypt), and S3 bucket policy in target account (Principal = caller, Action = s3:GetObject). Five layers if you also count caller-side SCP and target-side SCP. AccessDenied here requires methodically walking each.

Cross-account AccessDenied? Check both sides every time. Same-account access can succeed with just identity policy or just resource policy (most services). Cross-account requires explicit Allow on BOTH sides plus no Deny anywhere. The most efficient AccessDenied troubleshooting checklist for cross-account: (1) caller identity policy, (2) caller SCP, (3) target resource policy, (4) target SCP, (5) any boundary or session policy in either account. Skipping the target side because "the policy looks correct on the caller" is the #1 cross-account troubleshooting mistake.

Scenario Walkthrough — Lambda Reading Encrypted S3 in Another Account

A canonical SCS-C02 AccessDenied troubleshooting scenario. Walk it end-to-end.

Setup

Account A runs a Lambda that needs to read objects from an S3 bucket in account B. Bucket B uses SSE-KMS with a CMK in account B. The Lambda's execution role in account A has been granted s3:GetObject and kms:Decrypt on the relevant ARNs.

Symptom

Lambda invocation succeeds at the function code level, but reading the S3 object returns AccessDenied. CloudTrail in account A shows an s3.amazonaws.com event with errorCode = AccessDenied.

Diagnosis

Walk the seven check layers:

  1. Caller SCP: not denying s3:GetObject — confirmed.
  2. Caller identity policy: allows s3:GetObject and kms:Decrypt on correct ARNs — confirmed.
  3. Caller permissions boundary: not present, no cap.
  4. Target SCP (account B): not denying.
  5. Target bucket policy: missing — bucket policy does not list the Lambda role as Principal. First gap found.
  6. Target KMS key policy: missing — key policy in account B does not list the Lambda role. Second gap found.
  7. Target session policy: not applicable.

Fix

In account B, add a bucket policy statement granting s3:GetObject to the Lambda role's ARN as Principal. In account B, add a key policy statement granting kms:Decrypt and kms:DescribeKey to the same Principal. Re-run; success.

Lesson

Cross-account encrypted S3 always requires four allow points: caller IAM (S3 + KMS), target bucket policy, target key policy. Forgetting any one produces identical AccessDenied symptoms. CloudTrail in both accounts is required to see which side failed.

Scenario Walkthrough — Federated User Hitting AccessDenied After IdP Change

Another recurring SCS-C02 pattern.

Setup

Federated users sign in via SAML from corporate IdP. The role they assume has broad permissions (PowerUserAccess). Yesterday the IdP team updated the SAML configuration. Today users report AccessDenied on actions that worked before.

Diagnosis

CloudTrail shows eventName = AssumeRoleWithSAML succeeded — federation works. But subsequent action calls deny. Modern error message: "implicit deny — no statements allow this action."

The role's identity policy is unchanged. SCPs unchanged. Only thing different is the IdP. Check the AssumeRoleWithSAML CloudTrail event — responseElements includes the session policy applied. The IdP now injects a SessionPolicy ARN that restricts the role to a narrow subset of PowerUserAccess.

Fix

Coordinate with IdP team. Either (a) widen the session policy to cover the actions users need, or (b) remove the session policy injection if not needed. Session policies cannot expand permissions, but they can be made less restrictive within the role's grant.

Lesson

Session policies are a third-party variable in IAM evaluation. When IdP-driven federation changes, AccessDenied troubleshooting must include checking the AssumeRole event's session policy field. Many security engineers miss this because the role itself is unchanged.

Common SCS-C02 Authorization Traps

Trap 1 — Permissions Boundary Grants Permission

Wrong. Boundaries cap permissions; they never grant them. An identity policy must still explicitly allow an action. The boundary intersects.

Trap 2 — SCPs Apply to Management Account

Wrong. SCPs exempt the management account. Best practice: keep workloads out of the management account entirely.

Trap 3 — Resource Policy Alone Grants Cross-Account

Wrong for most services. Cross-account access requires both sides. The exception is IAM role AssumeRole (where the trust policy alone is the cross-account grant on the target side; the caller still needs identity policy).

Trap 4 — Implicit Deny and Explicit Deny Are the Same

Wrong. Implicit deny means no Allow was found and is overridable by adding an Allow. Explicit Deny means a "Effect": "Deny" statement matched and overrides every Allow. AccessDenied error messages now distinguish the two — read them.

Trap 5 — Policy Simulator Tests Cross-Account Fully

Partial. Policy Simulator simulates one principal's permissions at a time. Cross-account requires simulating both sides separately and combining results manually.

Trap 6 — Access Advisor Shows Authorization Failures

Wrong. Access Advisor shows successful service access. Failed (denied) calls do not appear in Access Advisor. To find denied calls, query CloudTrail with errorCode = AccessDenied.

Trap 7 — ABAC Eliminates RBAC

Wrong. ABAC scales bulk access; RBAC remains correct for narrow privileged roles. Production environments mix both.

Trap 8 — Session Policy Can Expand a Role's Permissions

Wrong. Session policies only restrict (intersect with role's permissions). They cannot grant beyond the role.

Trap 9 — IAM Policies Are Evaluated in Order

Wrong. IAM policy evaluation is set-based, not ordered. Every applicable policy is evaluated; explicit Deny wins regardless of attachment order.

Trap 10 — * in Resource Means All Resources Including Cross-Account

Wrong. "Resource": "*" in an identity policy means all resources for which the principal has the right ARN — but cross-account targets still require the target's resource policy to allow. Identity-policy * is necessary but not sufficient for cross-account.

The Authorization Mental Model — six checkpoints. (1) SCP — explicit Deny anywhere kills the request. (2) Permissions boundary — caps identity-policy grants. (3) Identity policy — must explicitly Allow. (4) Resource policy — must explicitly Allow for cross-account. (5) Session policy — intersects, cannot expand. (6) Implicit Deny default — no Allow found anywhere means Deny. Run every authorization, IAM policies, and AccessDenied troubleshooting question through these six checkpoints and the right answer falls out.

Key Numbers and Must-Memorize Authorization, IAM Policies, and AccessDenied Troubleshooting Facts

Policy Type Count

Five: identity-based, resource-based, permissions boundary, SCP, session policy. Managed vs inline applies to identity-based.

Evaluation Order

Default Deny. Explicit Deny wins. Implicit Deny if no Allow. Allow only when applicable Allow exists with no Deny.

Cross-Account Rule

Both sides must allow. Caller identity policy AND target resource policy.

CloudTrail Error Codes for AccessDenied

AccessDenied, AccessDeniedException, UnauthorizedOperation, Client.UnauthorizedOperation, InvalidClientTokenId (auth not authz, but related).

Tools for Troubleshooting

CloudTrail (what happened), Policy Simulator (what would happen), Access Advisor (last-accessed data), Access Analyzer (external + unused + policy generation), modern AccessDenied error messages (which layer denied).

ABAC Prerequisites

Tags on principal, tags on resource, policy comparing aws:PrincipalTag/X to aws:ResourceTag/X. Session tags from IdP for federation-driven ABAC.

Boundary Behaviour

Caps identity policy grants. Silent in error messages historically, named in modern messages. Always check PermissionsBoundary on user/role.

Session Policy Behaviour

Intersects, cannot expand. Passed at AssumeRole. Common in federation.

SCP Scope

Applies to all member accounts. Exempts management account. Denies override. Grants nothing.

FAQ — Authorization, IAM Policies, and AccessDenied Troubleshooting Top Questions

Q1 — A developer reports AccessDenied on s3:GetObject despite having AdministratorAccess. Where do I look first?

Modern AccessDenied messages tell you which layer caused the denial. Read the error message first. If it says "explicit deny in a service control policy," check SCPs. If it says "no resource-based policy allows," check the bucket policy (likely a cross-account or restricted bucket). If it says "with an explicit deny in identity-based policy," there is a Deny statement in some identity policy attached to the principal. If it says "implicit deny — no statements allow," the action is not granted. AdministratorAccess covers most services but cross-account targets still require the target's resource policy. Pull the CloudTrail event, read the message, walk to the named layer.

Q2 — What is the difference between a permissions boundary and an SCP?

Both are caps that grant nothing. SCPs attach to AWS Organizations roots, OUs, or accounts and apply to every principal in the affected accounts (except the management account). Permissions boundaries attach to a specific IAM user or role and apply only to that principal. SCPs are the org-wide guardrail; boundaries are the per-principal guardrail. Use SCPs to enforce immutable rules across accounts (no region outside approved list, no CloudTrail disable). Use boundaries to enable safe role-creation delegation (developers can create roles only if they attach the standard boundary). They stack independently.

Q3 — When should I use ABAC instead of RBAC?

Use ABAC when you have many resources and many principals that need scoped access by attribute (team, project, environment), and the count grows over time. ABAC tags principals and resources identically and uses one policy comparing them, scaling without policy edits. Use RBAC for small numbers of named, privileged roles where auditability of specific principals matters more than flexibility (SecurityAuditor, BreakGlass). Most production environments use both: ABAC for workload self-service, RBAC for privileged human access. Session tags from a SAML or OIDC IdP enable ABAC across federated users without IAM admin overhead.

Q4 — How do I generate a least-privilege policy from an existing role's actual usage?

Use IAM Access Analyzer policy generation. Open the role in IAM, select "Generate policy based on CloudTrail events," pick a time window (typically 30-90 days), and let the analyzer scan CloudTrail. The result is a JSON policy listing exactly the actions and resource ARNs the role used. Review, refine if necessary, and replace the broad starter policy. Combine with Access Advisor to confirm services with no recent activity, and with Policy Simulator to validate the new policy does not break expected operations. This is the canonical SCS-C02 least-privilege workflow.

Q5 — A cross-account API call works for some users but fails for others, all assuming the same role. Why?

Two likely causes. First, session policies — if some users assume the role via a federated IdP that injects session policies, they see narrowed permissions while users assuming directly do not. Check the AssumeRole CloudTrail event for responseElements showing the session policy. Second, MFA conditions — if the role's policies require aws:MultiFactorAuthPresent, users without active MFA on their session see denials while MFA-enabled users succeed. Pull the failing user's CloudTrail event; the userIdentity.sessionContext.attributes.mfaAuthenticated field tells you whether MFA was present.

Q6 — Why does CloudTrail not show every AccessDenied event?

It usually does. Confirm the trail is configured to log management events with read and write events captured. If the AccessDenied is on a data plane action (S3 object read, DynamoDB GetItem), enable data event logging on the trail for those resources. AccessDenied events on STS calls (AssumeRole failures) appear under the calling account's CloudTrail; cross-account AssumeRole denials may appear in either or both accounts depending on which side denied. For high-volume troubleshooting at scale, use CloudTrail Lake with SQL queries.

Q7 — Can I use the IAM Policy Simulator to test SCPs?

Yes, with caveats. The Simulator supports SCP inclusion when you select an account or principal in an Organization. The simulation will apply SCPs attached at the principal's account chain. Limitations: cross-account SCPs (the target's SCPs in cross-account scenarios) are not simulated. Session policies passed at AssumeRole are also outside Simulator scope. For comprehensive SCP testing before rollout, simulate against a battery of known principals and operations, and supplement with CloudTrail Lake queries against historical data to predict impact.

Q8 — How do I prevent privilege escalation when developers can create their own IAM roles?

Use permissions boundaries. The developer's role grants iam:CreateRole, iam:PutRolePolicy, iam:AttachRolePolicy, iam:PassRole — but with a Condition requiring iam:PermissionsBoundary to equal a specific managed policy ARN. The boundary policy explicitly denies privilege-escalating actions (no iam:* to other entities, no organizations:*, no cloudtrail:Stop*, etc.). Result: developers can create roles for their workloads, but every created role is capped by the boundary. Combine with an SCP that denies deletion of the boundary policy itself. This is the standard SCS-C02 self-service-without-escalation pattern.

Q9 — What does "implicit deny" mean in AccessDenied messages?

Implicit deny means no policy explicitly Allows the action — the request fell through to the default Deny. The fix is to add an Allow statement to some applicable policy (identity, resource, or permissions boundary path). Implicit deny is overridable by adding an Allow. Compare to "explicit deny," where a "Effect": "Deny" statement matched — explicit deny is not overridable except by removing the Deny statement. Modern AccessDenied error messages distinguish the two: "implicit deny — no statements allow this action" vs "explicit deny in a service control policy." The distinction matters for fix strategy.

Q10 — Should I prefer managed policies or inline policies?

Prefer customer-managed policies as the default. They are reusable across users/roles, versioned (you can roll back), and easier to audit (one ARN, multiple attachments). Use AWS-managed policies for well-understood broad standards (ReadOnlyAccess) but be cautious — they are not least-privilege. Use inline policies only when the policy is tightly coupled to a single entity and must always travel with it (e.g. a unique role with one-of-a-kind permissions that no other role will ever need). Inline policies are anonymous and disappear with the entity, so they are harder to audit centrally.

Further Reading — Official AWS Documentation

For depth beyond SCS-C02 scope, the authoritative AWS sources are: IAM User Guide policy evaluation logic, IAM policy types overview, permissions boundaries, Policy Simulator user guide, Access Advisor documentation, troubleshoot AccessDenied messages, ABAC introduction, session tags, session policies, and IAM global condition keys.

The AWS Security Reference Architecture (SRA) whitepaper codifies authorization patterns at organizational scale. The IAM best-practices documentation provides the canonical least-privilege guidance. AWS re:Inforce sessions on IAM deep dives and AccessDenied troubleshooting from the past two years are the richest source of real-world authorization, IAM policies, and AccessDenied troubleshooting walkthroughs.

Summary — Authorization, IAM Policies, and AccessDenied Troubleshooting Decision Tree

On exam day, when you see an authorization, IAM policies, and AccessDenied troubleshooting scenario, run this decision tree:

  1. Is the question about preventing an action org-wide regardless of identity? → SCP.
  2. Is the question about capping what developer-created roles can do? → Permissions boundary.
  3. Is the question about granting access to a specific principal? → Identity-based policy.
  4. Is the question about granting cross-account access on a resource? → Resource-based policy + caller's identity policy (both required).
  5. Is the question about restricting permissions for a specific federation session? → Session policy at AssumeRole.
  6. Is the question about an AccessDenied with "explicit deny in service control policy"? → SCP — find the Deny statement at root, OU, or account.
  7. Is the question about an AccessDenied with "no resource-based policy allows"? → Resource policy gap on cross-account target.
  8. Is the question about an AccessDenied with "implicit deny — no statements allow"? → Missing Allow in identity policy.
  9. Is the question about scaling access by team or project tag? → ABAC with aws:PrincipalTag matched to aws:ResourceTag.
  10. Is the question about generating a least-privilege policy from actual usage? → IAM Access Analyzer policy generation from CloudTrail.
  11. Is the question about which services a principal has used recently? → IAM Access Advisor.
  12. Is the question about validating a new policy before deployment? → IAM Policy Simulator.
  13. Is the question about decoding why a specific call failed? → CloudTrail event with errorCode = AccessDenied.
  14. Is the question about a cross-account call returning AccessDenied? → Check both sides — caller identity AND target resource policy.

Master these fourteen branches and you will answer every authorization, IAM policies, and AccessDenied troubleshooting question on SCS-C02 Domain 4.2 correctly. Authorization, IAM policies, and AccessDenied troubleshooting reward systematic policy-layer thinking — study how the layers combine, walk every layer methodically when troubleshooting, and the right authorization, IAM policies, and AccessDenied troubleshooting answer always emerges.

Official sources