Automating Let’s Encrypt SSL Certs via GoDaddy DNS Challenge

Let’s Encrypt is a widely recognized global Certificate Authority that offers free Domain Validation (DV) certificates.  Their certificates can be used by websites to enable secure HTTPS connections without scary browser warnings.  Modern day web-browsing and web-applications pretty much demand such a thing and being free is really nice!

There are many tutorials about getting a Let’s Encrypt DV certificate and the official documentation is thorough.  Pretty much anyone who controls a domain name can get a certificate for that domain using one of several authentication methods.  There are 2 main ways someone can prove they control a domain: provisioning a special DNS record in the domain’s DNS, or putting a special file in a well-known location on the domain’s website.   Automating the cert renewals is important because Let’s Encrypt only offers certificates with a 90 day lifetime.  They recommend renewing every 60 days.  Automation is key.

Enter Certbot — a full-featured client that can automate the tasks of obtaining certificates and configuring webservers to use them.  With some web hosting services and some domain registrars this is a super easy task.  There are plugins for many of the well-known services and some hosting services offer free automatically renewing certificates as part of their service.  Noticeably missing from this list of those who make Let’s Encrypt certificates easy to use is GoDaddy.  GoDaddy has 77 million domain names under management.  They sell these important SSL certificates for $74.99 / year for a single website, and up to $349.99 / year for a single website and all its subdomains — no incentive to make this easy there…

At FacetCorp we have paid the piper for years for our SSL certificates and considered it just a cost of having a website.  However a new web-application we developed uses WebRTC (Web Real-Time Communication) to connect to our PBX.  For all practical purposes WebRTC requires secure HTTP access to the server.  We needed SSL certificates for PBX servers sitting behind firewalls at all kinds of places beyond our control.  Being able to use free certificates and automating certificate renewals became paramount and doing this with DNS authentication for GoDaddy registered domains was important.

A weekend of research came up with no easy way to do this.  Lots of people looking for answers, but nobody with the answer.  I stumbled across part of the solution when a clue lead to the GoDaddy Domains API.  To get started with the GoDaddy API you’ll need an API Key.  API requests are sent with an API key and secret to ensure that the API request comes from an authorized source.  The API has a lot of functionality related to domains, but of particular usefulness for our purposes here, there are 5 related to DNS records for a domain.

Let’s Encrypt certificate renewal using the DNS challenge requires one to place a special TXT DNS record with specific content in the DNS records for the domain name.  The Let’s Encrypt authentication server then queries the DNS records for the domain to verify that the proper TXT DNS record exists and if so, the certificate gets renewed.  DNS records have a TTL (Time To Live) property and the GoDaddy Domains API enforces a minimum TTL of 600 seconds.  With the Add API function (the 1st listed above) it is pretty easy to add the required record and then continue on with cert renewal process.  However that only works the 1st time — to renew the cert a 2nd time you’d have to delete or modify the special DNS record so it can be re-added on the next renewal with different special TXT content.  There is no delete DNS record function in the GoDaddy Domains API so that becomes a challenge.  The 4th function listed above lets one replace a specific DNS record.  That would work for subsequent renewals, but you’d be stuck waiting for the 600 second TTL to expire before Let’s Encrypt servers would be able to query the DNS records to find the updated DNS record.  That leaves us 2 options to get rid of the special TXT record:  Replace ALL of the DNS records for the domain with the existing records minus the special TXT record (the 2nd API function above) or replace all of the DNS records for the domain with a specified type (the last API function listed above.)  If you are not using TXT records for anything else in your DNS, then this last option is not too horrible.  It is not bad at all really.

So that is the approach I took… Start the renewal process with Let’s Encrypt, get the special content from their renewal server, create a TXT DNS record with the special content, tell Let’s Encrypt’s renewal server to check the DNS records for this special record,  then after successful authentication and renewal of the certificate,  replace ALL of the TXT records in the DNS with a dummy TXT record that won’t interfere with subsequent renewals.  On subsequent renewals, replace the dummy TXT record with the new special content TXT record, get renewed, then replace the TXT record again with a dummy TXT record, repeat. This scheme works well and is pretty easy to automate and forget about it.

GoDaddy’s API function pages have a nice “Try it out” option to help you craft your API call which lets you fill in the blanks and click Execute to have it craft a Curl command-line which would sent your API request to their API server.  For a TXT record, we only need the Data parameter (special content provided by Let’s Encrypt), the Name parameter (“_acme_challenge”), and the TTL (600).  Our crafted Curl command using JSON content type would look something like this to replace all TXT records:

That is a scriptable thing!

With previously requested GoDaddy API Key, my Certbot “auth-hook” renewal script:

Certbot provides the Let’s Encrypt special DNS record content in the environment variable $CERTBOT_VALIDATION and the domain name in $CERTBOT_DOMAIN.  This renewal script is specified on the “certbot” command-line with the “–manual-auth-hook” option.  After the auth-hook script runs, Let’s Encrypt will check the DNS records for the special content TXT record.  When the special content TXT record is found, Let’s Encrypt renews the certificate.  After successful renewal, we use a clean-up script to rewrite the special DNS record so it will not interfere with subsequent renewals.

The cleanup script is identical to the auth-hook script except when we rewrite the TXT records we use a different name for the record that is NOT what the Let’s Encrypt DNS challenge looks for.  In this example, we prepend “previous” to the record name and put the record back how it was. It would work just as well to put some totally bogus TXT record back during the cleanup.  If GoDaddy’s API supported it, we would just delete the special TXT record.

The cleanup script is specified on the “certbot” command-line with the “–manual-cleanup-hook” option.  The only difference between the auth-hook script and the cleanup-hook script is in Line 20 where the auth-hook script creates the DNS record with the expected by Let’s Encrypt name and the cleanup-hook script creates the DNS record with a name that is NOT the expected name.

That’s it!  The auto-hook and the cleanup-hook.  To automate the whole deal, I wrapped the whole “certbot” command in a simple shell script to make it easier to schedule with a cronjob.  The docs recommend scheduling a renewal script to run twice a day.  The renewal process only happens when the certificate is near expiry, but in case something changes with a certificate and it must be renewed before normal expiry, checking more often is a good thing. I like details, so I have my cron script display the certificate details (including days before expiry) before it checks on renewal.

Schedule the cron script to run twice a day and never think about this again!

That’s all there is to know about this!  😉

If you have any trouble implementing a scheme like the above, please let me know in the comments below and I’ll try to help where I can.




Leave a Reply

Your email address will not be published. Required fields are marked *