Make cache options updateable; new remove methods
These are useful for advanced applications (like Caddy) which would like to remove certificates from the cache in a controlled way, and operate the cache with new settings while running.
This commit is contained in:
parent
d8b13df4d1
commit
93a28b732a
60
cache.go
60
cache.go
@ -48,7 +48,8 @@ import (
|
|||||||
// differently.
|
// differently.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
// User configuration of the cache
|
// User configuration of the cache
|
||||||
options CacheOptions
|
options CacheOptions
|
||||||
|
optionsMu sync.RWMutex
|
||||||
|
|
||||||
// The cache is keyed by certificate hash
|
// The cache is keyed by certificate hash
|
||||||
cache map[string]Certificate
|
cache map[string]Certificate
|
||||||
@ -56,7 +57,7 @@ type Cache struct {
|
|||||||
// cacheIndex is a map of SAN to cache key (cert hash)
|
// cacheIndex is a map of SAN to cache key (cert hash)
|
||||||
cacheIndex map[string][]string
|
cacheIndex map[string][]string
|
||||||
|
|
||||||
// Protects the cache and index maps
|
// Protects the cache and cacheIndex maps
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
||||||
// Close this channel to cancel asset maintenance
|
// Close this channel to cancel asset maintenance
|
||||||
@ -128,6 +129,12 @@ func NewCache(opts CacheOptions) *Cache {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (certCache *Cache) SetOptions(opts CacheOptions) {
|
||||||
|
certCache.optionsMu.Lock()
|
||||||
|
certCache.options = opts
|
||||||
|
certCache.optionsMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// Stop stops the maintenance goroutine for
|
// Stop stops the maintenance goroutine for
|
||||||
// certificates in certCache. It blocks until
|
// certificates in certCache. It blocks until
|
||||||
// stopping is complete. Once a cache is
|
// stopping is complete. Once a cache is
|
||||||
@ -226,7 +233,11 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) {
|
|||||||
|
|
||||||
// if the cache is at capacity, make room for new cert
|
// if the cache is at capacity, make room for new cert
|
||||||
cacheSize := len(certCache.cache)
|
cacheSize := len(certCache.cache)
|
||||||
if certCache.options.Capacity > 0 && cacheSize >= certCache.options.Capacity {
|
certCache.optionsMu.RLock()
|
||||||
|
atCapacity := certCache.options.Capacity > 0 && cacheSize >= certCache.options.Capacity
|
||||||
|
certCache.optionsMu.RUnlock()
|
||||||
|
|
||||||
|
if atCapacity {
|
||||||
// Go maps are "nondeterministic" but not actually random,
|
// Go maps are "nondeterministic" but not actually random,
|
||||||
// so although we could just chop off the "front" of the
|
// so although we could just chop off the "front" of the
|
||||||
// map with less code, that is a heavily skewed eviction
|
// map with less code, that is a heavily skewed eviction
|
||||||
@ -256,6 +267,7 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) {
|
|||||||
certCache.cacheIndex[name] = append(certCache.cacheIndex[name], cert.hash)
|
certCache.cacheIndex[name] = append(certCache.cacheIndex[name], cert.hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certCache.optionsMu.RLock()
|
||||||
certCache.logger.Debug("added certificate to cache",
|
certCache.logger.Debug("added certificate to cache",
|
||||||
zap.Strings("subjects", cert.Names),
|
zap.Strings("subjects", cert.Names),
|
||||||
zap.Time("expiration", expiresAt(cert.Leaf)),
|
zap.Time("expiration", expiresAt(cert.Leaf)),
|
||||||
@ -264,6 +276,7 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) {
|
|||||||
zap.String("hash", cert.hash),
|
zap.String("hash", cert.hash),
|
||||||
zap.Int("cache_size", len(certCache.cache)),
|
zap.Int("cache_size", len(certCache.cache)),
|
||||||
zap.Int("cache_capacity", certCache.options.Capacity))
|
zap.Int("cache_capacity", certCache.options.Capacity))
|
||||||
|
certCache.optionsMu.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeCertificate removes cert from the cache.
|
// removeCertificate removes cert from the cache.
|
||||||
@ -290,6 +303,7 @@ func (certCache *Cache) removeCertificate(cert Certificate) {
|
|||||||
// delete the actual cert from the cache
|
// delete the actual cert from the cache
|
||||||
delete(certCache.cache, cert.hash)
|
delete(certCache.cache, cert.hash)
|
||||||
|
|
||||||
|
certCache.optionsMu.RLock()
|
||||||
certCache.logger.Debug("removed certificate from cache",
|
certCache.logger.Debug("removed certificate from cache",
|
||||||
zap.Strings("subjects", cert.Names),
|
zap.Strings("subjects", cert.Names),
|
||||||
zap.Time("expiration", expiresAt(cert.Leaf)),
|
zap.Time("expiration", expiresAt(cert.Leaf)),
|
||||||
@ -298,6 +312,7 @@ func (certCache *Cache) removeCertificate(cert Certificate) {
|
|||||||
zap.String("hash", cert.hash),
|
zap.String("hash", cert.hash),
|
||||||
zap.Int("cache_size", len(certCache.cache)),
|
zap.Int("cache_size", len(certCache.cache)),
|
||||||
zap.Int("cache_capacity", certCache.options.Capacity))
|
zap.Int("cache_capacity", certCache.options.Capacity))
|
||||||
|
certCache.optionsMu.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaceCertificate atomically replaces oldCert with newCert in
|
// replaceCertificate atomically replaces oldCert with newCert in
|
||||||
@ -314,11 +329,13 @@ func (certCache *Cache) replaceCertificate(oldCert, newCert Certificate) {
|
|||||||
zap.Time("new_expiration", expiresAt(newCert.Leaf)))
|
zap.Time("new_expiration", expiresAt(newCert.Leaf)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (certCache *Cache) getAllMatchingCerts(name string) []Certificate {
|
// getAllMatchingCerts returns all certificates with exactly this subject
|
||||||
|
// (wildcards are NOT expanded).
|
||||||
|
func (certCache *Cache) getAllMatchingCerts(subject string) []Certificate {
|
||||||
certCache.mu.RLock()
|
certCache.mu.RLock()
|
||||||
defer certCache.mu.RUnlock()
|
defer certCache.mu.RUnlock()
|
||||||
|
|
||||||
allCertKeys := certCache.cacheIndex[name]
|
allCertKeys := certCache.cacheIndex[subject]
|
||||||
|
|
||||||
certs := make([]Certificate, len(allCertKeys))
|
certs := make([]Certificate, len(allCertKeys))
|
||||||
for i := range allCertKeys {
|
for i := range allCertKeys {
|
||||||
@ -339,7 +356,11 @@ func (certCache *Cache) getAllCerts() []Certificate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (certCache *Cache) getConfig(cert Certificate) (*Config, error) {
|
func (certCache *Cache) getConfig(cert Certificate) (*Config, error) {
|
||||||
cfg, err := certCache.options.GetConfigForCert(cert)
|
certCache.optionsMu.RLock()
|
||||||
|
getCert := certCache.options.GetConfigForCert
|
||||||
|
certCache.optionsMu.RUnlock()
|
||||||
|
|
||||||
|
cfg, err := getCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -373,6 +394,33 @@ func (certCache *Cache) AllMatchingCertificates(name string) []Certificate {
|
|||||||
return certs
|
return certs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveManaged removes managed certificates for the given subjects from the cache.
|
||||||
|
// This effectively stops maintenance of those certificates.
|
||||||
|
func (certCache *Cache) RemoveManaged(subjects []string) {
|
||||||
|
deleteQueue := make([]string, 0, len(subjects))
|
||||||
|
for _, subject := range subjects {
|
||||||
|
certs := certCache.getAllMatchingCerts(subject) // does NOT expand wildcards; exact matches only
|
||||||
|
for _, cert := range certs {
|
||||||
|
if !cert.managed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deleteQueue = append(deleteQueue, cert.hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
certCache.Remove(deleteQueue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes certificates with the given hashes from the cache.
|
||||||
|
// This is effectively used to unload manually-loaded certificates.
|
||||||
|
func (certCache *Cache) Remove(hashes []string) {
|
||||||
|
certCache.mu.Lock()
|
||||||
|
for _, h := range hashes {
|
||||||
|
cert := certCache.cache[h]
|
||||||
|
certCache.removeCertificate(cert)
|
||||||
|
}
|
||||||
|
certCache.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultCache *Cache
|
defaultCache *Cache
|
||||||
defaultCacheMu sync.Mutex
|
defaultCacheMu sync.Mutex
|
||||||
|
@ -21,6 +21,9 @@ func TestNewCache(t *testing.T) {
|
|||||||
c := NewCache(CacheOptions{GetConfigForCert: noop})
|
c := NewCache(CacheOptions{GetConfigForCert: noop})
|
||||||
defer c.Stop()
|
defer c.Stop()
|
||||||
|
|
||||||
|
c.optionsMu.RLock()
|
||||||
|
defer c.optionsMu.RUnlock()
|
||||||
|
|
||||||
if c.options.RenewCheckInterval != DefaultRenewCheckInterval {
|
if c.options.RenewCheckInterval != DefaultRenewCheckInterval {
|
||||||
t.Errorf("Expected RenewCheckInterval to be set to default value, but it wasn't: %s", c.options.RenewCheckInterval)
|
t.Errorf("Expected RenewCheckInterval to be set to default value, but it wasn't: %s", c.options.RenewCheckInterval)
|
||||||
}
|
}
|
||||||
|
@ -155,29 +155,32 @@ func (cfg *Config) loadManagedCertificate(ctx context.Context, domain string) (C
|
|||||||
|
|
||||||
// CacheUnmanagedCertificatePEMFile loads a certificate for host using certFile
|
// CacheUnmanagedCertificatePEMFile loads a certificate for host using certFile
|
||||||
// and keyFile, which must be in PEM format. It stores the certificate in
|
// and keyFile, which must be in PEM format. It stores the certificate in
|
||||||
// the in-memory cache.
|
// the in-memory cache and returns the hash, useful for removing from the cache.
|
||||||
//
|
//
|
||||||
// This method is safe for concurrent use.
|
// This method is safe for concurrent use.
|
||||||
func (cfg *Config) CacheUnmanagedCertificatePEMFile(ctx context.Context, certFile, keyFile string, tags []string) error {
|
func (cfg *Config) CacheUnmanagedCertificatePEMFile(ctx context.Context, certFile, keyFile string, tags []string) (string, error) {
|
||||||
cert, err := cfg.makeCertificateFromDiskWithOCSP(ctx, cfg.Storage, certFile, keyFile)
|
cert, err := cfg.makeCertificateFromDiskWithOCSP(ctx, cfg.Storage, certFile, keyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
cert.Tags = tags
|
cert.Tags = tags
|
||||||
cfg.certCache.cacheCertificate(cert)
|
cfg.certCache.cacheCertificate(cert)
|
||||||
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
||||||
return nil
|
return cert.hash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheUnmanagedTLSCertificate adds tlsCert to the certificate cache.
|
// CacheUnmanagedTLSCertificate adds tlsCert to the certificate cache
|
||||||
|
//
|
||||||
|
// and returns the hash, useful for removing from the cache.
|
||||||
|
//
|
||||||
// It staples OCSP if possible.
|
// It staples OCSP if possible.
|
||||||
//
|
//
|
||||||
// This method is safe for concurrent use.
|
// This method is safe for concurrent use.
|
||||||
func (cfg *Config) CacheUnmanagedTLSCertificate(ctx context.Context, tlsCert tls.Certificate, tags []string) error {
|
func (cfg *Config) CacheUnmanagedTLSCertificate(ctx context.Context, tlsCert tls.Certificate, tags []string) (string, error) {
|
||||||
var cert Certificate
|
var cert Certificate
|
||||||
err := fillCertFromLeaf(&cert, tlsCert)
|
err := fillCertFromLeaf(&cert, tlsCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
err = stapleOCSP(ctx, cfg.OCSP, cfg.Storage, &cert, nil)
|
err = stapleOCSP(ctx, cfg.OCSP, cfg.Storage, &cert, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -186,22 +189,23 @@ func (cfg *Config) CacheUnmanagedTLSCertificate(ctx context.Context, tlsCert tls
|
|||||||
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
||||||
cert.Tags = tags
|
cert.Tags = tags
|
||||||
cfg.certCache.cacheCertificate(cert)
|
cfg.certCache.cacheCertificate(cert)
|
||||||
return nil
|
return cert.hash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheUnmanagedCertificatePEMBytes makes a certificate out of the PEM bytes
|
// CacheUnmanagedCertificatePEMBytes makes a certificate out of the PEM bytes
|
||||||
// of the certificate and key, then caches it in memory.
|
// of the certificate and key, then caches it in memory, and returns the hash,
|
||||||
|
// which is useful for removing from the cache.
|
||||||
//
|
//
|
||||||
// This method is safe for concurrent use.
|
// This method is safe for concurrent use.
|
||||||
func (cfg *Config) CacheUnmanagedCertificatePEMBytes(ctx context.Context, certBytes, keyBytes []byte, tags []string) error {
|
func (cfg *Config) CacheUnmanagedCertificatePEMBytes(ctx context.Context, certBytes, keyBytes []byte, tags []string) (string, error) {
|
||||||
cert, err := cfg.makeCertificateWithOCSP(ctx, certBytes, keyBytes)
|
cert, err := cfg.makeCertificateWithOCSP(ctx, certBytes, keyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
cert.Tags = tags
|
cert.Tags = tags
|
||||||
cfg.certCache.cacheCertificate(cert)
|
cfg.certCache.cacheCertificate(cert)
|
||||||
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
cfg.emit(ctx, "cached_unmanaged_cert", map[string]any{"sans": cert.Names})
|
||||||
return nil
|
return cert.hash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeCertificateFromDiskWithOCSP makes a Certificate by loading the
|
// makeCertificateFromDiskWithOCSP makes a Certificate by loading the
|
||||||
|
27
config.go
27
config.go
@ -209,7 +209,10 @@ func New(certCache *Cache, cfg Config) *Config {
|
|||||||
if certCache == nil {
|
if certCache == nil {
|
||||||
panic("a certificate cache is required")
|
panic("a certificate cache is required")
|
||||||
}
|
}
|
||||||
if certCache.options.GetConfigForCert == nil {
|
certCache.optionsMu.RLock()
|
||||||
|
getConfigForCert := certCache.options.GetConfigForCert
|
||||||
|
defer certCache.optionsMu.RUnlock()
|
||||||
|
if getConfigForCert == nil {
|
||||||
panic("cache must have GetConfigForCert set in its options")
|
panic("cache must have GetConfigForCert set in its options")
|
||||||
}
|
}
|
||||||
return newWithCache(certCache, cfg)
|
return newWithCache(certCache, cfg)
|
||||||
@ -450,28 +453,6 @@ func (cfg *Config) manageOne(ctx context.Context, domainName string, async bool)
|
|||||||
return renew()
|
return renew()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmanage causes the certificates for domainNames to stop being managed.
|
|
||||||
// If there are certificates for the supplied domain names in the cache, they
|
|
||||||
// are evicted from the cache.
|
|
||||||
func (cfg *Config) Unmanage(domainNames []string) {
|
|
||||||
var deleteQueue []Certificate
|
|
||||||
for _, domainName := range domainNames {
|
|
||||||
certs := cfg.certCache.AllMatchingCertificates(domainName)
|
|
||||||
for _, cert := range certs {
|
|
||||||
if !cert.managed {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
deleteQueue = append(deleteQueue, cert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.certCache.mu.Lock()
|
|
||||||
for _, cert := range deleteQueue {
|
|
||||||
cfg.certCache.removeCertificate(cert)
|
|
||||||
}
|
|
||||||
cfg.certCache.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObtainCertSync generates a new private key and obtains a certificate for
|
// ObtainCertSync generates a new private key and obtains a certificate for
|
||||||
// name using cfg in the foreground; i.e. interactively and without retries.
|
// name using cfg in the foreground; i.e. interactively and without retries.
|
||||||
// It stows the renewed certificate and its assets in storage if successful.
|
// It stows the renewed certificate and its assets in storage if successful.
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -35,6 +34,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/klauspost/cpuid/v2"
|
"github.com/klauspost/cpuid/v2"
|
||||||
|
"github.com/zeebo/blake3"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"golang.org/x/net/idna"
|
"golang.org/x/net/idna"
|
||||||
)
|
)
|
||||||
@ -271,7 +271,7 @@ func (cfg *Config) loadCertResource(ctx context.Context, issuer Issuer, certName
|
|||||||
// which is the chain of DER-encoded bytes. It returns the
|
// which is the chain of DER-encoded bytes. It returns the
|
||||||
// hex encoding of the hash.
|
// hex encoding of the hash.
|
||||||
func hashCertificateChain(certChain [][]byte) string {
|
func hashCertificateChain(certChain [][]byte) string {
|
||||||
h := sha256.New()
|
h := blake3.New()
|
||||||
for _, certInChain := range certChain {
|
for _, certInChain := range certChain {
|
||||||
h.Write(certInChain)
|
h.Write(certInChain)
|
||||||
}
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/libdns/libdns v0.2.1
|
github.com/libdns/libdns v0.2.1
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/miekg/dns v1.1.55
|
github.com/miekg/dns v1.1.55
|
||||||
|
github.com/zeebo/blake3 v0.2.3
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/crypto v0.10.0
|
golang.org/x/crypto v0.10.0
|
||||||
golang.org/x/net v0.11.0
|
golang.org/x/net v0.11.0
|
||||||
|
7
go.sum
7
go.sum
@ -1,5 +1,6 @@
|
|||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||||
@ -11,6 +12,12 @@ github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60
|
|||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
|
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
|
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||||
|
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||||
|
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||||
|
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
|
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||||
|
@ -341,7 +341,9 @@ func (cfg *Config) getCertDuringHandshake(ctx context.Context, hello *tls.Client
|
|||||||
// perfectly full while still being able to load needed certs from storage.
|
// perfectly full while still being able to load needed certs from storage.
|
||||||
// See https://caddy.community/t/error-tls-alert-internal-error-592-again/13272
|
// See https://caddy.community/t/error-tls-alert-internal-error-592-again/13272
|
||||||
// and caddyserver/caddy#4320.
|
// and caddyserver/caddy#4320.
|
||||||
|
cfg.certCache.optionsMu.RLock()
|
||||||
cacheCapacity := float64(cfg.certCache.options.Capacity)
|
cacheCapacity := float64(cfg.certCache.options.Capacity)
|
||||||
|
cfg.certCache.optionsMu.RUnlock()
|
||||||
cacheAlmostFull := cacheCapacity > 0 && float64(cacheSize) >= cacheCapacity*.9
|
cacheAlmostFull := cacheCapacity > 0 && float64(cacheSize) >= cacheCapacity*.9
|
||||||
loadDynamically := cfg.OnDemand != nil || cacheAlmostFull
|
loadDynamically := cfg.OnDemand != nil || cacheAlmostFull
|
||||||
|
|
||||||
|
@ -53,8 +53,10 @@ func (certCache *Cache) maintainAssets(panicCount int) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
certCache.optionsMu.RLock()
|
||||||
renewalTicker := time.NewTicker(certCache.options.RenewCheckInterval)
|
renewalTicker := time.NewTicker(certCache.options.RenewCheckInterval)
|
||||||
ocspTicker := time.NewTicker(certCache.options.OCSPCheckInterval)
|
ocspTicker := time.NewTicker(certCache.options.OCSPCheckInterval)
|
||||||
|
certCache.optionsMu.RUnlock()
|
||||||
|
|
||||||
log.Info("started background certificate maintenance")
|
log.Info("started background certificate maintenance")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user