I’ve wanted to enable SSL on this static blog for some time, and was considering either buying an SSL Cert that could deal with multiple domain names (since I want www.dpron.com and dpron.com to both work), or using Let’s Encrypt since it’s free. I think buying an SSL cert would have been the easier route since Let’s Encrypt uses 90-day certificates, and even if I built the renewal process into the rebuild and publish script for this site, I don’t always get around to updates every quarter. Then I read the announcement that AWS was bringing out their own free SSL Certificate issuing service, AWS Certificate Manager. Since I’m already using S3, and Cloudfront to serve this site - decision made, let’s try it out.
Especially for smaller sites without big budgets, enabling SSL generally has a few drawbacks:
- It’s laborious - there are many steps to getting a cert, getting it installed and configured.
- Properly configuring SSL hosting requires a lot of knowledge - which cypher suites to enable, what signature hash and key length to use. Most importantly - the correct answers here change over time, as vulnerabilities are found, and cypher suites move forward and key lengths and hashes get longer. Not only do you have to set it up correctly, you have to reconfigure things repeatedly as the winds change.
- Cost - from buying certs to many hosting providers charging extra for SSL, this can be an issue. The extra fees charged for certs that can have multiple domain names are also a total ripoff.
This service has 4 killer features that make it worth using:
- It’s free. The price of a certificate is rapidly converging on $0 which isn’t great for companies that make their money on distributing expensive SSL certs, but it’s good for the rest of us as it encourages broader adoption of secured web browsing. Consider a site like this which nobody visits, and costs only a few dollars per YEAR to host. Buying even a $10 certificate is double or triple the annual cost. There are many sites out there that can’t justify the cost of a certificate. Amazon has really done the right thing here offering free certificates, and not charging a significant premium for hosting with SSL (there’s a slightly higher charge for HTTPS requests on CloudFront, but the data transfer cost is the same, and that typically makes up the majority of CDN cost).
- You never see the private key - this limits the possibility of having your cert compromised because if you never see the private key, you can never store the private key and save it unencrypted somewhere that gets compromised, or accidentally upload it to github for all to see. Although this does mean you can’t use it elsewhere, or to host via Apache/Nginx/HAProxy - you’re limited to CloudFront or an ELB for SSL termination. But if you’re running your own server - use Let’s Encrypt, since the overhead of automating renewal is trivial with cron.
- Automatic seamless renewals - no need to remember when your cert is going to expire, get it renewed and update your systems - all of this happens automatically. This is a huge deal, as cert expiries have hit so many places and it’s a needless embarrassment and annoyance. Anything that removes the complication or friction of dealing with SSL will make it more prevalent.
- Proper SSL configuration by default - There’s no requirement (or option) to pick your own set of cyphers, key-length or hash signature. All the decisions are made for you, and seemly made correct. The resulting configuration and cert get excellent ratings from various online SSL checkers. Assuming Amazon continues to do a phenomenal job of security, these decisions and configurations will be updated over time to stay correct.
Requesting a Certificate
I chose to use the CLI to request a new certificate be generated using this command (OS X / Linux). There’s plenty of information at the official AWS CLI site on how to install/configure it.
Note - The Certificate Manager service only has an endpoint in us-east-1 today, so I had to add the first line above because originally the request-certificate command failed on me, since I typically use the us-west-2 region in my day-to-day AWS usage, and thus had it set there. If you get a message such as “Could not connect to the endpoint URL: “https://acm.us-west-2.amazonaws.com/” - that’s your problem.
Once the command was executed, it quickly returned with a CertificateArn response. In the Web GUI I could see the certificate was pending validation.
Validating the Certificate Request
AWS will send an email to the various contact email addresses listed for the domain in the WHOIS registration. Those emails contain a link to approve the SSL certificate request. Although one knock on the process was that Amazon sent out two verification emails, one for dpron.com and one for www.dpron.com which as a sub-domain didn’t need a secondary verification (there’s no separate WHOIS/registration info for it anyways).
Once you receive the email, it will direct you to a web page to approve the certificate request, after which you will get a confirmation page indicating the certificate has been successfully approved.
After approving the certificate request, the cert quickly changed status to “Issued”.
Once the certificate is issued, I was then able to go into the CloudFront administration, and select this certificate to use on my CDN distribution. After making the change it took 10-15 minutes for my distribution to update, and the certificate to be visible to end clients. I probably cost myself a dime to a quarter refreshing my browser repeatedly to see when it would show secure.
I’m not just enabling SSL for the fun of it, I’m going all in, so let’s set CloudFront to redirect all HTTP traffic to HTTPS. Changing this is in the “Behaviors” tab of the CloudFront distribution.
Note - The setting at the bottom of this page to “Compress Objects Automatically” is relatively new, so if your distribution hasn’t been updated lately, it’s a good opportunity to enable this feature.
The Successful Result
End to end it took about 30 min to read the documentation, request a certificate, approve the verification, and update my CloudFront configuration. It took longer to write this post.