Networking & Content Delivery

Secure your Lambda function URLs using Amazon CloudFront origin access control

In 2022, we launched Lambda function URLs as a simple way to configure an HTTPS endpoint for your AWS Lambda function without having to learn, configure, and operate additional services. Customers who want to improve the performance and security of their applications running with Lambda function URLs can deploy Amazon CloudFront in front of Lambda function URLs to deliver data through hundreds of globally distributed points of presence (PoPs). However, this required keeping the Lambda function URLs publicly accessible for CloudFront to access them and required additional application logic to allow access to legitimate requests through custom methods such as secret values validated in the function code.

To strengthen security and deepen feature integration between Amazon CloudFront and AWS Lambda, we are introducing origin access control (OAC) for Lambda function URLs – a feature that secures Lambda functions by permitting access only from designated CloudFront distributions by using AWS Signature Version 4 (SigV4). OAC was already available to use with Amazon Simple Storage Service (Amazon S3) origins, which permits only designated CloudFront distributions to access specific S3 buckets. Now, OAC feature is available with Lambda function URL origins, too.

Pairing CloudFront with Lambda function URLs

Function URLs are a great fit for use cases where you must implement a single-function microservice with a public endpoint that doesn’t require advanced functionality, such as request validation, throttling, or custom authorizers. For example, it’s great for webhook handlers, form validators, mobile payment processing, advertisement placement, machine learning (ML) inference, and so on. Pairing Lambda functions with CloudFront allows you to avoid exposing your Lambda function URL publicly. Instead, you can route user requests through CloudFront over the globally distributed content distribution network to improve the latency, resulting in faster response times and better user experience. You can also define custom domain names, turn on HTTPS delivery over TLS, activate AWS WAF to protect your application from malicious bots and common application exploits and receive DDoS protection from AWS Shield Standard at no additional charge. With OAC, you can now block unintended users from directly accessing the function URLs. Enabling OAC improves the security posture by minimizing the attack surface. Furthermore, it ensures AWS Shield and AWS WAF protection for all requests, as they are required to pass through CloudFront where these security services are enforced.

Fig 1: Restricting access to Lambda function URLs using CloudFront OAC

Fig 1: Restricting access to Lambda function URLs using CloudFront OAC

Configuring OAC for Lambda function URLs

Let’s understand how to use OAC with Lambda function URLs and CloudFront. You can start with any serverless application that you are already running in a Lambda function, or create a new Lambda function. We will use the AWS management console in this blog post, but you can use the AWS Command Line (AWS CLI), AWS CloudFormation, or AWS SDK according to your preference. Note the AWS Region where you are creating your Lambda function if you are using AWS CLI because the Region configured on your AWS CLI profile must be the same as the Region where you are creating your Lambda function when running the commands.

If you want to enable OAC on an existing Lambda function URL, you can skip Step 1. Get your function URL and proceed to Step 2.

Step 1: Create a Lambda function with function URL

  1. Open the Functions page of the Lambda console.
  2. Choose Create function.
  3. Select Author from scratch.
  4. In the Basic information pane, for Function name, enter myLambdaFunction.
  5. For Runtime, choose either Node.js 20.x or Python 3.12.
  6. Expand Advanced settings and enable the function URL. Keep the Auth type as AWS_IAM.
  7. Leave all other settings at default values and choose Create function.
Fig 2: Creating a function URL for the Lambda function

Fig 2: Creating a function URL for the Lambda function

8. On the next screen, go to the Configuration tab and select Function URL. Copy the function URL and save it because we will use it in later steps.

Fig 3: Getting the Lambda function URL

Fig 3: Getting the Lambda function URL

Step 2: Create CloudFront OAC

  1. Sign in to the AWS Management Console and go to CloudFront.
  2. In the navigation pane on the left side of the screen, choose Origin access.
  3. Choose Create control setting.
  4. On the Create new OAC form, do the following:
    1. Enter a Name and (optionally) a Description for the OAC.
    2. For Signing behavior, we recommend that you leave the default setting (Sign requests (recommended)). For more information, see Advanced settings for origin access control.
  5. For Origin type, choose Lambda.
  6. Choose Create.
Fig 4: Configuring OAC with Lambda function as the origin

Fig 4: Configuring OAC with Lambda function as the origin

Step 3: Create a CloudFront distribution

  1. On the CloudFront console, Select Distributions from the sidebar and choose Create distribution.
  2. For Origin domain, ignore the suggestions in the dropdown (if any) and enter your Lambda function URL without the https:// and the trailing slash, for example, xyzabcdefghijk.lambda-url.region-name.on.aws
  3. Select HTTPS only for your origin’s protocol.
  4. In the Origin access control dropdown, select the OAC you created in the previous step.
  5. Leave all other settings at their default values and update the Web Application Firewall (WAF) setting to Enable security protections (optional, but recommended) to have CloudFront create and configure an AWS WAF web ACL with out-of-the-box protections recommended by AWS for all applications.
  6. Note that the Cache policy is automatically set to CachingDisabled. This is recommended for Lambda function URLs. You can customize this if you have a specific requirement to cache the responses from your Lambda function.
  7. Choose Create distribution.
