title: Cloudfront as a reverse proxy publishedAt: 1725206876000 updatedAt: 1742177576000 #
I run two services on AWS. One is a static website, the other is a serverless API.
The static website consists of the following setup:
flowchart TD
User --> Cloudfront
Cloudfront -- Default Behaviour --> S3
It's extremely simple, and handles global caching really easily.
The serverless API is a bit more complex, but it's still pretty simple.
flowchart LR
User --> APIGateway[API Gateway]
APIGateway -- GET /bar --> Lambda1[Lambda 1]
APIGateway -- GET /foo --> Lambda2[Lambda 2]
I've just setup Mastodon recently and need to update my /.well-known/webfinger to point to the mastodon instance. This will let me use my root domain as my mastodon username URL. Issue is - I'm already using the webfinger endpoint for OIDC...
So the solution is to set up a special API function that can handle this request. If It's meant for mastodon - send it there. Otherwise, return whatever else I want as JSON.
flowchart TD
User -- /.well-known/webfinger --> Cloudfront
Cloudfront -- Custom Behaviour --> APIGateway[API Gateway]
APIGateway --> Lambda[Lambda]
The issue I was running into was my cloudfront custom behaviour wasn't working. This was due to CloudFront forwarding the Host header to the origin. API Gateway doesn't like this & will always return a 403 {"message":"Forbidden"}.
I fixed this by ensuring the OriginRequestPolicyId was set up to a policy that forwarded everything except the Host header. AWS Incorrectly warn that this will break API Gateway, but it does not.
Here's my working truncated Cloudfront distribution config CacheBehaviors and Origins are the primary changes:
WebsiteCloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- DomainName: ${self:custom.s3Bucket}.s3.${opt:region}.amazonaws.com
Id: ${self:custom.s3Bucket}.s3.${opt:region}.amazonaws.com
OriginAccessControlId: !Ref WebsiteCloudfrontOriginAccessControl
S3OriginConfig:
OriginAccessIdentity: ""
- DomainName: api.pfy.ch
Id: api.pfy.ch
CustomOriginConfig:
OriginProtocolPolicy: https-only
DefaultRootObject: index.html
CacheBehaviors:
- PathPattern: /.well-known/*
TargetOriginId: api.pfy.ch
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # Disable caching
OriginRequestPolicyId: 88de81a8-de41-4bfc-a73-d5de1f3cd023 # Custom policy to forward everything except host!
AllowedMethods:
- GET
- HEAD
- OPTIONS
- PUT
- POST
- PATCH
- DELETE
CachedMethods:
- HEAD
- GET
ForwardedValues:
QueryString: true
If forwarding to API Gateway ENSURE that the Host header is not forwarded.