All Articles

AWS IAM Permission Denied Errors — How to Fix Every Variant (2026)

Getting 'Access Denied' or 'is not authorized to perform' errors in AWS? Here's how to diagnose and fix every IAM permission issue — EC2, EKS, Lambda, S3, and CLI.

DevOpsBoysApr 2, 20264 min read
Share:Tweet

AWS IAM errors are frustrating because the message tells you what failed but not why or how to fix it. Let's go through every common variant.


The Generic Error and What It Means

An error occurred (AccessDenied) when calling the DescribeInstances operation:
User: arn:aws:iam::123456789:user/dev-user is not authorized to perform:
ec2:DescribeInstances on resource: *

This tells you:

  • Who: arn:aws:iam::123456789:user/dev-user
  • What they tried: ec2:DescribeInstances
  • On what: * (all resources)

The fix is always: add a policy that allows this principal to perform this action on this resource.


Case 1: IAM User Missing Permissions

The simplest case — the user doesn't have a policy allowing the action.

Diagnose with IAM Policy Simulator:

bash
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789:user/dev-user \
  --action-names ec2:DescribeInstances \
  --resource-arns "*"

Fix — add an inline policy or attach a managed policy:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:DescribeVpcs",
        "ec2:DescribeSubnets"
      ],
      "Resource": "*"
    }
  ]
}
bash
aws iam put-user-policy \
  --user-name dev-user \
  --policy-name AllowEC2Describe \
  --policy-document file://policy.json

Case 2: EC2 Instance Role Missing Permissions

Your EC2 instance runs code that calls AWS APIs, but it gets AccessDenied.

Check the instance has a role:

bash
aws ec2 describe-instances \
  --instance-ids i-1234567890abcdef0 \
  --query 'Reservations[].Instances[].IamInstanceProfile'

If this returns null, the instance has no role — attach one.

Check what role the instance is using (from inside the instance):

bash
curl -s http://169.254.169.254/latest/meta-data/iam/info | jq .InstanceProfileArn

Add the missing permission to the role:

bash
aws iam attach-role-policy \
  --role-name my-ec2-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Case 3: Lambda Function Permission Denied

Lambda functions use an execution role. If the function calls S3, DynamoDB, etc., the execution role must have permission.

Check the execution role:

bash
aws lambda get-function-configuration \
  --function-name my-function \
  --query 'Role'
# arn:aws:iam::123456789:role/my-lambda-role

Add the missing permission to the role:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:UpdateItem"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789:table/my-table"
    }
  ]
}
bash
aws iam put-role-policy \
  --role-name my-lambda-role \
  --policy-name AllowDynamoDB \
  --policy-document file://policy.json

Case 4: S3 Bucket Policy Blocking Access

Even if your IAM policy allows S3 access, the bucket policy can explicitly deny it.

Check the bucket policy:

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

Look for any explicit "Effect": "Deny" statements. Also check:

bash
# Check if bucket blocks public/cross-account access
aws s3api get-bucket-policy-status --bucket my-bucket
aws s3api get-public-access-block --bucket my-bucket

Fix — add allow in bucket policy:

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

Remember: explicit Deny always wins over Allow — if there's a Deny anywhere in the chain (SCP, bucket policy, IAM policy), access is denied regardless of other allows.


Case 5: EKS — Pod Getting Access Denied to AWS Services

Your Kubernetes pod calls AWS APIs and gets AccessDenied. This is an IRSA (IAM Roles for Service Accounts) issue.

Check the pod's service account:

bash
kubectl describe pod my-pod | grep "Service Account"

Check if IRSA is configured on the service account:

bash
kubectl describe serviceaccount my-sa -n my-namespace | grep eks.amazonaws.com
# Should show: eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/my-role

If annotation is missing — add it:

bash
kubectl annotate serviceaccount my-sa \
  eks.amazonaws.com/role-arn=arn:aws:iam::123456789:role/my-eks-role \
  -n my-namespace

Check the IAM role's trust policy allows EKS OIDC:

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

The trust policy must have your EKS cluster's OIDC provider:

json
{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::123456789:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringEquals": {
      "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:my-namespace:my-sa"
    }
  }
}

After fixing, restart the pod — it needs to pick up the new credentials.


Case 6: AWS CLI Using Wrong Profile/Region

Sometimes the error isn't a policy problem — you're authenticated as the wrong identity.

Check who you're authenticated as:

bash
aws sts get-caller-identity
# {
#   "UserId": "AIDAIOSFODNN7EXAMPLE",
#   "Account": "123456789",
#   "Arn": "arn:aws:iam::123456789:user/wrong-user"
# }

Fix — use the correct profile:

bash
aws sts get-caller-identity --profile prod-admin
export AWS_PROFILE=prod-admin

Check if MFA is required:

Some organizations require MFA for sensitive actions. The error looks like:

An error occurred (AccessDenied): Explicit deny in a service control policy

Use aws-mfa or assume a role with MFA:

bash
aws sts assume-role \
  --role-arn arn:aws:iam::123456789:role/AdminRole \
  --role-session-name my-session \
  --serial-number arn:aws:iam::123456789:mfa/my-mfa-device \
  --token-code 123456

Case 7: SCP (Service Control Policy) Blocking Access

If you're in an AWS Organization, SCPs can block actions even if your IAM policy allows them. SCPs are the outermost layer.

An error occurred (AccessDenied): Explicit deny in a service control policy

Check if SCPs apply:

bash
aws organizations describe-effective-policy \
  --policy-type SERVICE_CONTROL_POLICY \
  --target-id <account-id>

You need Organization admin access to view/modify SCPs. Contact your AWS admin.


Diagnosis Flowchart

Got AccessDenied?
       │
       ▼
Who is the principal? (aws sts get-caller-identity)
       │
       ├─ Wrong account/role → fix AWS_PROFILE
       │
       ▼
Is it a bucket/resource policy issue?
       │
       ├─ Yes → check bucket policy for explicit Deny
       │
       ▼
Is there an SCP in the org?
       │
       ├─ Yes → check with org admin
       │
       ▼
Check IAM policy (simulate-principal-policy)
       │
       ├─ Missing → add the permission
       │
       ▼
Is it an EC2/Lambda/EKS role?
       │
       └─ Yes → check role + trust policy + IRSA annotation

Resources

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments