{"id":273,"date":"2021-04-21T23:50:39","date_gmt":"2021-04-21T22:50:39","guid":{"rendered":"https:\/\/simon.aldrich.cc\/blog\/?p=273"},"modified":"2021-04-21T23:50:39","modified_gmt":"2021-04-21T22:50:39","slug":"automating-lets-encrypt-wildcard-certificates-with-the-namecheap-api","status":"publish","type":"post","link":"https:\/\/simon.aldrich.cc\/blog\/2021\/04\/automating-lets-encrypt-wildcard-certificates-with-the-namecheap-api\/","title":{"rendered":"Automating Let&#8217;s Encrypt Wildcard Certificates with the Namecheap API"},"content":{"rendered":"\n<p>I&#8217;m a big fan of <a rel=\"noreferrer noopener\" href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\">Let&#8217;s Encrypt<\/a> but when I recently found out about TLS <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Certificate_Transparency#Certificate_Transparency_logs\" target=\"_blank\">Certificate Transparency Logs<\/a> and how easy they made <a rel=\"noreferrer noopener\" href=\"https:\/\/crt.sh\/\" target=\"_blank\">searching<\/a> for otherwise unpublished subdomains, I decided that it might be a good idea to look into using wildcard TLS certificates.<\/p>\n\n\n\n<p>A minor complication was that to validate a wildcard certificate Let&#8217;s Encrypt needs to create a TXT DNS record for your domain with a validation code. This is known as the <a rel=\"noreferrer noopener\" href=\"https:\/\/letsencrypt.org\/docs\/challenge-types\/#dns-01-challenge\" target=\"_blank\">DNS-01 challenge<\/a>. I happen to use <a rel=\"noreferrer noopener\" href=\"https:\/\/www.namecheap.com\/\" target=\"_blank\">Namecheap<\/a> as the registrar for most of my domains and luckily there is a Python <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/Bemmu\/PyNamecheap\" target=\"_blank\">library<\/a> to access their API and automatically create this DNS record.<\/p>\n\n\n\n<p>I&#8217;ve written a quick Python <a href=\"https:\/\/simon.aldrich.cc\/download\/letsencrypt-namecheap\/letsencrypt-namecheap-dns01-manual-auth-hook.py\">script<\/a> which works as a <a rel=\"noreferrer noopener\" href=\"https:\/\/certbot.eff.org\/docs\/using.html#hooks\" target=\"_blank\">manual authentication hook<\/a> for Let&#8217;s Encrypt&#8217;s <a rel=\"noreferrer noopener\" href=\"https:\/\/certbot.eff.org\/\" target=\"_blank\">certbot<\/a> and helps to automate the process of issuing \/ renewing a certificate using the DNS-01 challenge.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Usage:<\/h2>\n\n\n<ol>\n<li>Obtain API credentials for Namecheap as detailed <a href=\"https:\/\/github.com\/Bemmu\/PyNamecheap#how-to-sign-up-to-start-using-the-api\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a><\/li>\n<li>Download the <a href=\"https:\/\/simon.aldrich.cc\/download\/letsencrypt-namecheap\/letsencrypt-namecheap-dns01-manual-auth-hook.py\" target=\"_blank\" rel=\"noreferrer noopener\">script<\/a> and edit to add the API credentials to the appropriate variables<br data-rich-text-line-break=\"true\" \/><strong>N.B. <\/strong>Bad Things could happen if these credentials become public, please take appropriate precautions to keep them secure.<\/li>\n<li>To issue \/ renew a wildcard certificate for your domain run certbot something like this:\n<pre><code data-rich-text-format-boundary=\"true\">sudo certbot certonly \\<br \/> --non-interactive \\<br \/> --manual \\<br \/> --manual-public-ip-logging-ok \\<br \/> -d &lt;*.domain&gt; \\<br \/> --email &lt;email@address&gt; \\<br \/> --manual-auth-hook &lt;path\/to\/the\/script&gt;<\/code><\/pre>\n<\/li>\n<\/ol>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m a big fan of Let&#8217;s Encrypt but when I recently found out about TLS Certificate Transparency Logs and how easy they made searching for otherwise unpublished subdomains, I decided that it might be a good idea to look into using wildcard TLS certificates. A minor complication was that to validate a wildcard certificate Let&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[7,5,6,28],"tags":[72,71,66,67,46,70,69,68],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2Rw4E-4p","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/posts\/273"}],"collection":[{"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/comments?post=273"}],"version-history":[{"count":3,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/posts\/273\/revisions"}],"predecessor-version":[{"id":276,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/posts\/273\/revisions\/276"}],"wp:attachment":[{"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/media?parent=273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/categories?post=273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/simon.aldrich.cc\/blog\/wp-json\/wp\/v2\/tags?post=273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}