Fig 5: Configuring CloudFront distribution

Fig 5: Configuring CloudFront distribution

8. To allow CloudFront access to your Lambda function, you have to update your function policy. This requires running a CLI command because editing the AWS Identity and Access Management (IAM) policy in the Lambda console isn’t supported at this time. Copy the CLI command presented on the top of the console on the next screen. Update <YOUR_FUNCTION_NAME> with the name of your Lambda function. The copied command should look similar to this-

aws lambda add-permission \
--statement-id "AllowCloudFrontServicePrincipal" \
--action "lambda:InvokeFunctionUrl" \
--principal "cloudfront.amazonaws.com" \
--source-arn "arn:aws:cloudfront::1234567890:distribution/ABCDEFGHIJ" \
--function-name my_example_function

9. Run this command in a terminal window, either on your local machine if you have AWS CLI configured or using AWS CloudShell, which is a browser-based pre-authenticated shell that can launch directly from the AWS console. This command creates the necessary permissions for OAC to work with your Lambda function and returns a response showing the policy statement that was created.

Fig 6: CLI command to create Lambda policy statement

Fig 6: CLI command to create Lambda policy statement

Step 4: Review Lambda function

1. Go to the Lambda console and select the Lambda function you used as the origin for the CloudFront distribution.

2. Go to the Configuration tab and select Permissions. Scroll down to Resource-based policy statements, where you should now see the newly added permissions. If you select the Statement ID and choose View policy, you should see a policy document that looks similar to the following example.

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipal",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-1:<ACCOUNT_ID>:function:<FUNCTION_NAME>",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:cloudfront::<ACCOUNT_ID>:distribution/ABCDEFGHIJ"
        }
      }
    }
  ]
}

Testing OAC with Lambda function URLs

You can test that your Lambda function URL is accessible through CloudFront by making a curl request from a command prompt. You can use the terminal on your local machine or open CloudShell from the bottom of the AWS console. Make the following curl command, replacing the CLOUDFRONT_DOMAIN_NAME with the domain name of your CloudFront distribution. If you need to find the domain name, go to CloudFront on the console and select your distribution. Copy the distribution domain name from the General tab.

curl <CLOUDFRONT_DOMAIN_NAME> -kvv

You should get a 200 OK response for this request, similar to this the following.

$ curl https://d1234abcd.cloudfront.net/ -kvv
<<response truncated>>
< HTTP/2 200
< content-type: application/json
< content-length: 20

This shows that your Lambda function URL is accessible through CloudFront.

Now, make another curl command, this time directly to your Lambda function URL.

curl <LAMBDA_FUNCTION_URL> -kvv

You should get a 403 response for this request if your OAC is correctly configured because OAC will block direct access to your Lambda function URL if you try to access it by directly bypassing CloudFront. Your response should look similar to the following.

$ curl https://abcd1234.lambda-url.region-name.on.aws/ -kvv
<<response truncated>>
< HTTP/1.1 403 Forbidden
< Content-Type: application/json
< Content-Length: 23
{"Message":"Forbidden"}

This confirms that your Lambda function URL is not directly accessible, and you have successfully configured origin access control to restrict access to your serverless application running on Lambda through your CloudFront distribution.

Conclusion

To summarize, in this post you learned how to use origin access control to provide your Lambda functions with an additional layer of protection, providing them protection from unauthorized access. This control over origin access enhances the overall security of your serverless applications and provides you the flexibility to fine-tune user interactions by using the features of CloudFront paired with your Lambda functions.

CloudFront OAC support for AWS Lambda function URL origins is now available worldwide except for the CloudFront China AWS Region. You can enable OAC using the CloudFront console, SDK, CLI, or AWS CloudFormation. There are no additional fees associated with this feature. For more information, please refer to the Amazon CloudFront Developer Guide. To learn more about CloudFront, visit Getting Started with Amazon CloudFront.

About the authors

Karan Desai

Karan Desai

Karan is a Solutions Architect at AWS in Mumbai, India with a focus on edge technologies and security. He currently works with financial services companies in their modernization journeys and is an active contributor in the AWS developer community. Outside of work, he can be found traveling to offbeat places and trying out unusual foods.

Tanya Pahuja

Tanya Pahuja

Tanya is a Technical Account Manager at AWS based out of Delhi, India. With a passion for digital transformation, she is committed to partnering with customers to ensure their success on AWS. She is also a regular speaker at AWS events and on the AWS Twitch channel. Beyond her professional sphere, she has a penchant for classical musical instruments.