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.
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.
To allow anonymous users to write files to an S3 bucket there are generally two options:
- The user’s HTTP POST request is passed to a Lambda which then writes the data to the S3 bucket
- 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.
The pre-signer Lambda also writes a record to an AWS DynamoDB table for storing the metadata.
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.
A third Lambda function provides the gallery administration functions such as approving images, etc.
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.
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.