Clear Cloudfront Cache on S3 Bucket Change

Section Explanation

This section explains how to create a lambda which is triggered by changes to the S3 bucket; then clears CloudFront cache for the content that changed.

Requirements

This section depends on having Cloudfront setup as described in the Setup Cloudfront for SSL and Edge Cache.

Credit where Credit is due

This section is based on the work by Miguel Angel Nieto documented on his blog here.

Create an IAM Policy

Starting under Policies Section of IAM click Create Policy.

Select the JSON tab on the Create Policy Page.  Then Paste the content of the CodeBlock below into the text box.  When done click Review policy.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

I named my policy lambda_cloudfront_invalidation_execution.  Then click Create policy.

Create an IAM Role

Starting under Role Section of IAM click Create role.

Select Lambda for the Service and click Next Permissions.

Select the IAM Policy we just created and click Next: Review.

Name the role lambda_cloudfront_invalidation and click Create role.`

Lookup CloudFront Distribution ID

In CloudFront go into the distribution detail page for the website distribution of the site we want to invalidate.  Make note of the Distribution ID we will need it later.,

Create the Lambda

Starting in the Create function in the Lambda section of the AWS console.
Click ‘Arthur from scratch’.
Name your Lambda invalidate_site_name.  I used invalidate_www_beerontap_org.
In the pulldown select the IAM Role we just created.
Click Create function
Use the Runtime pulldown to select python 2.7.
Then copy the code from the below code block and paste it into the textbox.  As shown in the screenshot below.
Click Save
from __future__ import print_function

import boto3
import time
import os

def lambda_handler(event, context):
    distribution = os.environ['distribution']
    path = []
    for items in event["Records"]:
        if items["s3"]["object"]["key"] == "index.html":
            path.append("/*")
        else:
            path.append("/" + items["s3"]["object"]["key"])
    print(path)
    client = boto3.client('cloudfront')
    invalidation = client.create_invalidation(DistributionId=str(distribution),
        InvalidationBatch={
            'Paths': {
                'Quantity': 1,
                'Items': path
        },
        'CallerReference': str(time.time())
    })

Scroll Down to ‘Environment variables’ and expand the section.
Specify the Key ‘distribution’ with the Value of the CloudFront Distribution ID we looked up earlier.
Save the Lambda.
Now click the Triggers section and click ‘Add trigger’.
Click on the dotted box and type S3; then click Submit.
Select the S3 bucket which the website is stored.
Select Object Removed (All) for the Event type.
Then click submit.
We need to create a second trigger.
The second trigger is still for our website bucket.  The difference is the Event type select ‘Object Created (All)’.
Click Submit.

You’re Done!

That’s it your done.  You have a website in an S3 bucket and every time there is a change to S3 it will invalidate the CloudFront Cache.