SSL Certification on AWS using
ACM and Cloudfront


SSL certification on Bitnami WordPress Application using AWS Certificate Manager and Cloudfront.

SSL certification is currently in a price war converging to 0 which is great for the consumer (not so great for the companies selling SSL certification), but it also means that it is no longer becoming an optional extra for websites. As of 2017 google has started punishing sites without SSL certification, and for SEO reasons alone many sites will begin adopting SSL certification. This is a good thing as it will help make the broader net more secure.

This guide is following the steps I took to install SSL on a WordPress site that was running on AWS that I launched with Bitnami.

At the start of this guide I will assume the following conditions:

  • Operating WordPress site running on AWS launched with Bitnami
  • Domain DNS managed by Route53

Before you start this process make sure that you have access to one of these email addresses:

  • administrator@your_domain_name
  • hostmaster@your_domain_name
  • postmaster@your_domain_name
  • webmaster@your_domain_name
  • admin@your_domain_name

In the AWS documentation it also states they will send an email to your WHOIS contact email address but I did not receive any on those accounts. I had to create an admin@domain account to do this next step.

Registering your Certificate

Amazon recently introduced Certificate Manager which provides SSL certification free of charge certified by Amazon. This is great because it means that Amazon handles all of the certification that traditionally was a security minefield. Using AWS Certificate Manager the user never has access to the secret keys or manages the encryption this means that there is no risk of the keys being compromised and leaves the encryption to Amazon who do an excellent job of staying up to date with security.

The downside is that this certificate is only usable with Amazon assets – mainly the elastic load balancer or Cloudfront CDN. You will not be able to use this certificate for any sites not hosted on AWS as you do not get access to the actual certificate.

What we are going to use is Cloudfront CDN which will prove to be significantly cheaper than installing a load balancer if you have a small low traffic site like the one I am working with.

The first step is to register the domain on Certificate Manager.

It is important that you set your region to US East 1 (N. Virginia) for requesting your certificate. This is because you will only be able to connect your certificate with Cloudfront if it is registered in N.Virginia. Do not worry if your domain is not in that region (mine was in Sydney).

 

Click request certificate and add your domain name – you may want to include the following variants by clicking the add another name to this certificate:

  • domain.com
  • com
  • *domain.com

Hit review and request and then submit the request.

You will receive an email at your administrator email accounts that will give you a link to approve. Once you have clicked the link you should see your domain in the certificate manager with the following:

 

Setting up Cloudfront

Now it is time to set up Cloudfront which will act as the CDN for the WordPress site.

Go to Cloudfront and click Create Distribution.

Select the Web type of distribution

These are the settings I used but of course feel free to adjust to your requirements.

Origin name – your EC2 address (IP addresses are not allowed here)

All other values left as default (note that origin protocol policy is set to HTTP as the EC2  origin is not SSL secured, it will be Cloudfront that will be the secure connection between the client and the content).

Select redirect HTTP to HTTPS as we will be forcing the viewer to access the site securely using our shiny new SSL certification.

Allow the HTTP to perform all the CRUD actions just in case we need to make changes.

Whitelist the origin and host headers.  Host and Origin are used by CloudFront to make the caching decision. Host ensures that if we have multiple websites running on the same server, they won’t get tangled together from a caching perspective. We want CloudFront to look at the domain name and the URL (example.com/request), not just the URL (/request) to determine what it has in cache. Origin helps with CORS so that requests sent from external websites are inspected to identify the request’s origin.

 

Leave the TTL settings as default (change if you wish as this will only affect the caching time of the assets).

Whitelist the following cookies that used by WordPress:

comment_author_*

comment_author_email*

comment_author_url*

wordpress_logged_in_*

wordpress_test_cookie

wp-settings-*

 

NOTE – if your site uses additional cookies than that listed above you will need to whitelist them in the above box. An example would be woocommerce that uses user session and cart session cookies, otherwise your users cart will not be saved between pages.

 

Forward all Query String and cache based on all.

This option instructs Cloudfront to forward all query string parameters to the origin, a useful option to have on if any of your site uses query string parameters.

 

Compress Objects Automatically improves performance as Cloudfront will make the decision to compress objects in the cache automatically if they specify gzip.

 

 

Add your domain name with and without the www. prefix in the Alternate Domain Names input box.

 

Now we attach the SSL certificate we created in the Certificate Manager.  Click the Custom SSL certificate and then select the certificate in the drop down menu. If the Custom SSL radio button is greyed out and un-selectable it is most likely because you registered the certificate in the wrong region go back and make sure it is registered in US East 1.

 

 

Final settings and then hit create distribution. It will take at least 15 minutes for the distribution to be created but in the meantime we can start adding behaviours to account for all of the WordPress functionality.

 

There are 5 additional wordpress behaviours that need to be set:

 

 

These behaviours allows Cloudfront to set independent caching behaviours for each of these WordPress URL patterns. By setting them differently you can control how long each page is cached for in Cloudfront – for instance the Admin page should never be cached as you will want to maintain an accurate picture of the sites settings.

 

Again note that if your site uses other URL patterns that you do not want cached i.e. Woocommerce you should nominate them here. Woocommerce uses a cart, my account and checkout pages that should never be cached.

(image credit: 1strategy.com)

 

Repeat setting up behaviours for the remaining WordPress URL patterns.

 

Adjusting Route53

 

You may want to wait until the distribution status has changed from “in progress” to “deployed” before changing  your A records to minimise site down time.

 

Now that we have Cloudfront setup to handle the caching of assets from the EC2 instance that is running our WordPress site, it is time to point the A records to Cloudfront so that when users go to the URL of our site they will be routed through Cloudfront.

 

To do this we just need to adjust our existing A records. If you were set up like I was your current A records will be pointing to the IP of the EC2 instance running the site. To point the A record to the Cloudfront we can use the Amazon alias functionality – select the alias radio button and then find your Cloudfront distribution from the drop down list.

 

 

That’s it! You have configured your A records to point to your Cloudfront distribution – make sure that update both A records (www.domain.com and domain.com) to the Cloudfront alias address.

 

Adjusting wp-config file

 

This may not be required by everyone but I needed to do it in order to get the SSL certificate working. You will need an FTP program (I use Filezilla) to access the wordpress configuration files.

 

Connect to your server by using the key files provided by Bitnami (Google how to connect Filezilla to Bitnami if you are unsure there is heaps of guides out there).

 

Then navigate to /opt/bitnami/apps/wordpress/htdocs

 

From there download the wp-config file and make the following adjustment:

Simply add an “s” to the end of the http: defining the default URLs of WordPress.

 

 

 

 

You may need to restart the Apache server here but I didn’t need to.

 

If you need to you can SSH into your instance and use the following command:

 

sudo /opt/bitnami/ctlscript.sh restart apache

 

Insecure Content Fix

 

If you go to your domain now you will most likely see an error that your css and js files are being blocked as they coming from insecure sources. This is because they are being loaded in with HTTP rather than HTTPS, the easiest way to fix this is with the SSL Insecure Content Fixer plugin.

 

Which can be downloaded from here: https://wordpress.org/plugins/ssl-insecure-content-fixer/

 

Now if you’re using Bitnami to load your wordpress application, this plugin will falsely detect an SSL script in the application and will show you a “recommended setting”. Make sure you ignore this and instead select unable to detect HTTPS as the HTTPS detection setting. This is because Bitnami loads in a dummy certificate in place to assist with loading in a custom SSL cert. The plugin is detecting this certificate and will try to configure your site accordingy. Because we are using Cloudfront the SSL certificate is not actually attached to the instance and therefore is impossible for the plugin to detect. Thankfully the plugin author has allowed the above option to configure the site even without a detectable cert.

 

If you are still having insecure content issues after using this plugin you can troubleshoot some the issues following this link:

 

https://managewp.com/wordpress-ssl-settings-and-how-to-resolve-mixed-content-warnings

 

After following all these steps you should have a beautiful green padlock next to your site’s URL designating it a secure site. Please let me know how you go in the comments below, any bugs or improvements are welcome as well, we are all learning – all the time.