highFoundationSymptom-first#iam#ec2#s3#accessdenied

AccessDenied on S3 from an EC2 instance

aws s3 ls s3://<BUCKET>/ fails with AccessDenied on the instance

Likely source:securityconfiguration

Focused incident mode — strips away everything but this runbook.

Symptoms

  • aws s3 ls s3://<BUCKET>/ fails with AccessDenied on the instance
  • App that earlier read S3 suddenly gets 403
  • Works from your laptop/CI but fails from the instance role

Evidence to grab

Collect these artifacts before you change anything — they prove (or rule out) each cause.

  • Caller identity on the instance

    aws sts get-caller-identity
  • Attached role policies

    aws iam list-attached-role-policies --role-name <ROLE-NAME>

Diagnostic flow

Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.

Guided decision tree is ready.

Steps with commands, expected output, and pass/fail branches.

Ranked root causes

Evidence checklist

  • No policy granting s3:GetObject/ListBucket on <BUCKET>
  • Error appears after a policy rewrite

Confirm before fixing

aws iam get-role-policy --role-name <ROLE-NAME> --policy-name <POLICY-NAME>
READ

Inspect the inline policy

Fix

aws iam put-role-policy --role-name <ROLE-NAME> --policy-name s3-read --policy-document file://s3-access.json
CHANGE

Attach a policy permitting the required actions on arn:aws:s3:::<BUCKET>/*

Expected: policy attached

Resolution runbook

Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.

1
aws sts get-caller-identity
READ

Identify the active role

2
aws s3api head-object --bucket <BUCKET> --key <KEY> --debug 2>&1 | grep -i denied
READ

Capture the exact denied action

3
aws iam put-role-policy --role-name <ROLE-NAME> --policy-name s3-access --policy-document file://s3-access.json
CHANGE

Grant the needed s3 actions scoped to the bucket

4
aws s3api head-object --bucket <BUCKET> --key <KEY>
READ

Re-test until it succeeds

Prevention

  • Use IAM condition keys like s3:ResourceAccount and glue/role specific policies per app.
  • Adopt Infrastructure permissions boundaries so role policies and bucket policies agree.
  • Run an automated IAM Access Analyzer for cross-account access before deploys.

Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.