Multi-Level Wildcard Domain Authentications

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: jeffsani.com

I ran this command:
certbot certonly --preferred-challenges dns-01 --manual --manual-auth-hook {INSTALL_PATH}/automation/authenticators/godaddy_authenticator_1.0.sh --manual-cleanup-hook {INSTALL_PATH}/automation/authenticators/godaddy_cleanup_1.0.sh -d "*.${domain}" -d "$domain" --server $ACME_SERVER --email $EMAIL_ADDRESS --manual-public-ip-logging-ok

It produced this output:

Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for jeffsani.com
dns-01 challenge for jeffsani.com

My web server is (include version):
None

The operating system my web server runs on is (include version):

Ubuntu 18.04

My hosting provider, if applicable, is:

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):
certbot 0.31.0

In order for wildcard certificates to be valid for both *.domain.com and domain.com, you have to specify both host options with the -d parameter when running certbot. However, this results in authentication being done twice for the same domain. Is there any way to produce a wild card certificate that is valid for any host as well as the 2nd level domain which avoids having to authenticate twice?

2 Likes

Unfortunately, no. The apex domain name and the first-level wildcard each result in a dns-01 challenge (_acme-challenge.jeffsani.com). Are you running into trouble with having the two validations?

As a technical hint, you can "cheat the system" by running certbot once and fulfilling only one dns-01 challenge then running certbot again and fulfilling the remaining dns-01 challenge. This is due to the fact that successful authorizations for challenges are cached for 30 days. If you ran certbot a third time (after successfully fulfilling both dns-01 challenges), you would not need to fulfill any challenges at all (automatic certification)!

By the by, your version of certbot is rather old (0.31.0 vs 1.8.0). If you wish to upgrade, you may need to use snap to install that latest version.

3 Likes

If your GoDaddy authenticator is written in the correct way, having double authentication on the same domain doesn't matter.

The pitfall is in the PUT /v1/domains/{domain}/records/{type}/{name} API:

Replace all DNS Records for the specified Domain with the specified Type and Name

If you use this, you need to include all of the existing records, as well as your new record, in the PUT request. That way, each invocation of your authenticator script doesn't end up wiping out the actions of the previous one.

You can check how the acme.sh GoDaddy authenticator is written for guidance.

4 Likes

I want to wipe it out though. If I do not then, the authentication fails right? Regardless of what is happening in the script, there seems to be no way to control Certbot so that if the *.domain.com and the domain.com are equal, it should not do a second authentication. In this scenario, the domains that are passed to the authentication script are identical.

1 Like

For Authentication I use:

curl -s -X PATCH "{GODADDY_URL}/v1/domains/{CERTBOT_DOMAIN}/records" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: sso-key {GODADDY_API_KEY}:{GODADDY_API_SECRET}" -d "[{ "data": "{DNS_REC_DATA}\", \"name\": \"{DNS_REC_NAME}", "ttl": ${DNS_REC_TTL}, "type": "TXT" }]"

For Cleanup:

curl -s -X PUT "{GODADDY_URL}/v1/domains/{CERTBOT_DOMAIN}/records/TXT/{DNS_REC_NAME}" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: sso-key {GODADDY_API_KEY}:{GODADDY_API_SECRET}" -d "[{ \"data\": \"{DNS_REC_DATA}", "name": "{DNS_REC_NAME}\", \"ttl\": {DNS_REC_TTL} }]"

1 Like

That's not certbot. That's the Let's Encrypt CA and the ACME protocol. If you want to see the http responses in action from Let's Encrypt for dns-01 challenges, I currently have my Open ACME website client in "debug mode" at openacme.org. You can submit a valid CSR and see the magic unfold to get an :eye: on things.

3 Likes

The authentication will succeed as long as any one of the records matches.

From the perspective of Let's Encrypt and the ACME protocol it uses, it has to authenticate example.com and *.example.com separately.

It just so happens that for both identifiers, it wants you to perform that authentication by demonstrating proof using _acme-challenge.example.com.

That's why Certbot ends up calling your script with the same domain twice.

There is something about GoDaddy's PATCH API which makes it do the wrong thing in the presence of multiple TXT records. This is why pretty much all authenticators use the PUT API instead.

I don't remember what the reason is. Give me a little while to try it out.

3 Likes

@_az

Easily circumvented with a kludge... :upside_down_face:

2 Likes

GoDaddy's API doesn't really have a concept of different records with the same name and type. So multiple A (or TXT) records is represented as a single record with multiple values in the data property of the object.

So when you PATCH against domains/{domain}/records with your single valued TXT record, you're overwriting any other values that already exist for that name in the zone. It's the same thing if you PUT against domains/{domain}/records/TXT/{name}.

Like @_az said, you need to query for existing values first and add to the record if it already exists and PATCH or PUT back the whole record with the multiple values. Similarly on delete, you should do the same thing and only remove the value you're trying to remove rather than the whole record unless it's the only value left.

4 Likes

But that would generate 2 certs and not one right? At the end of the day, I need a single certificate that is valid for both *.domain.com and domain.com.

1 Like

The idea in the kludge is that Let's Encrypt remembers your successful authorizations, so you repeatedly run Certbot, solving 1 authorization at a time.

The first time you run Certbot, you get 2 authorizations to complete. You complete the second one, but fail the first one. (Because of the behavior of PATCH).

The next time you run Certbot, you only get 1 authorization, because you already completed the other one.

All of a sudden, you have no authorizations left to complete, and you get your 1 certificate.

Not that I endorse doing it :stuck_out_tongue: . It also might not work, it could rely on a specific order of operations.

3 Likes

:smiling_imp:

But the quicksand is so soft...

@jeffsani

For the time being, it works. I don't know if it's spec though, so it could change (as could anything though).

2 Likes

Just a somewhat related note, if you ever check certificate transparency records and see pairs of identical certificates listed back-to-back, the older/bottom is a precertificate and the newer/top is the actual certificate.

As seen here:

2 Likes

LOL. Hmm I will try this. I suppose I could just use PUT and then have some other manual process to deal with stale records cleanup.

2 Likes

Or just PUT nothing afterwards?

1 Like

Yeah those are all the old HTTP based validated ones.

2 Likes

A lot of people ask why they have "duplicates". :slightly_smiling_face:
Didn't want you to become one of them, especially with your endeavor.

This is the magic:

CT Precertificate Poison: critical

2 Likes

Strange, I updated certbot as per your suggestion with snap and then rebooted but it is still showing the old version:
root@certbot:/etc/letsencrypt/automation# snap install certbot
error: This revision of snap "certbot" was published using classic confinement and thus may perform
arbitrary system changes outside of the security sandbox that snaps are usually confined to,
which may put your system at risk.

   If you understand and want to proceed repeat the command including --classic.

root@certbot:/etc/letsencrypt/automation# snap install certbot --classic
certbot 1.8.0 from Certbot Project (certbot-eff✓) installed
root@certbot:/etc/letsencrypt/automation# certbot --version
certbot 0.31.0

1 Like

which certbot

You need to heed step 3 well... :slightly_smiling_face:

  1. Remove any Certbot OS packages

If you have any Certbot packages installed using an OS package manager like apt, dnf, or yum, you should remove them before installing the Certbot snap to ensure that when you run the command certbot the snap is used rather than the installation from your OS package manager. The exact command to do this depends on your OS, but common examples are sudo apt-get remove certbot, sudo dnf remove certbot, or sudo yum remove certbot.

https://certbot.eff.org/lets-encrypt/ubuntubionic-other

2 Likes

Crap - Sorry RTFM. Thanks I will try removing it.

3 Likes