- 13 Aug 2024
- Print
- DarkLight
Install the AWS Lambda@Edge Enforcer
- Updated on 13 Aug 2024
- Print
- DarkLight
If your organization uses AWS CloudFront services, you can use HUMAN’s Lambda@Edge Enforcer to protect against malicious behavior. This Enforcer uses AWS Lambda functions to deploy the Enforcer on your content delivery network (CDN) and determine how traffic to your organization’s server should be handled.
You can learn how to install the Enforcer with this article.
Prerequisites
An AWS account with appropriate permissions and access to the following (see AWS’ help article for more information):
AWS CloudFront with an existing CloudFront distribution. See AWS’ help article to learn how to create one.
AWS Lambda and permissions to deploy Lambda functions to CloudFront distributions
AWS CloudWatch
AWS IAM with permissions to create and modify IAM roles
A command-line interface (CLI).
A text editor.
GitHub CLI. See GitHub's repository to learn how to install it.
Node Version Manager (nvm) installed on your device. See nvm's GitHub repository to learn how to install it.
The latest version of Node.js. After installing nvm, enter
nvm install stable
in your CLI to install it.Your unique HUMAN information:
Your Application ID. You can find this under Platform Settings > Applications > Overview in the HUMAN console. If you have multiple environments, you will also have multiple Application IDs, so be sure to choose the correct ID for the environment you want to install on.
Your Server Token. You can find this under Platform Settings > Applications > Status & Settings > Server Token.
Your Risk Cookie Key. You can find this under Bot Defender > Policies > Policy Settings > Policy Information. You may need to generate a new key if you do not already have one.
Define the Lambda functions
The Lambda@Edge Enforcer consists of three Lambda functions. Each function is integrated at a different event in an Amazon CloudFront distribution. They are:
Note
For more information on CloudFront events, see AWS’ help article.
HumanEnforcer Lambda (required): Triggered by the viewer request event. You must create this Lambda function to properly install the Enforcer.
HumanActivities Lambda (optional): Triggered by the origin response. You should only integrate this Lambda if you have enabled features or products that require response data.
HumanFirstParty Lambda (optional): Triggered by the origin request. This Lambda will only be used for first-party requests from HUMAN, and it will not monitor typical website traffic.
The process for defining your Lambda functions is different depending on if you have an existing Lambda project or not.
If you do not have an existing Lambda project, see Define with the HUMAN template.
If you do have an existing Lambda project, see Define with an existing project.
Define with the HUMAN template
If you do not have an existing AWS project, then you can use HUMAN's premade templates to quickly create and install the AWS Lambda@Edge Enforcer. This Enforcer is publicly available from our GitHub repository.
In your CLI, enter
git clone https://github.com/PerimeterX/aws-lambda-edge-template
.Enter
cd aws-lambda-edge-template
.Enter
npm install
. This installs the necessary dependencies to use the Enforcer template.In your preferred text editor, open
src/custom/config.ts
and update thepx_app_id
,px_auth_token
, andpx_cookie_secret
fields with your Application ID, Server Token, and Risk Cookie Key respectively.
Note
These are the minimum required settings to configure the Enforcer. To customize it further, see our custom configurations. We recommend adding your configurations before uploading any Lambda function to your CloudFront distribution for the first time.
You can store sensitive information, such as your Server Token and Risk Cookie Key, in the AWS Secrets Manager rather than inserting them directly into your configuration. See AWS’ help article to learn how to do so.
Save
config.ts
.In your CLI, enter
npm run zip
to bundle your Lambda functions into ZIP files. This should createPXActivities.zip
,PXEnforcer.zip
, andPXFirstParty.zip
.
Next, see the steps in Deploy the Enforcer to complete your setup.
Define with an existing project
If you already have a Lambda project that you want to integrate the HUMAN Enforcer with, then you can follow the steps below.
Note
Each Lambda function requires slightly different steps to configure and deploy to CloudFront. Be sure to follow the right section to complete each one.
The HumanEnforcer Lambda is required.
To get started:
Navigate to the
src
directory of your Lambda project.Enter
npm i --save @humansecurity/aws-lambda-edge-enforcer
. This will update yourpackage.json
dependencies with the latest Lambda@Edge Enforcer package.Create a new
config
directory with aconfig.ts
file. We recommend doing this if you are creating multiple Lambda functions or want to add custom configurations.
Then, follow the appropriate section for each Lambda function:
Define the HumanEnforcer Lambda (required)
Define the HumanEnforcer Lambda
The HumanEnforcer Lambda is the primary Lambda that determines the behavior of traffic activity in your CloudFront distribution. This Lambda is required so that the AWS Lambda@Edge Enforcer can function.
In your
config.ts
file, insert the following code and update theAPP_ID
,AUTH_TOKEN
, andCOOKIE_SECRET
fields with your Application ID, Server Token, and Risk Cookie Key respectively.
Note
We recommend using the AWS Secrets Manager to securely store sensitive tokens such as your Server Token and Risk Cookie Key in the AWS Secrets Manager rather than inserting them directly into your configuration. See AWS’ help article to learn how to do so.
If you also want to add any custom configurations, we recommend doing so in this step before uploading any Lambda function to AWS CloudFront for the first time. You can review our available configurations with our help article.
// config.ts
import { HumanSecurityConfiguration } from '@humansecurity/aws-lambda-edge-enforcer';
// define configuration
const config: HumanSecurityConfiguration = {
px_app_id: '<APP_ID>',
px_auth_token: '<AUTH_TOKEN>',
px_cookie_secret: '<COOKIE_SECRET>',
};
In the file with your existing Lambda’s source code, add the appropriate code from below depending on if you have existing handler logic.
Integrating without handler logic
// index.ts
import { createHumanEnforceHandler } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
// create and export the handler
export const handler = createHumanEnforceHandler(config);
Integrating with handler logic
// index.ts
import { CloudFrontRequest, CloudFrontRequestEvent, CloudFrontResponseResult, Context } from 'aws-lambda';
import { HumanSecurityEnforcer } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
// initialize the enforcer
const enforcer = HumanSecurityEnforcer.initialize(config);
// define a handler
export async function handler(
event: CloudFrontRequestEvent,
context: Context
): Promise<CloudFrontRequest | CloudFrontResponseResult> {
// extract the request from the event
const request = event.Records[0].cf.request;
// call enforce() and await the response
// recommend calling before any existing logic
// request is a required argument, context is optional
const result = await enforcer.enforce(request, context);
// return the result if it exists
if (result) {
return result;
}
// execute your existing logic on the request here
// eventually return the request
return request;
};
Integrating with callback-based handler logic
AWS Lambda considers it best practice to use async/await syntax, but if you use callback-based syntax, you can use the following alternative.
// index.ts
import { CloudFrontRequest, CloudFrontRequestEvent, CloudFrontResponseResult, Context } from 'aws-lambda';
import { HumanSecurityEnforcer } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
// initialize the enforcer
const enforcer = HumanSecurityEnforcer.initialize(config);
// define a handler
export function handler(event, context, callback) {
context.callbackWaitsForEmptyEventLoop = false;
const request = event.Records[0].cf.request;
enforcer.enforce(request, context).then((result) => {
if (result) {
callback(null, result);
} else {
// continue processing until eventually...
callback(null, request);
}
});
};
If you want to deploy other Lambdas with the Enforcer, complete the setup for each by following the steps in either Define the HumanActivities Lambda or Define the HumanFirstParty Lambda.
Save
config.ts
.Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named
index.ts
into thedist
directory, you would run:esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js
.Zip your bundled function.
Once you’ve zipped your function, see the steps in Deploy the Enforcer to complete your setup.
Define the HumanActivities Lambda
You only need to configure the HumanActivities Lambda if you want to send the custom HUMAN configuration additional_s2s_activity
to the origin. This lets HUMAN analyze data related to the response in addition to the request.
In your
config.ts
file, insert the following code and update theAPP_ID
,AUTH_TOKEN
, andCOOKIE_SECRET
fields with your Application ID, Server Token, and Risk Cookie Key respectively.
Note
We recommend defining this using the same configuration you used for the HumanEnforcer Lambda.
// config.ts
import { HumanSecurityConfiguration } from '@humansecurity/aws-lambda-edge-enforcer';
// define configuration
const config: HumanSecurityConfiguration = {
px_app_id: '<APP_ID>',
px_auth_token: '<AUTH_TOKEN>',
px_cookie_secret: '<COOKIE_SECRET>',
// add the custom s2s activity configuration for HumanActivities
px_automatic_additional_s2s_activity_enabled: true,
};
In the file with your existing Lambda’s source code, add the appropriate code from below depending on if you have existing handler logic.
Integrating without handler logic
// index.ts
import { createHumanActivitiesHandler } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
// create and export the handler
export const handler = createHumanActivitiesHandler(config);
Integrating with handler logic
// index.ts
import { CloudFrontResponseEvent, CloudFrontResponseResult, Context } from 'aws-lambda';
import { HumanSecurityPostEnforcer } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
// initialize the postEnforcer
const postEnforcer = HumanSecurityPostEnforcer.initialize(config);
// define a handler
export async function handler(
event: CloudFrontResponseEvent,
context: Context
): Promise<CloudFrontResponseResult> {
// extract the request and response from the event
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
// execute your custom logic on the response here
// call and await the postEnforce() function
await postEnforcer.postEnforce(request, response);
// return the response
return response;
};
If you want to deploy other Lambdas with the Enforcer, complete the setup for each by following the steps in either Deploy the HumanEnforcer Lambda or Deploy the HumanFirstParty Lambda. Otherwise, continue to the next step.
Save
config.ts
.Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named
index.ts
into thedist
directory, you would run:esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js
.Zip your files.
Once you’ve zipped your function, see the steps in Deploy the Enforcer to complete your setup.
Define the HumanFirstParty Lambda
You only need to configure the HumanFirstParty Lambda if you want to support first-party requests. You can learn more about these requests with our help article.
In your
config.ts
file, insert the following code and update theAPP_ID
field with your Application ID and add relevant first-party custom configurations you want to include to the definition.
Note
We recommend defining this using the same configuration you used for the HumanEnforcer Lambda.
// config.ts
import { HumanSecurityConfiguration } from '@humansecurity/aws-lambda-edge-enforcer';
// define configuration
export const config = {
px_app_id: '<APP_ID>',
// insert custom configurations
};
In the file with your existing Lambda’s source code, add the following code:
// index.ts
import { createHumanFirstPartyHandler } from '@humansecurity/aws-lambda-edge-enforcer';
import { config } from './config';
export const handler = createHumanFirstPartyHandler(config);
If you want to deploy other Lambdas with the Enforcer, complete the setup for each by following the steps in either Deploy the HumanEnforcer Lambda or Deploy the HumanActivities Lambda. Otherwise, continue to the next step.
Save
config.ts
.Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named
index.ts
into thedist
directory, you would run:esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js
.Zip your files.
Once you’ve zipped your function, see the steps in Deploy the Enforcer to complete your setup.
Deploy the Enforcer
Now that you have your Lambda functions ready, you must upload them to AWS CloudFront and deploy them. The steps to upload each type of Lambda are different, so be sure to follow the correct instructions for the Lambda you’re uploading.
Note
Ensure you are on US East (N. Viriginia), us-east-1 when creating Lambda functions. Lambda@Edge functions can only be deployed from us-east-1. For more information, see AWS’ help article.
Upload the HumanEnforcer Lambda (required)
Complete the following steps to upload the HumanEnforcer Lambda.
Navigate to Lambda > Functions.
Select Create function to make a new Lambda function.
Select the option to Author from scratch.
Complete the fields to create a new function. You can leave most of the fields with their default values, but be sure to update the following:
Function name: Enter the name for your function.
Runtime: Select at least Node.js 18.x or higher.
Permissions > Change default execution role > Execution role: Choose the appropriate role defined by your Lambda permissions and fill in the fields that appear if necessary. The role is determined by your organization’s AWS policy.
If your organization already has a role with the appropriate permissions, select Use an existing role.
If your organization does not have an appropriate role, create a new one with one of the available options.
Select Create function to finish making your function.
From your Lambda > Functions table, select the function you just created.
In the Code source section, select Upload from and choose .zip file.
Select the Lambda function ZIP file.
Select Save.
Select Actions > Publish new version.
Copy the Function ARN.
Navigate to CloudFront > Distributions.
Select a Distribution ID > Behaviors.
If you already have a behavior that uses the Default (*) path pattern, select it. Otherwise, select Create behavior.
Complete the following fields:
Path Pattern: Default (*)
Cache policy and origin request policy (recommended): Select an origin request policy to ensure you do not remove important headers. If one does not exist, see AWS’ help article to create one. Our recommendations are:
AllViewerExceptHostHeader: We recommend using this policy, especially if you are also uploading the HumanFirstParty Lambda.
Viewer request event:
Select Lambda@Edge for the function type.
Paste the Function ARN from Step 11 in the field that appears.
Select Save changes.
You have successfully integrated the HUMAN AWS Lambda@Edge Enforcer with your CloudFront distribution. Make sure to reach out to our support team to complete your tuning process.
Upload the HumanActivities Lambda
Complete the following steps to upload the HumanActivities Lambda.
Navigate to Lambda > Functions.
Select Create function to make a new Lambda function.
Select the option to Author from scratch.
Complete the fields to create a new function. You can leave most of the fields with their default values, but be sure to update the following:
Function name: Enter the name for your function.
Runtime: Select at least Node.js 18.x or higher.
Permissions > Change default execution role > Execution role: Choose the appropriate role defined by your Lambda permissions and fill in the fields that appear if necessary. The role is determined by your organization’s AWS policy.
If your organization already has a role with the appropriate permissions, select Use an existing role.
If your organization does not have an appropriate role, create a new one with one of the available options.
Select Create function to finish making your function.
From your Lambda > Functions table, select the function you just created.
In the Code source section, select Upload from and choose .zip file.
Select the Lambda function ZIP file.
Select Save.
Select Actions > Publish new version.
Copy the Function ARN.
Navigate to CloudFront > Distributions.
Select a Distribution ID > Behaviors.
If you already have a behavior that uses the Default (*) path pattern, select it. Otherwise, select Create behavior.
Complete the following fields:
Path Pattern: Default (*)
Origin response:
Select Lambda@Edge for the function type.
Paste the Function ARN from Step 11 in the field that appears.
Select Save changes.
Make sure you also upload the HumanEnforcer Lambda. Once you do, you have successfully integrated the HUMAN AWS Lambda@Edge Enforcer with your CloudFront distribution. Make sure to reach out to our support team to complete your tuning process.
Upload the HumanFirstParty Lambda
Complete the following steps to upload the HumanFirstParty Lambda.
Navigate to Lambda > Functions.
Select Create function to make a new Lambda function.
Select the option to Author from scratch.
Complete the fields to create a new function. You can leave most of the fields with their default values, but be sure to update the following:
Function name: Enter the name for your function.
Runtime: Select at least Node.js 18.x or higher.
Permissions > Change default execution role > Execution role: Choose the appropriate role defined by your Lambda permissions and fill in the fields that appear if necessary. The role is determined by your organization’s AWS policy.
If your organization already has a role with the appropriate permissions, select Use an existing role.
If your organization does not have an appropriate role, create a new one with one of the available options.
Select Create function to finish making your function.
From your Lambda > Functions table, select the function you just created.
In the Code source section, select Upload from and choose .zip file.
Select the Lambda function ZIP file.
Select Save.
Select Actions > Publish new version.
Copy the Function ARN.
Navigate to CloudFront > Policies > Cache and select Create cache policy.
Create a cache policy with the following settings:
Minimum TTL: 0
Maximum TTL: 10
Default TTL: 5
Headers: Include the following headers
Host
User-agent
Query strings: All
Cookies: Including the following cookies
*_px*
px**
Select Create.
Warning
If the Enforcer was configured to use custom first party endpoints, you must create additional cache behaviors for the custom first party path patterns. Otherwise, requests using the custom paths will not be handled properly.
Navigate to CloudFront > Distributions.
Select a Distribution ID > Behaviors.
Select Create behavior.
Complete the following fields:
Path Pattern:
/<APP_ID_without_PX>/*
. For example, for an ID that is PX123456, the path pattern should be/123456/*
.Viewer protocol policy: HTTP and HTTPS
Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cache policy: Select the cache policy you created in Step 14.
Origin request policy: AllViewerExceptHostHeader. You should have created this origin request policy while completing the steps in Upload the HumanEnforcer Lambda (required).
Origin request:
Select Lambda@Edge for the function type.
Paste the Function ARN from Step 11 in the field that appears.
Select Save changes.
Make sure you also upload the HumanEnforcer Lambda. Once you do, you have successfully integrated the HUMAN AWS Lambda@Edge Enforcer with your CloudFront distribution. Make sure to reach out to our support team to complete your tuning process.