Skip to content

Persistent 403 Access Denied on S3 Static Hosting, even after all standard fixes

0

I am facing a persistent "403 Access Denied" error on what should be a simple S3 static website setup. I have spent many hours troubleshooting and have followed all standard advice, including solutions from other re:Post threads, but the issue remains. I am now suspecting an account-level problem.

What I Have Tried:

  1. CloudFront + Private S3 with OAC (The Recommended Method):

I created a CloudFront distribution pointing to a private S3 bucket.

I correctly configured Origin Access Control (OAC) and let CloudFront update the bucket policy.

I set the "Default Root Object" to index.html.

I even created and associated a CloudFront Function to rewrite root requests to index.html.

Result: 403 Access Denied.

  1. Complete Re-creation:

To eliminate any hidden misconfigurations, I completely deleted the original CloudFront distribution and re-created it from scratch with all the correct settings mentioned above applied at once.

Result: Still 403 Access Denied.

  1. Minimal Diagnostic Test (Fully Public S3 Bucket):

To completely isolate the problem, I performed a final, minimal test, removing CloudFront from the equation entirely.

I created a brand new S3 bucket:

Region: ap-northeast-1

Block all public access: DISABLED

Static website hosting: ENABLED (with index.html as the index document)

Bucket Policy: Attached a policy to allow public s3:GetObject for everyone ("Principal": "*").

Result: Accessing the direct S3 bucket website endpoint URL still results in a 403 Access Denied error.

My Core Question:

Given that even a direct request to a minimal, fully public S3 static website endpoint is failing, it seems the issue is not with my resource configurations (which I have reset multiple times).

What could cause this behavior beyond standard S3/CloudFront settings? Could there be an account-level restriction (like an SCP), a permission boundary, or a specific limitation on my account type that is blocking public S3 hosting capabilities?

Any insight into this unusual situation would be greatly appreciated. Thank you.

asked a month ago68 views
2 Answers
0

Based on your thorough troubleshooting, there are several potential causes for the persistent 403 Access Denied errors you're experiencing with your S3 static website.

First, let's address the account-level possibilities you mentioned:

  1. Service Control Policies (SCPs): If your AWS account is part of an AWS Organization, there might be SCPs in place that restrict S3 public access regardless of your bucket settings. These organization-level policies override individual bucket configurations.

  2. Permission Boundaries: If permission boundaries are applied to the IAM roles/users you're using, they could be limiting S3 actions even if your bucket policy allows them.

For your specific CloudFront + OAC setup issues:

  1. Origin Configuration Mismatch: When using OAC, you should be using the S3 REST API endpoint (bucket-name.s3.amazonaws.com) rather than the S3 website endpoint (bucket-name.s3-website-region.amazonaws.com). These are incompatible - OAC doesn't work with S3 website endpoints.

  2. Static Website Hosting vs. OAC: You cannot use both static website hosting and OAC together effectively. If you're using OAC, you should disable static website hosting on the bucket.

For your public S3 bucket test:

  1. Bucket Policy Format: Ensure your bucket policy is correctly formatted. The policy should look like:
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}
  1. Object Ownership Settings: Check your bucket's Object Ownership settings. If set to "Bucket owner enforced," ACLs are disabled and might affect access.

  2. Object-Level Permissions: Even if your bucket is public, individual objects might have different permissions. Ensure the objects themselves are accessible.

  3. Enhanced Access Denied Messages: Check for enhanced access denied messages in your S3 console, which might provide more specific information about why access is being denied.

To resolve this issue, I recommend:

  1. For the CloudFront + OAC approach (recommended for security):
  • Keep your S3 bucket private (Block all public access ON)
  • Disable static website hosting
  • Configure CloudFront to use the S3 REST API endpoint
  • Ensure your bucket policy grants the CloudFront service principal access
  • Set index.html as the default root object in CloudFront
  1. For direct S3 website hosting:
  • Confirm all "Block public access" settings are OFF at both bucket and account levels
  • Enable static website hosting
  • Add a properly formatted bucket policy allowing public read access
  • Check for any organization-level policies that might be overriding your settings

If the issue persists after these steps, it would be worth contacting AWS Support as there might be an account-specific configuration affecting your setup.
Sources
Troubleshoot access denied (403 Forbidden) errors in Amazon S3 - Amazon Simple Storage Service
Higgsfield AI Mod APK Premium Unlocked - S3 static site returning 403 Forbidden? | AWS re:Post
S3/Cloudfront & OAC: Access denied when accessing path other than index site | AWS re:Post
Cloudfront cannot access s3 bucket | AWS re:Post
Access Denied for CloudFront to S3 static site | AWS re:Post

answered a month ago
EXPERT
reviewed a month ago
0

Hello.

Will a 403 error occur even if You create S3 and CloudFront using the following CloudFormation template?
I have confirmed that index.html can be displayed normally in my AWS account.
If you get a 403 error even after creating the CloudFormation below, as you suspected, it may be a problem with your AWS account, so I recommend contacting AWS Support.
"Account and billing" inquiries are free of charge.

AWSTemplateFormatVersion: 2010-09-09
Description: Static contents distribution using S3 and CloudFront.
 
Parameters:
  SiteName:
    Type: String
    Description: domain name e.g. test-site.com
 
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Sub ${SiteName}-s3-bucket-${AWS::AccountId}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      WebsiteConfiguration:
        IndexDocument: index.html
 
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${Bucket}/*
            Principal:
              Service: "cloudfront.amazonaws.com"
            Condition:
              StringEquals:
                AWS:SourceArn:
                  - !Join
                    - ""
                    - - !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/"
                      - !Ref CloudFrontDistribution
 
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - Id: S3
            DomainName: !GetAtt Bucket.RegionalDomainName
            OriginAccessControlId: !GetAtt OAC.Id
            S3OriginConfig:
              OriginAccessIdentity: ""
        Enabled: true
        DefaultRootObject: index.html
        Comment: !Ref SiteName
        DefaultCacheBehavior:
          AllowedMethods:
            - HEAD
            - GET
          CachedMethods:
            - HEAD
            - GET
          DefaultTTL: 0
          MaxTTL: 0
          MinTTL: 0
          TargetOriginId: S3
          ForwardedValues:
            QueryString: false
          ViewerProtocolPolicy: redirect-to-https
        IPV6Enabled: false
 
  OAC:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: !Ref SiteName
        Name: !Ref SiteName
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4
 
Outputs:
  CloudFrontDistributionDomain:
    Value: !GetAtt CloudFrontDistribution.DomainName
    Description: CloudFront Domain Name
    Export:
      Name: !Sub ${SiteName}-CloudFrontDomainName

Please note that after creating an S3 bucket, it may take up to 24 hours for the bucket name to propagate to all AWS regions.
If the S3 bucket endpoint specified in your CloudFront distribution is in the Tokyo region (ap-northeast-1), accessing it within 24 hours may result in a redirection to the S3 object URL.
You may be redirected directly to S3, resulting in a 403 error.
To resolve this issue, try setting the S3 regional endpoint in CloudFront's origin settings as described in the following document.
In the above CloudFormation template, the origin setting is set to reference "RegionalDomainName".
https://repost.aws/knowledge-center/s3-http-307-response

After you create an Amazon S3 bucket, it can take up to 24 hours before the bucket name propagates across all AWS Regions. During this time, you might receive the 307 Temporary Redirect response for requests to Regional endpoints that aren't in the same Region as your bucket. For more information, see Temporary request redirection.

EXPERT
answered a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.