I'm just trying to get a static site on a S3 bucket and have it being accessible only trough a CloudFront distribution, but something is missing and I cannot figure out what.
Currently my stack have
- an S3 bucket for site hosting
- a cloudfront distribution for serving the site
- a bucket policy to let only the distribution accessing the bucket
- a default cache policy for the distribution
When trying to access the website directly from the bucket website url I get a 403 (forbidden, access denied) and that's ok.
When trying to access it from the distribution domain I get a generic error page with the message Failed to contact the origin.
When trying to access it from my registered domain I get a 403 error page with the message The request could not be satisfied.
followed by generics tips on how to fix it (login later, contact website owner, check documentation, etc)
Since I'm using CloudFormation template from my cli every resource is in the same region, and everything else too looks right to me, but obviously something is wrong.
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:
StringLike:
aws:Referer: !Sub 'https://*.${CloudFrontDistribution}.cloudfront.net/*'
Resource: !Sub arn:aws:s3:::${AppBucket}/*
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
DependsOn:
- AppBucket
- DefaultCachePolicy
Properties:
DistributionConfig:
Enabled: true
Origins:
- Id: AppBucket
DomainName: !GetAtt AppBucket.DomainName
OriginPath: /*
S3OriginConfig: {}
DefaultCacheBehavior:
ViewerProtocolPolicy: redirect-to-https
TargetOriginId: AppBucket
CachePolicyId: !Ref DefaultCachePolicy
AppBucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: 'test-spa-stack-bucket-app'
PublicAccessBlockConfiguration:
BlockPublicAcls : false
BlockPublicPolicy : false
IgnorePublicAcls : false
RestrictPublicBuckets : false
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: 'AES256'
WebsiteConfiguration:
IndexDocument: index.html
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
CodePudding user response:
Your bucket policy seems wrong.
You need to allow Origin access control of your CloudFront distribution to access the S3 bucket.
{
"Version": "2012-10-17",
"Statement": {
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
}
}
}
}
You also need to provide the same origin access control id in your CloudFront distribution definition:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
DependsOn:
- AppBucket
- DefaultCachePolicy
Properties:
DistributionConfig:
Enabled: true
Origins:
- Id: AppBucket
DomainName: !GetAtt AppBucket.DomainName
OriginPath: /*
OriginAccessControlId: "EDFDVBD6EXAMPLE" <- PROVIDE ID HERE
DefaultCacheBehavior:
ViewerProtocolPolicy: redirect-to-https
TargetOriginId: AppBucket
CachePolicyId: !Ref DefaultCachePolicy