Documentation

How to Serve Private Media via Signed Amazon CloudFront URLs

In this guide you’ll learn how to configure Amazon CloudFront and WP Offload Media to enable signed expiring CloudFront URLs for offloaded Media Library items that should have restricted access.

You typically want to restrict access to offloaded Media Library items that are downloadable Product Files for WooCommerce or Easy Digital Downloads, or perhaps to ensure media URLs available on members-only pages can not be used outside of the site. We generally call these kinds of files “private” to distinguish them from public media such as images that you usually want to be freely seen on the site.

By setting up WP Offload Media to deliver private media via signed Amazon CloudFront URLs you get all the benefits of improved worldwide delivery speeds of your media via the CDN with your own domain, while keeping the files relatively secure. You can read more about signed expiring URLs in our How to Restrict Access to Offloaded Media doc.

This doc assumes you have already set up WP Offload Media to offload the Media Library to Amazon S3 and deliver those files via Amazon CloudFront by following the CloudFront Setup for Media Offloaded to Amazon S3 guide.

You can set up WP Offload Media to sign Amazon CloudFront URLs that use either a default CloudFront domain (cloudfront.net) or a custom domain (recommended). This guide uses a custom domain, but there is no difference to the steps when using a default CloudFront domain.

For added security it is recommended that you have followed our advice and enabled Block All Public Access to Bucket when setting up CloudFront as the delivery provider.

This article covers the following steps:

  1. Create a Key Pair for a Trusted Key Group
  2. Create a New Amazon CloudFront Behavior for Private Media
  3. Configure WP Offload Media to Deliver Private Media via Signed Amazon CloudFront URLs

Create a Key Pair for a Trusted Key Group

