Serverless authentication for S3
Are you a developer looking to protect your S3 content using G Suite, Active Directory, Auth0 or GitHub for authentication?
At The Scale Factory, we host a static website containing documentation of our customers’ infrastructure that we support. Internally we use Google’s G Suite of apps. We wanted to find a solution to authenticate requests to our documentation using our existing Google Sign-In, so that all users can get easy access our docs, using the login they use for everything else.
Check out github.com/scalefactory/terraform-cloudfront-auth to get going in less than 20 lines of Terraform.
One solution could have been to use signed URLs or cookies with CloudFront to protect our files. This would involve spinning up EC2 and using NGINX or Apache as middleware to proxy the requests to G Suite. Managing an EC2 proxy layer seems unnecessarily complicated and expensive. What about a serverless solution?
If you’ve been Googling frantically like we have, then you might have stumbled across the handiwork from the team at Widen. Widen published widen/cloudfront-auth, a Lambda function to authenticate requests that you can use with AWS CloudFront Lambda@Edge. Here’s what it says on the tin: “An AWS CloudFront Lambda@Edge function to authenticate requests using Google Apps, Microsoft, Auth0, OKTA, and GitHub login”.
That’s exactly what we were after! We also found ourselves using this Lambda function more and more for internal projects so decided to spend some time removing the manual work. We’ve since published terraform-cloudfront-auth, a Terraform module to package up your authentication configuration and deploy the necessary AWS resources to guard your content and get you going in no time.
Head on over to github.com/scalefactory/terraform-cloudfront-auth to check it out.
So how does it work?
terraform-cloudfront-auth is a Terraform module that wraps around the widen/cloudfront-auth Lambda function. It removes the manual steps required and creates a CloudFront distribution to serve private content in an S3 bucket. Under the hood, it’s using AWS CloudFront’s Lambda@Edge to authorise requests using your existing authentication service.
Use the example above to get going. Tweak the module settings and run terraform apply
.
The Terraform above will pass your authentication configuration into a Lambda function that gets deployed to the us-east-1
region. Functions must be deployed here where they will be replicated globally in order to be used by CloudFront. Lambda@Edge allows you to execute Lambda functions to modify the CloudFront requests and responses to your CloudFront origins. The Lambda execution happens at CloudFront’s edge locations which means that the response times to your requests are going to be really fast.
On every viewer request, CloudFront executes the Lambda function which redirects unauthenticated users to your chosen authentication provider and puts them through the OAuth2 Authorization Code grant flow. On success, a cookie is created containing a signed JSON Web Token (JWT) and then the user is redirected back to the originally requested path. The JWT inside the cookie is parsed on each subsequent request to ensure that is is still valid and has not expired. This gives us serverless request authentication and, like Lambda, with Lambda@Edge you only pay for each invocation.
The module then configures an Origin Access Identity (OAI) and associates it with the CloudFront distribution. OAI acts as a special CloudFront user which you can reference in your S3 Bucket Policy to control access. This means you can grant read permissions to the CloudFront user but keep your content private to everybody else. Take a look at the sample bucket policy below; this gives the CloudFront OAI with id E1BCPJGK8NL1TZ
permission to get objects and list the content in the bucket.example.com
bucket. (Don’t worry, our Terraform module will do this all for you).
Note: This solution relies on using HTTPS. You’ll need to create a certificate for use with your CloudFront distribution. This isn’t part of the module currently. If you’ve already generated a certificate in AWS Certificates Manager, use Terraform data sources to reference them in your manifests. You must issue ACM certificates for CloudFront in the North Virginia (us-east-1) region.
So there you have it; if you’ve been looking for a quick way to protect the origins of your CloudFront distributions using your existing authentication service then check out our repository at github.com/scalefactory/terraform-cloudfront-auth. You could be up and running within minutes* (Subject to CloudFront deployment waiting time).
Do you use a different authentication provider that supports OAuth2? Why don’t you go ahead and fork our repository and change it to meet your own needs. We love to see how you use our open source contributions. If you like our work, please give our GitHub repository and our friends at Widen a ★; we’d really appreciate it!
If you’d like to be sure your cloud infrastructure is as efficient as possible, The Scale Factory also offer free AWS Well-Architected reviews — we’ll spend a few hours reviewing your workload and provide you with a report and recommendations.