A few weeks ago Amazon announced a new feature for Amazon CloudFront to run code in Edge Locations. But where is the difference between Lambda@Edge and CloudFront Functions?
CloudFront Functions are running in Edge locations whereas Lambda@Edge functions are executed in a regional edge cache (eg.: the AWS region closest to the CloudFront edge location reached by the client). Therefore CloudFront Functions are even closer to the client and are at the same time approximately 1/6th the price of Lambda@Edge.
Use Cases
- Authorization: Implement authorization for the content delivered through CloudFront using Basic Authentication or by creating and validating user-generated tokens.
- Redirects: Redirect users to a different URL - eg.: If you change to a new website structure you can redirect the user to the new URL.
- Header Manipulation: Add, modify, or delete any of the request/response headers - eg.: foward the IP of the client using the Header to your origin.
CloudFront Functions versus Lambda@Edge
Features
Most important differences - if you need more information check this docs: Choosing between CloudFront Functions and Lambda@Edge.
| CloudFront Functions | Lambda@Edge | |
|---|---|---|
| Execution location | CloudFront Edge Locations | CloudFront Regional Edge Caches | 
| Programming languages | JavaScript (ECMAScript 5.1 compliant) | Python, Nodejs | 
| Event sources | Viewer request Viewer response | Viewer request Viewer response Origin request Origin response | 
| Memory | 2 MB | 128 MB (viewer triggers) – 10 GB (origin triggers) | 
| Max size of Function | 10 KB | 1 MB (viewer request / response) 50 MB (origin request / response) | 
| Max execution time | 1 ms | 5 seconds (viewer request / response) 30 seconds (origin request / response) | 
| Access to geolocation and device data | ✅ | ❌ (viewer request) ✅ (viewer response) ✅ (origin request) ✅ (origin response) | 
| Access to the request body | ❌ | ✅ | 
Pricing example
| Service | Price per Invocation | Price per Duration (for every GB-second) | Invocations | Duration | Allocated Memory | Total Cost | 
|---|---|---|---|---|---|---|
| CloudFront Function | $0.1 | - | 2 Million | 1ms | - | $2.0 | 
| Lambda@Edge | $0.6 | $0,00005001 | 2 Million | 10ms | 128MB | $12.26 | 
- The prices were checked on 30.05.2021 from Lambda@Edge pricing and CloudFront Function pricing
Example template for Basic Auth with CloudFront Functions
Following you will find a CloudFront Function for Basic Auth - I am using it as a second layer of security for private CloudFront origins. For example I am generating exports of Jira content to S3 using a Lambda as a Backup. In Front of CloudFront I have a WAF to restrict to spefic IPs plus these CloudFront functions.
AWSTemplateFormatVersion: 2010-09-09
Description: Creates a Base CloudFront Function for Authentification
Metadata:
  Author:
    Description: David Krohn
Parameters:
  CloudFrountUsername:
    Description: Username CloudFront
    Type: String
  CloudFrountPassword:
    Description: Password CloudFront
    Type: String
    NoEcho: true
Ressources:
  CloudFrontFunctionBasicAuth:
    Type: AWS::CloudFront::Function
    Properties: 
      AutoPublish: true
      FunctionCode: !Sub |
        var USERS = {
            Website: [{
                username: '${CloudFrountUsername}',
                password: '${CloudFrountPassword}',
            }],
        };
        //Response when auth is not valid.
        var response401 = { 
            statusCode: 401,
            statusDescription: 'Unauthorized',
            headers: {
                'www-authenticate': {
                    value: 'Basic'
                },
            },
        };
        var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        function btoa(input) {
            input = String(input);
            var bitmap, a, b, c,
                result = "",
                i = 0,
                rest = input.length % 3; // To determine the final padding
            for (; i < input.length;) {
                if ((a = input.charCodeAt(i++)) > 255 ||
                    (b = input.charCodeAt(i++)) > 255 ||
                    (c = input.charCodeAt(i++)) > 255)
                    throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
                bitmap = (a << 16) | (b << 8) | c;
                result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
                    b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
            }
            // If there's need of padding, replace the last 'A's with equal signs
            return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
        }
        function handler(event) {
            var request = event.request;
            var headers = request.headers;
            var auth = request.headers.authorization && request.headers.authorization.value;
            var users = USERS['Website'];
            if (users) {
                if (!auth || !auth.startsWith('Basic ')) {
                    return response401;
                }
                if(!users.find(function(user) {
                        // Construct the Basic Auth string
                        var authString = 'Basic ' + btoa(user.username + ':' + user.password);
                        return authString === auth;
                    })) {
                    return response401;
                }
            }
            return request;
        }
      FunctionConfig:
        Comment: !Sub 'Basic Auth for S3 Bucket ${MyWebsiteBucket}'
        Runtime: cloudfront-js-1.0
More samples can be found here: Amazon CloudFront Functions Samples.
 

 
                      
 
    
Top comments (0)