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.)
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
I suppose * is a valid subject -- technically -- but it probably won't
be accepted by browsers. They usually only accept wildcards
for subdomains.
Related, but only tangentially:
https://github.com/caddyserver/caddy/issues/3977
This is necessary to support a nuance in Caddy where we have to see if a
subject qualifies for a public certificate but with custom wildcard
checking. So we separate the wildcard check from other checks.
CertMagic currently does wildcard matching in two places:
- Cache.AllMatchingCertificates() for finding all certs in cache
- Config.getCertificate() for finding one cert in cache at handshake
But those implementations will not use MatchWildcard() because their
looping logic is slightly customized.
Caddy, however, has need to compare DNS names with wildcards in at
least two places:
- Matching TLS connection policies by ServerName (SNI)
- Matching TLS automation policies by subject names
So this function is a good implementation for that.
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.
* 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