Skip to content

Instantly share code, notes, and snippets.

@mikebroberts
Last active March 7, 2024 13:45
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mikebroberts/09e8c8b4aaac6e26149c4622fd492414 to your computer and use it in GitHub Desktop.
Save mikebroberts/09e8c8b4aaac6e26149c4622fd492414 to your computer and use it in GitHub Desktop.
CloudFront Functions Demo with CloudFormation
Description: CloudFront Functions Demo
# This example shows how to use CloudFront, CloudFront Functions, and CloudFormation.
# In this simple example we setup CloudFront so that on any request we redirect to another site.
# While basic, this example can be expanded to provide typical redirect scenarios, based
# on the event passed to the function.
# This example written by Mike Roberts (https://twitter.com/mikebroberts), Symphonia.
# For more ideas about using AWS more effectively,see our blog at https://blog.symphonia.io/
Parameters:
RedirectDomainName:
Type: String
Default: www.google.com
Outputs:
# Go to the value of this output in a browser, and you'll be redirected to the domain specified in RedirectDomainName
CloudfrontDomainName:
Value: !GetAtt CloudFrontDistribution.DomainName
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
# This example doesn't set custom aliases, but those can be added in the usual way
DistributionConfig:
Enabled: true
DefaultCacheBehavior:
TargetOriginId: redirectOrigin
ViewerProtocolPolicy: 'redirect-to-https'
# "Managed-CachingDisabled" from https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad
FunctionAssociations:
- EventType: viewer-request
FunctionARN: !GetAtt RedirectFunction.FunctionMetadata.FunctionARN
# CloudFront requires at least one origin, even though we're always going to redirect
Origins:
- DomainName: !Ref RedirectDomainName
Id: redirectOrigin
CustomOriginConfig:
OriginProtocolPolicy: match-viewer
RedirectFunction:
Type: AWS::CloudFront::Function
Properties:
AutoPublish: true
FunctionCode: !Sub |
function handler(event) {
return {
statusCode: 302,
statusDescription: 'Found',
headers: {
location: { value: 'https://${RedirectDomainName}/' }
}
}
}
FunctionConfig:
Comment: !Sub 'Redirect to ${RedirectDomainName}'
Runtime: cloudfront-js-1.0
Name: !Sub "${AWS::StackName}-redirectFunction"
@dependerCompro
Copy link

Instead of writing code for CloudFront function inside the template, can we read it from some other .js file?

@mikebroberts
Copy link
Author

Yes! :) I did it all in 1 file here just to keep everything together for a simple example. I have a more complicated example (based on what I use for symphonia.io and blog.symphonia.io) at https://github.com/symphoniacloud/coffee-store-web-full (see CloudFront src under src/cloudfront)

@kpturner
Copy link

kpturner commented Mar 7, 2024

Thanks for the interesting example of defining a CF function in serverless.yml. I too was interested in finding a way to define the function externally (preferably in TS) but I am afraid the link you provided here https://github.com/symphoniacloud/coffee-store-web-full did not really join up the dots for me. How does the AWS::CloudFront::Function definition in serverless.yml reference that external function?

As an aside I also my AWS::CloudFront::Distribution is defined elsewhere so I need a way of providing that with the ARN of the function. But first I need to make the next step and externalise the function somehow :D

@mikebroberts
Copy link
Author

Hi @kpturner - I have a terrible memory so it took me a while to remember all of this. :) So the short answer is that when using vanilla CloudFormation you can't actually use an external file - it has to be inline (and when I googled I came across my own AWS post here - https://repost.aws/questions/QUKVgjWKaPT0Ofb0XNXL9Eww/is-it-possible-to-use-cloudfront-functions-with-cloudformation-and-have-the-source-code-in-an-external-file) .

My solution for using an external file which I referenced here in Feb last year was dependent on using CDK as a tool on top of CloudFormation - which will read the entire file and put it in the template on your behalf (the code for that is here - https://github.com/symphoniacloud/cdk-website/blob/main/src/index.ts#L190-L201)

You mention "serverless.yml" which sounds like you might be using Serverless Framework. If you are then someone may have created a Serverless Framework plugin - but I haven't used the Serverless Framework for a few years.

@kpturner
Copy link

kpturner commented Mar 7, 2024

OK thanks. I have started investigating the AWS-CLI cloudfront create-function command where you can now reference an external JS file like this:

aws cloudfront create-function \
  --name my-function \
  --function-code fileb://functions/my-function.js \
  --function-config Comment="My description",Runtime=cloudfront-js-2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment