Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another use case: http-01 with remote server #189

Open
tlhackque opened this issue Mar 10, 2020 · 8 comments
Open

Another use case: http-01 with remote server #189

tlhackque opened this issue Mar 10, 2020 · 8 comments

Comments

@tlhackque
Copy link
Contributor

I've encountered another use case that mod_md needs help handling.

Consider this situation (handled by the client I'm trying to retire...):

Remote server, a VPS with a vendor who doesn't support LE, needs a certificate; updating DNS is painful as the DNS provider has no supported API. Currently, I get/renew the certificates for the remote server from one of my local machines.

The remote server has a disk area that maps to /.well-known/acme-challenge.

The current client, running locally (not on the remote server), will call-out to a script, providing the token & key authorization. The script constructs a file (named by the token) containing the key authorization. It then uses scp to place the token on disk. Validation happens. The script is called to remove the token. Certificate issued.

For mod_md to support this, it needs a call-out like MDMessageCmd that provides an action (http-01-add|http-01-remove), domain, the token and the key authorization (could be the filename in $MD_STORE/challenges) to be stored. It needs to be configured on a per MD basis. Your current handler is great for local certificates!

Ideally, the MDHttpProvider directive is compatible with MDMessageCmd - in fact, I want the same script to handle both types of events. (My message events handler already has the necessary configuration and deployment infrastructure.)

When MDHttpProvider is not configured in a domain, your handler would continue to work.
When it is configured, you will never see the GET (it goes to the remote server). But you do get the challenge (invoke and wait for the provider script), respond with the empty object. And when the status changes from "pending" to "valid" or "invalid", invoke the provider to de-provision.

Of course, I expect the MDMessageCmd handler to be called with 'installed' as usual - it knows how to get the certificate installed.

It doesn't seem like a big change - the hardest parts are finding the right places to call out, and adding to your test system...

@icing
Copy link
Owner

icing commented Mar 10, 2020

That sounds a bit like MDChallengeDns01 but for other challenge types as well. Except it would be optional.

I think we are drifting towards a more general event interface, like MDMessageCmd but for all sorts of things - including challenge setup/teardowns. This could help solving use cases of other people as well, that have distributed installations where not all domain names end up at the same host.

In Apache internals, there are hooks for callbacks and these MDEventsshould also trigger one, I guess, so one can also write modules that act on these. One of the callbacks is the md internal one that calls a configurable command with event name, domain, an environment, etc. (I think the whole httpd should have something like this, but one thing at a time...)

An MDEvent is something that is either pre or post a thing that happened. It has a variable list of named parameters and a common list of variables (for all events), the environment.

An MDEventHandler is a callback (external command or internal hook) that gets invoked for all such events. It does not have a return value. (MDChallengeDns01 has a return value. It is not an event handler but a necessary part of the ACME process.)

We send events synchronous. They are invoked just before/right after things happen. The should not block for long, else they block the mod_md watchdog jobs. But it is no harm if they take a second or two.

Which events do you want for your use case?

@tlhackque
Copy link
Contributor Author

Yes, I realized that the external http-01 events are almost the same as the Dns-01 case when I woke up!

I'll give this some more thought when I'm even more awake :-)

To start with, I think MDEvents are the current list used by MDMessageCmd and MDChallengeDns01'. Adding optional args and environ args to MDChallengeDns01 might work - 'setup and 'teardown meaning 'DNS' as now. Perhaps 'setup-http01 and 'teardown-http01` coud indicate the external http-01 case. Pass the domain name and content as for DNS - but also the token name & MD_STORE. It does need a return value - e.g. if the remote is unreachable and the token can't be placed.

Optional args would help for DNS too - for example, my DNS server uses TSIG keys, so being able to pass the filename for the key and server name to use would help...

You'll see in my current handler that one of the challenges is config data - reserving a place in the MD_STORE tree for event config would be simpler for the handler.

There might be a case for an API to store/access config - but it needs to be simple enough for a script...

One issue with passing data via args and environ variables is visiblity. E.g. the ps and --password problem.

As I mentioned elsewhere, being able to deploy on renewal would be helpful - perhaps a root thread could be kept around for notifying trusted event handlers. This would also eliminate the need for periodic reloads of the server to install...

Hope this helps - I'll give this some more thought later.

tlhackque added a commit to tlhackque/mod_md that referenced this issue Mar 10, 2020
This script is a preliminary version of a handler for the
md_events discussed in issue icing#189.  It has gone through some
unit testing, but is not production qualified.  Nothing about
it should be considered stable.

This version is to drive discussion of the mod_md interfaces.

It should work as an MDMessageCmd and MDChallengeDns01 provider,
as well as for the (hypothetical) MDChallengeHttp01 events.

Feedback and testing is encouraged.

To get started, run contrib/md_events/md_events -h for usage.

Then contrib/md_events/md_events -I, which will do a default install.

/etc/httpd/md_events.conf and /etc/httpd/md_events.d will be
informative.

You can play with it from the command line as installed:
  contrib/md_events/md_events -uroot installed example.net

I have also provided a few dns-01 update scripts; md_events has
an (untested) wrapper that should make them useful.
@tlhackque
Copy link
Contributor Author

I pushed a commit with a VERY preliminary and rough version of md_events and some supporting files (for dns-01). Read the commit comment for details.

This is not production ready - but hopefully is a good base for defining MDEvents.

FWIW, I used the term "events" for the current MDMessageCmd interface from day 0...

Out of time for now...

@tlhackque
Copy link
Contributor Author

I noticed one related issue in dns-01 handling.

Often, it can take some time for a challenge to become visible to the validation servers.
This may be due to negative caching in the DNS servers they use, or other network effects.

In any case, with other clients I've seen it take up to several minutes between when
the record is placed in the DNS and when the validation servers admit to seeing it.
Some clients try to poll an external DNS server to see if the record is visible, and don't
send the 'proceed' to LE until it is. I've seen 50-100 such probes at 10 sec intervals
before success... Even then, the LE servers can take a while to see the record.

Obviously, a MDChallengeDns01 script should not block long enough for this
to settle out. Instead, I think the mod_md process should requeue/suspend its
thread after a successful invocation of the MDChallengeDns01 program and
before sending the "proceed". After the delay, it can send the "proceed".

Waiting minimizes the chance of negative caching.

A good value for the delay time is hard to estimate. It should be configurable.
There's really no urgency. Perhaps MDDnsPropagationTime with a default
of 5 or 10 minutes?

@icing
Copy link
Owner

icing commented Mar 12, 2020

  • I agree that the domain setup/status polling needs to suspend/resume jobs, so that other renewal may proceed in the mean time.
  • MDCAChallenges should better be named MDChallenges, maybe I make an alias.
  • An MDChallengeStartDelay duration [ chtype=duration ... ] could do the job.

@tlhackque
Copy link
Contributor Author

MDChallengeResponseDelay might be better. The validation server starts the challenge, mod_md responds.... The challenge is started - it's the response that's delayed.

I don't have a problem with MDCAChallenges - while MDChallenges is better, not sure it's worth adding another alias that has to be documented/explained/tested...

@tlhackque
Copy link
Contributor Author

Also, the required delay depends on the challenge type. DNS can take time to propagate. tls-apln and mod_md internal http are instantly available. external http usually is visible when the script returns from the copy commend - but there might be a cache/CDN to update. ..

So scope needs to be per-MDomain. Since mod_md can announce ability to respond to more than one challenge type, server can choose.

So perhaps syntax is `MDChallengeResponseDelay http-01=[duration] tls-alpn=[duration] ...

OTOH, it doesn't have to be TOO precise. Doesn't make sense for internal responses to wait 10s of minutes for getting the first certificate. But the slow ones have to work. Cert renewal happens every 60 days, so a coarse solution should suffice.

@tlhackque
Copy link
Contributor Author

I pushed a document (event_interface_notes.txt) that tried to collect the threads of this conversation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants