Skip to content
errata/docs

AccessDenied

S3 PutObject AccessDenied with a valid IAM policy

Product
AWS S3
Severity
Severity: medium
Updated
Read
5 min

The identity policy allows s3:PutObject, but another layer — bucket policy, KMS key policy, or an SCP — denies it. Explicit denies always win.

Error message
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

Symptoms

  • Uploads fail while ListBucket and GetObject succeed.
  • The IAM policy simulator reports "allowed" for the action.
  • Failures only occur on buckets with default SSE-KMS encryption.

Cause

  • The role lacks kms:GenerateDataKey on the bucket’s KMS key.
  • A bucket policy requires a header, such as x-amz-server-side-encryption, that the client omits.
  • An Organizations SCP denies writes outside approved regions.

Resolution

  1. Step 1: Confirm the calling identity

    Make sure the request is signed by the role you think it is.

    bash
    aws sts get-caller-identity
  2. Step 2: Grant KMS permissions

    Add the key actions to the role, and confirm the key policy trusts the account.

    json
    {
      "Effect": "Allow",
      "Action": ["kms:GenerateDataKey", "kms:Decrypt"],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/<key-id>"
    }
  3. Step 3: Search CloudTrail for the deny source

    Filter by errorCode AccessDenied and read the errorMessage — it often names the policy type that denied the request.

    bash
    aws cloudtrail lookup-events \
      --lookup-attributes AttributeKey=EventName,AttributeValue=PutObject \
      --max-results 5

← Back to index