advanced 35 min read aws Updated: 2025-08-25

Solving AWS Access Denied: The Comprehensive Guide (2025)

An advanced troubleshooting guide for diagnosing and fixing complex AWS Access Denied errors. Covers IAM policies, SCPs, permissions boundaries, VPC endpoints, and session policies.

💡 From Frustration to Fix

`AccessDenied` is the most common error in AWS, but its causes can be complex and hidden. This guide provides a systematic, layer-by-layer playbook to diagnose *any* permissions issue, turning frustrating guesswork into a predictable debugging process.

The IAM Decision Logic: How AWS Evaluates Policies

To solve `AccessDenied` errors, you must understand how AWS makes a permission decision. It's a multi-step process where an explicit `Deny` always wins.

  1. Explicit Deny: AWS first checks all applicable policies (Identity, Resource, SCPs, etc.) for an explicit `Deny` statement. If one is found, access is immediately denied.
  2. Explicit Allow: If there are no `Deny` statements, AWS looks for an `Allow` statement in any applicable policy.
  3. Implicit Deny: If no `Allow` statement is found, access is denied by default.

The "applicable policies" can include up to five different types, which we'll investigate next.

Step 1: Decode the Authorization Failure Message

Your first step should always be AWS CloudTrail. Often, `AccessDenied` errors contain an encoded message that tells you exactly why the request failed. You can decode it with the AWS CLI.

Terminal: Decode CLI Command

# 1. Find the event in CloudTrail and copy the encoded "authorizationFailure" message.
# 2. Run the decode command:
aws sts decode-authorization-message --encoded-message "ENCODED_MESSAGE_HERE"

The output is a JSON object that often reveals the specific policy (`Deny` in an SCP, missing permission in a resource policy, etc.) that caused the failure.

Step 2: Troubleshoot the 5 Layers of AWS Permissions

If decoding the message isn't enough, you must systematically check the five policy types that can affect a request.

Layer 1: Identity-Based Policies

These are policies attached to your IAM user, group, or role. This is the most common place to look. Check: Does the IAM identity have an `Allow` for the action? Is there an explicit `Deny`?

Layer 2: Resource-Based Policies

These policies are attached directly to resources like S3 buckets, SQS queues, or KMS keys. Check: If you're accessing a resource in another account, does its resource policy trust your identity's account or role?

Layer 3: IAM Permissions Boundaries

A permissions boundary sets the *maximum* permissions an identity can have. Even if a user has `AdministratorAccess`, a permissions boundary can prevent them from creating certain resources. Check: Is there a permissions boundary on the IAM role/user that restricts the required action?

Layer 4: Service Control Policies (SCPs)

SCPs are organizational guardrails applied at the AWS Organization level. They can block actions for *all* principals in an account, including the root user. Check: Is there an SCP attached to your account's OU that explicitly denies the service or action?

Layer 5: Session Policies

When you assume a role programmatically, you can pass a session policy that further restricts the session's permissions. Check: If you are using an assumed role, was a restrictive session policy passed as part of the `AssumeRole` API call?

Common Scenarios & Gotchas

Cross-Account Role Access

Requires a "double allow." The user's IAM policy must `Allow` `sts:AssumeRole` on the target role, AND the target role's Trust Policy must `Allow` the user's account/role to assume it.

S3 Access via VPC Endpoint

A VPC Endpoint Policy acts as an additional gatekeeper. Even if your IAM and Bucket policies are correct, a restrictive Endpoint Policy can deny access to S3 from within a VPC.

KMS Encryption/Decryption

KMS requires two-sided permissions. The user needs IAM permissions for KMS actions (`kms:Decrypt`), AND the KMS Key Policy must grant those permissions to the user.