1

When updating a wildcard-letsencrypt-certificate you're being asked to deploy a DNS TXT record with some sort of hash-value before continuing with the verification.

Like this:

Please deploy a DNS TXT record under the name
_acme-challenge.my-domain.com with the following value:

fsLb985adfK4wO1jdawkawgk-4QPTTE3k8x110

Before continuing, verify the record is deployed.

Usually i change the entry by hand but i tried to automate it... so i wrote a bash script which first starts certbot - pipes the output in to a tmpfile - cuts the needed hash out of the file - safes it as a variable - then passes the variable to a python script, which then updates my bind zonefile.

Somewhat like this:

certbot -d *.my-domain.com --server https://acme-v02.api.letsencrypt.org/directory --manual --manual-public-ip-logging-ok --preferred-challenges dns certonly > /tmpfile

keystring=$(grep -A 2 '_acme-challenge.my-domain.com with the following value:' /tmpfile | cut -d':' -f2-)

python update-bind-my-domain-wildcard.py $keystring

It works... but not as i expected... if i look up the acme-challange entry with dig i can see the modified TXT record - but hence i first start the certbot and update my zone file with dnspython afterwards - the verification process of letsencrpyt fails.

Dig request (@localhost and @1.1.1.1):

;; ANSWER SECTION:
_acme-challenge.my-domain.com. 300 IN  TXT     "fsLb985adfK4wO1jdawkawgk-4QPTTE3k8x110"

Letsencrypt verification failure:

Waiting for verification...
Cleaning up challenges
Failed authorization procedure. my-domain.com (dns-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Incorrect TXT record "o7dawgrh3234jTcB9YH-lbI-dEYfdawfFWsRoY" found at _acme-challenge.my-domain.com

...where the "o7dawgrh323xxx"-entry is the old (before running the renewal) DNS TXT value...

So my question is if there is a possibility to skip the initial verification and do some sort of a "certbot verification only" after my dns update went through? Or is there a possibility to break out of the certbot renewal, work off the rest of the script first, and come back to the first verification after the rest of the script passed through? Or maybe an even better/simpler way i haven't thought off?

Thanks in advance

C333D

Greg Askew
  • 35,880
  • 5
  • 54
  • 82
C333D
  • 11
  • 1
  • 2
  • Is there a reason why you cannot use one of the normal certbot plugins for DNS-01, as in eg https://serverfault.com/a/989069/183318 ? – Håkan Lindqvist Sep 14 '20 at 13:46
  • (Or possibly add your own such plugin) – Håkan Lindqvist Sep 14 '20 at 13:49
  • Thanks man - There might be also a few obstacles but it nevertheless seems like a good idea to implement my own plugin - i'll give it a try! – C333D Sep 14 '20 at 14:22
  • The existing rfc2136 plugin would be the obvious choice for the typical scenario with BIND (provided that you allow dynamic updates, which is a way BIND and other common nameserver software allows for doing programmatic updates to zone data). I don't know if there is something special going on in your case that prevents the use of that, but I do think that using the certbot DNS plugin interface would be preferable even if you were to roll your own. – Håkan Lindqvist Sep 14 '20 at 14:34
  • (If you have other things that rely on a directly editable zone file for instance, that would pose a problem.) – Håkan Lindqvist Sep 14 '20 at 14:37
  • Hey Håkan - thank you so much! Switched to dns-rfc2136 and i think it's working perfectly (sadly is the cert is not due for renewal yet - but at least the dry-run accepts the credentials for dnspython and went through successfully) I'll keep y'all updated and I really appreciated your help! – C333D Sep 15 '20 at 11:16

1 Answers1

2

While not a direct answer to the question, I think a better solution was reached in the discussion of the question.

Let's Encrypt as a whole is centered around automation and certbot has built-in facilities for this.
The intended way of automating certbot DNS-01 validation is to use their plugin interface.

certbot also ships with a number of ready-to-use plugins for various types of DNS services:

  • certbot-dns-cloudflare
  • certbot-dns-cloudxns
  • certbot-dns-digitalocean
  • certbot-dns-dnsimple
  • certbot-dns-dnsmadeeasy
  • certbot-dns-google
  • certbot-dns-linode
  • certbot-dns-luadns
  • certbot-dns-nsone
  • certbot-dns-ovh
  • certbot-dns-rfc2136
  • certbot-dns-route53

Where the certbot-dns-rfc2136 plugin is suitable for use with common on-premise nameservers that support RFC2136 dynamic updates, including BIND.

An example command could look like this:

certbot certonly \
  --dns-rfc2136 \
  --dns-rfc2136-credentials ~/.secrets/certbot/rfc2136.ini \
  -d example.com

Where the ~/.secrets/certbot/rfc2136.ini file specifies the credentials, like this:

dns_rfc2136_server = 192.0.2.1
dns_rfc2136_port = 53
dns_rfc2136_name = letsencrypt-example.
dns_rfc2136_secret = XNinzY9ff5u01DSgM+a34TXHM6D4DSLCdjFyp98NFVA=
dns_rfc2136_algorithm = HMAC-SHA256

(You would obviously generate your own TSIG key, using eg tsig-keygen example-key.)

Håkan Lindqvist
  • 35,011
  • 5
  • 69
  • 94