Netflix / lemur

Repository for the Lemur Certificate Manager
Apache License 2.0
1.71k stars 322 forks source link

Mix and match Acme challenges #3177

Open peschmae opened 3 years ago

peschmae commented 3 years ago

As posted by @hosseinsh

Today, I learned about an important edge case that the current two plugin design doesn't support, namely, a SAN certificate request that requires mixing the validation methods. For instance, a wildcard SAN which would require DNS validation. I am still figuring out if ACME, this case Let's Encrypt, supports this use-case (url). My initial intuition is this should be supported since, for each domain, all types of validations are returned in the Authorization object. It certainly gets more tricky with how to decide on the validation method per domain. I need to do more thinking about this, but one idea could be to differentiate based on the presence of wildcard domain. For instance, in a plugin design, we would branch off to http-01 validation, unless a wildcard domain is present. In this case, a hybrid approach is required, during which we first answer_challenge for all non-wild-card SANs, and then trigger the normal DNS flow for the remaining DNS authorization.

To make this possible it would be necessary to use a single AcmeIssuerPlugin which can handle all types of challenge, depending on what is offered by the Acme provider, and what is configured in Lemur.

Right now the proposed implementation in #3167 creates a new IssuerPlugin which only handles http challenges, but after the refactoring is done, it should be relatively easy to convert it into a single AcmeIssuerPlugin, which can handle both dns and http challenges.

To allow mix and matching challenges, we need a way to find the dns authority, and if none exist, the relevant destination. Therefore it might make sense, to have the destination mapping on the domain, and no longer on the authority, but this would mean, you either need to preconfigure the domains, or add the destination after creating the certificate. It would also require some kind of deduplication on the domains, because right now a domain exists multiple times, once for each certificate.

peschmae commented 3 years ago

I'll try to create an example as a basis for discussion which forces a mix and match, and try to demonstrate what I think would be a good way to handle it

The only configured dns provider is for the san.example.biz zone.

Certificate: san.example.biz

Offered challenges (I'll ignore TLS since they are very uncommon)

san.example.biz

domain/challenge mapping

san.example.biz -> can be answered using DNS -> prefer DNS *.san.example.biz -> only DNS available -> DNS second-sub.example.biz -> no DNS provider available -> must use HTTP


The domain/dns-provider mapping can be done easily, that is already implemented, but now we would need a way to get the destination to use for second-sub.example.biz.

It would also require to refactor the http challenge, into a celery task, or at least the order finalisation in cases where there are different challenge types used. (Which means, implementing pending_certificates for http challenge, as I avoided them until now)

peschmae commented 3 years ago

While refactoring #3167 I realized that when you get the challenges the first time around, some of them could already be in the state 'valid/ready' since the ACME provider can cache the validation per account.

I think it might make sense, to check for that before starting the handle any domain validation tasks, and only do the domain validation where needed.

peschmae commented 3 years ago

While refactoring #3167 I realized that when you get the challenges the first time around, some of them could already be in the state 'valid/ready' since the ACME provider can cache the validation per account.

I think it might make sense, to check for that before starting the handle any domain validation tasks, and only do the domain validation where needed.

This is now done in the HTTP-01 challenge, but would need to be adapted to the DNS challenge as well.