Install the AWS Lambda@Edge Enforcer
  • 13 Aug 2024
  • Dark
    Light

Install the AWS Lambda@Edge Enforcer

  • Dark
    Light

Article summary

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.

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.

  1. In your CLI, enter git clone https://github.com/PerimeterX/aws-lambda-edge-template.

  2. Enter cd aws-lambda-edge-template.

  3. Enter npm install. This installs the necessary dependencies to use the Enforcer template.

  4. In your preferred text editor, open src/custom/config.ts and update the px_app_id, px_auth_token, and px_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.

  1. Save config.ts.

  2. In your CLI, enter npm run zip to bundle your Lambda functions into ZIP files. This should create PXActivities.zip, PXEnforcer.zip, and PXFirstParty.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:

  1. Navigate to the src directory of your Lambda project.

  2. Enter npm i --save @humansecurity/aws-lambda-edge-enforcer. This will update your package.json dependencies with the latest Lambda@Edge Enforcer package.

  3. Create a new config directory with a config.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

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.

  1. In your config.ts file, insert the following code and update the APP_ID, AUTH_TOKEN, and COOKIE_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>',
};
  1. 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);
        }
    });
};
  1. 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.

  2. Save config.ts.

  3. Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named index.ts into the dist directory, you would run: esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js.

  4. 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.

  1. In your config.ts file, insert the following code and update the APP_ID, AUTH_TOKEN, and COOKIE_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,
};
  1. 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;
};
  1. 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.

  2. Save config.ts.

  3. Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named index.ts into the dist directory, you would run: esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js.

  4. 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.

  1. In your config.ts file, insert the following code and update the APP_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
};
  1. 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);
  1. 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.

  2. Save config.ts.

  3. Bundle your Lambda function into a JavaScript file. For example, if you are bundling a function in a TypeScript file named index.ts into the dist directory, you would run: esbuild ./index.ts --bundle --minify --platform=node --target=es2022 --outfile=dist/index.js.

  4. 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.

  1. Navigate to Lambda > Functions.

  2. Select Create function to make a new Lambda function.

  3. Select the option to Author from scratch.

  4. 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.

  5. Select Create function to finish making your function.

  6. From your Lambda > Functions table, select the function you just created.

  7. In the Code source section, select Upload from and choose .zip file.

  8. Select the Lambda function ZIP file.

  9. Select Save.

  10. Select Actions > Publish new version.

  11. Copy the Function ARN.

  12. Navigate to CloudFront > Distributions.

  13. Select a Distribution ID > Behaviors.

  14. If you already have a behavior that uses the Default (*) path pattern, select it. Otherwise, select Create behavior.

  15. 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:

    • Viewer request event:

      • Select Lambda@Edge for the function type.

      • Paste the Function ARN from Step 11 in the field that appears.

  16. 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.

  1. Navigate to Lambda > Functions.

  2. Select Create function to make a new Lambda function.

  3. Select the option to Author from scratch.

  4. 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.

  5. Select Create function to finish making your function.

  6. From your Lambda > Functions table, select the function you just created.

  7. In the Code source section, select Upload from and choose .zip file.

  8. Select the Lambda function ZIP file.

  9. Select Save.

  10. Select Actions > Publish new version.

  11. Copy the Function ARN.

  12. Navigate to CloudFront > Distributions.

  13. Select a Distribution ID > Behaviors.

  14. If you already have a behavior that uses the Default (*) path pattern, select it. Otherwise, select Create behavior.

  15. 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.

  16. 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.

  1. Navigate to Lambda > Functions.

  2. Select Create function to make a new Lambda function.

  3. Select the option to Author from scratch.

  4. 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.

  5. Select Create function to finish making your function.

  6. From your Lambda > Functions table, select the function you just created.

  7. In the Code source section, select Upload from and choose .zip file.

  8. Select the Lambda function ZIP file.

  9. Select Save.

  10. Select Actions > Publish new version.

  11. Copy the Function ARN.

  12. Navigate to CloudFront > Policies > Cache and select Create cache policy.

  13. 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**

  14. 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.

  1. Navigate to CloudFront > Distributions.

  2. Select a Distribution ID > Behaviors.

  3. Select Create behavior.

  4. 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.

  5. 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.


Was this article helpful?

What's Next