Heroku, SSL & Me. We’ve come a long way.
tl;dr: SSL is no longer expensive and complicated. We wrote some code to make it awesome.
I’ve said it a few times in the past but SSL is the future. If you’re not encrypting your users’ traffic while they’re on your site, you should be and you’re irresponsible for not doing so. It’s no longer a ‘nice to have’, it’s a necessity. My coworkers are probably sick of me piping up on projects that I have no part in and saying things like:
- Do they have a certificate already?
- Are we buying it?
- Is there time to install it?
- Is the renewal in the diary?
But like your nan who tries to get you to take your medicine, despite the bad taste, you know it’s the right thing to do.
Our infrastructure stack these days is almost always Heroku, CloudFlare, AWS (s3, CloudFront), 123-reg SSL certificate. Can you see the weak link there? It sure as hell sticks out like a sore thumb to me, and not just because I’ve put it in bold type. Here’s how that process usually goes:
- Use Terraform to instantly provision Heroku, CloudFlare and AWS resources.
- Buy SSL credit from 123-reg.
- Make sure client has access to the firstname.lastname@example.org email address.
- Wait for authorisation email from SSL provider.
- Wait an unspecified amount of time for SSL certificate to be delivered.
- Find the right intermediate certificate.
- Realise it’s the wrong intermediate certificate.
- Generate a PEM.
- Upload it to Heroku.
- Sob quietly in to a, now cold, cup of tea on the realisation that I misspelt the domain name in the CSR.
Plus all of the other steps of this horrible, unautomated, inconsistent and unrepeatable process that I’ve forgotten about.
According to the (always useful) XKCD “Is it worth the time?” chart, automating this process is likely to save in the region of 10-20 billion years (I’m extrapolating slightly).
Until now, automating this process has been fraught with issues.
- Heroku doesn’t offer free SSL endpoints. (They do now.)
- SSL certificates are expensive relative to the amount of work required to generate them. (Not anymore.)
- It requires knowledge of how certificate chains work. (Do I need an intermediate certificate?) (Not anymore.)
- You have to verify ownership of a domain via email. (Nope!)
To quickly address point 1: Heroku recently started a rollout of what they call http-sni. To you and me, this means free SSL endpoints. Previously these cost $20/month. You can bin the old SSL Endpoint add-on and just use these new feature instead. Your end users will notice nothing (unless they’re using IE6.) So that wraps point 1 up nicely.
Next, the cost of SSL. This has, finally, been reduced by LetsEncrypt and reduced to zero. SSL certificates now cost nothing. Even better, you can generate certificates via an API so you can totally automate the process of generation, renewal and even revocation! (YAY!)
Last of all, the validation process. Traditionally, part of requesting an SSL certificate meant verifying that you own the domain by responding to an email sent to that domain. It’s a pretty solid idea that’s been around forever that works on the principle of “I control the DNS, therefore I own the domain.”. But email is slow and we like things that are fast, repeatable and automated. Short of writing a script to read incoming emails and responding to them automatically, there’s not much you can do here.
LetsEncrypt (via the ACME protocol) allows us to validate ownership of a domain by placing a TXT DNS record on the domains and subdomains we want to generate certificates for. It follow the same principle as before but allows us to automate this by using a DNS provider’s API (lots of them have one now).
We thought we’d make a start…
What if we could turn that process in to an API? Let me pass a bunch of parameters (domain name, subdomains, Heroku app name etc.) to an endpoint and let a computer do the work for me.
Well, we made a start and we open sourced our solution too with the intention of growing the project to be the de-facto solution for SSL on Heroku. Let us know how it works for you and add any issues to GitHub!