DNSMadeEasy automatic cert generation returns 400

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. https://crt.sh/?q=example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is: cominor.com

I ran this command:
docker run -it --rm --name certbot -v /etc/letsencrypt:/etc/letsencrypt -v /var/lib/letsencrypt:/var/lib/letsencrypt -v /var/log/letsencrypt:/var/log/letsencrypt -v /var/ifixit/dns/:/var/ifixit/dns/ certbot/dns-dnsmadeeasy certonly --agree-tos --dns-dnsmadeeasy --dns-dnsmadeeasy-credentials /var/ifixit/dns/dnsmadeeasy.ini --dns-dnsmadeeasy-propagation-seconds 120 --email devs@ifixit.com --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges=dns-01 -d ‘.cominor.com’ -d '.djmetzle.cominor.com’ <… approximately 3 dozen more subdomains>

It produced this output:

aving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-dnsmadeeasy, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for cominor.com
dns-01 challenge for djmetzle.cominor.com
<… approximately 3 dozen more subdomains>
Unsafe permissions on credentials configuration file: /var/ifixit/dns/dnsmadeeasy.ini
Cleaning up challenges
Error determining zone identifier: 400 Client Error: Bad Request for url: https://api.dnsmadeeasy.com/V2.0/dns/managed/name?domainname=djmetzle.cominor.com.

My web server is (include version):

The operating system my web server runs on is (include version): Fedora, then docker. Same problem.

My hosting provider, if applicable, is: AWS

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

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot):
Local: certbot 0.31.0
Docker: certbot 0.38.0


I believe that DNSMadeEasy may have changed their API?

It works for me. Can you try invoke Lexicon directly on the domain that is experiencing the issue?

docker run -it --rm --entrypoint '/usr/local/bin/lexicon' \
certbot/dns-dnsmadeeasy dnsmadeeasy \
--auth-username=API_TOKEN --auth-token=API_SECRET \
list example.org A

Making sure to substitute API_TOKEN, API_SECRET and example.org.

Did you try the zone apex or a subdomain?

Both work for me, though I’m using https://api.sandbox.dnsmadeeasy.com/V2.0 and not https://api.dnsmadeeasy.com/V2.0.

I suppose it’s possible they broke production and not the sandbox … but I’d expect that someone else should have complained by now.

2 Likes

I ran the list command successfully.

ID TYPE NAME CONTENT TTL


23501775 A .cominor.com 50.18.174.128 86400

It’s worth noting that the first portion of the process seems be working just fine. The TXT records for the various challenges are created just fine, and are visible on the DME dashboard, almost instantly.

It then hangs for a good amount of time (a minute or two?) on

Cleaning up challenges

before returning:

Error determining zone identifier: 400 Client Error: Bad Request for url:

My letsencrypt.log contains:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/usr/local/bin/certbot”, line 11, in
load_entry_point(‘certbot’, ‘console_scripts’, ‘certbot’)()
File “/opt/certbot/src/certbot/main.py”, line 1378, in main
return config.func(config, plugins)
File “/opt/certbot/src/certbot/main.py”, line 1265, in certonly
lineage = _get_and_save_cert(le_client, config, domains, certname, lineage)
File “/opt/certbot/src/certbot/main.py”, line 121, in _get_and_save_cert
lineage = le_client.obtain_and_enroll_certificate(domains, certname)
File “/opt/certbot/src/certbot/client.py”, line 405, in obtain_and_enroll_certificate
cert, chain, key, _ = self.obtain_certificate(domains)
File “/opt/certbot/src/certbot/client.py”, line 348, in obtain_certificate
orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
File “/opt/certbot/src/certbot/client.py”, line 384, in _get_order_and_authorizations
authzr = self.auth_handler.handle_authorizations(orderr, best_effort)
File “/opt/certbot/src/certbot/auth_handler.py”, line 69, in handle_authorizations
resps = self.auth.perform(achalls)
File “/opt/certbot/src/certbot/plugins/dns_common.py”, line 58, in perform
self._perform(domain, validation_domain_name, validation)
File “/opt/certbot/src/certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy/dns_dnsmadeeasy.py”, line 55, in _perform
self._get_dnsmadeeasy_client().add_txt_record(domain, validation_name, validation)
File “/opt/certbot/src/certbot/plugins/dns_common_lexicon.py”, line 40, in add_txt_record
self._find_domain_id(domain)
File “/opt/certbot/src/certbot/plugins/dns_common_lexicon.py”, line 95, in _find_domain_id
raise result
certbot.errors.PluginError: Error determining zone identifier: 400 Client Error: Bad Request for url: https://api.dnsmadeeasy.com/V2.0/dns/managed/name?domainname=agilbert.cominor.com.

If it is happening only during the cleanup phase, it cannot be an API change. That /name?domainname= call is used during the authentication phase as well, which shows that it works at least some of the time.

Could you post the /var/log/letsencrypt.org related to one of these runs, so we can see the timings of the API calls?

Some potential ideas:

  • Rate limiting (maybe they produce HTTP 400 instead of 429). Cleanup might set off a very rapid iteration of calls if you have a lot of subdomains.
  • If a network connection is hanging, the HMAC request date and signature might be considered invalid by the time it arrives at DNSMadeEasy’s server. In particular, you are on AWS, where everything is in a “NAT” that aggressively kills idle connections. Certbot might be trying to re-use an idle connection to DME that it doesn’t realize is dead.

If you’re feeling particularly adventurous, you could modify your Python package (lexicon/providers/dnsmadeeasy.py), adding

print(response.text)

right above:

response.raise_for_status()

And you could also ask DNSMadeEasy’s support what the 400 is about, though I’m not sure how responsive they are.

This is the cause. I've created an issue for it.

1 Like

That sounds like the problem! Yeah!

I just checked and we’re actually trying to sign 56 domains. So just a guess, it must be doing 3 API calls to crack the default 150/5mins rate limit? Ref: https://api-docs.dnsmadeeasy.com/?version=latest

I just gave it a try trimming down the number of domains, and this works fine.

I’ll keep an eye on the new Github issue! The error message was not useful here. We could provide a more useful error, or warn when providing 50+ domains. Now that we know the actual problem (the DNE rate limit) this thread could be resolved/closed.

Thank you very much @_az!

Can’t hurt to ask - is there a reason you can’t drastically reduce the number of domains with a wildcard? Or do you have a bunch of multi-label a.b.c.d.example.com domains?

Edit: nevermind, I see you are heavily using wildcards already :laughing: : .

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.