1

The problem

I'm trying to deploy an S3 bucket hosting my static website asset and a cloudfront distribution to access it, but the distribution still return a bare xml file for an 'access denied' error:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>5N0Z412GZ0VGV79E</RequestId>
  <HostId>GkpQbOpKeDiaCdFJM7kDq6ouWL/dvdijNu7NseC7KeIIogNabowVrDcfjPZ0xajKpDTx3SmgoEI=</HostId>
</Error>

As this docs page states in the blue Notice alert, I've not made the bucket a website endpoint, this way I can use an OAC to restrict access to its content.

A strange thing is that checking the distribution origin from the web console I see this blue alert, but the copyable policy is the same I found in the bucket permission at the given link.

enter image description here

I have no error during deploy, so it must be a silly configuration error, but it keeps giving me headaches since a week now and I can't figure out what is wrong.

Bucket and object owners corresponds

Since mi website assets are uploaded to the bucket from a different project/pipeline i followed this guide to check if the bucket and the object owners were different but actually corresponds:

> aws s3api list-buckets --query Owner.ID
"3fdbd1e5cad4dd2bbf4c66a3dbaded6b888fdb67ff6aa6e66203a4107fe17b72"

> aws s3api list-objects --bucket my-test-bucket --prefix index.html { "Contents": [ { "Key": "index.html", "LastModified": "2023-01-20T11:05:38+00:00", "ETag": "&quot;52f2df5ddf8c35391f3f15a7614def58&quot;", "Size": 325, "StorageClass": "STANDARD", "Owner": { "ID": "3fdbd1e5cad4dd2bbf4c66a3dbaded6b888fdb67ff6aa6e66203a4107fe17b72" } } ] }

CloudFormation template

Resources:

BucketPolicy: Type: 'AWS::S3::BucketPolicy' DependsOn: - AppBucket - CloudFrontDistribution Properties: Bucket: !Ref AppBucket PolicyDocument: Id: MyPolicy Version: '2012-10-17' Statement: Sid: PolicyForCloudFrontPrivateContent Action: s3:GetObject Effect: Allow Principal: Service: cloudfront.amazonaws.com Condition: StringEquals: AWS:SourceArn: !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution} Resource: !Sub arn:aws:s3:::${AppBucket}/*

CloudFrontDistribution: Type: AWS::CloudFront::Distribution DependsOn: - AppBucket - DefaultCachePolicy - DistributionOAC Properties: DistributionConfig: Enabled: true Origins: - Id: AppBucket DomainName: !GetAtt AppBucket.DomainName OriginPath: /* S3OriginConfig: {} OriginAccessControlId: !Ref DistributionOAC DefaultRootObject: index.html DefaultCacheBehavior: ViewerProtocolPolicy: redirect-to-https TargetOriginId: AppBucket CachePolicyId: !Ref DefaultCachePolicy

DistributionOAC: Type: AWS::CloudFront::OriginAccessControl Properties: OriginAccessControlConfig: Name: ExampleOAC OriginAccessControlOriginType: s3 SigningBehavior: always SigningProtocol: sigv4

AppBucket: Type: 'AWS::S3::Bucket' Properties: BucketName: 'test-spa-stack-bucket-app' PublicAccessBlockConfiguration: BlockPublicAcls : false BlockPublicPolicy : false IgnorePublicAcls : false RestrictPublicBuckets : false

DefaultCachePolicy: Type: AWS::CloudFront::CachePolicy Properties: CachePolicyConfig: Name: test-cache-policy DefaultTTL: 10 MaxTTL: 10 MinTTL: 1 ParametersInCacheKeyAndForwardedToOrigin: CookiesConfig: CookieBehavior: none EnableAcceptEncodingBrotli: true EnableAcceptEncodingGzip: true HeadersConfig: HeaderBehavior: none QueryStringsConfig: QueryStringBehavior: none

fudo
  • 151

2 Answers2

1

I had the same error. In my case I had set the default root object on the Distribution (General > Settings) to /index.html and I also set the origin path (Origins > my s3 origin) to /index.html. I only needed to set the object as index.html on the Distribution for it to start responding as expected.

This helped me discover the problem.

-1

Ok, I found a YT video that worked from cloud console, then I replicated it via CloudFormation stack template.

I think that my problem could be caused from either of these configurations:

  • bucket encription: I read somewhere (sorry I can't find the exact page) that CloudFront distribution cannot (directly) read bucket objects if encripted with anything different from SSE-S3, and since I omitted that configuration it probably did fallback on a non-compatible configuration
  • objects ownership: here too I forgot to add the cuket owner enforced policy
  • distribution accepted http version: here I accepted v.2

working template

Resources:
  BucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    DependsOn:
      - AppBucket
      - CloudFrontDistribution
    Properties:
      Bucket: !Ref AppBucket
      PolicyDocument:
        Id: PolicyForCloudFrontPrivateContent
        Version: '2008-10-17'
        Statement:
          Sid: AllowCloudFrontServicePrincipal
          Action: s3:GetObject
          Effect: Allow
          Principal:
            Service: cloudfront.amazonaws.com
          Condition:
            StringEquals:
              AWS:SourceArn: !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}
          Resource: !Sub arn:aws:s3:::${AppBucket}/*

CloudFrontDistribution: Type: AWS::CloudFront::Distribution DependsOn: - AppBucket - DistributionOAC - LogsBucket Properties: DistributionConfig: Enabled: true HttpVersion: http2 Origins: - Id: AppBucket DomainName: !GetAtt AppBucket.DomainName S3OriginConfig: {} OriginAccessControlId: !Ref DistributionOAC DefaultRootObject: index.html DefaultCacheBehavior: Compress: true ViewerProtocolPolicy: allow-all TargetOriginId: AppBucket CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # default CachingOptimized Logging: Bucket: !GetAtt LogsBucket.DomainName IncludeCookies: true Prefix: distribution/

AppBucket: Type: 'AWS::S3::Bucket' DependsOn: - LogsBucket Properties: BucketName: 'test-spa-stack-bucket-app' OwnershipControls: Rules: - ObjectOwnership: BucketOwnerEnforced PublicAccessBlockConfiguration: BlockPublicAcls : true BlockPublicPolicy : true IgnorePublicAcls : true RestrictPublicBuckets : true BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 LoggingConfiguration: DestinationBucketName: !Ref LogsBucket LogFilePrefix: app/

DistributionOAC: Type: AWS::CloudFront::OriginAccessControl Properties: OriginAccessControlConfig: Name: test-spa-distribution-oac OriginAccessControlOriginType: s3 SigningBehavior: always SigningProtocol: sigv4

LogsBucket: Type: 'AWS::S3::Bucket' Properties: BucketName: 'test-spa-stack-bucket-logs' PublicAccessBlockConfiguration: BlockPublicAcls : true BlockPublicPolicy : true IgnorePublicAcls : true RestrictPublicBuckets : true AccessControl: LogDeliveryWrite VersioningConfiguration: Status: Enabled BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: 'AES256'

fudo
  • 151