# Adding HTTP Security Headers Using Lambda@Edge.

In the previous section, we've got the basics down on Lambda@Edge and web security headers. Now, let's roll up our sleeves and learn how to set up a Lambda function that'll give your web defenses a rock-solid boost. In Part II, we'll walk you through deploying a Lambda@Edge to shield your web apps from the latest threats and vulnerabilities.

### **Security inspection**

The first step is to check the status of our website. We going to use [https://observatory.mozilla.org/](https://observatory.mozilla.org/) to scan our domain.

for this demo, I will use my domain `wilmomartinez.com` but replace this domain name with your own.

The following is the result of the scanning.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699888709111/425a860a-148e-4fa3-8ed0-2b8e8cf28632.png align="center")

### **Create a Lambda Function**

Lets create the lambda function that would add the security headers to the responses from the origin in our CloudFront distribution.

In the AWS Lambda console go to functions, click `create function` and select Author from scratch. In the create function session will specify the following:

| Field | Value |
| --- | --- |
| Name | lambda-edge-security-headers |
| Runtime | Node.js 18.x |
| Role | Chose an existing role |
| Existing role | existing role |

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699889726374/d3aa7e42-6014-435f-bed1-f79123d95ed1.png align="center")

Then click the `create function` button.

### **Write function code**

I used the following code for the lambda function. It basically sets `Strict-Transport-Security`, `Content-Security-Policy`, `X-XSS-Protection`, `X-Content-Type-Options`, `X-Frame-Options`, and `Referrer-Policy` headers, then returns the updated response that include the security headers.

```javascript
'use strict';

export const handler = async (event, context, callback) => {
    console.log('Event: ', JSON.stringify(event, null, 2));

    const response = event.Records[0].cf.response;
    
    response.headers['strict-transport-security'] = [{ value: 'max-age=31536000; includeSubDomains' }];
    response.headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}]; 
    response.headers['x-xss-protection'] = [{ value: '1; mode=block' }];
    response.headers['x-content-type-options'] = [{ value: 'nosniff' }];
    response.headers['x-frame-options'] = [{ value: 'DENY' }]; 
    response.headers['Referrer-Policy'] = [{ value: 'strict-origin' }];  
       
    return response;
};
```

See more about security headers:

* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) \*
    
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
    

### **Test the function**

It is highly recommended to test if our functions execute successfully and return the expected response before proceeding with the association with CloudFront. To do that we are going to take advantage of the test invoke function in the Lambda console.

Click the `test`, and you will be prompted with the window to configure your test event. In this case we will use the `CloudFront Modify Response Header` template. Select invoke

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699908320480/07d955a3-b6bc-4f78-b8d8-48c3a0de91d4.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699909235545/5232a1c5-1cb8-419b-aa3a-2ba7f65705cc.png align="center")

### **Deploy lambda**

once we confirm that our lambda works as expected, now is time to deploy.

In order to deploying a function to Lambda@Edge we need to complete to process:

* Create a function version
    
* Associate the function version with the CloudFront distribution by selecting an applicable Cache Behavior and an event trigger type (viewer request, viewer response, origin request or origin response).
    

We can do both at once by selecting in `Actions` the option Deploy to `Lambda@Edge`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699909288188/d608c53f-030e-4e4e-bc49-0696883cda52.png align="center")

Set the trigger properties as shown below and click `Deploy`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1700516804123/672464ff-c8f8-4be5-987f-dad813b5d8d9.png align="center")

After that, we will see the message that both, lambda version and CloudFront trigger has bee successfully created.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699909369253/d92b09c9-6eb7-491a-aa87-4d9794d8e7c6.png align="center")

### **Validate the security headers**

Lets check the header response form our Cloudflare distribution now.

```bash
curl --head https://<your cloudfront distribution or Domain name>
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699910484341/292eaeae-8889-460c-8925-4ea3ec40b95a.png align="center")

### **Rerun inspection**

Lets rescan our domain.

[https://observatory.mozilla.org/](https://observatory.mozilla.org/). Now we have a A+ score

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699911113511/86375511-d21b-4032-8abe-5374048aa20c.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1699911586586/69c017f1-de47-4472-9549-90f9ad1ff7ba.png align="center")

### **Conclusion**

Enhancing security through Lambda@Edge involves strategically integrating security headers into the origin response trigger of a CloudFront distribution behavior. In this demonstration, We've gone through the process of creating a Lambda@Edge function, associating it with a CloudFront distribution trigger, and verifying the effectiveness while actively monitoring the results. While this demo shows what Lambda@Edge can do, there's a lot more it can offer for coming up with clever and flexible ways to boost and strengthen security.
