DEV Community

David Krohn for AWS Community Builders

Posted on • Originally published at globaldatanet.com on

CloudFront Functions

CloudFront Functions

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

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
Enter fullscreen mode Exit fullscreen mode

More samples can be found here: Amazon CloudFront Functions Samples.

Top comments (0)