Menu
DeeprRacer.ML / MattCamp.ML – Matt's adventures in tech
  • Home
  • About
  • Contact
DeeprRacer.ML / MattCamp.ML – Matt's adventures in tech

Building a serverless image gallery on AWS

Posted on August 3, 2020August 3, 2020 by Matt

A while back we wanted a way of hosting images taken at our various AWS Machine Learning Community events and while there are many image hosting options available I figured that since we are an AWS-focused community why not try to build an entirely serverless image gallery using the AWS tech stack?

The requirements were fairly simple: Anyone should be able to upload images which an administrator would review and approve for public display.

Images should be uploaded with some metadata recording what event they were from, and who the photographer is.

Basic website

Hosting the basic website is easy… In it’s simplest form it’s just a public S3 bucket with web-hosting turned on. For real-world hosting I would then also probably enable an AWS CloudFront distribution to give SSL termination and a nice custom domain name, but you can add all that on later.

The website itself is a fairly simple static HTML site using BootStrap4, plus some simple jQuery javascript.

Image uploading

To allow anonymous users to write files to an S3 bucket there are generally two options:

  1. The user’s HTTP POST request is passed to a Lambda which then writes the data to the S3 bucket
  2. The user is given a pre-signed URL which allows them to directly write to the S3 bucket.

Option 2 is generally the better approach as it removes the need for a Lambda to process large amounts of data and is more secure as the signed URL is only valid for a short time.

I’m not going to go into the exact details of how the S3 pre-signing process works but in a nutshell the client website javascript calls a Lambda (via an AWS API Gateway API) which generates the presigned url. The web user can then POST their content directly to the presigned URL of the uploads S3 bucket.

The pre-signer Lambda also writes a record to an AWS DynamoDB table for storing the metadata.

Thumbnails

The uploads S3 bucket has an event trigger which automatically fires another Lambda to resize each image as it is uploaded to create thumbnail versions.

At this time the thumb Lambda only supports JPG and PNG type images, however I hope a future version will also support HEIC allowing easier upload directly from newer Apple IOS devices.

Gallery Administration

A third Lambda function provides the gallery administration functions such as approving images, etc.

Instead of using API Gateway the admin Lambda is directly invoked from the browser using the AWS javascript SDK.

AWS Cognito is used to store administrator credentials, and the browser again uses the AWS Javascript SDK to perform in-browser authentication of an admin session.

Deployment

For deployment I used Terraform to define all AWS resources as code and deploy with a single command. AWS CloudFormation would have also been another option here, however I’m simply just more familiar with Terraform.

While Terraform creates all the base resources you will still manually need to copy the HTML and javascript files over into the public bucket, and you’ll need to manually create at least one user in the Cognito user pool before you can use the admin interface.

Code and detailed instructions

The full code for all Lambdas, the website and all the Terraform to deploy the stack is available at https://github.com/mattcamp/serverless-gallery

Caveats and known issues

This is a very simple gallery designed to get something working quickly, and also to prove that the serverless design would work. Currently some actions require manual intervention, such as removing an existing gallery which requires you to manually remove entries from the DynamoDB table.

As previously mentioned it should really also be deployed behind AWS CloudFront to gain the benefits of SSL termination, caching, a nice domain name, etc.

Also, because the uploads do not have public-read access the admin approval interface is only able to access the thumbnails (which DO have public-access). This means the admin can currently only view either small or blurry versions of the images prior to uploading. Fixing this would require using the cognito-authenticated session to download the full-size image for preview instead of the direct unauthenticed HTTP S3 bucket link… Again, something for a future version maybe.

And finally, Javascript isn’t really my thing so I have probably done all sorts of horrible things. Feel free to comment or raise github issues (or better yet, submit a PR).

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Instagram

View on Instagram

Recent Tweets

Tweets by Mattcampnz

©2021 DeeprRacer.ML / MattCamp.ML – Matt's adventures in tech | Powered by WordPress & Superb Themes