In the previous post, we’ve presented an AWS Lambda function to automatically invalidate resources in CloudFront distribution when underlying objects in an S3 bucket change.
Instead of clicking and copy-pasting in the AWS Console, we can use
terraform to set this function up. In fact, I’ve
already made it a part of my terraform static aws
website —
terraform module which sets up an S3 bucket to host a static website and
CloudFront as a cache; it also handles a redirect www.domain.com --> domain.com
and, provided with an AWS generated https cert, the https://
bit.
The file invalidate_cache.tf sets the lambda up. Please consult it for all the details. We’ll focus on the big picture here.
Let’s go through the resource we need to define.
resource "aws_lambda_function" "invalidate_cloud_front_lambda"
represents the lambda function. It specifies the function name and any extra environment variables. In our case the ID of CloudFront distribution, so that the lambda knows which of the distributions in our account to invalidate.The lambda function resource needs to reference a zip file bundling the code. We store the source code directly, and then use
data "archive_file" "invalidate_cloud_front_lambda_zip"
to create the zip file for us.By default everything is locked, a lambda doesn’t have the permissions needed to invalidate any CloudFront distributions at all. We need to craft a policy that will let our lambda invalidate the distribution we want. Enter
resource "aws_iam_policy" "invalidate_cloud_front_policy"
{ "Version": "2012-10-17", "Statement": [ { // (1) "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" }, { // (2) "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation" ], "Resource": [ "*" // <-- in fact, we should be more restrictive here ] } ] }
The policy does two things: (1) it allows writing CloudWatch logs and (2) it allows to create invalidations in CloudFront distributions. We could split the policy into two distinct ones, esp. if we have more lambda and plan to reuse parts of the policy, but for our simple case, this is OK.
The policy can’t be associated directly with the lambda. We need to create a role
resource "aws_iam_role" "invalidate_cloud_front_role"
, which we then link to the policy viaresource "aws_iam_role_policy_attachment" "invalidate_cloud_front_attachment"
. Finally, the role is being referenced in the lambda resource.Our lambda can write log items to CloudWatch and create CloudFront invalidations, but it also needs to tap to the bucket event stream. This is being taken care of by
resource "aws_s3_bucket_notification" "bucket_notification"
. It specifies the bucket and the types of events that will be delivered to the lambda function. Also, we need to let the S3 bucket call the lambda function (because of security). We do it withresource "aws_lambda_permission" "allow_s3_event_notifications"
.
In the short post, we’ve described AWS resources which we need to create for a simple lambda function to work. I hope this is useful to understand what happens behind the hood or if you want to terraform your own lambda.
>> Home