The problem

I want to obtain Let’s Encrypt certificates with wildcard subdomains, but to do so, one must prove that they own the entire domain and not just a particular subdomain. This means that the standard HTTP challenges are not enough.

I was tired of manually doing DNS-01 challenges through Namecheap’s dashboard, which involved a laborious process of logging in, navigating to the domain I wanted to obtain certificates for, copying and pasting a special challenge code into a TXT record, waiting for the change to propagate, and repeating this for every single domain I owned, every three months.

The research

Certbot plugins are available for some DNS providers, but Namecheap is not one of those. I was faced with two options: one, move to a different supported provider and transfer all of my domains. Or, two: write a script that could run as a validation hook and thus automate the whole thing.

Certbot allows for the specification of pre and post validation hooks when run in manual mode. The flags to specify these scripts are –manual-auth-hook and –manual-cleanup-hook respectively and can be used as follows […] This will run the authenticator.sh script, attempt the validation, and then run the cleanup.sh script. Additionally certbot will pass relevant environment variables to these scripts […]

https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks

Namecheap also provides an API to anyone who has spent at least $50 within the last 2 years, among other alternative requirements.

The solution

I wrote the manual auth hook found here: https://github.com/trwnh/namecheap

The hook I wrote uses Python, Requests, and BeautifulSoup. Since I just wanted the hook to work, I didn’t bother over-engineering this – this script has some limitations:

  • Namecheap’s API uses SLD and TLD instead of a singular domain variable. My script uses an extremely naive approach and simply splits the domain at the dot. I think this might not matter, but I haven’t tested further because I don’t own any domains with multipart TLDs.
  • None of the API calls are paginated. This means the script only works on accounts with up to 20 domains. I own less than 20 domains, so this is not an issue for me. Also, the methods that require pagination are currently unused in the main function.
  • No error checking or handling was implemented. Theoretically, the script could fail if the domain is expired or locked, but I trust myself to keep all my domains valid and registered.
  • API username, key, etc. are hardcoded instead of being read from some external file. This script was written for my personal use, so I didn’t bother going further.

Logic

The pseudocode for this script is as follows:

  1. Get CERTBOT_DOMAIN from Certbot.
  2. Get the host records for this domain.
  3. Get the CERTBOT_VALIDATION code.
  4. Create a TXT host record using this challenge code.
  5. Add this host record to the existing host records.
  6. Upload the host records back to Namecheap.

The source code can be examined at https://github.com/trwnh/namecheap/blob/master/auth – I made sure to leave docstrings and use clear function names, so hopefully this is good, readable code.

The result

It works! Now, I can automate my certificate renewals instead of doing it all manually every three months. Maybe one day, I’ll even write a cleanup script to delete the TXT challenge records… :)