Challenge type stability

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:
danmacdonald3.sigmanetcorp.us

I ran this command:
I'm not using certbot, I am testing out an in-house Java application I'm building that uses https://github.com/shred/acme4j to communicate to Let's Encrypt's staging environment 'acme://letsencrypt.org/staging'. I have a question about the stability of the challenge for a domain. Our use case is pretty similar to certBot in that we request challenge types, then show the DNS challenge TXT name and value to our users and ask them to add the record to their DNS provider. They may take some time, several days possibly, to add their DNS TXT record and then come back to us to 'verify'. In this 'veriy' stage, we'll query DNS and make sure they added the expected TXT record with the correct value. Then we'll start a new Session with the ACME server, request Authorizations and choose DNS. We'll verify that the ACME server has sent the same DNS challenge information and then trigger the challenge.

My question is: How long does the user have to add the DNS TXT record and us trigger the challenge? In other words, how long can we count on the ACME server to return the exact same DNS challenge data for a domain?

It produced this output:

My web server is (include version):

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

My hosting provider, if applicable, is:

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

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

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot):

In ACME, pending orders are guaranteed to have an expires field.

So, assuming you store and reuse the order URL, you have a reasonable idea for how long you have until you have to create a new order (and authorization), resulting in a new DNS TXT record.

expires (optional, string): The timestamp after which the server
will consider this order invalid, encoded in the format specified
in [RFC3339]. This field is REQUIRED for objects with "pending"
or "valid" in the status field.

That said ...

This doesn't sound like a flow which supports automatic renewal. The user would have to update the TXT record every 60-90 days.

Depending on what you're doing, why not ask the user to either:

  1. Set up a permanent CNAME from _acme-challenge.example.com to example.com.acme-validation.your-java-app.com. That way, you can update the DNS TXT record whenever you want and no further human interaction is required.
  2. Point their domain at your server and use HTTP validation? Not suitable if you need a wildcard or for non-HTTP protocols perhaps, but definitely the simplest option otherwise.
1 Like

Thanks. About the suitability for automatic renewal. We would like to start with DNS challenge, have the user add the TXT and CNAME both, then switch to HTTP challenge for the renewals. This is because our architecture would initially block the HTTP challenge. After completing the DNS challenge and installing the certificate, the HTTP challenge would be possible, and not require user intervention, so we plan to switch to HTTP for the renewals.

About the storage and re-use of the Order URL. I've not been doing that. Instead, I've been creating a new Order for the account but I have been getting the same DNS challenge for the same domain.

Order order = account.newOrder().domains(domain).create();

In my testing, this is giving me the same DNS challenge. Is this the wrong way to do it?

That sounds peculiar, but okay!

Not "wrong" per-se, but the Let's Encrypt ACME server is not guaranteed to behave this way. In fact, it didn't behave this way until sometime in 2017.

If you make your client rely on this idiosyncrasy (reuse of pending authorizations in new orders), then your client risks breaking if Let's Encrypt ever change their mind about the behavior.

If you reuse your order objects, your client will be less fragile.

2 Likes

Can you provide any more information about the URL I need to save and how to use that to reuse my order object? I know Let's Encrypt doesn't specifically endorse GitHub - shred/acme4j: Java client for ACME (Let's Encrypt) but I'm not seeing an obvious way to do that with the library.

The maintainer suggests in this comment to use Login::bindOrder:

The best way to persist an object is to get its URL (via getLocation() ) and store it locally in some kind of database. When you later need to restore the object, use one of the Login::bind* methods and pass the stored URL, to retrieve a working object.

For example, to store your order for later use, use Order::getLocation , and later use Login::bindOrder to get a new Order object.

1 Like

This worked, thanks!

//orderUrl is persisted from the original thread with Order::getLocation

//later after the DNS records are added, this thread gets triggered
Login login = new AccountBuilder().useKeyPair(accountKeyPair).createLogin(session);
Order order = login.bindOrder(orderUrl);

for (Authorization auth : order.getAuthorizations()) {
//trigger the auth
}

1 Like

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