Cloudfront differentiate origin based on hostname of the request - amazon-web-services

I have a Cloudfront distribution that I want to use it to serve two different hostnames (let's say 1.hostname.com and 2.hostname.com). In my CloudFormation template, I include these as aliases like below.
AppDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: !Ref ALBDomainName1
Id: ALBOrigin1
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
- DomainName: !Ref ALBDomainName2
Id: ALBOrigin2
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
Aliases:
- "1.hostname.com"
- "2.hostname.com"
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
- OPTIONS
- PUT
- PATCH
- POST
- DELETE
TargetOriginId: ALBOrigin1
ForwardedValues:
QueryString: False
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
MinTTL: 0
DefaultTTL: 60
MaxTTL: 60
ResponseHeadersPolicyId: "123123"
I want to configure the cloudformation to use one origin if the request is coming to 1.hostname.com and the other origin if the request is coming to 2.hostname.com. The path pattern can be the same in both cases. Is there a way to add CacheBehaviors achieve this?

Related

http2 for one origin in aws cloudfront

I have two origins, one refers to k8s, and the second I redirected the page from another site .
I tried to include in general http2 , but I need only one origin project with http2 ,
this is my clouformation
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: !Sub Frontend (${Stage})
Aliases:
- !If
- isProd
- !Sub ${Domain}
- !Sub ${Stage}.${Domain}
Origins:
- DomainName: !Ref LBEndpoint
Id: LBEndpoint
CustomOriginConfig:
OriginProtocolPolicy: http-only
OriginCustomHeaders:
- HeaderName: cdn_header
HeaderValue: !Ref CndHeader
- DomainName: !If
- isProd
- site.com
- staging.site.com
Id: project
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: cdn_header
HeaderValue: !Ref CndHeader
where should it be inserted ``` HTTPVersion: HTTP2```so that it works correctly?
can i not pass such values ​​only for one origin ?
so question - how to enable http2 for one origin in aws cloudfront using aws cloudfront or simply in the web panel

How to get the CloudFront distribution ARN in a CloudFormation stack for WebACLAssociation?

I've setup a CloudFront distribution in CloudFormation and I'm building an AWS WAF ACL to act as a firewall for it. To associate the ACL to the CloudFront distribution, I've added a AWS::WAFv2::WebACLAssociation entry which requires the ARN of the CloudFront distribution for the ResourceArn entry. However, I can't seem to find out how to get the CloudFront distribution ARN from the official documentation. I thought I could use !Ref however it used the CloudFront ID as per the documentation instead of the ARN.
How do I reference the CloudFront distribution ARN from the WebACLAssociation entry?
Example below (other resources omitted for brevity):
---
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront
Parameters:
# ...
CloudFront:
Type: AWS::CloudFront::Distribution
DependsOn:
- IssuedCertificate
- S3Bucket
Properties:
DistributionConfig:
Origins:
- DomainName: !Sub
- ${S3Bucket}.${S3WebEndpoint}
- {
S3Bucket: !Ref S3Bucket,
S3WebEndpoint:
!FindInMap [RegionMap, !Ref "AWS::Region", websiteendpoint],
}
Id: S3origin
CustomOriginConfig:
OriginProtocolPolicy: http-only
Enabled: "true"
Comment: !Sub Distribution for ${DomainName}
HttpVersion: http2
Aliases:
- !Ref DomainName
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
- OPTIONS
TargetOriginId: S3origin
Compress: True
DefaultTTL: 604800
ForwardedValues:
QueryString: "false"
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
PriceClass: PriceClass_100
ViewerCertificate:
AcmCertificateArn: !Ref Certificate
SslSupportMethod: sni-only
# ...
AWSWAF:
Type: AWS::WAFv2::WebACL
Properties:
Name: allowlist
Description: Allowlist
Scope: CLOUDFRONT
DefaultAction:
Block: {}
Rules:
- Name: ipset-rule
Priority: 0
Action:
Allow: {}
Statement:
IPSetReferenceStatement:
Arn: # <ARN>
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ipset-metrics
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: allowlist-metrics
AWSWAFAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
ResourceArn: !Ref CloudFront
WebACLArn: !Ref AWSWAF
There is no direct Attribute for the same but you can construct it:
arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFront}
Turns out I had been approaching the problem wrong all along. Diving into the docs, I found that AWS details how to deploy an ACL for a CloudFront distribution here under the ResouceArn entry.
To fix this issue, all I had to do was add the following to the CloudFront distribution DistributionConfig and remove the WebACLAssociation entry:
WebACLId: !GetAtt AWSWAF.Arn
So the final CloudFront entry looked like this:
CloudFront:
Type: AWS::CloudFront::Distribution
DependsOn:
- IssuedCertificate
- S3Bucket
Properties:
DistributionConfig:
Origins:
- DomainName: !Sub
- ${S3Bucket}.${S3WebEndpoint}
- {
S3Bucket: !Ref S3Bucket,
S3WebEndpoint:
!FindInMap [RegionMap, !Ref "AWS::Region", websiteendpoint],
}
Id: S3origin
CustomOriginConfig:
OriginProtocolPolicy: http-only
Enabled: "true"
Comment: !Sub Distribution for ${DomainName}
HttpVersion: http2
Aliases:
- !Ref DomainName
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
- OPTIONS
TargetOriginId: S3origin
Compress: True
DefaultTTL: 604800
ForwardedValues:
QueryString: "false"
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
PriceClass: PriceClass_100
ViewerCertificate:
AcmCertificateArn: !Ref Certificate
SslSupportMethod: sni-only
WebACLId: !GetAtt AWSWAF.Arn

