mirror of
https://github.com/mjl-/mox.git
synced 2025-01-14 01:06:27 +03:00
at startup, request missing acme tls certificates more quickly/silently
This commit is contained in:
parent
dbd6773f6b
commit
4701857d7f
2 changed files with 42 additions and 0 deletions
|
@ -200,6 +200,40 @@ func Load(name, acmeDir, contactEmail, directoryURL string, eabKeyID string, eab
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CertAvailable checks whether a non-expired ECDSA certificate is available in the
|
||||||
|
// cache for host. No other checks than expiration are done.
|
||||||
|
func (m *Manager) CertAvailable(ctx context.Context, log mlog.Log, host dns.Domain) (bool, error) {
|
||||||
|
ck := host.ASCII // Would be "+rsa" for rsa keys.
|
||||||
|
data, err := m.Manager.Cache.Get(ctx, ck)
|
||||||
|
if err != nil && errors.Is(err, autocert.ErrCacheMiss) {
|
||||||
|
return false, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return false, fmt.Errorf("attempt to get certificate from cache: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The cached keycert is of the form: private key, leaf certificate, intermediate certificates...
|
||||||
|
privb, rem := pem.Decode(data)
|
||||||
|
if privb == nil {
|
||||||
|
return false, fmt.Errorf("missing private key in cached keycert file")
|
||||||
|
}
|
||||||
|
pubb, _ := pem.Decode(rem)
|
||||||
|
if pubb == nil {
|
||||||
|
return false, fmt.Errorf("missing certificate in cached keycert file")
|
||||||
|
} else if pubb.Type != "CERTIFICATE" {
|
||||||
|
return false, fmt.Errorf("second pem block is %q, expected CERTIFICATE", pubb.Type)
|
||||||
|
}
|
||||||
|
cert, err := x509.ParseCertificate(pubb.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("parsing certificate from cached keycert file: %v", err)
|
||||||
|
}
|
||||||
|
// We assume the certificate has a matching hostname, and is properly CA-signed. We
|
||||||
|
// only check the expiration time.
|
||||||
|
if time.Until(cert.NotBefore) > 0 || time.Since(cert.NotAfter) > 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetAllowedHostnames sets a new list of allowed hostnames for automatic TLS.
|
// SetAllowedHostnames sets a new list of allowed hostnames for automatic TLS.
|
||||||
// After setting the host names, a goroutine is start to check that new host names
|
// After setting the host names, a goroutine is start to check that new host names
|
||||||
// are fully served by publicIPs (only if non-empty and there is no unspecified
|
// are fully served by publicIPs (only if non-empty and there is no unspecified
|
||||||
|
|
|
@ -801,6 +801,14 @@ func Serve() {
|
||||||
i := 0
|
i := 0
|
||||||
for m, hosts := range ensureManagerHosts {
|
for m, hosts := range ensureManagerHosts {
|
||||||
for host := range hosts {
|
for host := range hosts {
|
||||||
|
// Check if certificate is already available. If so, we don't print as much after a
|
||||||
|
// restart, and finish more quickly if only a few certificates are missing/old.
|
||||||
|
if avail, err := m.CertAvailable(mox.Shutdown, pkglog, host); err != nil {
|
||||||
|
pkglog.Errorx("checking acme certificate availability", err, slog.Any("host", host))
|
||||||
|
} else if avail {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if i >= 10 {
|
if i >= 10 {
|
||||||
// Just in case someone adds quite some domains to their config. We don't want to
|
// Just in case someone adds quite some domains to their config. We don't want to
|
||||||
// hit any ACME rate limits.
|
// hit any ACME rate limits.
|
||||||
|
|
Loading…
Reference in a new issue