Mastering Custom Responses in Amazon CloudFront to Block Behaviour — Default(*)

Tech Community • 7 min read

Introduction

When deploying an e-commerce application on Amazon Web Services (AWS), ensuring robust security measures is paramount. However, traditional setups with Amazon CloudFront might present challenges, especially when attempting to disable default behaviors for specific paths. In this blog post, we’ll explore how AWS Lambda@Edge, coupled with Amazon CloudFront’s Origin Request events, can be leveraged to create custom responses and enhance security for e-commerce applications

Challenges with Default Behaviors in CloudFront

In many cases, e-commerce applications require tailored responses for certain paths, such as restricting access to sensitive areas or redirecting users to specific pages. However, Amazon CloudFront’s default behaviors (*) lack the option to disable them, necessitating alternative solutions for custom responses.

Introducing AWS Lambda@Edge for Custom Responses

AWS Lambda@Edge offers a powerful solution to this challenge by enabling the execution of custom code at Amazon CloudFront’s edge locations. By leveraging Amazon CloudFront’s Origin Request events, we can intercept incoming requests before they reach the origin server, such as an Amazon S3 bucket or an Amazon EC2 instance. This interception point provides the perfect opportunity to generate custom responses based on specific criteria.

When you associate a Amazon CloudFront distribution with a AWS Lambda@Edge function, Amazon CloudFront intercepts requests and responses at Amazon CloudFront edge locations. You can execute AWS Lambda functions when the following Amazon CloudFront events occur:

  • When Amazon CloudFront receives a request from a viewer (viewer request)
  • Before Amazon CloudFront forwards a request to the origin (origin request)
  • When Amazon CloudFront receives a response from the origin (origin response)
  • Before Amazon CloudFront returns the response to the viewer (viewer response)

In this blog post, we'll demonstrate how to utilize Amazon CloudFront's origin request events to restrict access to specific URLs that would normally be processed through default behavior. To achieve this, we'll employ an AWS Lambda@Edge function, which allows us to intercept and customize responses directly at the CloudFront edge locations. By implementing this setup, the AWS Lambda@Edge function will evaluate incoming requests and, based on the default behavior configuration, block access to the request by using AWS Lambda@Edge function. This method effectively overrides the default behavior of CloudFront, providing a tailored response mechanism that can enforce more granular access controls on your content delivery network.

Architecture

Prerequisites

  • An AWS Account with full access to Amazon S3, Amazon Cloudfront & Amazon Lambda functions

Implementation Steps

  1. Create a AWS Lambda Function as per the below screenshot with the name Block_CF_Default_Behavior_Access

Note : AWS Lambda function needs to be created in us-east-1 region

  1. Create an IAM policy

CF_Lambda_Edge_Policy with below permission

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "cloudfront:GetDistribution",
                "iam:CreateServiceLinkedRole",
                "lambda:GetFunction",
                "cloudfront:UpdateDistribution",
                "cloudfront:CreateDistribution",
                "lambda:EnableReplication*",
                "lambda:DisableReplication*"
            ],
            "Resource": [
                "arn:aws:cloudfront:us-east-1:<AWS Account ID>:distribution/*",
                "arn:aws:lambda:us-east-1:<AWS Account ID>:function:*",
                "arn:aws:iam::<AWS Account ID>:role/*"
            ]
        }
    ]
}

Navigate to IAM → Roles → select Block_CF_Default_Behavior_Access_Role → Click on Add permission button on the right hand corner and select Attach policies

Select IAM policy CF_Lambda_Edge_Policy created above and click Add permissions

  1. Modify the AWS Lambda function with the below code
  • Open the Functions page of the AWS Lambda console.
  • Choose Block_CF_Default_Behavior_Access function and then choose Code tab. In the console’s built-in code editor, you should see the function code that AWS Lambda created.
  • Paste the below code into the lambda_function.py tab, replacing the code that Lambda created.
  • Select Deploy to update your function’s code. When AWS Lambda has deployed the changes, the console displays a banner letting you know that it’s successfully updated your function.
