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.
Most important differences - if you need more information check this docs: Choosing between CloudFront Functions and Lambda@Edge.
The prices were checked on 30.05.2021 from Lambda@Edge pricing and CloudFront Function pricing
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 specify 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.