The Power Of Lambda - A serverless approach to invalidating AWS CloudFront
Tags: aws, lambda, cloudfront
Published: 2022-01-04 15:42:14

It's no secret that since I began my cloud journey in late 2018 i've been intrigued by serverless computing. At work i've even gone as far as  designing and implementing a few **Azure Functions** that are used in production. I thought now would be the perfect time to write a blog post on a practical use case for AWS ***Lambda***. 

**What is Lambda  ?**

***Lambda***  is a function as a service offering from AWS that allows you to focus on writing code and letting AWS provision and maintain the underlying technology stack that your code runs on. As of this current moment in time ***Lambda***  supports runtime versions for Node.js, Python, Ruby, Go, Java, C# (.NET Core), and PowerShell (.NET Core).

<!-- more --> 

In this blog post i'll show you how to create a function that removes objects from CloudFront edge caches around the world after an object has been uploaded to an S3 bucket and create an SNS topic that sends an email notification once the CloudFront has been invalidated. If you host a static website from S3 this solution will come in handy.



# ***Requirements*** #

<br>
<br>

• Existing S3 Bucket

•The Lambda function that you will create needs to reside in the same region as the existing S3 bucket that will be used as an event source.

<br>

Once you have logged into the AWS management console, search for ***Lambda***  in the main search bar and select the service from the list of services displayed.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0q563uexav6qumxumjgm.png)

<br>

Select the **Author from scratch** tile and provide a name for the function as well as choosing the **Python 3.8** Runtime. Leave the existing default settings as is and proceed by clicking the **Create function** button.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adwf5l0zcm8uf8s1f2lc.png)

<br>

From the main **Function overview**, select **Add trigger**.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wb6qwb6o0tib1rztz1i9.png)

<br>

From the next page search for **S3** in the **Trigger configuration** dropdown and select the bucket that will be used as the event source. For the sake of simplicity select **All object create events** from the **Event type** dropdown. Acknowledge the **Recursive invocation** banner at the bottom of the page and select **Add**.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlwqag3cj6lyr4mlpn2g.png)


<br>

Scroll down the page till you reach the **Code source** widget.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83n0jzqupwo3yht3bbl3.png)

<br>

I've added the code that you can replace in the on screen code editor. You'll only need to enter the Distribution ID value of your CloudFront distribution. Once you've added the code select **Deploy**.


{% gist https://gist.github.com/AdrianM10/479f87f53108bb93dba0e4ad8015d9c4 %}

<br>


# ***Invoke the Lambda Function*** #


<br>

From within the **Code source** widget select the **Test** tab and select **Configure test event**, select **hello-world** from the **Event template** dropdown, lastly you will need to provide a name for the **Event** and select the **Create** button.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1mjh2966ev23oree931.png)

<br>

Once you have created the test event, select the **Test** button, the test should execute the Lambda function on your behalf. You'll notice that a **Failed** status is returned. 

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs1kf5mogguqxgii5rg7.png)

<br>

In order for **Lambda** to be able to invalidate **CloudFront**, a role needs to be created with permissions that will grant it access to the AWS service on your behalf.

The next step is to create a role by navigating towards **IAM** and selecting roles from the left-hand pane. 

Select **Create role**, from the proceeding screen select **AWS service** from the type of trusted entity and select **Lambda** from the list of services.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk6ik9tfgz3hv19a0pqb.png)

<br>

From the next screen, select the **Create policy** button. We will use the visual editor to create two policies, the first of which will allow **Lambda** the ability to invalidate **CloudFront** and the second policy will allow our **Lambda** function to send logs to **CloudWatch**.

A new tab will open in your browser. Search for **CloudFront** in the search box that appears next to **Service**. Under **Actions**, specify the actions (List, Read, Write) allowed that are shown in the below screenshot and specify **All resources**, in a real world scenario you would define permissions for the specific resource.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovmmbnfsmafu0wmguxqy.png)

<br>

The next policy to create is for **CloudWatch Logs**, select the **+ Add additional permissions** button and ensure the policy has the same configuration as the screenshot below:


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ra6gohjvvr93xraggu.png)


<br>

On the **Review policy** screen, provide a name for the policy and a description.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fktins1ayhwk8r8lhydd.png)

<br>

Once you have created the policy, navigate back to the previous tab, search for the policy and select it.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2aju979x1qh66gms7tx.png)

<br>

At the last screen you'll need to provide a name as well as a description for the role you are about to create.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mv3m2jgo85nze4a9hnkk.png)

<br>

Navigate towards the **Lambda** function you created earlier and  under the **Configuration** tab, select **Permissions**, select **Edit** under Execution role.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b06dtng0lb6lmsbn7ds2.png)

<br>

At this step we will use the existing role we created previously and save the settings.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7apr1qf3tfxkxiwziv7v.png)

<br>

It's time to invoke our **Lambda** function again, this time around our test should succeed as evident in the below screenshot.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ol12grz2xw8he523wsu0.png)

<br>



# ***SNS (Simple Notification Service)*** #


<br>

The last component of this solution is the implementation of SNS. This will notify us via email when our function has been successfully invoked. 

<br>

<blockquote>

Amazon SNS is a managed messaging service that lets you decouple publishers from subscribers. This is useful for application-to-application messaging for microservices, distributed systems, and serverless applications.

</blockquote>

<br>

Navigate towards **SNS**, select **Topics** and create a topic. 


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7nxbhdkemfe346gc7d2w.png)

<br>

At the next screen, select **Standard** for the **Topic** type and provide a name.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrchh3zrih75d7uekygb.png)

<br>

You'll need to create a **subscription** and choose the type of protocol you would like to subscribe to, in this case select email, input your email address and confirm the subscription.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jds9w7dk3ek68d9ieg4r.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/641gdf49hbrjho86e8nq.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dnfxobv3h1cgoedgb4au.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rixktubv0xh0a7iqz7il.png)

<br>

Navigate back to the **Lambda** function... we're almost done.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34qhpqyr17l44ezhlyl1.png)

<br>

The last step is to select the SNS topic created in the previous step, select **+ Add destination** under the Function overview widget and ensure that the condition is set to **On success** and save the destination configuration.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zf8k50lh3l2mfjkbokm2.png)

<br>

Our solution is now complete. It took a while. 

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04attr4jrwcir36yd3ma.png)

<br>

You can now upload an object to the **S3** bucket you had selected as the source trigger at the beginning of the tutorial to invoke the **Lambda** function.

You'll receive a JSON payload in your email inbox once the **Lambda** function has been successfully invoked.

That concludes this post. I hope you've learnt something new, if you're keen on a challenge you could clean up the format of the message sent from SNS.