summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/caddyserver
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/caddyserver')
-rw-r--r--vendor/github.com/caddyserver/certmagic/acmeclient.go12
-rw-r--r--vendor/github.com/caddyserver/certmagic/certificates.go6
-rw-r--r--vendor/github.com/caddyserver/certmagic/certmagic.go4
-rw-r--r--vendor/github.com/caddyserver/certmagic/config.go233
-rw-r--r--vendor/github.com/caddyserver/certmagic/crypto.go11
-rw-r--r--vendor/github.com/caddyserver/certmagic/dnsutil.go14
-rw-r--r--vendor/github.com/caddyserver/certmagic/go.mod10
-rw-r--r--vendor/github.com/caddyserver/certmagic/go.sum59
-rw-r--r--vendor/github.com/caddyserver/certmagic/handshake.go4
-rw-r--r--vendor/github.com/caddyserver/certmagic/maintain.go126
10 files changed, 352 insertions, 127 deletions
diff --git a/vendor/github.com/caddyserver/certmagic/acmeclient.go b/vendor/github.com/caddyserver/certmagic/acmeclient.go
index 8a61a08255..cc876b9252 100644
--- a/vendor/github.com/caddyserver/certmagic/acmeclient.go
+++ b/vendor/github.com/caddyserver/certmagic/acmeclient.go
@@ -298,14 +298,22 @@ func (c *acmeClient) throttle(ctx context.Context, names []string) error {
}
rateLimitersMu.Unlock()
if c.mgr.Logger != nil {
- c.mgr.Logger.Info("waiting on internal rate limiter", zap.Strings("identifiers", names))
+ c.mgr.Logger.Info("waiting on internal rate limiter",
+ zap.Strings("identifiers", names),
+ zap.String("ca", c.acmeClient.Directory),
+ zap.String("account", c.mgr.Email),
+ )
}
err := rl.Wait(ctx)
if err != nil {
return err
}
if c.mgr.Logger != nil {
- c.mgr.Logger.Info("done waiting on internal rate limiter", zap.Strings("identifiers", names))
+ c.mgr.Logger.Info("done waiting on internal rate limiter",
+ zap.Strings("identifiers", names),
+ zap.String("ca", c.acmeClient.Directory),
+ zap.String("account", c.mgr.Email),
+ )
}
return nil
}
diff --git a/vendor/github.com/caddyserver/certmagic/certificates.go b/vendor/github.com/caddyserver/certmagic/certificates.go
index 09dc340d03..e6dab5e0ff 100644
--- a/vendor/github.com/caddyserver/certmagic/certificates.go
+++ b/vendor/github.com/caddyserver/certmagic/certificates.go
@@ -47,8 +47,11 @@ type Certificate struct {
// The hex-encoded hash of this cert's chain's bytes.
hash string
- // Whether this certificate is under our management
+ // Whether this certificate is under our management.
managed bool
+
+ // The unique string identifying the issuer of this certificate.
+ issuerKey string
}
// NeedsRenewal returns true if the certificate is
@@ -126,6 +129,7 @@ func (cfg *Config) loadManagedCertificate(domain string) (Certificate, error) {
return cert, err
}
cert.managed = true
+ cert.issuerKey = certRes.issuerKey
return cert, nil
}
diff --git a/vendor/github.com/caddyserver/certmagic/certmagic.go b/vendor/github.com/caddyserver/certmagic/certmagic.go
index 03844b4ad9..bb33b90c55 100644
--- a/vendor/github.com/caddyserver/certmagic/certmagic.go
+++ b/vendor/github.com/caddyserver/certmagic/certmagic.go
@@ -410,6 +410,10 @@ type CertificateResource struct {
// Any extra information associated with the certificate,
// usually provided by the issuer implementation.
IssuerData interface{} `json:"issuer_data,omitempty"`
+
+ // The unique string identifying the issuer of the
+ // certificate; internally useful for storage access.
+ issuerKey string `json:"-"`
}
// NamesKey returns the list of SANs as a single string,
diff --git a/vendor/github.com/caddyserver/certmagic/config.go b/vendor/github.com/caddyserver/certmagic/config.go
index 1428a14e46..cce969b8bd 100644
--- a/vendor/github.com/caddyserver/certmagic/config.go
+++ b/vendor/github.com/caddyserver/certmagic/config.go
@@ -24,6 +24,7 @@ import (
"crypto/x509/pkix"
"encoding/asn1"
"encoding/json"
+ "errors"
"fmt"
weakrand "math/rand"
"net"
@@ -247,7 +248,7 @@ func newWithCache(certCache *Cache, cfg Config) *Config {
// interactive use (i.e. when an administrator is present) so
// that errors can be reported and fixed immediately.
func (cfg *Config) ManageSync(domainNames []string) error {
- return cfg.manageAll(nil, domainNames, false)
+ return cfg.manageAll(context.Background(), domainNames, false)
}
// ClientCredentials returns a list of TLS client certificate chains for the given identifiers.
@@ -326,7 +327,12 @@ func (cfg *Config) manageOne(ctx context.Context, domainName string, async bool)
}
// if we don't have one in storage, obtain one
obtain := func() error {
- err := cfg.ObtainCert(ctx, domainName, !async)
+ var err error
+ if async {
+ err = cfg.ObtainCertAsync(ctx, domainName)
+ } else {
+ err = cfg.ObtainCertSync(ctx, domainName)
+ }
if err != nil {
return fmt.Errorf("%s: obtaining certificate: %w", domainName, err)
}
@@ -357,7 +363,12 @@ func (cfg *Config) manageOne(ctx context.Context, domainName string, async bool)
// for an existing certificate, make sure it is renewed
renew := func() error {
- err := cfg.RenewCert(ctx, domainName, !async)
+ var err error
+ if async {
+ err = cfg.RenewCertAsync(ctx, domainName, false)
+ } else {
+ err = cfg.RenewCertSync(ctx, domainName, false)
+ }
if err != nil {
return fmt.Errorf("%s: renewing certificate: %w", domainName, err)
}
@@ -401,34 +412,38 @@ func (cfg *Config) Unmanage(domainNames []string) {
cfg.certCache.mu.Unlock()
}
-// ObtainCert obtains a certificate for name using cfg, as long
-// as a certificate does not already exist in storage for that
-// name. The name must qualify and cfg must be flagged as Managed.
-// This function is a no-op if storage already has a certificate
-// for name.
-//
-// It only obtains and stores certificates (and their keys),
-// it does not load them into memory. If interactive is true,
-// the user may be shown a prompt.
-// TODO: consider moving interactive param into the Config struct,
-// and maybe retry settings into the Config struct as well? (same for RenewCert)
-func (cfg *Config) ObtainCert(ctx context.Context, name string, interactive bool) error {
+// ObtainCertSync generates a new private key and obtains a certificate for
+// 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 DOES NOT load the certificate into the in-memory cache. This method
+// is a no-op if storage already has a certificate for name.
+func (cfg *Config) ObtainCertSync(ctx context.Context, name string) error {
+ return cfg.obtainCert(ctx, name, true)
+}
+
+// ObtainCertAsync is the same as ObtainCertSync(), except it runs in the
+// background; i.e. non-interactively, and with retries if it fails.
+func (cfg *Config) ObtainCertAsync(ctx context.Context, name string) error {
+ return cfg.obtainCert(ctx, name, false)
+}
+
+func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool) error {
if len(cfg.Issuers) == 0 {
return fmt.Errorf("no issuers configured; impossible to obtain or check for existing certificate in storage")
}
+
+ // if storage has all resources for this certificate, obtain is a no-op
if cfg.storageHasCertResourcesAnyIssuer(name) {
return nil
}
+
// ensure storage is writeable and readable
// TODO: this is not necessary every time; should only perform check once every so often for each storage, which may require some global state...
err := cfg.checkStorage()
if err != nil {
return fmt.Errorf("failed storage check: %v - storage is probably misconfigured", err)
}
- return cfg.obtainCert(ctx, name, interactive)
-}
-func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool) error {
log := loggerNamed(cfg.Logger, "obtain")
if log != nil {
@@ -437,7 +452,7 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
// ensure idempotency of the obtain operation for this name
lockKey := cfg.lockKey(certIssueLockOp, name)
- err := acquireLock(ctx, cfg.Storage, lockKey)
+ err = acquireLock(ctx, cfg.Storage, lockKey)
if err != nil {
return fmt.Errorf("unable to acquire lock '%s': %v", lockKey, err)
}
@@ -467,16 +482,24 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
return nil
}
- privateKey, err := cfg.KeySource.GenerateKey()
+ // if storage has a private key already, use it; otherwise,
+ // we'll generate our own
+ privKey, privKeyPEM, issuers, err := cfg.reusePrivateKey(name)
if err != nil {
return err
}
- privKeyPEM, err := encodePrivateKey(privateKey)
- if err != nil {
- return err
+ if privKey == nil {
+ privKey, err = cfg.KeySource.GenerateKey()
+ if err != nil {
+ return err
+ }
+ privKeyPEM, err = encodePrivateKey(privKey)
+ if err != nil {
+ return err
+ }
}
- csr, err := cfg.generateCSR(privateKey, []string{name})
+ csr, err := cfg.generateCSR(privKey, []string{name})
if err != nil {
return err
}
@@ -484,21 +507,37 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
// try to obtain from each issuer until we succeed
var issuedCert *IssuedCertificate
var issuerUsed Issuer
- for _, issuer := range cfg.Issuers {
+ for i, issuer := range issuers {
+ log.Debug(fmt.Sprintf("trying issuer %d/%d", i+1, len(cfg.Issuers)),
+ zap.String("issuer", issuer.IssuerKey()))
+
if prechecker, ok := issuer.(PreChecker); ok {
err = prechecker.PreCheck(ctx, []string{name}, interactive)
if err != nil {
continue
}
}
+
issuedCert, err = issuer.Issue(ctx, csr)
if err == nil {
issuerUsed = issuer
break
}
+
+ // err is usually wrapped, which is nice for simply printing it, but
+ // with our structured error logs we only need the problem string
+ errToLog := err
+ var problem acme.Problem
+ if errors.As(err, &problem) {
+ errToLog = problem
+ }
+ log.Error("could not get certificate from issuer",
+ zap.String("identifier", name),
+ zap.String("issuer", issuer.IssuerKey()),
+ zap.Error(errToLog))
}
if err != nil {
- // TODO: only the error from the last issuer will be returned, oh well?
+ // only the error from the last issuer will be returned, but we logged the others
return fmt.Errorf("[%s] Obtain: %w", name, err)
}
@@ -532,6 +571,47 @@ func (cfg *Config) obtainCert(ctx context.Context, name string, interactive bool
return err
}
+// reusePrivateKey looks for a private key for domain in storage in the configured issuers
+// paths. For the first private key it finds, it returns that key both decoded and PEM-encoded,
+// as well as the reordered list of issuers to use instead of cfg.Issuers (because if a key
+// is found, that issuer should be tried first, so it is moved to the front in a copy of
+// cfg.Issuers).
+func (cfg *Config) reusePrivateKey(domain string) (privKey crypto.PrivateKey, privKeyPEM []byte, issuers []Issuer, err error) {
+ // make a copy of cfg.Issuers so that if we have to reorder elements, we don't
+ // inadvertently mutate the configured issuers (see append calls below)
+ issuers = make([]Issuer, len(cfg.Issuers))
+ copy(issuers, cfg.Issuers)
+
+ for i, issuer := range issuers {
+ // see if this issuer location in storage has a private key for the domain
+ privateKeyStorageKey := StorageKeys.SitePrivateKey(issuer.IssuerKey(), domain)
+ privKeyPEM, err = cfg.Storage.Load(privateKeyStorageKey)
+ if _, ok := err.(ErrNotExist); ok {
+ err = nil // obviously, it's OK to not have a private key; so don't prevent obtaining a cert
+ continue
+ }
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("loading existing private key for reuse with issuer %s: %v", issuer.IssuerKey(), err)
+ }
+
+ // we loaded a private key; try decoding it so we can use it
+ privKey, err = decodePrivateKey(privKeyPEM)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ // since the private key was found in storage for this issuer, move it
+ // to the front of the list so we prefer this issuer first
+ issuers = append([]Issuer{issuer}, append(issuers[:i], issuers[i+1:]...)...)
+ break
+ }
+
+ return
+}
+
+// storageHasCertResourcesAnyIssuer returns true if storage has all the
+// certificate resources in storage from any configured issuer. It checks
+// all configured issuers in order.
func (cfg *Config) storageHasCertResourcesAnyIssuer(name string) bool {
for _, iss := range cfg.Issuers {
if cfg.storageHasCertResources(iss, name) {
@@ -541,23 +621,36 @@ func (cfg *Config) storageHasCertResourcesAnyIssuer(name string) bool {
return false
}
-// RenewCert renews the certificate for name using cfg. It stows the
-// renewed certificate and its assets in storage if successful. It
-// DOES NOT update the in-memory cache with the new certificate.
-func (cfg *Config) RenewCert(ctx context.Context, name string, interactive bool) error {
+// RenewCertSync renews the certificate for 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 DOES NOT update the in-memory
+// cache with the new certificate. The certificate will not be renewed if it
+// is not close to expiring unless force is true.
+//
+// Renewing a certificate is the same as obtaining a certificate, except that
+// the existing private key already in storage is reused.
+func (cfg *Config) RenewCertSync(ctx context.Context, name string, force bool) error {
+ return cfg.renewCert(ctx, name, force, true)
+}
+
+// RenewCertAsync is the same as RenewCertSync(), except it runs in the
+// background; i.e. non-interactively, and with retries if it fails.
+func (cfg *Config) RenewCertAsync(ctx context.Context, name string, force bool) error {
+ return cfg.renewCert(ctx, name, force, false)
+}
+
+func (cfg *Config) renewCert(ctx context.Context, name string, force, interactive bool) error {
if len(cfg.Issuers) == 0 {
return fmt.Errorf("no issuers configured; impossible to renew or check existing certificate in storage")
}
+
// ensure storage is writeable and readable
// TODO: this is not necessary every time; should only perform check once every so often for each storage, which may require some global state...
err := cfg.checkStorage()
if err != nil {
return fmt.Errorf("failed storage check: %v - storage is probably misconfigured", err)
}
- return cfg.renewCert(ctx, name, interactive)
-}
-func (cfg *Config) renewCert(ctx context.Context, name string, interactive bool) error {
log := loggerNamed(cfg.Logger, "renew")
if log != nil {
@@ -566,7 +659,7 @@ func (cfg *Config) renewCert(ctx context.Context, name string, interactive bool)
// ensure idempotency of the renew operation for this name
lockKey := cfg.lockKey(certIssueLockOp, name)
- err := acquireLock(ctx, cfg.Storage, lockKey)
+ err = acquireLock(ctx, cfg.Storage, lockKey)
if err != nil {
return fmt.Errorf("unable to acquire lock '%s': %v", lockKey, err)
}
@@ -597,13 +690,22 @@ func (cfg *Config) renewCert(ctx context.Context, name string, interactive bool)
// check if renew is still needed - might have been renewed while waiting for lock
timeLeft, needsRenew := cfg.managedCertNeedsRenewal(certRes)
if !needsRenew {
- if log != nil {
- log.Info("certificate appears to have been renewed already",
- zap.String("identifier", name),
- zap.Duration("remaining", timeLeft))
+ if force {
+ if log != nil {
+ log.Info("certificate does not need to be renewed, but renewal is being forced",
+ zap.String("identifier", name),
+ zap.Duration("remaining", timeLeft))
+ }
+ } else {
+ if log != nil {
+ log.Info("certificate appears to have been renewed already",
+ zap.String("identifier", name),
+ zap.Duration("remaining", timeLeft))
+ }
+ return nil
}
- return nil
}
+
if log != nil {
log.Info("renewing certificate",
zap.String("identifier", name),
@@ -629,14 +731,27 @@ func (cfg *Config) renewCert(ctx context.Context, name string, interactive bool)
continue
}
}
+
issuedCert, err = issuer.Issue(ctx, csr)
if err == nil {
issuerUsed = issuer
break
}
+
+ // err is usually wrapped, which is nice for simply printing it, but
+ // with our structured error logs we only need the problem string
+ errToLog := err
+ var problem acme.Problem
+ if errors.As(err, &problem) {
+ errToLog = problem
+ }
+ log.Error("could not get certificate from issuer",
+ zap.String("identifier", name),
+ zap.String("issuer", issuer.IssuerKey()),
+ zap.Error(errToLog))
}
if err != nil {
- // TODO: only the error from the last issuer will be returned, oh well?
+ // only the error from the last issuer will be returned, but we logged the others
return fmt.Errorf("[%s] Renew: %w", name, err)
}
@@ -705,6 +820,9 @@ func (cfg *Config) generateCSR(privateKey crypto.PrivateKey, sans []string) (*x5
// RevokeCert revokes the certificate for domain via ACME protocol. It requires
// that cfg.Issuers is properly configured with the same issuer that issued the
// certificate being revoked. See RFC 5280 ยง5.3.1 for reason codes.
+//
+// The certificate assets are deleted from storage after successful revocation
+// to prevent reuse.
func (cfg *Config) RevokeCert(ctx context.Context, domain string, reason int, interactive bool) error {
for i, issuer := range cfg.Issuers {
issuerKey := issuer.IssuerKey()
@@ -730,17 +848,9 @@ func (cfg *Config) RevokeCert(ctx context.Context, domain string, reason int, in
cfg.emit("cert_revoked", domain)
- err = cfg.Storage.Delete(StorageKeys.SiteCert(issuerKey, domain))
- if err != nil {
- return fmt.Errorf("certificate revoked, but unable to delete certificate file: %v", err)
- }
- err = cfg.Storage.Delete(StorageKeys.SitePrivateKey(issuerKey, domain))
+ err = cfg.deleteSiteAssets(issuerKey, domain)
if err != nil {
- return fmt.Errorf("certificate revoked, but unable to delete private key: %v", err)
- }
- err = cfg.Storage.Delete(StorageKeys.SiteMeta(issuerKey, domain))
- if err != nil {
- return fmt.Errorf("certificate revoked, but unable to delete certificate metadata: %v", err)
+ return fmt.Errorf("certificate revoked, but unable to fully clean up assets from issuer %s: %v", issuerKey, err)
}
}
@@ -877,6 +987,29 @@ func (cfg *Config) storageHasCertResources(issuer Issuer, domain string) bool {
cfg.Storage.Exists(metaKey)
}
+// deleteSiteAssets deletes the folder in storage containing the
+// certificate, private key, and metadata file for domain from the
+// issuer with the given issuer key.
+func (cfg *Config) deleteSiteAssets(issuerKey, domain string) error {
+ err := cfg.Storage.Delete(StorageKeys.SiteCert(issuerKey, domain))
+ if err != nil {
+ return fmt.Errorf("deleting certificate file: %v", err)
+ }
+ err = cfg.Storage.Delete(StorageKeys.SitePrivateKey(issuerKey, domain))
+ if err != nil {
+ return fmt.Errorf("deleting private key: %v", err)
+ }
+ err = cfg.Storage.Delete(StorageKeys.SiteMeta(issuerKey, domain))
+ if err != nil {
+ return fmt.Errorf("deleting metadata file: %v", err)
+ }
+ err = cfg.Storage.Delete(StorageKeys.CertsSitePrefix(issuerKey, domain))
+ if err != nil {
+ return fmt.Errorf("deleting site asset folder: %v", err)
+ }
+ return nil
+}
+
// lockKey returns a key for a lock that is specific to the operation
// named op being performed related to domainName and this config's CA.
func (cfg *Config) lockKey(op, domainName string) string {
diff --git a/vendor/github.com/caddyserver/certmagic/crypto.go b/vendor/github.com/caddyserver/certmagic/crypto.go
index 8d9f3c7669..a705cdde2c 100644
--- a/vendor/github.com/caddyserver/certmagic/crypto.go
+++ b/vendor/github.com/caddyserver/certmagic/crypto.go
@@ -229,25 +229,24 @@ func (cfg *Config) loadCertResourceAnyIssuer(certNamesKey string) (CertificateRe
// loadCertResource loads a certificate resource from the given issuer's storage location.
func (cfg *Config) loadCertResource(issuer Issuer, certNamesKey string) (CertificateResource, error) {
- var certRes CertificateResource
- issuerKey := issuer.IssuerKey()
+ certRes := CertificateResource{issuerKey: issuer.IssuerKey()}
normalizedName, err := idna.ToASCII(certNamesKey)
if err != nil {
- return certRes, fmt.Errorf("converting '%s' to ASCII: %v", certNamesKey, err)
+ return CertificateResource{}, fmt.Errorf("converting '%s' to ASCII: %v", certNamesKey, err)
}
- certBytes, err := cfg.Storage.Load(StorageKeys.SiteCert(issuerKey, normalizedName))
+ certBytes, err := cfg.Storage.Load(StorageKeys.SiteCert(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.CertificatePEM = certBytes
- keyBytes, err := cfg.Storage.Load(StorageKeys.SitePrivateKey(issuerKey, normalizedName))
+ keyBytes, err := cfg.Storage.Load(StorageKeys.SitePrivateKey(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.PrivateKeyPEM = keyBytes
- metaBytes, err := cfg.Storage.Load(StorageKeys.SiteMeta(issuerKey, normalizedName))
+ metaBytes, err := cfg.Storage.Load(StorageKeys.SiteMeta(certRes.issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
diff --git a/vendor/github.com/caddyserver/certmagic/dnsutil.go b/vendor/github.com/caddyserver/certmagic/dnsutil.go
index 85f7714a80..2573cb9663 100644
--- a/vendor/github.com/caddyserver/certmagic/dnsutil.go
+++ b/vendor/github.com/caddyserver/certmagic/dnsutil.go
@@ -313,11 +313,17 @@ func updateDomainWithCName(r *dns.Msg, fqdn string) string {
}
// recursiveNameservers are used to pre-check DNS propagation. It
-// prepends user-configured nameservers (custom) to the defaults
-// obtained from resolv.conf and defaultNameservers and ensures
-// that all server addresses have a port value.
+// picks user-configured nameservers (custom) OR the defaults
+// obtained from resolv.conf and defaultNameservers if none is
+// configured and ensures that all server addresses have a port value.
func recursiveNameservers(custom []string) []string {
- servers := append(custom, systemOrDefaultNameservers(defaultResolvConf, defaultNameservers)...)
+ var servers []string
+ if len(custom) == 0 {
+ servers = systemOrDefaultNameservers(defaultResolvConf, defaultNameservers)
+ } else {
+ servers = make([]string, len(custom))
+ copy(servers, custom)
+ }
populateNameserverPorts(servers)
return servers
}
diff --git a/vendor/github.com/caddyserver/certmagic/go.mod b/vendor/github.com/caddyserver/certmagic/go.mod
index a17f10f1bd..42665bf1b3 100644
--- a/vendor/github.com/caddyserver/certmagic/go.mod
+++ b/vendor/github.com/caddyserver/certmagic/go.mod
@@ -4,10 +4,10 @@ go 1.14
require (
github.com/klauspost/cpuid/v2 v2.0.6
- github.com/libdns/libdns v0.2.0
+ github.com/libdns/libdns v0.2.1
github.com/mholt/acmez v0.1.3
- github.com/miekg/dns v1.1.30
- go.uber.org/zap v1.15.0
- golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
- golang.org/x/net v0.0.0-20200707034311-ab3426394381
+ github.com/miekg/dns v1.1.42
+ go.uber.org/zap v1.17.0
+ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
+ golang.org/x/net v0.0.0-20210525063256-abc453219eb5
)
diff --git a/vendor/github.com/caddyserver/certmagic/go.sum b/vendor/github.com/caddyserver/certmagic/go.sum
index ac4235326f..1251ac84f0 100644
--- a/vendor/github.com/caddyserver/certmagic/go.sum
+++ b/vendor/github.com/caddyserver/certmagic/go.sum
@@ -1,4 +1,3 @@
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -12,12 +11,12 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/libdns/libdns v0.2.0 h1:ewg3ByWrdUrxrje8ChPVMBNcotg7H9LQYg+u5De2RzI=
-github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
+github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
+github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk=
github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
-github.com/miekg/dns v1.1.30 h1:Qww6FseFn8PRfw07jueqIXqodm0JKiiKuK0DeXSqfyo=
-github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
+github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY=
+github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -25,54 +24,62 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
+go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
-golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
-golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
diff --git a/vendor/github.com/caddyserver/certmagic/handshake.go b/vendor/github.com/caddyserver/certmagic/handshake.go
index beb5cc3e9f..5506719c2b 100644
--- a/vendor/github.com/caddyserver/certmagic/handshake.go
+++ b/vendor/github.com/caddyserver/certmagic/handshake.go
@@ -375,7 +375,7 @@ func (cfg *Config) obtainOnDemandCertificate(hello *tls.ClientHelloInfo) (Certif
defer cancel()
// Obtain the certificate
- err = cfg.ObtainCert(ctx, name, false)
+ err = cfg.ObtainCertAsync(ctx, name)
// immediately unblock anyone waiting for it; doing this in
// a defer would risk deadlock because of the recursive call
@@ -520,7 +520,7 @@ func (cfg *Config) renewDynamicCertificate(hello *tls.ClientHelloInfo, currentCe
// Renew and reload the certificate
renewAndReload := func(ctx context.Context, cancel context.CancelFunc) (Certificate, error) {
defer cancel()
- err = cfg.RenewCert(ctx, name, false)
+ err = cfg.RenewCertAsync(ctx, name, false)
if err == nil {
// even though the recursive nature of the dynamic cert loading
// would just call this function anyway, we do it here to
diff --git a/vendor/github.com/caddyserver/certmagic/maintain.go b/vendor/github.com/caddyserver/certmagic/maintain.go
index 3e5a8736a7..63d475ced7 100644
--- a/vendor/github.com/caddyserver/certmagic/maintain.go
+++ b/vendor/github.com/caddyserver/certmagic/maintain.go
@@ -25,6 +25,7 @@ import (
"strings"
"time"
+ "github.com/mholt/acmez/acme"
"go.uber.org/zap"
"golang.org/x/crypto/ocsp"
)
@@ -250,7 +251,7 @@ func (certCache *Cache) queueRenewalTask(ctx context.Context, oldCert Certificat
}
// perform renewal - crucially, this happens OUTSIDE a lock on certCache
- err := cfg.RenewCert(ctx, renewName, false)
+ err := cfg.RenewCertAsync(ctx, renewName, false)
if err != nil {
if cfg.OnDemand != nil {
// loaded dynamically, remove dynamically
@@ -280,7 +281,7 @@ func (certCache *Cache) queueRenewalTask(ctx context.Context, oldCert Certificat
// Ryan Sleevi's recommendations for good OCSP support:
// https://gist.github.com/sleevi/5efe9ef98961ecfb4da8
func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
- log := loggerNamed(certCache.logger, "maintenance")
+ logger := loggerNamed(certCache.logger, "maintenance")
// temporary structures to store updates or tasks
// so that we can keep our locks short-lived
@@ -293,9 +294,13 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
certHash string
lastNextUpdate time.Time
}
+ type renewQueueEntry struct {
+ oldCert Certificate
+ ocspResp *ocsp.Response
+ }
updated := make(map[string]ocspUpdate)
- var updateQueue []updateQueueEntry
- var renewQueue []Certificate
+ var updateQueue []updateQueueEntry // certs that need a refreshed staple
+ var renewQueue []renewQueueEntry // certs that need to be renewed (due to revocation)
configs := make(map[string]*Config)
// obtain brief read lock during our scan to see which staples need updating
@@ -324,8 +329,8 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
cfg, err := certCache.getConfig(cert)
if err != nil {
- if log != nil {
- log.Error("unable to refresh OCSP staple because getting automation config for certificate failed",
+ if logger != nil {
+ logger.Error("unable to refresh OCSP staple because getting automation config for certificate failed",
zap.Strings("identifiers", cert.Names),
zap.Error(err))
}
@@ -333,8 +338,8 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
}
if cfg == nil {
// this is bad if this happens, probably a programmer error (oops)
- if log != nil {
- log.Error("no configuration associated with certificate; unable to manage OCSP staples",
+ if logger != nil {
+ logger.Error("no configuration associated with certificate; unable to manage OCSP staples",
zap.Strings("identifiers", cert.Names))
}
continue
@@ -344,8 +349,8 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
if err != nil || ocspResp == nil {
if cert.ocsp != nil {
// if there was no staple before, that's fine; otherwise we should log the error
- if log != nil {
- log.Error("stapling OCSP",
+ if logger != nil {
+ logger.Error("stapling OCSP",
zap.Strings("identifiers", cert.Names),
zap.Error(err))
}
@@ -357,8 +362,8 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
// If there was no staple before, or if the response is updated, make
// sure we apply the update to all names on the certificate.
if cert.ocsp != nil && (lastNextUpdate.IsZero() || lastNextUpdate != cert.ocsp.NextUpdate) {
- if log != nil {
- log.Info("advancing OCSP staple",
+ if logger != nil {
+ logger.Info("advancing OCSP staple",
zap.Strings("identifiers", cert.Names),
zap.Time("from", lastNextUpdate),
zap.Time("to", cert.ocsp.NextUpdate))
@@ -366,10 +371,12 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
updated[certHash] = ocspUpdate{rawBytes: cert.Certificate.OCSPStaple, parsed: cert.ocsp}
}
- // If a managed certificate was revoked, we should attempt
- // to replace it with a new one. If that fails, oh well.
+ // If a managed certificate was revoked, we should attempt to replace it with a new one.
if cert.managed && ocspResp.Status == ocsp.Revoked && len(cert.Names) > 0 {
- renewQueue = append(renewQueue, cert)
+ renewQueue = append(renewQueue, renewQueueEntry{
+ oldCert: cert,
+ ocspResp: ocspResp,
+ })
configs[cert.Names[0]] = cfg
}
}
@@ -386,35 +393,61 @@ func (certCache *Cache) updateOCSPStaples(ctx context.Context) {
// We attempt to replace any certificates that were revoked.
// Crucially, this happens OUTSIDE a lock on the certCache.
- for _, oldCert := range renewQueue {
- if log != nil {
- log.Warn("OCSP status for managed certificate is REVOKED; attempting to replace with new certificate",
- zap.Strings("identifiers", oldCert.Names),
- zap.Time("expiration", oldCert.Leaf.NotAfter))
+ for _, renew := range renewQueue {
+ if logger != nil {
+ logger.Warn("OCSP status for managed certificate is REVOKED; attempting to replace with new certificate",
+ zap.Strings("identifiers", renew.oldCert.Names),
+ zap.Time("expiration", renew.oldCert.Leaf.NotAfter))
}
- renewName := oldCert.Names[0]
+ renewName := renew.oldCert.Names[0]
cfg := configs[renewName]
- // TODO: consider using a new key in this situation, but we don't know if key storage has been compromised...
- err := cfg.RenewCert(ctx, renewName, false)
+ // if revoked for key compromise, we can't be sure whether the storage of
+ // the key is still safe; however, we KNOW the old key is not safe, and we
+ // can only hope by the time of revocation that storage has been secured;
+ // key management is not something we want to get into, but in this case
+ // it seems prudent to replace the key - and since renewal requires reuse
+ // of a prior key, we can't do a "renew" to replace the cert if we need a
+ // new key, so we'll have to do an obtain instead
+ var obtainInsteadOfRenew bool
+ if renew.ocspResp.RevocationReason == acme.ReasonKeyCompromise {
+ err := cfg.moveCompromisedPrivateKey(renew.oldCert, logger)
+ if err != nil && logger != nil {
+ logger.Error("could not remove compromised private key from use",
+ zap.Strings("identifiers", renew.oldCert.Names),
+ zap.String("issuer", renew.oldCert.issuerKey),
+ zap.Error(err))
+ }
+ obtainInsteadOfRenew = true
+ }
+
+ var err error
+ if obtainInsteadOfRenew {
+ err = cfg.ObtainCertAsync(ctx, renewName)
+ } else {
+ // notice that we force renewal; otherwise, it might see that the
+ // certificate isn't close to expiring and return, but we really
+ // need a replacement certificate! see issue #4191
+ err = cfg.RenewCertAsync(ctx, renewName, true)
+ }
if err != nil {
// probably better to not serve a revoked certificate at all
- if log != nil {
- log.Error("unable to obtain new to certificate after OCSP status of REVOKED; removing from cache",
- zap.Strings("identifiers", oldCert.Names),
+ if logger != nil {
+ logger.Error("unable to obtain new to certificate after OCSP status of REVOKED; removing from cache",
+ zap.Strings("identifiers", renew.oldCert.Names),
zap.Error(err))
}
certCache.mu.Lock()
- certCache.removeCertificate(oldCert)
+ certCache.removeCertificate(renew.oldCert)
certCache.mu.Unlock()
continue
}
- err = cfg.reloadManagedCertificate(oldCert)
+ err = cfg.reloadManagedCertificate(renew.oldCert)
if err != nil {
- if log != nil {
- log.Error("after obtaining new certificate due to OCSP status of REVOKED",
- zap.Strings("identifiers", oldCert.Names),
+ if logger != nil {
+ logger.Error("after obtaining new certificate due to OCSP status of REVOKED",
+ zap.Strings("identifiers", renew.oldCert.Names),
zap.Error(err))
}
continue
@@ -566,6 +599,37 @@ func deleteExpiredCerts(ctx context.Context, storage Storage, gracePeriod time.D
return nil
}
+// moveCompromisedPrivateKey moves the private key for cert to a ".compromised" file
+// by copying the data to the new file, then deleting the old one.
+func (cfg *Config) moveCompromisedPrivateKey(cert Certificate, logger *zap.Logger) error {
+ privKeyStorageKey := StorageKeys.SitePrivateKey(cert.issuerKey, cert.Names[0])
+
+ privKeyPEM, err := cfg.Storage.Load(privKeyStorageKey)
+ if err != nil {
+ return err
+ }
+
+ compromisedPrivKeyStorageKey := privKeyStorageKey + ".compromised"
+ err = cfg.Storage.Store(compromisedPrivKeyStorageKey, privKeyPEM)
+ if err != nil {
+ // better safe than sorry: as a last resort, try deleting the key so it won't be reused
+ cfg.Storage.Delete(privKeyStorageKey)
+ return err
+ }
+
+ err = cfg.Storage.Delete(privKeyStorageKey)
+ if err != nil {
+ return err
+ }
+
+ logger.Info("removed certificate's compromised private key from use",
+ zap.String("storage_path", compromisedPrivKeyStorageKey),
+ zap.Strings("identifiers", cert.Names),
+ zap.String("issuer", cert.issuerKey))
+
+ return nil
+}
+
const (
// DefaultRenewCheckInterval is how often to check certificates for expiration.
// Scans are very lightweight, so this can be semi-frequent. This default should