By default, WP Offload Media signs private offloaded media files using the same Access Key ID and Secret Access Key credentials that are used to access the Amazon S3 bucket. These signed URLs use raw Amazon S3 URLs (e.g. https://media-example-com.s3.eu-west-2.amazonaws.com/…).

To create signed Amazon CloudFront URLs that use the domain assigned to the distribution (e.g. https://media.example.com/…), Amazon CloudFront needs to have the public key for a key pair you generate. The private key file must be saved on your site’s server so that WP Offload Media can use it to create signed CloudFront URLs. CloudFront then uses the public key to check that the URLs were properly signed before delivering the requested file.

For more information on signing CloudFront URLs with a public key assigned to a trusted key group as detailed in this article, please see Amazon’s documentation.

Generate a Key Pair

To generate the key pair, you will need to use openssl to create an RSA key in the PEM format. There’s a good chance that your server or development machine already has openssl installed, but if not, please consult your operating system’s documentation on how to install it. If you have another prefered way of creating RSA keys in the PEM format, that should work too.

Using openssl to generate a key pair requires two commands, first you generate the private key file:

openssl genrsa -out private_key.pem 2048

Then you extract the public key from the private key file:

openssl rsa -pubout -in private_key.pem -out public_key.pem

It’s a good idea to use file names that are appropriate for the site, and better still, something completely random. For example:

ian@ians-tuxedo:/srv/ian $ openssl genrsa -out example_cvxQzy5jkh7heg2NXG_private.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..........................+++++
..................+++++
e is 65537 (0x010001)
ian@ians-tuxedo:/srv/ian $ openssl rsa -pubout -in example_cvxQzy5jkh7heg2NXG_private.pem \
    -out example_cvxQzy5jkh7heg2NXG_public.pem
writing RSA key

You will later upload the contents of the public key file to CloudFront.

Upload Public Key to CloudFront

Log into the AWS Console and navigate to the CloudFront console.

From the left hand navigation menu, select Public keys from within the Key management section.

OME Signed CloudFront Setup - Screenshot of Amazon CloudFront Public Keys page

In the above screenshot you can see that we already have a couple of public key pairs set up on our account, but chances are you will not. If you do already have a few public key pairs set up, please be aware that you can only have a maximum of four key groups associated with a single Cloudfront distribution, and up to five public key pairs assigned to each key group.

We haven’t talked about them yet, but key groups are a way to allow multiple public key pairs to be used with a CloudFront distribution, making it easier to add and remove keys, or rotate keys for better security. We’ll come back to key groups in a bit.

To upload your public key, click the orange Create public key button, which should show you a Create public key page.

OME Signed CloudFront Setup - Screenshot of Amazon CloudFront Create public key page

Enter the details for the new public key:

Name: Something to uniquely identify the public key. Must be all lowercase, no spaces or punctuation except “-”. Description: A short description for the public key. Probably best to mention it’ll be used with WP Offload Media. Key: The contents of the public key file you generated earlier.

To get the contents of the public key file, you should be able to cat it, and then copy and paste into the Key field.

ian@ians-tuxedo:/srv/ian $ cat example_cvxQzy5jkh7heg2NXG_public.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqlouwS68wO9hf/AD+4o1
A4xYmQbw/3ltn83L32VVV7HG6Kw2rDYXoz6CpuYe/Ct8e7+mdX9LdGRrI7orPJmV
8v6ezSav9geHnKm5kn4jcksU6oXnOevP9IdcPuEAKi4ryUX8lc/iZ5DTI+1Iq/PK
YAjidPIT+JPU74p6gUovToXWA3PtN4Lu+8vJIs02bPVRMH8kTh/RVUubfF+Tju0y
6S8I7WnriAYzCPB3WmS0EQYP6KhmZ6LJdqhjEIjw4+K2mh1tSC7pJIWmqWyHmAFj
EhnTPoSEWn1dyLAVBfZkCkjum/+OoqZB+cSvtyXmD8l87E63JgU68Ze6ue5zZS8f
6QIDAQAB
-----END PUBLIC KEY-----

OME Signed CloudFront Setup - Screenshot of filled in Amazon CloudFront Create public key page

Once you’ve filled in all the fields, use the orange Create public key button below the form to save the public key.

You should now see your new CloudFront public key pair in the list.

OME Signed CloudFront Setup - Screenshot of Amazon CloudFront Public Keys page with new public key

You can now see the ID for the new CloudFront public key pair (which looks suspiciously similar to an Access Key ID 😉), you will need that later.

Add the Public Key to a Key Group

As mentioned earlier, Amazon CloudFront uses key groups to allow multiple key pairs to be used to sign URLs. This improves security and flexibility by allowing you to uniquely identify key pairs by the application that uses them, and add and retire key pairs to keep them fresh and mitigate potential issues with unauthorized access to a private key file.

While still in the CloudFront console, use the left hand navigation menu to select Key groups from within the Key management section.

OME Signed CloudFront Setup - Screenshot of Amazon CloudFront Key Groups list page

Use the orange Create key group button to create a new key group.

Enter the details for the new key group:

Name: Something to uniquely identify the key group. Must be all lowercase, no spaces or punctuation except “-”. Description: A short description for the key group. Probably best to mention it’ll be used with a particular distribution or site. Public keys: Here you pick the public key you uploaded earlier.

OME Signed CloudFront Setup - Screenshot of filled in Amazon CloudFront Create key group page

Once you’ve filled in all the fields, use the orange Create key group button below the form to save the key group.

Create a New Amazon CloudFront Behavior for Private Media

We can now configure Amazon CloudFront to restrict access to certain files so that they can only be viewed or downloaded by a signed URL that WP Offload Media will generate.

At present you should have a CloudFront distribution set up that is happily delivering offloaded Media Library items on publicly accessible URLs. What we want to do now is have CloudFront designate a certain path prefix as “private” and require signed URLs in order to access them. We do this by adding a new Behavior to the CloudFront distribution.

Later we’ll configure WP Offload Media to move all private objects to the new private path.

Ensure you’re in the Distributions section of the AWS Console’s CloudFront page, click the ID of the CloudFront distribution that you’re using with WP Offload Media on your WordPress site.

Screenshot of CloudFront distributions list with distribution used for offloaded media that has a custom domain shown

Click on the Behaviors tab, and then the Create Behavior button.

OME Signed CloudFront Setup - View Behaviors tab for CloudFront distribution with custom domain name

Enter a relative Path Pattern that matches how you wish the path of all private objects to start. The path should not start with a /, but should end with /* to indicate that all files in the path pattern are subject to the Behavior.

In our example we’re going to have WP Offload Media move all the private objects into new paths that start with private/…, so we’ll enter private/ as our Path Pattern. However, you could just as easily enter downloads/, store/, or even secure/content/.

The key thing to remember is that WP Offload Media will be moving private objects into this new path prefix, with the rest of their normal bucket path appended. So the matching Path Pattern in the new CloudFront Behavior should be a relative folder path, with an / appended. You should not use a filename pattern such as private/.zip because WP Offload Media requires that all objects under the specified private path prefix be signed.

After entering a Path pattern, you should ensure that the Origin and origin groups is the Amazon S3 bucket that you’re offloading media to with WP Offload Media.

Otherwise, the only other field that needs attention is the Restrict viewer access radio button. Select Yes, and ensure that the newly exposed Trusted key groups (recommended) option is checked under the Trusted authorization type subheading.

From the Add key groups dropdown select box, select the Key Group you created earlier. You should see the selected key group displayed under the dropdown once selected.

OME Signed CloudFront Setup - Create Behavior page with highlighted example data for private prefix

Once you’ve filled in all the fields, use the orange Create behavior button near the bottom of the page to save the new Behavior.

You should now see your new Behavior first in the list, showing a Precedence of “0”, and all the expected details including Trusted key groups with the newly created key group’s ID.

OME Signed CloudFront Setup - View Behaviors tab for custom domain CloudFront distribution with new Behavior

If you do not see the Trusted key groups column in the list, use the little cog icon at the top right of the list to change the visible columns preference.

OME Signed CloudFront Setup - Screenshot of CloudFront distribution behaviors list preferences for changing visible columns

Configure WP Offload Media to Deliver Private Media via Signed Amazon CloudFront URLs

While the updated Amazon CloudFront distribution deploys, you can set up WP Offload Media to use a matching private prefix for private media and sign their CloudFront URLs.

The first thing to do is add the key pair’s Private Key File to the site’s server.

Through whatever means you have at your disposal, such as FTP or a file browser via your hosting provider’s control panel, upload the private key file to a private area of the server that is accessible to your WordPress site’s PHP processes, but is not accessible from the public internet.

Often you’ll be able to upload files to an area that is one folder up from the WordPress site’s root folder which is usually not accessible by the internet. For example, if your site’s wp-config.php file can be found at /var/www/example.com/htdocs/wp-config.php, then /var/www/example.com/ would likely be a safe place to put the Private Key File.

In our example, the site’s root folder is at /srv/ian/example.local, so we’ll upload our Private Key File to /srv/ian/example_cvxQzy5jkh7heg2NXG_private.pem. We’ll need to know this full absolute path when configuring WP Offload Media to use it.

Remember, the Private Key File is literally the key to access your private files being served via the CloudFront distribution. If someone gets hold of that file they can create their own signed CloudFront URLs to access your objects. So if you are not sure whether your Private Key File is going to be secret and safe from unwanted access, please consult with your server administrator or service provider.

Gandalf saying Keep it secret, keep it safe.

Log into your WordPress site’s admin dashboard and navigate to WP Offload Media’s settings page via the Settings menu.

In the Delivery Settings panel where the settings delivering public media via Amazon CloudFront can be seen, click the switch to turn on Serve Private Media from CloudFront.

OME Signed CloudFront Setup - WP Offload Media settings with Serve Private Media from CloudFront switch highlighted

You should now see 3 new fields, Public Key ID, Private Key File Path and Private Bucket Path.

In the Public Key ID field enter the ID that you saw when you uploaded your public key to CloudFront.

For the Private Key Path enter the full absolute path to the Private Key File you uploaded to the server. For our example we entered /srv/ian/example_cvxQzy5jkh7heg2NXG_private.pem.

Finally, in the Private Bucket Path field you should enter the relative path that you set up the new CloudFront Behavior to match against, but do not include the “*” wildcard character. In our example we entered “private”, but we could also have entered “private/” (which is what it’ll actually be saved as in either case).

OME Signed CloudFront Setup - WP Offload Media settings with Serve Private Media from CloudFront settings entered

Click the Save Changes button to proceed.

WP Offload Media now prompts you to move any already offloaded private media to the new private path. Say “Begin Move” unless you have some reason to keep your private objects where they are.

If you say Skip here then WP Offload Media will continue to serve already offloaded private media via signed S3 URLs instead. Only media made private after this point would then be served via signed CloudFront URLs as they will be placed in the expected private path.

Screenshot of WP Offload Media showing move private media prompt

If you took our recommendation and said Begin Move to moving private media into the new private path, then WP Offload Media will analyze every offloaded Media Library item to move any private files, including any thumbnail sizes that have been made private. This process happens in the background on the server, so you can close your browser or put your machine to sleep if you like.

Screenshot of WP Offload Media showing the move private objects tool in progress

At the completion of the move process, WP Offload Media will post a notice in the admin dashboard.

Screenshot of WP Offload Media finished moving private media files notice

You should now be able to see that private media is being served via signed CloudFront URLs that include the private path 🎉.