# AWS IAM Permission Denied

Common Error Patterns

IAM permission errors typically appear as:

bash
User: arn:aws:iam::123456789012:user/test is not authorized to perform: ec2:DescribeInstances
bash
AccessDenied when calling the AssumeRole operation
bash
User is not authorized to perform: s3:GetObject on resource: arn:aws:s3:::my-bucket/key

Root Causes and Solutions

1. Missing IAM Policy Permissions

The user or role lacks the required action in their policy.

Solution:

Identify the missing permission and add it:

```bash # Check user policies aws iam list-user-policies --user-name test aws iam list-attached-user-policies --user-name test

# Check role policies aws iam list-role-policies --role-name MyRole aws iam list-attached-role-policies --role-name MyRole ```

Add inline policy:

bash
aws iam put-user-policy \
  --user-name test \
  --policy-name EC2ReadAccess \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "ec2:Describe*"
        ],
        "Resource": "*"
      }
    ]
  }'

2. Explicit Deny in Policy

A policy explicitly denies the action.

Solution:

Review all policies for deny statements:

bash
# Get all policies for user
aws iam get-user-policy --user-name test --policy-name PolicyName

Deny statements override allow statements:

json
{
  "Effect": "Deny",
  "Action": "s3:*",
  "Resource": "*"
}

Remove or modify the deny statement to allow the required action.

3. Resource-Based Policy Restrictions

The resource policy doesn't allow the principal.

Solution:

For S3 buckets, check bucket policy:

bash
aws s3api get-bucket-policy --bucket my-bucket

For cross-account access, ensure the resource policy allows the principal:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

4. AssumeRole Failure

Cross-account or service role assumption fails.

Solution:

Verify trust policy allows the principal:

bash
aws iam get-role --role-name MyRole --query 'Role.AssumeRolePolicyDocument'

Trust policy example:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "my-external-id"
        }
      }
    }
  ]
}

Also ensure the source account has sts:AssumeRole permission:

json
{
  "Effect": "Allow",
  "Action": "sts:AssumeRole",
  "Resource": "arn:aws:iam::999999999999:role/MyRole"
}

5. Permission Boundaries

Permission boundaries restrict maximum permissions.

Solution:

Check for permission boundaries:

```bash aws iam get-user --user-name test --query 'User.PermissionsBoundary'

aws iam get-role --role-name MyRole --query 'Role.PermissionsBoundary' ```

Update boundary to allow required actions or remove boundary:

bash
aws iam delete-user-permissions-boundary --user-name test

6. Service-Linked Role Issues

Service requires a service-linked role.

Solution:

Create the required service-linked role:

bash
aws iam create-service-linked-role \
  --aws-service-name ecs.amazonaws.com

7. Session Policies

Temporary credentials have session policy restrictions.

Solution:

When assuming a role, session policies limit permissions:

bash
# Check session policies when assuming role
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/MyRole \
  --role-session-name MySession \
  --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"*"}]}'

Troubleshooting Tools

IAM Policy Simulator

Use the IAM Policy Simulator to test permissions:

  1. 1.Navigate to IAM Console > Policy Simulator
  2. 2.Select user, group, or role
  3. 3.Select actions to test
  4. 4.Run simulation

AWS CLI Troubleshooting

```bash # Simulate policy aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789012:user/test \ --action-names s3:GetObject \ --resource-arns arn:aws:s3:::my-bucket/key

# Check access keys aws iam list-access-keys --user-name test

# Check user groups aws iam list-groups-for-user --user-name test ```

CloudTrail Analysis

Find the denied action in CloudTrail:

bash
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AccessDenied \
  --max-results 10

Common Scenarios

EC2 Instance Profile

```bash # Check instance profile aws iam get-instance-profile --instance-profile-name MyProfile

# Attach role to instance aws ec2 associate-iam-instance-profile \ --instance-id i-0123456789abcdef0 \ --iam-instance-profile Name=MyProfile ```

Lambda Execution Role

```bash # Check Lambda role aws lambda get-function-configuration --function-name my-function \ --query 'Role'

# Update Lambda role aws lambda update-function-configuration \ --function-name my-function \ --role arn:aws:iam::123456789012:role/LambdaExecutionRole ```

Cross-Account S3 Access

Required configuration:

  1. 1.Source account: Allow s3:* on bucket
  2. 2.Destination account: Allow s3:* on bucket policy
  3. 3.User policy: Allow s3:* on bucket AND sts:AssumeRole if using role

Debugging Checklist

CheckCommand
User policiesaws iam list-attached-user-policies
Inline policiesaws iam list-user-policies
Group membershipsaws iam list-groups-for-user
Permission boundaryaws iam get-user --query 'User.PermissionsBoundary'
Role trust policyaws iam get-role --query 'Role.AssumeRolePolicyDocument'
Simulate accessaws iam simulate-principal-policy

Prevention Tips

  1. 1.Use IAM Access Analyzer to identify unintended access
  2. 2.Implement least-privilege permissions
  3. 3.Use AWS managed policies as templates
  4. 4.Enable CloudTrail for audit logging
  5. 5.Review permissions regularly with IAM credential report
  • [AWS S3 Access Denied](#)
  • [AWS EC2 Instance Not Reachable](#)
  • [AWS Lambda Timeout](#)