Use a Custom Domain and SSL Certificate With Amazon Cloudfront

Running your own CDN has become incredibly cheap and easy these days thanks to Amazon’s Web Services (AWS). I’ve been using an Amazon Cloudfront CDN distribution to host assets for several websites for a couple of years now. They’re super easy to set up and they cost pennies a month for the average site. The only problem was that, until recently, if you wanted your CDN to serve assets over HTTPS then you either had to pay thousands a month for Amazon to give you a dedicated IP address or you were forced to use the default Cloudfront domain which was long, ugly, and looked something like https://dsy12448xkv.cloudfront.net/. No one wants that. But now there’s a cheaper option! Amazon allows you to upload your own SSL certificate to use with your custom Cloudfront domain for no extra cost. The process was a bit confusing the first time I set it up so I’m documenting it here for anyone who needs a reference.

Step 1: Set up Cloudfront

Before you can have an SSL secured CloudFront CDN you need to have a CloudFront distribution set up to use a custom domain. I won’t go into how to create a CloudFront distribution but I will tell you that once you have it set up, take note of your distribution’s Cloudfront URL. The first step is to create a new CNAME record that points to the Cloudfront URL. So if your domain is “example.com” and you want “cdn.example.com” to point to your AWS Cloudfront distribution then you need to enter “cdn” as the host and the Cloudfront URL as the URL it aliases to.

Now you’re all set to have a custom SSL secured CDN using Cloudfront. Just be sure to let the DNS changes propogate (it usually takes an hour for me but could take as long as 72 hours) and test the URL over regular HTTP to ensure that the CNAME is set up correctly.

Step 2: Generate an SSL certificate

Now you’ll need to create an SSL certificate. I won’t go into too much detail here but I’ll give you the basics. The command to generate a CSR for a new certificate is:

1
2
3
4
5
6
7
# You may need to use sudo for this
openssl req \
    -sha256 \
    -new -newkey \
    rsa:2048 -nodes \
    -keyout cdn.mywebsite.com.key \
    -out cdn.mywebsite.com.csr

You can run this command on a server you have or locally. It really doesn’t matter.

Then you’ll fill in the information it asks for. Do not enter a password and be sure the email address you enter is one that you have access to because that’s where your certificate will be sent. Once the command has finished you’ll have a .csr file and a .key file. You’ll copy the contents of the CSR file and give it to whoever you buy your SSL certificate from (I use Namecheap because they’re the cheapest, easiest, and give out $2 SSL certs with domain purchases).

Now just wait for a bit until you receive your certificate in an email. Once you get it, unzip the file and then you need to do 2 things in order to be ready for the next steps.

  1. Open a new terminal window and enter the directory where you unzipped the certificate files
  2. Remember that key file you generated when you first created the certificate signing request? If you generated the CSR on a server make sure to download the key file and have it available locally. I recommend you put it in the same folder as the files that came with your SSL certificate.
  3. Often times the company providing your SSL certificate gives you more than one certificate chain file. Comodo, the provider I tend to use, does this. I can’t tell you what your chain files will be called but if you bought a Comodo PositiveSSL certificate then this command will concatenate your chain files into a single new file: cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > chain.crt

Step 3: Set up AWS IAM and related tools

Unfortunately there’s no web interface for uploading your certificate files so you’ll need to create an IAM user with sufficient privileges to upload the certificate files from the command line. You’ll also need to install the AWS command line tools locally as well. Here’s how to do all that.

Set up the IAM user

You’ll need to create an admin user on Amazon IAM (Identity Access Management). These steps were taken from Bryce Fisher-Fleig’s Cloudfront guide which is more detailed

  1. On the AWS Web Console, go to the IAM service
  2. Click on the “Users” tab
  3. Click “Create New Users”
  4. Enter the first user name. E.g. “MySuperAdmin”
  5. Click “Create”
  6. Show or download the credentials – we’ll need them a little bit later.
  7. Click on the newly created user
  8. In the user console at the bottom of the page, choose the “Permissions” tab
  9. Click “Attach User Policy”
  10. Copy and paste this JSON snippet into the Policy Editor and click save:
1
2
3
4
5
6
7
8
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["*"],
    "Resource": ["*"]
  }]
}

That JSON snippet gives the user full permission to do ANYTHING so I’d reserve the use of that user to your own local use and never have that user do anything with the AWS SDK in any web app or something.

Install the AWS CLI tools

On Mac you can brew install aws-cfn-tools awscli to get it. You will likely need to install some Java related software in the process. That’s unfortunate but normal.

On Debian or Ubuntu sudo apt-get install python python-pip && sudo pip install awscli will get you what you need.

The Amazon docs cover Windows and other platforms.

Now run aws configure . It’ll ask you some questions. You need to use the IAM admin user you created in the previous step for the rest of this guide to work. So be sure to enter that IAM user’s username and use the credentials from the file you downloaded after creating that user on IAM.

Step 4: Upload the certificate

Now you can finally do what you came here to do. To upload and install the certificate run the following command:

1
2
3
4
5
6
7
cd /path/to/certificate/files/
aws iam upload-server-certificate \
  --server-certificate-name cdn.mywebsite.com \
  --certificate-body file://cdn.mywebsite.com.crt \
  --private-key file://cdn.mywebsite.com.key \
  --certificate-chain file://PostivieSSLCA2.crt \
  --path /cloudfront/

Be very careful with this command. Here’s what each option here means/does:

  • server-certificate-name– This is just a label you’re giving the certificate. It can be anything you want. Just make sure you can identify it later as it’ll show up in the AWS web interface.
  • certificate-body – The certificate you bought. This is the actual domain’s cert, not the chain or root certificates. If you got a Comodo certificate it’ll be the name of your site (or whatever you entered as the FQDN during the CSR creation step)
  • private-key – This is the key file you copied from your server and put into the folder with your SSL certs. We talked about this in Step 2
  • certificate-chain – Remember that special chain.crt file we created earlier? This is what you need to enter here.
  • path – This ends in a slash, and it must start with /cloudfront/. Just keep this as is, there’s no reason to change it and if you have a reason to change it then you don’t need this guide.

You may be asking why we use the file:// protocol in front of the file names. That’s because the command fails without it. It’s telling the CLI tool to read what we’re passing it as a file and not as a literal value.

Step 5: Configure Cloudfront

Now you just need to enable the certificate. Log into your AWS account, go to the Cloudfront admin interface, and then choose the Cloudfront distribution that you want to enable this SSL certificate on. On the “General” tab, click the Edit button. Now look at the third option on the page called “SSL Certificate”. Make sure you choose “Custom SSL Certificate” and then choose from the dropdown the name of the SSL certificate you uploaded in the AWS CLI command. Now save the changes and you’re good to go. It’ll take a bit but once your distribution is finished updating you’ll be able to visit your CDN URL over SSL.

The only catch is that your CDN links will only work in browsers that support SNI. If you need to support older browsers (IE6 basically and Firefox 2) then you’ll need to choose the very expensive option which gets you a dedicated IP address for your distribution. These days it’ll be quite rare that you can’t safely support SNI. There are edge cases out there but most of us don’t need to worry about it.

From now on you’ll only need to have your DNS set up with a new CNAME record, buy an SSL certificate, and then upload and configure your certificate on Cloudfront. The hardest parts of this process you’ll be able to skip the next time you do this unless you uninstall the AWS CLI tools.

System administration, Web development

« What is it really like to run a company? Understanding Rails by Building a Ruby Web Framework from Scratch »

Comments