Commit Graph

47 Commits

Author SHA1 Message Date
Matthew Holt
74862ff45a
Upgrade acmez to v2 beta
Adds support for customizing NotBefore/NotAfter times of certs
2024-04-08 14:05:43 -06:00
Matthew Holt
98d2930e1d
Improve DNS related logging 2024-04-08 12:24:15 -06:00
Matt Holt
6095ab8069
Initial implementation of ZeroSSL API issuer (#279)
* Initial implementation of ZeroSSL API issuer

Still needs CA support for CommonName-less certs

* Accommodate ZeroSSL CSR requirements; fix DNS prop check

* Fix README example

* Fix comment
2024-04-08 10:59:55 -06:00
pgeh
c3c4a1263a
DNS propagation check succeeds if any configured resolver succeeds (#274)
* Changed solver DNS propagation check to only check authoritative nameservers directly if there are no explicitly given resolvers.

* Changed solver DNS propagation check to only succeed of any one of the checked nameservers has the required TXT entry
2024-03-14 15:21:07 -06:00
Matthew Holt
93305b0e56
Improv port in use warning message (fix #250) 2023-09-07 16:59:03 -06:00
Matthew Holt
76f61c2947
Use different context for DNS challenge cleanup
Fix #200, probably
2022-08-18 10:50:50 -06:00
Matthew Holt
9e63f36fa3
Revert "Prepend _acme-challenge label to OverrideDomain"
This reverts commit e0227517e0.

According to discussion in #160, there was a misunderstanding and the previous implementation seems more correct:
https://github.com/caddyserver/certmagic/pull/160#issuecomment-1213138105
2022-08-12 14:29:05 -06:00
Matthew Holt
56c70f3808
Update to Go 1.18; use any 2022-08-08 10:45:24 -06:00
Matthew Holt
e0227517e0
Prepend _acme-challenge label to OverrideDomain
This way the user does not need to explicitly configure that
(which is not intuitive).
2022-08-08 10:19:38 -06:00
Matthew Holt
dce2de273d
Improve DNS solver efficiency and resolve deadlock
Previously, simultaneously solving for example.com and *.example.com
using the DNS challenge (i.e. both SANs on the same cert, which CertMagic
doesn't do; but this is a general-purpose library) would cause a deadlock
because both those names use the same-name TXT record. This caused
problems with previous dependencies like lego and legacy DNS solvers,
but the new acmez library and libdns packages support this.

I've removed the locking around same-name records, which resolves
the deadlock, and improves efficiency as well, since we can now solve
challenges for example.com and *.example.com at the same time.
2022-08-02 14:07:34 -06:00
gjung56
23ca487b74
Use OverrideDomain when cleaning up DNS solver (#193) 2022-07-27 16:14:57 -06:00
Matthew Holt
8d92ff95bf
Configurable propagation checks in DNS solver
Lots of users over the years have reported that the propagation checks
time out, yet the challenges would/did still succeed. Example:
https://caddy.community/t/hard-time-getting-a-response-on-a-dns-01-challenge/15721?u=matt

We are not sure why this happens, but it seems prudent to be able to
disable or delay the propagation checks.
2022-04-22 14:49:34 -06:00
Matthew Holt
55be6d8695
Rename ACMEManager -> ACMEIssuer, CertificateManager -> Manager
This is necessary to eliminate confusing naming conventions, since now
we have Manager types, having an issuer called ACMEManager was
confusing.

CertificateManager is a redundant name as this package is called
CertMagic, so that a Manager manages certificates should be obvious.
It's also more succinct. Plus, it's consistent with Issuer which is not
named CertificateIssuer.
2022-03-24 11:34:31 -06:00
Ran Chen
ae2a5ddada
solvers: Always call checkDNSPropagation in DNS01Solver (#179)
Calling checkAuthoritativeNss is wrong as it's not inter-changeable with
checkDNSPropagation.

Though IIUC it's not necessary to follow CNAME when in Wait(), with or
without OverrideDomain, let's wait until the override domain gets some
usage to change this. The reason that following CNAME is not necessary
is that CNAME cannot co-exist with other DNS records, if we succeed in
setting a TXT record on that domain, it cannot have a CNAME record.

@IndeedNotJames
2022-03-24 11:21:26 -06:00
Dave Henderson
9a56fcd4f9
Propagate context in the Storage interface methods (#155)
* Add context propagation to the Storage interface

Signed-off-by: Dave Henderson <dhenderson@gmail.com>

* Bump to Go 1.17

* Minor cleanup

* filestorage: Honor context cancellation in List()

Co-authored-by: Matthew Holt <mholt@users.noreply.github.com>
2022-03-07 12:26:52 -07:00
Ran Chen
f60ce01d6d
Implement OverrideDomain is DNS01Solver (#160)
* Add OverrideDomain option to DNS01Solver

This is to delegate the challenge to a different domain. With this
change, the solver no longer follows CNAME chain when checking for
propagation as well.

* Update solvers.go

* Only check the authoritative NS when OverrideDomain is set

and keep the old code path otherwise.

Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
2022-03-07 10:34:57 -07:00
Herman Slatman
3966eeb00d
Fix TLS-ALPN-01 challenge for IP Identifiers (#139)
* Fix TLS-ALPN-01 challenge for IP Identifiers

See #133

* Add tests for challengeKey function

* Add more tests

* Fix PR comments

* Remove deletion of TLS-ALPN-01 challenge certificate
2021-07-15 18:41:44 -06:00
Matthew Holt
a1d00125a6
Sync discovered contact email (fix #127) 2021-04-12 11:57:20 -06:00
Matthew Holt
7550222c4a
Conform to libdns relative record names convention
See https://github.com/libdns/libdns/issues/12
2021-02-24 11:46:02 -07:00
Matthew Holt
7271e2f615
Export access to global challenge info cache
Turns out this is needed when solving the HTTP challenge in Caddy, in certain situations.

This does not provide access to challenge info in distributed challenge storage (that would require a Config, and isn't exported anyway since it is handled internally).
2021-01-23 14:28:02 -07:00
Matthew Holt
2a9ad38637
Refactor challenge info / solving
This allows any challenges initiated within the process to be solved by whatever HTTP or TLS server is running, even if they do not know about the challenges themselves.

This is useful when a process has multiple servers running, but only one can solve the challenges (which is often the case, since a socket belongs to one listener at a time) and they do not know about each other or share configs. The trick is to wrap the solvers with a thin wrapper that stores all the challenge info in memory while the challenge is active.

A nice side-effect is I've simplified/unified the code that gets the challenge info when actually solving the challenges.
2021-01-22 17:43:33 -07:00
Matt Holt
0f8a9f6887
Implement multiple issuer support (#109)
* Implement multiple issuer support

This change refactors Config.Issuer to be Config.Issuers, an array of
issuers. Each Issuer will be tried in turn until one succeeds. During
retries, each attempt will try each configured Issuer. When loading
certs from storage, CertMagic will look in each Issuer's storage
location for a qualifying asset. If multiple Issuers have one in storage
then the most-recently-issued cert will be selected.

This is a breaking change in that Config now accepts a slice of Issuers
rather than a single Issuer. The Revoker field is removed, as supporting
it is optional anyway. If the Issuer is also a Revoker, it can be used
implicitly to revoke certificates.

Also added a const for ZeroSSL's ACME endpoint.

* Load matching wildcard on-demand from storage

With this change, a config using on-demand TLS can load a certificate
for "sub.example.com" from storage using a matching  wildcard cert
(i.e. "*.example.com") if no better matching certificate is available.

* Fix distributed solving with tls-alpn challenges

The type assertion in handshake.go was problematic since there's no
guarantee that an ACME issuer would be a concrete ACMEManager type.

Refactored the code to accept IssuerKey values generally, rather than
specific ACMEManager values only.

This fixes solving tls-alpn challenges in distributed settings.

More cleanup can be done, another time.
2020-11-16 10:53:41 -07:00
Matthew Holt
4fd8ae48ef
Configure custom DNS resolvers to be preferred over default resolvers
This makes the DNS challenge usable with split-horizon DNS.

Related:
- https://github.com/go-acme/lego/issues/461
- https://github.com/caddyserver/caddy/issues/1580
- https://github.com/go-acme/lego/issues/379/
- https://github.com/go-acme/lego/pull/293/
2020-08-21 20:22:42 -06:00
Matthew Holt
c2f851df75
Synchronize same-name DNS challenges
Wildcard domain names collide with the same subdomain for the ACME TXT
record as the non-wildcard parent domain (for example, example.com and
*.example.com both use _acme-challenge.example.com), so we need to solve
those challenges mutually exclusively.

One potential problem with this current implementation is that we don't
wait for the DNS record to un-propagate after it is deleted; I've found
that re-running it works fine, after waiting just a few seconds. I am
not sure how to generalize this logic in all cases though. It is likely
provider-dependent. (I was testing with Cloudflare.)

Should fix https://github.com/caddyserver/caddy/issues/3474
2020-08-18 16:37:01 -06:00
Matthew Holt
7d9dfc3fe6
Add DNS-01 solver implementation that uses acmez and libdns APIs
Before when we used lego as our ACME library, DNS solvers abounded in
the lego repository and they could be used directly. Our new acmez lib
is very lightweight, and "bring-your-own-solvers", let alone your own
DNS provider implementations.

DNS providers are implemented in libdns: https://github.com/libdns

This commit adds an implementation of acmez.Solver that solves the DNS
challenge using libdns providers.

Unlike the other solvers, this one is exported because it is not a
challenge type that is enabled by default, and there is more config
surface.

We borrowed some DNS utility functions and tests from the lego repo.

But this is a very lightweight implementation that has a much, much
simpler API and smaller footprint.
2020-07-30 14:07:04 -06:00
Matt Holt
b76b76abfc
Replace lego with ACMEz (close #71) (#78) 2020-07-27 16:50:41 -06:00
Matthew Holt
5ed364019b
Add nil check; recover from all goroutines 2020-05-12 09:28:56 -06:00
Matthew Holt
79862506fe
Minor cosmetic tweaks 2020-04-07 07:26:31 -06:00
Matthew Holt
03d064592b
Handle the heck out of those socket errors
Kind of a desperate fix for a critical bug I haven't been able to
reproduce myself.
2020-04-03 17:31:51 -06:00
Matthew Holt
82f093d174 Revert "Fix error handling logic with embedded solvers"
This reverts commit f8be3e9594.
2020-04-03 16:26:40 -06:00
Matthew Holt
f8be3e9594
Fix error handling logic with embedded solvers
We always returned an error even if it was an error we could ignore

https://caddy.community/t/v2-upgrade-to-caddy2-failing-with-errors/7423
2020-04-03 16:14:39 -06:00
Matthew Holt
18ec60ab5d
Let's just close that channel once, shall we?
Introduced in a2d5eabbe6
2020-04-03 09:15:54 -06:00
Matthew Holt
ca857ff8fb
Workaround apparent contradiction in Windows
https://caddy.community/t/caddy-retry-error/7317?u=matt
2020-03-27 10:30:58 -06:00
Matthew Holt
a2d5eabbe6
Fix sync issue related to solver cleanup
After twenty trials, was unable to reproduce nondeterministic stalling
with successful validations.

Was able to consistently reproduce hanging after failed validations,
which this fixes.
2020-03-20 08:34:23 -06:00
Matthew Holt
cbeee6e6b2
A few tweaks and fixes 2020-02-24 12:23:54 -07:00
Matthew Holt
37e754b40c
Major refactor to improve performance, correctness, and extensibility
Breaking changes; thank goodness we're not 1.0 yet 😅 - read on!

This change completely separates ACME-specific code from the rest of the
certificate management process, allowing pluggable sources for certs
that aren't ACME.

Notably, most of Config was spliced into ACMEManager. Similarly, there's
now Default and DefaultACME.

Storage structure had to be reconfigured. Certificates are no longer in
the acme/ subfolder since they can be obtained by ways other than ACME!
Certificates moved to a new certificates/ subfolder. The subfolders in
that folder use the path of the ACME endpoint instead of just the host,
so that also changed. Be aware that unless you move your certs over,
CertMagic will not find them and will attempt to get new ones. That is
usually fine for most users, but for extremely large deployments, you
will want to move them over first.

Old certs path:
  acme/acme-staging-v02.api.letsencrypt.org/...

New certs path:
  certificates/acme-staging-v02.api.letsencrypt.org-directory/...

That's all for significant storage changes!

But this refactor also vastly improves performance, especially at scale,
and makes CertMagic way more resilient to errors. Retries are done on
the staging endpoint by default, so they won't count against your rate
limit. If your hardware can handle it, I'm now pretty confident that you
can give CertMagic a million domain names and it will gracefully manage
them, as fast as it can within internal and external rate limits, even
in the presence of errors. Errors will of course slow some things down,
but you should be good to go if you're monitoring logs and can fix any
misconfigurations or other external errors!

Several other mostly-minor enhancements fix bugs, especially at scale.
For example, duplicated renewal tasks (that continuously fail) will not
pile up on each other: only one will operate, under exponential backoff.

Closes #50 and fixes #55
2020-02-21 14:32:57 -07:00
Matthew Holt
9893774184
Fix close signaling 2020-02-06 12:49:49 -07:00
Matthew Holt
2e1c223b47
Rewrite HTTP and TLS-ALPN solvers; always use our own solvers
This solves several issues related to solving for multiple names
concurrently. The basic idea is that now we always use our own solvers,
which is actually much simpler. We just wrap them in a distributedSolver
which writes the keyAuth material to storage. Our solvers then proceed
to solve the challenges: either by allowing whatever is currently
listening on the challenge port to solve it, or by starting their own
servers. Our solvers keep track of how many challenges each solver is
answering, and the "last one out turns off the lights" so to speak.

Also, where we used to try dialing a port then listening if it was
available, now we just try listening, and if it fails, we make sure it
is in use by dialing it. I've added locking around this as well to
ensure that races for the socket, along with the counters, do not happen.

Overall, this is a much improved solver implementation that can handle
more use cases at a larger scale than before.

Also, a minor data race was revealed in user.go, which only happens in
some rare edge cases as far as I can tell, but I marked them with a TODO
so we can get around to fixing them later.
2020-02-05 17:23:13 -07:00
Matthew Holt
925f85ac0e
go.mod: Update to lego v3.0.2 2019-09-12 16:18:25 -06:00
Matthew Holt
6a42ef9fe8
Optional tags for unmanaged certificates
This allows for user-loaded certificates to be associated with arbitrary
values such as user-provided IDs or categories. This can be useful if
multiple certificates satisfy a ClientHello but if a specific one still
needs to be chosen. See for example:
https://github.com/mholt/caddy/issues/2588

This is a breaking API change since we need to expose a tags parameter
to the caching functions, but we're not 1.0 yet so we will try this
API change and see how it goes.
2019-06-24 11:51:58 -06:00
Matt Holt
8f7a1caa59
Significant refactoring to improve correctness and flexibility (#39)
* Significant refactor

This refactoring expands the capabilities of the library for advanced
use cases, as well as improving the overall architecture, including
possible memory leak fixes if used over a long period with many certs
loaded into memory. This refactor enables using different configs
depending on the certificate.

The public API has changed slightly, however, and arguably it is
slightly less convenient/elegant. I have never quite found the perfect
design for this package, and this certainly isn't it, but I think it's
better than what we had before.

There is still work to be done, but this is a good step forward. I've
decoupled Storage from Cache, and made it easier and more correct for
Configs (and Storage values) to be short-lived. Cache is the only value
that should be long-lived.

Note that CertMagic no longer automatically takes care of storage (i.e.
it used to delete old OCSP staples, but now it doesn't). The functions
to do this are still there and even exported, and now we expect the
application to call the cleanup functions when it wants to.

* Fix little oopsies

* Create Manager abstraction so obtain/renew isn't limited to ACME
2019-04-20 10:44:55 -06:00
David Schwartz
ee1543e2f2 use go-acme/lego (#31)
* use go-acme/lego

* Use master branch of go-lego/acme since v2.3.0 still has a dependency on xenolf/lego

* Use golangci-lint since gometalinter is depricated

* different way of installing golangci-lint for appveyor

* Removing golangci-lint from Appveyor because of https://github.com/client9/shlib/issues/13
2019-03-19 12:38:00 -06:00
Matthew Holt
a7f18a937c
Fix nil pointer dereference and cleanup after TLS-ALPN challenge 2019-02-02 16:10:51 -07:00
securityclippy
8261565d73 exported KeyBuilder.Safe to use with external pkgs (#13)
* exported KeyBuilder.Safe to use with external pkgs

* fixing comment for Safe function
2019-01-06 20:59:41 -07:00
Matthew Holt
5b3085c491
Export methods to build storage keys and prefixes
Also adjust clients so that they use the configured HTTPPort or
HTTPSPort for solving challenges, if different from the default
challenge port (not as preferred as the Alt*Port values, of course)
2018-12-11 15:48:47 -07:00
Matthew Holt
1f94da1ed1
Compatibility with refactored lego core
lego commit: 42941ccea6b431ebff203d4cb520991fb7b47951
2018-12-10 00:26:09 -07:00
Matthew Holt
bea13a36c8
Initial commit 2018-12-09 20:15:26 -07:00