Securing GitHub pages with Terraform, CloudFront and Lambda

(Yousef Alam) #1

One of the common recurring requests for our team is the ability to host static web pages for small projects that don’t require a backend or lots of custom configuration. GitHub pages is the perfect place to host this sort of stuff as it’s reliable and lets the team keep the autonomy of updating their website, along with being low overhead and low cost for us. However, GitHub pages has two main issues:

  • No SSL on custom domains
  • No ability to change the headers sent by the server

I’ve written a Terraform module that can deploy everything needed to add a secure CloudFront distribution in front of any public-facing website in just a few lines:

This configuration stops a lot of smaller attack vectors, and takes us from an F score to a B- on the HTTP Observatory:

How it works
The module deploys an Amazon CloudFront CDN distribution that sits in front of the origin website, providing SSL via Amazon’s Certificate Manager. It additionally deploys a Amazon Lambda function that runs on each request, modifying the headers sent back to the viewer to add some headers recommended in the Web Security Guidelines. These are sane defaults for most static sites but in the future I’d like this module to be able to add any header with any value. The function is just a few lines of JS and executes in under 20ms, meaning costs are minimal.

We’ve now deployed this to six of our sites that are hosted on GitHub pages or Amazon S3, and hope it’s of use to anyone else who wants to add some security to their hosted pages. Thanks to @jclaudius and @kang who did pretty much all of the heavy lifting on the Lambda side, I just made it easier to deploy. The module is of course open-source and contributions are greatly appreciated:

IAM/CoSS Sprint A Review
(Michael Kohler) #2

As somebody who has taken advantage of it by hosting campaign websites on GitHub pages, congrats to everyone involved, great work!

(kang) #3

This is the Cloud Formation template we use on that the gist is from, in case you do not use Terraform.

Note that Terraform can associate Lambda@Edge functions with Cloud Front, while when we made this, Cloud Formation could not do it natively (ie not without writing an API call “as Cloud Formation function”).