import json
def lambda_handler(event, context):
    ### Fetch Cloudfront Domain Name
    cf_domain_name = event['Records'][0]['cf']['config']['distributionDomainName']
    ### Fetch Cloudfront URI (/test1/jpeg)
    cf_uri = event['Records'][0]['cf']['request']['uri']
    ### Combining Domain Name and URI to form an URL
    cf_url = cf_domain_name+cf_uri
    ### Custom response 
    response = {
      'status': '200',
      'statusDescription': 'OK',
      'headers': {
          'Content-Type': [
            {
              'key': 'Content-Type',
              'value': 'application/json'
            }
          ]
      },
      'body': "Access to the URL " + cf_url + " not allowed"
    }
    return response
  1. Publish a new version for AWS Lambda@Edge
  • Open the Functions page of the AWS Lambda console.
  • Choose Block_CF_Default_Behavior_Access function and then choose Versions tab
  • On the versions configuration page, choose Publish new version.
  • (Optional) Enter a version description.
  • Choose Publish.
  1. Add a Amazon CloudFront trigger to run the function
  • In the AWS Lambda console, on the Function overview page for your function, choose Add trigger
  • For Trigger configuration, choose Amazon CloudFront.
  • Choose Deploy to AWS Lambda@Edge.
  • In the Deploy to AWS Lambda@Edge pane, under Configure Amazon CloudFront trigger select the following information:
    1. Distribution
    2. Cache Behavior — ‘*’
    3. CloudFront event — ‘Origin Request’
  • Select the Confirm deploy to AWS Lambda@Edge check box
  • Choose Deploy to add the trigger and replicate the function to AWS locations worldwide.

Note: The function executes only when Amazon CloudFront forwards a request to your origin. When the requested object is in the CloudFront cache, the function doesn’t execute

  1. Add a trigger by using the Amazon CloudFront console
  • Get the ARN of the AWS Lambda function that was created above.
  • Open the Amazon CloudFront console
  • In the list of distributions, choose the ID of the distribution that you want to add triggers to.
  • Choose the Behaviors tab
  • Select the Default (*) cache behavior to add triggers to, and then choose Edit.
  • For Function associations, in the Function type list, choose AWS Lambda@Edge for origin responses.
  • In the Function ARN / Name text box, paste the ARN of the Lambda function which should include the version at the end.
  • Choose Save changes

Testing the Custom Response for Amazon CloudFront Default Behaviour

To test the custom response functionality in Amazon CloudFront, you can follow these steps to access a Amazon CloudFront URL:

  1. Upload an Image to the AWS S3 Bucket:

First, upload an image to the root of the AWS S3 bucket or to a prefix that wasn’t explicitly defined in the Amazon CloudFront behavior. This step ensures that the image won’t be served through Amazon CloudFront’s default behavior, allowing us to trigger the custom response logic.

  1. Access the Image Using Amazon CloudFront URL:

Once the image is uploaded, obtain the Amazon CloudFront URL associated with the image. This URL is typically in the format of https://[CloudFront_Distribution_ID].cloudfront.net/[image_name.jpg].

  1. Testing the Custom Response:

Use a web browser or any HTTP client to access the image via the Amazon CloudFront URL. This action will trigger a request to Amazon CloudFront, which will then invoke the custom response logic implemented using AWS Lambda@Edge.

  1. Observing the Response:

After accessing the image through the Amazon CloudFront URL, observe the response returned by Amazon CloudFront. If the custom response logic is correctly configured, Amazon CloudFront will execute the AWS Lambda@Edge function associated with the Origin Request event and return the customized response specified in the AWS Lambda function.

  1. Verification and Troubleshooting:

Verify that the custom response behaves as expected. This may involve checking for redirections, error messages, or any other customized behavior defined in the AWS Lambda@Edge function. If the response doesn’t match the expected behavior, review the AWS Lambda function code and Amazon CloudFront configuration for any potential issues.

  1. Adjustments and Iteration:

If necessary, make adjustments to the AWS Lambda@Edge function or Amazon CloudFront configuration based on the observed behavior. Iterate on the testing process until the desired custom response is consistently returned for requests made through the Amazon CloudFront URL.

By following these steps, you can effectively test the custom response functionality in Amazon CloudFront and ensure that it behaves as intended when accessing resources via Amazon CloudFront URLs.

Get in Touch.

Let’s discuss how we can help with your cloud journey. Our experts are standing by to talk about your migration, modernisation, development and skills challenges.

Ilja Summala
Ilja’s passion and tech knowledge help customers transform how they manage infrastructure and develop apps in cloud.
Ilja Summala LinkedIn
Group CTO