A Step-by-step Guide to Creating a Password Protected S3 bucket

In the spirit of “serverless” web applications and websites, this guide will outline how to setup a pasword protected series of files hosted in an S3 bucket – no EC2 layer in-between. This takes advantage of the latest [email protected] features to intercept HTTP requests to CloudFront, which we will configure in front of your S3 bucket.

Create Your S3 Bucket

First things first, create your S3 bucket where you will house your files. To ensure things are secure, do not grant public access. This will prevent visitors from circumventing the CloudFront/Lambda implementation in front of the S3 bucket.

Create Your CloudFront Distribution

The CloudFront distribution acts as a middle-man between the visitor and the files in the S3 bucket. The distribution will be connected to a Lambda script that houses the authentication routine.

  1. Create your CloudFront distribution and choose the S3 bucket you just created as the Origin source.
  2. Select “Restrict Bucket Access” and “Create a New Identity” for the Origin Access Identity option.
  3. Select the “Yes, Update Bucket Policy” for the Grant Read Permissions on Bucket option.
  4. Since we’re serving a website (or application) from our S3 bucket, be sure to set the Default Root Object as index.html.
  5. Save your new distribution and make note of the ID (if you have multiple distributions).

Create the Lambda function

A Lambda function will provide the authentication service for the files in the S3 bucket.

Create the Lambda Function

  1. Create a new Lambda function, but use one of the pre-existing Blueprints instead of a blank function.
  2. Search for “cloudfront” and select cloudfront-response-generation from the search results.
  3. On the following screen name your function and select the “Create new role from template(s)”. Give the role a name and add the “Basic Edge Lambda permission” policy template to the role.
  4. In the cloudfront section, choose the CloudFront instance you created.
  5. Leave the Cache Behavior as “*” and select “Viewer Request” as the _CloudFront Event_.
  6. Finally, check the “Enable trigger and replicate” box and click the Save button.

You should now have a Lambda script created (albeit with no real functionality).

Update the Lambda Script and Publish a New Version

Since you cannot assign the $LATEST version of the Lambda script as a trigger, we will need to publish a new version with our updated script content. Use the following code to provide the authentication services. Be sure to change the credentials to what you want for authenticating your users:

  1. In the Function Code section, choose the Click here to go to $LATEST link.
  2. Under the Function Code section, update the code with the authentication code above and Save.
  3. Select Publish new version from the Actions drop-down menu.
  4. Enter a version description and Save

Add the CloudFront Trigger

Now that we have a new version of the Lambda script with our authentication code we can link it as a trigger to our CloudFront distribution.

  1. Select CloudFront from the Add Triggers menu of the Designer section.
  2. Re-select the CloudFront distribution ID for the one you created earlier.
  3. Select “Viewer Request” and check the “Enable trigger and replicate” box.
  4. Click Add to add the Trigger to the list.
  5. Click Save to save the Lambda trigger.

Profit

You should now have a fully functioning, authenticatable S3 bucket stack. All that is left to do is upload your files and clear CloudFront’s cache with an Invalidation Batch.

  1. Upload your files to your S3 bucket – leave options as default.
  2. Browse to the Invalidations tab for your CloudFront distribution and create a new Invaliation.
  3. Enter /* as the path for the Invalidation to invalidate everything and click the Invalidate button.

After a short time you should see your uploaded files behind your password authentication!

Automating Upload and Clearing

Once you’ve set things up initially, you’ll want to make deploying as simple as possible. I recommend using the aws CLI tool. If you’re running a Mac, the easiest way to get this installed is to use Homebrew and install the awscli package.

S3 Sync

Once you’ve got your AWS CLI tool setup and configured, you can sync files from your project’s build folder to your S3 bucket with the sync command:

CloudFront Invalidation Batching

You will need to ensure that your user has permission to create batch invalidations. Create a custom IAM policy with the following value to enable batch invalidation on all your CloudFront distributions:

Assign this custom policy to your user and any other user that you want to allow batch invalidation on your CloudFront distributions.

Once you have assigned the above policy to your user, you can use the cloudfront create-invalidation AWS CLI command to create an invalidation batch. First, create a file in your project that contains the invalidation batch data:

invalidation-batch.json

Now you can clear your CloudFront cache by running:

If you’re running a project with a package.json file you can create a simple deploy script:

Then you can simply run npm run deploy to build, upload, and invalidate whenever you make a change.

Leave a Reply