The short answer to your question is that you cannot reference a CF2 as an external file. It needs to be inlined. As Franky mentioned, you can consider using Lambda@Edge instead. However, if you do want to use CF2, here are a few ways that I have accomplished what you are looking for.
- Consider using CDK to dynamically generate your CloudFormation template. This won't allow you to reference your CF2 js code externally in the template, but it will allow you to package your js code into a template at the time of template creation with CDK.
- My preferred option is to use CodePipeline + Lambda to insert the updated CF2 js code directly into the CloudFormation template. Using this approach you would setup your repo as a source in CodePipeline, so that any time you commit changes the pipeline invokes. The second stage is a Lambda that looks at the changed files in the commit, and if it includes a CF2 js file change, then take the entire contents of the js file, and replace the FunctionCode block in the CloudFormation template with the updated js file. It is a lot of work, and a little clunky, but if you have a pipeline running anyways then this can fit in nicely. Tbh, you don't even need to use CodePipeline, you could write your own scripts to manually do the same thing. CodePipeline just automates it.
Thanks Franky and Jeremy.
The situation here is that I was using a L@E function, but wanted to switch to CFF because (a) it's a little easier in the CloudFormation / tighter integration with CloudFront and (b) I have no idea what's going on with L@E longer term - CFF is the new hotness!
The function itself is operationally very lightweight - it's just a redirect function based on the original path. But the source code is about 100 lines long (about 2/3 of which is a map of redirect locations) . So in this case being able to edit the code as an actual .js file would be much more convenient, AND I'd be able to unit test it. But I can't do that with inline code.
Your option #2 Jeremy is ... ummm ... clever? But as you say a lot of work! :) For me this is just a one-js-file function, with a 2-resource CloudFormation template (the distribution, and the CFF function) . I really don't want to do anything to deploy other than
sam deploy or
aws cloudformation deploy.
This is a situation where I don't want to use CDK because it's a piece of infrastructure that doesn't change very often, and IMO CDK apps require more "tending" over the long term than a vanilla CloudFormation / SAM app (see more on my thoughts on CDK here if you're interested: https://blog.symphonia.io/posts/2022-06-07_cdk_good_bad_scary).
Can this become a feature request for CloudFront, in which case does anyone know how I request that?
CloudFront functions should be small and light.
If you got a large piece of code, please consider using Lambda@Edge which does support other sources of code.
Comparison between CloudFront functions and Lambda function is available in this blog post: https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/
Please see if this documents helps:
- CloudFront distribution association with Lambda function: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-lambdafunctionassociation.html
- Lambda function: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html
- Lambda function code: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-code
Hi Mike, thanks for the context! Posting a new answer since the comment option limited my response to 600 characters.
I agree, the ideal option is to support an operation similar to how Lambda@Edge is packaged using sam package/deploy. It might be possible to do this with aws cloudformation package, but I am not sure if it supports AWS::CloudFront::Function as a supported resource type. To my knowledge it does not, but I would be happy to be wrong in this instance!
Re-thinking my option 2 above, I use that workflow as part of a much larger CodePipeline deploy workflow, but in this use-case it is un-neccessarily complex. I would instead just create a simple node app that performs some simple logic. Something like:
node cf2packager --viewerReq viewer-req-function.js --viewerResp viewer-resp-function.js --template cf-distro-template.json
This would take the viewerReq and viewerResp js files which can be edited and version controlled independently, and then replaces the appropriate FunctionCode block(s) in the CloudFormation template and spits out a new template file. Then you can just run your aws cloudformation deploy.
- AWS OFFICIALUpdated 2 years ago
- What do I do if I get an "It looks like you aren't authorized" error when trying to use Amazon Lightsail?AWS OFFICIALUpdated 3 years ago
- How can I resolve the "Export EXPORT_NAME cannot be updated as it is in use by STACK_NAME" error in AWS CloudFormation?AWS OFFICIALUpdated 2 years ago
- How do I use the Fn::Sub function in AWS CloudFormation with Fn::FindInMap, Fn::ImportValue, or other supported functions?AWS OFFICIALUpdated 2 years ago
- EXPERTpublished 2 months ago