Cloudfront distribution directs to S3 instead of API Gateway, producing 404 Error NoSuchKey

I have created an API Gateway that works. If I trigger the endpoint manually by https://example-api.amazonaws.com/Prod/some/endpoint the API gives me the desired result. Also I have set up a cloudfront behavior to route to this endpoint whenever the path contains /api/*.
If I now visit the endpoint through the cloudfront distribution: https://xxxxxxx.cloudfront.net/some/endpoint it gives me a 404 error. Cloudfront correctly appends the /prod to the path which tells me that something is working at least.
More specifically it gives me:
404 Not Found
Code: NoSuchKey
Message: The specified key does not exist.
An Error Occurred While Attempting to Retrieve a Custom Error Document
I can see the cloudfront distribution working since it redirects correctly. I have been struggling with this for a while now. Is this error code to ambiguous to be helpful?
After doing some more digging it seems as if the cloudfront distribution is looking in my s3 for an object with the key. So for some reason the PathPattern: /api/v1/* is not redirecting to the APIOrigin.
I have attached my Cloudformation template below:
Resources:
WebsiteCloudfront:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: Cloudfront Distribution pointing to S3 bucket and API Gateway.
Origins:
- Id: S3Origin
DomainName: bucket-for-static-files.amazonaws.com
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: http-only
- Id: APIOrigin
DomainName: example.api.endpoint.amazonaws.com
OriginPath: /prod
CustomOriginConfig:
# HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
Enabled: true
HttpVersion: 'http2'
DefaultRootObject: index.html
Aliases:
- !Ref DomainName
DefaultCacheBehavior:
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
Compress: true
# Logging: Logging
TargetOriginId: S3Origin
ForwardedValues:
QueryString: true
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
CacheBehaviors:
- TargetOriginId: APIOrigin
ViewerProtocolPolicy: https-only
PathPattern: /api/v1/*
ForwardedValues:
QueryString: true
Headers:
- Host
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
PriceClass: PriceClass_All
ViewerCertificate:
AcmCertificateArn: arn:aws:acm:SOME_HARD_CODED_ARN
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2019
However, the strange part remains where the cloudfront distribution appends the /prod. Making it seem as if the pathPattern correctly routes to API Gateway.
Edit: Currently thinking I might be missing Headers for the API Gateway.

Cloudfront does not redirect properly to https and subdomain

According to this post and this article, one should create a second cloudfront distribution in front of an S3 bucket which redirects to another bucket, which contains the static files.
Asuuming the frontend bucket name is www.example.com and the redirect bucket is example.com. I have set up my AWS resources according to the following cloudformation template.
However, some problems occur: If I hit example.com it does not redirect to www.example.com, only when I have clicked another link on the site. In addition, it does not load the favicon for example. http://example.com is redirect to https://example.com. http://www.example.com it does not redirect to https, the webiste is not found.
What am I missing in my AWS settings?
This mentions to not set the Default Root Object property, which I did not. But maybe it is related somehow?
FrontendBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.frontendBucketName}
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: 404.html
RedirectdBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.redirectBucketName}
AccessControl: PublicRead
WebsiteConfiguration:
RedirectAllRequestsTo:
HostName: ${self:custom.frontendBucketName}
Protocol: https
WebAppCloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: ${self:custom.frontendBucketName}.s3-website.${self:provider.region}.amazonaws.com
Id: Frontend
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: http-only
Enabled: 'true'
Aliases:
- ${self:custom.frontendBucketName}
CustomErrorResponses:
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
DefaultCacheBehavior:
DefaultTTL: 31536000
MaxTTL: 31536000
MinTTL: 31536000
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
TargetOriginId: Frontend
ForwardedValues:
QueryString: 'false'
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
AcmCertificateArn: 'arn:aws:acm:us-east-1:xxxx:certificate/xxxx'
SslSupportMethod: 'sni-only'
RedirectCloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: ${self:custom.redirectBucketName}.s3-website.${self:provider.region}.amazonaws.com
Id: Redirect
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: http-only
Enabled: 'true'
Aliases:
- {self:custom.redirectBucketName}
DefaultCacheBehavior:
DefaultTTL: 31536000
MaxTTL: 31536000
MinTTL: 31536000
AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
TargetOriginId: Redirect
ForwardedValues:
QueryString: 'false'
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
ViewerCertificate:
AcmCertificateArn: 'arn:aws:acm:us-east-1:xxxx:certificate/xxxx'
SslSupportMethod: 'sni-only'
DnsRecord:
Type: "AWS::Route53::RecordSet"
Properties:
AliasTarget:
DNSName:
Fn::GetAtt:
- WebAppCloudFrontDistribution
- DomainName
HostedZoneId: XXXXX
HostedZoneId: XXXX
Name: ${self:custom.frontendBucketName}
Type: 'A'
RedirectDnsRecord:
Type: "AWS::Route53::RecordSet"
Properties:
AliasTarget:
DNSName:
Fn::GetAtt:
- RedirectCloudFrontDistribution
- DomainName
HostedZoneId: XXXX
HostedZoneId: XXXX
Name: ${self:custom.redirectBucketName}
Type: 'A'
Currently, you have a DNS problem, you haven't published DNS record for "www.example.com".
You have DNS for example.com --> CloudFront but not for www.example.com , even though you have added www.example.com to a CloudFront CNMAE/Alternative filed, when client gets a 301/302 with a new location and see the change in host, it resolves it again.
curl -I --resolve www.example.com:443:13.249.210.66 https://www.example.com/index.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 80232
Connection: keep-alive
Date: Sun, 23 Jun 2019 10:07:43 GMT
Last-Modified: Fri, 21 Jun 2019 07:21:38 GMT
ETag: "8d536768b2173a7f3869f4178f75b331"
Server: AmazonS3
X-Cache: Miss from cloudfront
Via: 1.1 7db8064d915149cac923df11147875f9.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: BLR50-C3
X-Amz-Cf-Id: wOpVoz1gVlxYDBORSfGr9fmt8L-Q6vhWyEm1XPgJVQy-sbes9HTuuQ==
You just need to create a alias record in Route53 for www.example.com as well.

Getting "Missing Authentication Token" behind CloudFront distribution

I have an API Gateway as a custom origin on a CloudFront distribution hosted on a custom domain. The API works great when I call it from amazonaws.com url but from my custom domain I get "Missing Authentication Token". I assume I have the CloudFront distribution configured wrong somehow?
Dashboard:
Type: 'AWS::CloudFront::Distribution'
Properties:
DistributionConfig:
Aliases:
- promptdash.com
CacheBehaviors:
- AllowedMethods:
- DELETE
- GET
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
ForwardedValues:
QueryString: false
Headers: []
PathPattern: api/*
TargetOriginId: rest-api-origin
ViewerProtocolPolicy: https-only
DefaultCacheBehavior:
Compress: true
ForwardedValues:
QueryString: false
Headers: []
Cookies:
Forward: none
TargetOriginId: static-site-origin
ViewerProtocolPolicy: allow-all
DefaultRootObject: index.html
Enabled: true
Origins:
- DomainName: ddg-prompt.s3.amazonaws.com
Id: static-site-origin
S3OriginConfig:
OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${AccessIdentity}
- DomainName: !Sub ${Api}.execute-api.${AWS::Region}.amazonaws.com
Id: rest-api-origin
CustomOriginConfig:
OriginProtocolPolicy: https-only
OriginPath: /prod
PriceClass: PriceClass_100
ViewerCertificate:
AcmCertificateArn: arn:aws:acm:us-east-1:(my AccountId):certificate/(the certificate)
SslSupportMethod: sni-only