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
Move DNS providers out of the lego executable #111
Comments
I wonder how many DNS providers really require a whole library to be imported in order to set and delete TXT records. For example, when I implemented DigitalOcean's DNS solver I simply used net/http. If we can strip down the code of each provider to just using standard library functions, then I'm OK with adding more providers as long as they go in their own package. But if each provider is going to add another tree of dependencies, then... I'd rather avoid that. |
I agree with @mholt, that stripping down the code might be the way forward. I started to write a challenge solver for Gandi API before realizing I could make http-01 work with the Stdlib reverse proxy. However, I got far enough to realize that the (huge) Gandi Go package was not necessary and I could just marshall/unmarshall the XML myself quite easily, since as you say it's only a couple of functions needed. If anyone has a desperate need for a Gandi solver I can finish off what I did. Just leave a comment here. But as I said, I no longer need it just now. |
I agree that it's possible to implement many providers in terms of I think it's pragmatic to re-use existing libraries, though admittedly the scale of the AWS client library colors my thinking. (I use both |
Hmm… maybe it makes sense to use both strategies? Keep zero-dependency providers internal, and spin off e.g. |
That is a fair point you make @willglynn that tracking libaries is easier than tracking protocols. Especially if the person who writes the solver disappears. Each solver will likely have a different author and they may not stick around to maintain it. But I guess it comes down to balance and a sort of cost/benefit analysis as to whether to use the lib or not. |
Thinking about this some more, maybe this would work: Have each DNS solver in a seperate package, say under:
Keep the plain acme package just for the non-dns solvers An API user would then just import whichever solver they want, and get the bloat they want. For the CLI app, lego, we could have the default |
I've been tinkering with moving DNS providers out of
This model would suit conditional compilation just fine. I should also mention an additional motivation for my original proposal: I have a use case for an external DNS challenge provider. One of my clients has a bizarre environment that I expect no one else will ever encounter. I could plop a provider in (Besides being simple, the child process approach also means I could write If we're leaning towards keeping |
I'm sorry that I'm a bit late to the party but I had to think about this. As I said in #100 I'm in favor of moving the DNS providers apart from the manual provider out of the ACME package to lessen the dependency burden. The manual provider should remain in the package as I think every challenge should be solvable by just importing the package. Concerning the other providers, I think it makes sense to put them into their own packages to allow people to only import what they need... Using the DO provider should not mean to import the huge AWS library for example. I imagine the folder structure as follows: This gives us the freedom to add providers for the other challenges as well. (Some have already been requested like a manual provider for HTTP-01) For the CLI the best method would probably be to support build tags in order to allow people to customize their build by using go get. As far as "plugins" to the CLI go I'm torn back and forth. I intended the CLI to be simple and only a thin wrapper around the library and this would kinda break it. Looking forward to your thoughts. |
That is a good point about keeping the manual DNS provider within the core acme package, and within whatever the "basic" build of the CLI is. |
I took a stab at some reshuffling in #112. I put the DNS providers in
Moving to one package per provider makes total sense to me. Consuming applications can then import I think the registry populated on Speaking of available: I think |
You are right, I am not objected to making them siblings. I agree that I would also like to think about how providers to other challenges would fit into your approach. I know that at the moment we have more providers for DNS-01 compared to the other two challenges but I expect that to change and I don't want to introduce any barriers for the future. |
With the merge of #144, I guess we can close this. Feel free to reopen if there is still something left to discuss. |
lego
could grow indefinitely by supporting every DNS provider API ever made, but this seems less than ideal (#100). I'd like to discuss how to move DNS providers out of thelego
executable.It is fortunate that DNS-01 has a very small surface area in terms of what functions are required. There's basically just two operations:
_acme-challenge.whatever IN TXT "abc123"
lego
can monitor the authoritative DNS servers to watch and wait for success, so communication from the DNS provider back tolego
can be as little as just signaling failure.Go limits the mechanisms by which external code can interact with a project like
lego
. The most straightforward mechanism is to launch a child process and interact with it, and based on my understanding of the requirements, I think that model would work fine:lego
does everything ACME-related, ultimately deciding that it needs to create_acme-challenge.whatever IN TXT "abc123"
.lego
, having been invoked with--dns=foo
, spawnslego-dns-foo "_acme-challenge.whatever" "abc123"
, passing on its environment variables.lego-dns-foo
usesFOO_USERNAME
andFOO_PASSWORD
to create the record indicated by its arguments, then waits.lego
spins and waits for a)_acme-challenge.whatever
to show the correct value, b)lego-dns-foo
to exit, or c) some configurable timeout.lego
sees_acme-challenge.whatever
get created and proceeds in its ACME dance, yielding a completed challenge and a certificate forwhatever
.lego
no longer needs_acme-challenge.whatever
, and indicates this by closinglego-dns-foo
's stdin.lego-dns-foo
sees its stdin close, removes the record, and terminates successfully.This scheme avoids unnecessary complexity (it's simple enough that a provider could be implemented with a shell script) and platform dependence (i.e. signals don't really port well to Windows).
lego-dns-foo
could communicate back by printing to stdout/stderr and by exiting with a failure code, which seems like it's enough.Some negatives of this approach are:
lego-dns-foo
doesn't get run until late in the operation, which means DNS-related configuration errors aren't detected until late in the operation. This could be mitigated by launchinglego-dns-foo
with no arguments before doing anything else (i.e. "don't actually create any records, but do fail immediately if you would fail immediately"), or by adding a separatedns-test
function which creates a TXT record and verifies its content outside an ACME exchange (lego dns-test
feature request #110).go get github.com/xenolf/lego
becomes insufficient. (That's sort of the point, though.) Would it be okay to make users saygo get github.com/xenolf/lego-dns-foo
? Do we want users to have a kitchen sink option?Thoughts?
The text was updated successfully, but these errors were encountered: