Commit Graph

43 Commits

Author SHA1 Message Date
Matt Holt
0e88b3eaa1
Initial implementation of ARI (#286)
* Initial implementation of ARI

* Enhance redundancy, robustness, and logging

* Improve ARI updating; integrate on-demand TLS; detect changed window
2024-05-07 09:46:03 -06:00
Matthew Holt
aa4d957707
Return error if cert manager returns error
Don't try to issue certificate. If a cert manager returns an error, it indicates that
it was supposed to be able to get a cert for that
name but was unable to do so.
2024-04-12 10:09:24 -06:00
Matthew Holt
7681257d05
Try cert Manager before asking permission
Managers are expected to have 'asking permission' built in
2024-04-12 08:48:27 -06:00
Matthew Holt
f7ea6fb698
Enhancements to make ZeroSSL issuer more usable in Caddy 2024-04-11 12:23:53 -06:00
Andreas Kohn
f0038ffe14
Add context arg to DecisionFunc (#255)
* Optionally pass the context argument down to the OnDemand decision func

* Remove the "compatibility shims"

This "breaks" the API here, but the change should be trivially obvious to an implementor
and it gives a lot less headache later.
2023-10-30 07:47:31 -06:00
Matthew Holt
7836d86c96 Change slice to map to avoid O(n^2) performance 2023-06-30 18:45:39 -06:00
Matt Holt
65d3af6938
Issuer policies that can randomize issuer used (#238) 2023-06-13 22:05:29 -06:00
Matt Holt
8728b186fa
Refactor Managers into on-demand config (#231) 2023-05-11 12:36:44 -06:00
Matthew Holt
69cca0e742
Fix decision func enforcement (d'oh) 2023-05-06 12:30:48 -06:00
Matthew Holt
6670b5e1cc
Improve handshake logic
- Only load cert from storage (or manager) if allowed to do so  (fix #174)
- Sync cert loading so storage isn't stampeded (fix #185)
- Update dependencies
2023-05-05 20:26:50 -06:00
Matthew Holt
5deb7c2fb0 Make logger values required
Eliminates a bajillion nil checks and footguns
(except in tests, which bypass exported APIs, but that is expected)

Most recent #207

Logging can still be disabled via zap.NewNop(), if necessary.
(But disabling logging in CertMagic is a really bad idea.)
2022-09-26 10:19:30 -06:00
Matthew Holt
56c70f3808
Update to Go 1.18; use any 2022-08-08 10:45:24 -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
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
Matt Holt
797d29bcf3
GetCertificate from external certificate sources (Managers) (#163)
This work made possible by Tailscale: https://tailscale.com - thank you to the Tailscale team!

* Implement custom GetCertificate callback

Useful if another entity is managing certificates and can
provide its own dynamically during handshakes.

* Refactor CustomGetCertificate into OnDemandConfig

* Set certs to managed=true

This is only sorta true, but it allows handshake-time maintenance of the
certificates that are cached from CustomGetCertificate.

Our background maintenance routine skips certs that are OnDemand so it
should be fine.

* Change CustomGetCertificate into interface value

Instead of a function

* Case-insensitive subject name comparison

Hostnames are case-insensitive

Also add context to GetCertificate

* Export a couple of outrageously useful functions

* Allow multiple custom certificate getters

Also minor refactoring and enhancements

* Fix tests

* Rename Getter -> Manager; refactor

And don't cache externally managed certs

* Minor updates to comments
2022-02-17 14:37:50 -07:00
Matthew Holt
1bbe11e291
Change ManageSync() to take a context (close #146)
This brings it in line with ObtainSync and RenewSync, and makes it consistent with ManageAsync.
2021-09-23 14:35:51 -06:00
Matt Holt
07f7d0dec1
Allow forced renewals; fix renew on OCSP revoke; change key on compromise (#134)
* Begin refactor of ObtainCert and RenewCert to allow force renews

* Don't reuse private key in case of revocation due to key compromise

* Improve logging in renew

* Run OCSP check at start of cache maintenance

Otherwise we wait until first tick (currently 1 hour) which might be too long

* Fix obtain; move some things around

Obtain now tries to reuse private key if exists, but if it doesn't exist, that shouldn't be an error (so we clear the error in that case).

Moved the removal of compromised private keys to have logging make more sense.
2021-06-12 13:47:47 -06: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
81657a2337
Lower max stack trace size
64 MB... what was I thinking?
2020-09-17 12:16:14 -06:00
Matthew Holt
3e4c11b75f
Remove HTTP protos from ALPN unless serving HTTP (#97) 2020-09-14 12:10:52 -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
renthraysk
47d02f7329
Fix CertificateResource.NamesKeys() truncation (#65) 2020-04-07 07:14:59 -06:00
Matthew Holt
11467829d4
Update HostQualifies logic to be specific for public certs
Because CertMagic can now be used for more than just publicly-trusted
certificates.
2020-03-07 18:56:16 -07:00
Matthew Holt
8a7197beca
Change renewal window to a ratio of cert lifetime instead of hard coded
This allows CertMagic to accommodate certificates with extremely short
lifetimes (new defaults work with cert lifetimes < 24h, but I wouldn't
want to push it < 30m with these defaults).
2020-02-24 18:42:27 -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
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
74b63c8f35
ManageAsync: retry with exponential backoff; honor context cancellation 2019-10-16 11:11:48 -06:00
Matthew Holt
c52848a21d
Background cert operations; ManageSync() and ManageAsync()
Split Manage() into ManageSync() and ManageAsync().

In accordance with developing best practices, ACME operations should be
allowed to happen in the background and not block server startup in
non-interactive environments.

We also no longer return an error during batch cert renewals, because
we always treat it as a background operation. (The ManageSync() method
can perform foreground renewal if that is desired.)
2019-10-16 00:19:57 -06:00
Matthew Holt
925f85ac0e
go.mod: Update to lego v3.0.2 2019-09-12 16:18:25 -06:00
Matthew Holt
be4f86a2eb Refactor, simplify, and correct on-demand config; update README
The MaxObtain and other checks such as rate limiting were crippling to
some use cases at scale and incorrect if configs are short-lived; these
changes allow the user to implement their own rate limiting (and simply
limiting the number of certificates to obtain is a bad idea and
shouldn't be done) and to better enforce hostname whitelists for
on-demand config when the high-level functions are used
2019-06-20 18:48:07 -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
My1
f1fdb7fe9c Change default KeyType to EC256 (P256) (#37)
will also allow IE11 to use GCM ciphers
2019-04-01 12:30:34 -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
Joël Gähwiler
c777edeef8 Use DefaultServerName when SNI missing (#23)
* properly test non sni connections by passing in a fake connection

* added default server name

* Refactor default server name (SNI) implementation
2019-02-02 11:10:17 -07:00
Matthew Holt
707b20497e
client: Make cert obtain timeout configurable
Also make compatible with lego v2.0.1 (fixes #15)
2019-01-10 19:46:25 -07:00
Matthew Holt
52238b486f
Make HTTPS() use production-ready TLS and HTTP configurations (issue #9) 2018-12-17 12:24:17 -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
d2f9fba738
Combine Locker interface into Storage; improve docs 2018-12-11 11:46:55 -07:00
Matthew Holt
277fd1bdc5
Use fmt.Errorf; customize HTTPTimeout and UserAgent 2018-12-10 18:52:10 -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