Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Setting up S3 & CloudFront to Deliver Static Assets Across the Web

Suraj Patil

Full-stack Development

If you have a web application, you probably have static content. Static content might include files like images, videos, and music. One of the simpler approaches to serve your content on the internet is Amazon AWS’s “S3 Bucket.” S3 is very easy to set up and use.

Problems with only using S3 to serve your resources

But there are a few limitations of serving content directly using S3. Using S3, you will need:

  • Either keep the bucket public, which is not at all recommended
  • Or, create pre-signed urls to access the private resources. Now, if your application has tons of resources to be loaded, then it will add a lot of latency to pre-sign each and every resource before serving on the UI.

For these reasons, we will also use AWS’s CloudFront.

Why use CloudFront with S3?

Amazon CloudFront (CDN) is designed to work seamlessly with S3 to serve your S3 content in a faster way. Also, using CloudFront to serve s3 content gives you a lot more flexibility and control.

It has below advantages:

  • Using CloudFront provides authentication, so there’s no need to generate pre-signed urls for each resource.
  • Improved Latency, which results in a better end-user experience.
  • CloudFront provides caching, which can reduce the running costs as content is not always served from S3 when cached.
  • Another case for using CloudFront over S3 is that you can use an SSL certificate to a custom domain in CloudFront.

Setting up S3 & CloudFront

Creating an S3 bucket

1. Navigate to S3 from the AWS console and click on Create Bucket. Enter a unique bucket name and select the AWS Region.

2. Make sure the Block Public Access settings for this bucket is set to “Block All Public Access,” as it is recommended and we don’t need public access to buckets.

3. Review other options and create a bucket. Once a bucket is created, you can see it on the S3 dashboard. Open the bucket to view its details, and next, let’s add some assets.

4. Click on upload and add/drag all the files or folders you want to upload. 

5. Review the settings and upload. You can see the status on successful upload. Go to bucket details, and, after opening up the uploaded asset, you can see the details of the uploaded asset.

If you try to copy the object URL and open it in the browser, you will get the access denied error as we have blocked direct public access. 

We will be using CloudFront to serve the S3 assets in the next step. CloudFront will restrict access to your S3 bucket to CloudFront endpoints rendering your content and application will become more secure and performant.

Creating a CloudFront

1. Navigate to CloudFront from AWS console and click on Create Distribution. For the Origin domain, select the bucket from which we want to serve the static assets.

2. Next, we need Use a CloudFront origin access identity (OAI) to access the S3 bucket. This will enable us to access private S3 content via CloudFront. To enable this, under S3 bucket access, select “Yes use OAI.” Select an existing origin access identity or create a new identity.
You can also choose to update the S3 bucket policy to allow read access to the OAI if it is not already configured previously.

3. Review all the settings and create distribution. You can see the domain name once it is successfully created.

4. The basic setup is done. If you can try to access the asset we uploaded via the CloudFront domain in your browser, it should serve the asset. You can access assets at {cloudfront domain name}/{s3 asset}
for e.g. https://d1g71lhh75winl.cloudfront.net/sample.jpeg

Even though we successfully served the assets via CloudFront. One thing to note is that all the assets are publicly accessible and not secured. In the next section, we will see how you can secure your CloudFront assets.

Restricting public access

Previously, while configuring CloudFront, we set Restrict Viewer access to No, which enabled us to access the assets publicly.

Let’s see how to configure CloudFront to enable signed URLs for assets that should have restricted access. We will be using Trusted key groups, which is the AWS recommended way for restricting access.

Creating key group

To create a key pair for a trusted key group, perform the following steps:

1. Creating the public–private key pair.

The below commands will generate an RSA key pair and will store the public key & private key in public_key.pem & private_key.pem files respectively.

CODE: https://gist.github.com/velotiotech/fdff1643db83fb1f45fa76ec1af06ab7.js

Note: The above steps use OpenSSL as an example to create a key pair. There are other ways to create an RSA key pair as well.

2. Uploading the Public Key to CloudFront.

To upload, in the AWS console, open CloudFront console and navigate to Public Key. Choose Create Public Key. Add name and copy and paste the contents of public_key.pem file under Key. Once done, click Create Public Key.

3. Adding the public key to a Key Group.

To do this, navigate to Key Groups. Add name and select the public key we created. Once done, click Create Key Group.

Adding key group signer to distribution

  1. Navigate to CloudFront and choose the distribution whose files you want to protect with signed URLs or signed cookies.
  2. Navigate to the Behaviors tab. Select the cache behavior, and then choose Edit.
  3. For Restrict Viewer Access (Use Signed URLs or Signed Cookies), choose Yes and choose Trusted Key Groups.
  4. For Trusted Key Groups, select the key group, and then choose Add.
  5. Once done, review and Save Changes.

Cheers, you have successfully restricted public access to assets. If you try to open any asset urls in the browser, you will see something like this:

You can either create signed urls or cookies using the private key to access the assets.

Setting cookies and accessing CloudFront private urls

You need to create and set cookies on the domain to access your content. Once cookies are set,  they will be sent along with every request by the browser.

The cookies to be set are:

  • CloudFront-Policy: Your policy statement in JSON format, with white space removed, then base64 encoded.
  • CloudFront-Signature: A hashed, signed using the private key, and base64-encoded version of the JSON policy statement.
  • CloudFront-Key-Pair-Id: The ID for a CloudFront public key, e.g., K4EGX7PEAN4EN. The public key ID tells CloudFront which public key to use to validate the signed URL.

Please note that the cookie names are case-sensitive. Make sure cookies are http only and secure.

CODE: https://gist.github.com/velotiotech/127a456fa5f875f766d3e6cbd0934216.js 

Cookies can be created in any language you are working on with help of the AWS SDK. For this blog, we will create cookies in python using the botocore module.

CODE: https://gist.github.com/velotiotech/e5fe8d0baf3dbef5b92a7bca126b6a6f.js 

For more details, you can follow AWS official docs.

Once you set cookies using the above guide, you should be able to access the asset.

This is how you can effectively use CloudFront along with S3 to securely serve your content.

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Setting up S3 & CloudFront to Deliver Static Assets Across the Web

If you have a web application, you probably have static content. Static content might include files like images, videos, and music. One of the simpler approaches to serve your content on the internet is Amazon AWS’s “S3 Bucket.” S3 is very easy to set up and use.

Problems with only using S3 to serve your resources

But there are a few limitations of serving content directly using S3. Using S3, you will need:

  • Either keep the bucket public, which is not at all recommended
  • Or, create pre-signed urls to access the private resources. Now, if your application has tons of resources to be loaded, then it will add a lot of latency to pre-sign each and every resource before serving on the UI.

For these reasons, we will also use AWS’s CloudFront.

Why use CloudFront with S3?

Amazon CloudFront (CDN) is designed to work seamlessly with S3 to serve your S3 content in a faster way. Also, using CloudFront to serve s3 content gives you a lot more flexibility and control.

It has below advantages:

  • Using CloudFront provides authentication, so there’s no need to generate pre-signed urls for each resource.
  • Improved Latency, which results in a better end-user experience.
  • CloudFront provides caching, which can reduce the running costs as content is not always served from S3 when cached.
  • Another case for using CloudFront over S3 is that you can use an SSL certificate to a custom domain in CloudFront.

Setting up S3 & CloudFront

Creating an S3 bucket

1. Navigate to S3 from the AWS console and click on Create Bucket. Enter a unique bucket name and select the AWS Region.

2. Make sure the Block Public Access settings for this bucket is set to “Block All Public Access,” as it is recommended and we don’t need public access to buckets.

3. Review other options and create a bucket. Once a bucket is created, you can see it on the S3 dashboard. Open the bucket to view its details, and next, let’s add some assets.

4. Click on upload and add/drag all the files or folders you want to upload. 

5. Review the settings and upload. You can see the status on successful upload. Go to bucket details, and, after opening up the uploaded asset, you can see the details of the uploaded asset.

If you try to copy the object URL and open it in the browser, you will get the access denied error as we have blocked direct public access. 

We will be using CloudFront to serve the S3 assets in the next step. CloudFront will restrict access to your S3 bucket to CloudFront endpoints rendering your content and application will become more secure and performant.

Creating a CloudFront

1. Navigate to CloudFront from AWS console and click on Create Distribution. For the Origin domain, select the bucket from which we want to serve the static assets.

2. Next, we need Use a CloudFront origin access identity (OAI) to access the S3 bucket. This will enable us to access private S3 content via CloudFront. To enable this, under S3 bucket access, select “Yes use OAI.” Select an existing origin access identity or create a new identity.
You can also choose to update the S3 bucket policy to allow read access to the OAI if it is not already configured previously.

3. Review all the settings and create distribution. You can see the domain name once it is successfully created.

4. The basic setup is done. If you can try to access the asset we uploaded via the CloudFront domain in your browser, it should serve the asset. You can access assets at {cloudfront domain name}/{s3 asset}
for e.g. https://d1g71lhh75winl.cloudfront.net/sample.jpeg

Even though we successfully served the assets via CloudFront. One thing to note is that all the assets are publicly accessible and not secured. In the next section, we will see how you can secure your CloudFront assets.

Restricting public access

Previously, while configuring CloudFront, we set Restrict Viewer access to No, which enabled us to access the assets publicly.

Let’s see how to configure CloudFront to enable signed URLs for assets that should have restricted access. We will be using Trusted key groups, which is the AWS recommended way for restricting access.

Creating key group

To create a key pair for a trusted key group, perform the following steps:

1. Creating the public–private key pair.

The below commands will generate an RSA key pair and will store the public key & private key in public_key.pem & private_key.pem files respectively.

CODE: https://gist.github.com/velotiotech/fdff1643db83fb1f45fa76ec1af06ab7.js

Note: The above steps use OpenSSL as an example to create a key pair. There are other ways to create an RSA key pair as well.

2. Uploading the Public Key to CloudFront.

To upload, in the AWS console, open CloudFront console and navigate to Public Key. Choose Create Public Key. Add name and copy and paste the contents of public_key.pem file under Key. Once done, click Create Public Key.

3. Adding the public key to a Key Group.

To do this, navigate to Key Groups. Add name and select the public key we created. Once done, click Create Key Group.

Adding key group signer to distribution

  1. Navigate to CloudFront and choose the distribution whose files you want to protect with signed URLs or signed cookies.
  2. Navigate to the Behaviors tab. Select the cache behavior, and then choose Edit.
  3. For Restrict Viewer Access (Use Signed URLs or Signed Cookies), choose Yes and choose Trusted Key Groups.
  4. For Trusted Key Groups, select the key group, and then choose Add.
  5. Once done, review and Save Changes.

Cheers, you have successfully restricted public access to assets. If you try to open any asset urls in the browser, you will see something like this:

You can either create signed urls or cookies using the private key to access the assets.

Setting cookies and accessing CloudFront private urls

You need to create and set cookies on the domain to access your content. Once cookies are set,  they will be sent along with every request by the browser.

The cookies to be set are:

  • CloudFront-Policy: Your policy statement in JSON format, with white space removed, then base64 encoded.
  • CloudFront-Signature: A hashed, signed using the private key, and base64-encoded version of the JSON policy statement.
  • CloudFront-Key-Pair-Id: The ID for a CloudFront public key, e.g., K4EGX7PEAN4EN. The public key ID tells CloudFront which public key to use to validate the signed URL.

Please note that the cookie names are case-sensitive. Make sure cookies are http only and secure.

CODE: https://gist.github.com/velotiotech/127a456fa5f875f766d3e6cbd0934216.js 

Cookies can be created in any language you are working on with help of the AWS SDK. For this blog, we will create cookies in python using the botocore module.

CODE: https://gist.github.com/velotiotech/e5fe8d0baf3dbef5b92a7bca126b6a6f.js 

For more details, you can follow AWS official docs.

Once you set cookies using the above guide, you should be able to access the asset.

This is how you can effectively use CloudFront along with S3 to securely serve your content.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings