Automate New Cert Request w/Crypt::LE on IIS DNS challenge


#1

I’m trying to automate cert requests for new website customers of ours who have not yet pointed their DNS to us. Our software requires HTTPS to be turned on the moment a new website is created, so http challenge is not an option for the original cert request since new customers are not pointed to us. DNS challenge is what we’re hoping to use, but the TXT DNS record generated does not appear to persist when I run the script again later or just try to complete the verification later. We will need to generate the DNS TXT verification entry, send it to our new customer, and then wait for them to get it created. This can sometimes take days.

Ideal Process:

  1. We run a script that takes a domain as input & requests a new cert from LE
  2. We get back a TXT entry that we send to the customer
  3. Once that entry is created, we complete the DNS verification step & get our cert

Is this possible with Crypt-LE? @leader

How long are those DNS TXT entries valid?

My domain is: test.madbray.com

Client: Crypt::LE (le64.exe on Windows) https://github.com/do-know/Crypt-LE

I ran this command:

le64.exe --key test.madbray.com\acco
unt.key --csr test.madbray.com\test_madbray_com_csr.csr --csr-key test.madbray.c
om\test_madbray_com_priv.crt --crt test.madbray.com\test_madbray_com.crt --domai
ns test.madbray.com --handle-as dns --generate-missing --live

It produced this output:

2018/10/30 15:00:27 [ ZeroSSL Crypt::LE client v0.31 started. ]
2018/10/30 15:00:27 Loading an account key from test.madbray.com\account.key
2018/10/30 15:00:27 Loading a CSR from test.madbray.com\test_madbray_com_csr.csr

2018/10/30 15:00:28 Registering the account key
2018/10/30 15:00:28 The key is already registered. ID: 34310605
2018/10/30 15:00:28 Current contact details: redactd@madbray.com
Challenge for 'test.madbray.com' requires the following DNS record to be created
:
Host: _acme-challenge.test.madbray.com, type: TXT, value: ibrwvLeJsCM8pPwXyEwJRB
_5UXsDg_wAUa7Z9mBt9IY
Wait for DNS to update by checking it with the command: nslookup -q=TXT _acme-ch
allenge.test.madbray.com
When you see a text record returned, press <Enter>

Here is where I simulated a customer taking a day to get the DNS entry in place (I actually left the script open for a day just to test). I put the requested TXT entry in place on my active DNS servers, then hit Enter:

2018/10/31 10:30:50 Processing the 'dns' verification for 'test.madbray.com'
2018/10/31 10:30:50 Domain verification results for 'test.madbray.com': error. J
WS has invalid anti-replay nonce POVfkWIRpRIJDBUsy0SOILcWrUSIz6CYGNxXokGHbEU
2018/10/31 10:30:50 You can now delete '_acme-challenge.test.madbray.com' DNS re
cord
2018/10/31 10:30:50 All verifications failed

My web server is (include version): IIS 6 & 7

The operating system my web server runs on is (include version): Windows Server 2008 R2 (and Serve 2003 R2)

My hosting provider, if applicable, is: n/a - we are a hosting company

I can login to a root shell on my machine (yes or no, or I don’t know): Yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel): No


#2

This host TXT record is not found.
Have you since deleted it?
Can you create a test TXT record for _acme-challenge.test.madbray.com?


#3

I show it does still exist:

https://www.whatsmydns.net/#TXT/_acme-challenge.test.madbray.com


#4

OK, I must have fat fingered it…
I do see the test shown:

returns:
“ibrwvLeJsCM8pPwXyEwJRB_5UXsDg_wAUa7Z9mBt9IY”

I just wonder if perhaps you did not wait long enough for it to sync…

But I see you said you waited one day, so the problem must be elsewhere.
Let me check something else…

Other than lack of DNS site diversity (single AS) and only two IPv4 nameservers (none using IPv6), I don’t really see a problem.
Maybe there is some disconnect between LE and those two DNS servers…
Can you test from another domain that uses other DNS servers?
Can you add more DNS servers from other locations?


#5

I just looked back through my test logs again, and I see when I ran the same command again today that it did indeed send me the same DNS TXT entry to use for verification. And it completed successfully that time.

When I saw this line, it made me think the DNS TXT entry I was initially given had expired, but maybe that’s not the case:

2018/10/31 10:30:50 Domain verification results for 'test.madbray.com': error. J
WS has invalid anti-replay nonce POVfkWIRpRIJDBUsy0SOILcWrUSIz6CYGNxXokGHbEU

I guess my question is: Is this feasible (to wait days for the customer to setup the DNS), then go back & run the same command again and let it verify?


#6

That is a good question that I don’t have the answer to.
Maybe someone else that’s on now can assist with an answer… @Osiris @stevenzhu


#7

Hi,

Generally speaking, it’s fine to wait a few days for the customer to setup his DNS records.

However, the issue is not “record does not exist”…
The last line of the error you supplied clearly states the issue: anti-replay token expired.

Since I have little knowledge on this… Quoting from an older post (responsed by other user)

In conclusion, (technically) you should be able to wait a few hours / days before proceed on validation, but due to Boulder’s settings, it’s better to proceed validation as soon as the records are ready.

Thank you


#8

Thanks @rg305 & @stevenzhu

Is the nonce the same thing as the “value” of the TXT DNS record? We are proceeding with testing, so I’m trying to get as much info as possible so we can better rely on this in production.

Anyone who can point me in the right direction? I would much appreciate it!


#9

Hi @bradpcmac,

I would request to your customer to create a CNAME record pointing to a domain that you control so you can update the txt record in the domain you control to issue a certificate.

Example:

Your customer domain is customer.tld
Your domain (you control the DNS of this domain): bradpcmac.tld

So you ask to your customer to create a CNAME record pointing to a subdomain controlled by you (for example customer.tld.bradpcmac.tld):

_acme-challenge.customer.tld. IN CNAME customer.tld.bradpcmac.tld

Once the customer confirms that they have added the CNAME record in their DNS servers you can proceed to issue a new certificate and when you get the token you only need to add it as a TXT record in the subdomain you control customer.tld.bradpcmac.tld

customer.tld.bradpcmac.tld. IN TXT herethetoken

Then Let’s Encrypt will try to validate the token and when it goes to _acme-challenge.customer.tld it follows the cname till your subdomain customer.tld.bradpcmac.tld that already has the TXT record with the right token to validate the domain.

I hope it is clear.

Cheers,
sahsanu


#10

No.
(Correct me if I’m wrong)
The nonce is a value / variable used in Boulder’s validation, (however I’m not sure what is the use of it) it is different from txt record and (seems) will affect order operations…

Pinging @cpu or @schoen for more information…

Thank you


#11

Both @sahsanu and @stevenzhu are correct here.

The challenge token that you are asked to put in the TXT record is valid for 7 days. However, some customers might take longer than 7 days to do it. So having them set up the CNAME lets you wait until they are ready, and do the whole challenge process all in one go. This will generally be more reliable.


#12

No, the anti-replay nonces are completely separate. It’s just a nonce sent by the server to the client in an HTTP header, which the client subsequently sends back.

They expire on a somewhat short timescale, and can be invalid for other reasons – often because the client’s IP address changes and the next request is routed to a different data center.

When an ACME client gets a bad nonce error, it can retry with a new one. (The error response includes one, or it can send a different request to retrieve another.)

Modifying the client to automatically retry would solve the nonce issue, but can’t do anything about the pending authorization’s 7 day expiry period.

(The nonces exist to prevent an HTTPS MITM – such as a corporate middlebox, or the CDN Let’s Encrypt uses – from replaying requests and making mischief.)


#13

Sorry for the delay with this, being a bit under the weather I might have missed a few mails/notifications recently. On the subject here, the advice given above in the thread is the good one. As for the replay, normally the delay is reasonably short, so that should not be happening, but I will check the nonce-related code to ensure that nonce gets reloaded before you continue with the process after a long wait.


#14

The scenario of a long wait between the challenge request and the verification step, which could trigger the nonce error, has actually been covered in the web client of ZeroSSL long time ago. Now it should also be covered in v0.32 of the Perl client (binaries and the Docker image are yet to be updated).

On the topic of automation, I have updated the code and also added an example of how the process can be automated, see https://github.com/do-know/Crypt-LE/blob/master/Plugins/DNS.pm. Effectively all the necessary information (such as command line parameters passed to the client, challenge requirements and results) is available to the plugin code. You can then run whatever process you need - for example call dnscmd with the appropriate parameters. Once binaries are updated (either later today or tomorrow), you should be able to use such plugin by simply pointing to it like this:

le64.exe -key account.key -domains test.com -csr test.csr -csr-key test.key -crt test.crt -generate-missing -handle-with DNS.pm -handle-as dns -api 2

NB: There is NO NEED to install Perl or anything - having the binary file and the plugin file is sufficient.

Additionally, a “-delayed” mode [experimental] flag has been added. It forces the process to stop once the challenge has been received (and data about it printed or processed). When the process then started again, with the same parameters but without -delayed flag, it should continue as normal. This can be useful if you expect a long delay between the DNS update attempt and when it is going to get actually reflected for example. This might be useful in your scenario as well - run the command with -delayed flag first, send an email (or take some other action), once it is confirmed that the record is set, re-run without the flag.


#15

Thank you for this @leader ! I have been able to move forward with setting this up.