From e9c9a35a61385894754dd22bcf4e1bed4efe7744 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 1 Jan 2022 17:43:28 +0800 Subject: [PATCH] Upgrade certmagic from v0.14.1 to v0.15.2 (#18138) --- cmd/web_letsencrypt.go | 3 +- go.mod | 3 +- go.sum | 10 +- .../caddyserver/certmagic/README.md | 16 +-- .../caddyserver/certmagic/account.go | 4 - .../caddyserver/certmagic/acmeclient.go | 4 +- .../github.com/caddyserver/certmagic/cache.go | 44 ++++++- .../caddyserver/certmagic/certificates.go | 2 - .../caddyserver/certmagic/certmagic.go | 10 +- .../caddyserver/certmagic/config.go | 76 ++++++----- .../caddyserver/certmagic/crypto.go | 12 +- .../github.com/caddyserver/certmagic/go.mod | 6 +- .../github.com/caddyserver/certmagic/go.sum | 12 +- .../caddyserver/certmagic/handshake.go | 120 ++++++++++++++---- .../caddyserver/certmagic/solvers.go | 39 +++--- .../mholt/acmez/acme/certificate.go | 2 +- vendor/github.com/mholt/acmez/acme/http.go | 7 +- vendor/github.com/mholt/acmez/acme/problem.go | 40 +++++- vendor/github.com/mholt/acmez/client.go | 21 +-- vendor/modules.txt | 5 +- 20 files changed, 294 insertions(+), 142 deletions(-) diff --git a/cmd/web_letsencrypt.go b/cmd/web_letsencrypt.go index 066208457bae..866b88f7c9d5 100644 --- a/cmd/web_letsencrypt.go +++ b/cmd/web_letsencrypt.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -47,7 +48,7 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) magic.Issuers = []certmagic.Issuer{myACME} // this obtains certificates or renews them if necessary - err := magic.ManageSync([]string{domain}) + err := magic.ManageSync(graceful.GetManager().HammerContext(), []string{domain}) if err != nil { return err } diff --git a/go.mod b/go.mod index 70eb74e99767..070ab653251f 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.0 github.com/boombuler/barcode v1.0.1 // indirect github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect - github.com/caddyserver/certmagic v0.14.1 + github.com/caddyserver/certmagic v0.15.2 github.com/chi-middleware/proxy v1.1.1 github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect github.com/couchbase/gomemcached v0.1.2 // indirect @@ -78,7 +78,6 @@ require ( github.com/mattn/go-sqlite3 v1.14.8 github.com/mholt/archiver/v3 v3.5.0 github.com/microcosm-cc/bluemonday v1.0.16 - github.com/miekg/dns v1.1.43 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/minio-go/v7 v7.0.12 github.com/minio/sha256-simd v1.0.0 // indirect diff --git a/go.sum b/go.sum index 7296a6574e33..c9c37e70c0ae 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,8 @@ github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/caddyserver/certmagic v0.14.1 h1:8RIFS/LbGne/I7Op56Kkm2annnei7io9VW/IWDttE9U= -github.com/caddyserver/certmagic v0.14.1/go.mod h1:oRQOZmUVKwlpgNidslysHt05osM9uMrJ4YMk+Ot4P4Q= +github.com/caddyserver/certmagic v0.15.2 h1:OMTakTsLM1ZfzMDjwvYprfUgFzpVPh3u87oxMPwmeBc= +github.com/caddyserver/certmagic v0.15.2/go.mod h1:qhkAOthf72ufAcp3Y5jF2RaGE96oip3UbEQRIzwe3/8= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -767,7 +767,6 @@ github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -848,14 +847,13 @@ github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxz github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mholt/acmez v0.1.3 h1:J7MmNIk4Qf9b8mAGqAh4XkNeowv3f1zW816yf4zt7Qk= -github.com/mholt/acmez v0.1.3/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= +github.com/mholt/acmez v1.0.1 h1:J7uquHOKEmo71UDnVApy1sSLA0oF/r+NtVrNzMKKA9I= +github.com/mholt/acmez v1.0.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/microcosm-cc/bluemonday v1.0.16 h1:kHmAq2t7WPWLjiGvzKa5o3HzSfahUKiOq7fAPUiMNIc= github.com/microcosm-cc/bluemonday v1.0.16/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= diff --git a/vendor/github.com/caddyserver/certmagic/README.md b/vendor/github.com/caddyserver/certmagic/README.md index 19aa9f891963..9948d5483037 100644 --- a/vendor/github.com/caddyserver/certmagic/README.md +++ b/vendor/github.com/caddyserver/certmagic/README.md @@ -10,9 +10,9 @@

-Caddy's automagic TLS features—now for your own Go programs—in one powerful and easy-to-use library! +Caddy's [automagic TLS features](https://caddyserver.com/docs/automatic-https)—now for your own Go programs—in one powerful and easy-to-use library! -CertMagic is the most mature, robust, and capable ACME client integration for Go... and perhaps ever. +CertMagic is the most mature, robust, and powerful ACME client integration for Go... and perhaps ever. With CertMagic, you can add one line to your Go application to serve securely over TLS, without ever having to touch certificates. @@ -40,11 +40,6 @@ Compared to other ACME client libraries for Go, only CertMagic supports the full CertMagic - Automatic HTTPS using Let's Encrypt =============================================== -**Sponsored by Relica - Cross-platform local and cloud file backup:** - -Relica - Cross-platform file backup to the cloud, local disks, or other computers - - ## Menu - [Features](#features) @@ -116,6 +111,7 @@ CertMagic - Automatic HTTPS using Let's Encrypt ## Requirements +0. ACME server (can be a publicly-trusted CA, or your own) 1. Public DNS name(s) you control 2. Server reachable from public Internet - Or use the DNS challenge to waive this requirement @@ -270,7 +266,7 @@ myACME := certmagic.NewACMEManager(magic, certmagic.ACMEManager{ magic.Issuer = myACME // this obtains certificates or renews them if necessary -err := magic.ManageSync([]string{"example.com", "sub.example.com"}) +err := magic.ManageSync(context.TODO(), []string{"example.com", "sub.example.com"}) if err != nil { return err } @@ -279,6 +275,10 @@ if err != nil { // you can get a TLS config to use in a TLS listener! tlsConfig := magic.TLSConfig() +// be sure to customize NextProtos if serving a specific +// application protocol after the TLS handshake, for example: +tlsConfig.NextProtos = append([]string{"h2", "http/1.1"}, tlsConfig.NextProtos...) + //// OR //// // if you already have a TLS config you don't want to replace, diff --git a/vendor/github.com/caddyserver/certmagic/account.go b/vendor/github.com/caddyserver/certmagic/account.go index 8633f92fcbe9..1cc6723429a2 100644 --- a/vendor/github.com/caddyserver/certmagic/account.go +++ b/vendor/github.com/caddyserver/certmagic/account.go @@ -405,10 +405,6 @@ var ( discoveredEmailMu sync.Mutex ) -// agreementTestURL is set during tests to skip requiring -// setting up an entire ACME CA endpoint. -var agreementTestURL string - // stdin is used to read the user's input if prompted; // this is changed by tests during tests. var stdin = io.ReadWriter(os.Stdin) diff --git a/vendor/github.com/caddyserver/certmagic/acmeclient.go b/vendor/github.com/caddyserver/certmagic/acmeclient.go index cc876b9252b0..a22dc19a7ae0 100644 --- a/vendor/github.com/caddyserver/certmagic/acmeclient.go +++ b/vendor/github.com/caddyserver/certmagic/acmeclient.go @@ -370,11 +370,11 @@ var ( // RateLimitEvents is how many new events can be allowed // in RateLimitEventsWindow. - RateLimitEvents = 20 + RateLimitEvents = 10 // RateLimitEventsWindow is the size of the sliding // window that throttles events. - RateLimitEventsWindow = 1 * time.Minute + RateLimitEventsWindow = 10 * time.Second ) // Some default values passed down to the underlying ACME client. diff --git a/vendor/github.com/caddyserver/certmagic/cache.go b/vendor/github.com/caddyserver/certmagic/cache.go index 30bfc2a3f7d0..4e986303a9bd 100644 --- a/vendor/github.com/caddyserver/certmagic/cache.go +++ b/vendor/github.com/caddyserver/certmagic/cache.go @@ -194,6 +194,14 @@ func (certCache *Cache) cacheCertificate(cert Certificate) { func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) { // no-op if this certificate already exists in the cache if _, ok := certCache.cache[cert.hash]; ok { + if certCache.logger != nil { + certCache.logger.Debug("certificate already cached", + zap.Strings("subjects", cert.Names), + zap.Time("expiration", cert.Leaf.NotAfter), + zap.Bool("managed", cert.managed), + zap.String("issuer_key", cert.issuerKey), + zap.String("hash", cert.hash)) + } return } @@ -209,6 +217,13 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) { i := 0 for _, randomCert := range certCache.cache { if i == rnd { + if certCache.logger != nil { + certCache.logger.Debug("cache full; evicting random certificate", + zap.Strings("removing_subjects", randomCert.Names), + zap.String("removing_hash", randomCert.hash), + zap.Strings("inserting_subjects", cert.Names), + zap.String("inserting_hash", cert.hash)) + } certCache.removeCertificate(randomCert) break } @@ -223,6 +238,17 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) { for _, name := range cert.Names { certCache.cacheIndex[name] = append(certCache.cacheIndex[name], cert.hash) } + + if certCache.logger != nil { + certCache.logger.Debug("added certificate to cache", + zap.Strings("subjects", cert.Names), + zap.Time("expiration", cert.Leaf.NotAfter), + zap.Bool("managed", cert.managed), + zap.String("issuer_key", cert.issuerKey), + zap.String("hash", cert.hash), + zap.Int("cache_size", len(certCache.cache)), + zap.Int("cache_capacity", certCache.options.Capacity)) + } } // removeCertificate removes cert from the cache. @@ -233,9 +259,10 @@ func (certCache *Cache) removeCertificate(cert Certificate) { // delete all mentions of this cert from the name index for _, name := range cert.Names { keyList := certCache.cacheIndex[name] - for i, cacheKey := range keyList { - if cacheKey == cert.hash { + for i := 0; i < len(keyList); i++ { + if keyList[i] == cert.hash { keyList = append(keyList[:i], keyList[i+1:]...) + i-- } } if len(keyList) == 0 { @@ -247,6 +274,17 @@ func (certCache *Cache) removeCertificate(cert Certificate) { // delete the actual cert from the cache delete(certCache.cache, cert.hash) + + if certCache.logger != nil { + certCache.logger.Debug("removed certificate from cache", + zap.Strings("subjects", cert.Names), + zap.Time("expiration", cert.Leaf.NotAfter), + zap.Bool("managed", cert.managed), + zap.String("issuer_key", cert.issuerKey), + zap.String("hash", cert.hash), + zap.Int("cache_size", len(certCache.cache)), + zap.Int("cache_capacity", certCache.options.Capacity)) + } } // replaceCertificate atomically replaces oldCert with newCert in @@ -260,7 +298,7 @@ func (certCache *Cache) replaceCertificate(oldCert, newCert Certificate) { certCache.mu.Unlock() if certCache.logger != nil { certCache.logger.Info("replaced certificate in cache", - zap.Strings("identifiers", newCert.Names), + zap.Strings("subjects", newCert.Names), zap.Time("new_expiration", newCert.Leaf.NotAfter)) } } diff --git a/vendor/github.com/caddyserver/certmagic/certificates.go b/vendor/github.com/caddyserver/certmagic/certificates.go index e6dab5e0ff82..067bfc508bd3 100644 --- a/vendor/github.com/caddyserver/certmagic/certificates.go +++ b/vendor/github.com/caddyserver/certmagic/certificates.go @@ -283,8 +283,6 @@ func fillCertFromLeaf(cert *Certificate, tlsCert tls.Certificate) error { return fmt.Errorf("certificate has no names") } - // save the hash of this certificate (chain) and - // expiration date, for necessity and efficiency cert.hash = hashCertificateChain(cert.Certificate.Certificate) return nil diff --git a/vendor/github.com/caddyserver/certmagic/certmagic.go b/vendor/github.com/caddyserver/certmagic/certmagic.go index bb33b90c559d..88080a8036df 100644 --- a/vendor/github.com/caddyserver/certmagic/certmagic.go +++ b/vendor/github.com/caddyserver/certmagic/certmagic.go @@ -73,7 +73,7 @@ func HTTPS(domainNames []string, mux http.Handler) error { DefaultACME.Agreed = true cfg := NewDefault() - err := cfg.ManageSync(domainNames) + err := cfg.ManageSync(context.Background(), domainNames) if err != nil { return err } @@ -178,7 +178,7 @@ func TLS(domainNames []string) (*tls.Config, error) { DefaultACME.Agreed = true DefaultACME.DisableHTTPChallenge = true cfg := NewDefault() - return cfg.TLSConfig(), cfg.ManageSync(domainNames) + return cfg.TLSConfig(), cfg.ManageSync(context.Background(), domainNames) } // Listen manages certificates for domainName and returns a @@ -195,7 +195,7 @@ func Listen(domainNames []string) (net.Listener, error) { DefaultACME.Agreed = true DefaultACME.DisableHTTPChallenge = true cfg := NewDefault() - err := cfg.ManageSync(domainNames) + err := cfg.ManageSync(context.Background(), domainNames) if err != nil { return nil, err } @@ -223,9 +223,9 @@ func Listen(domainNames []string) (net.Listener, error) { // // Calling this function signifies your acceptance to // the CA's Subscriber Agreement and/or Terms of Service. -func ManageSync(domainNames []string) error { +func ManageSync(ctx context.Context, domainNames []string) error { DefaultACME.Agreed = true - return NewDefault().ManageSync(domainNames) + return NewDefault().ManageSync(ctx, domainNames) } // ManageAsync is the same as ManageSync, except that diff --git a/vendor/github.com/caddyserver/certmagic/config.go b/vendor/github.com/caddyserver/certmagic/config.go index d408418f6571..3d031fa627ec 100644 --- a/vendor/github.com/caddyserver/certmagic/config.go +++ b/vendor/github.com/caddyserver/certmagic/config.go @@ -247,8 +247,28 @@ func newWithCache(certCache *Cache, cfg Config) *Config { // of the given domainNames. This behavior is recommended for // 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(context.Background(), domainNames, false) +func (cfg *Config) ManageSync(ctx context.Context, domainNames []string) error { + return cfg.manageAll(ctx, domainNames, false) +} + +// ManageAsync is the same as ManageSync, except that ACME +// operations are performed asynchronously (in the background). +// This method returns before certificates are ready. It is +// crucial that the administrator monitors the logs and is +// notified of any errors so that corrective action can be +// taken as soon as possible. Any errors returned from this +// method occurred before ACME transactions started. +// +// As long as logs are monitored, this method is typically +// recommended for non-interactive environments. +// +// If there are failures loading, obtaining, or renewing a +// certificate, it will be retried with exponential backoff +// for up to about 30 days, with a maximum interval of about +// 24 hours. Cancelling ctx will cancel retries and shut down +// any goroutines spawned by ManageAsync. +func (cfg *Config) ManageAsync(ctx context.Context, domainNames []string) error { + return cfg.manageAll(ctx, domainNames, true) } // ClientCredentials returns a list of TLS client certificate chains for the given identifiers. @@ -274,26 +294,6 @@ func (cfg *Config) ClientCredentials(ctx context.Context, identifiers []string) return chains, nil } -// ManageAsync is the same as ManageSync, except that ACME -// operations are performed asynchronously (in the background). -// This method returns before certificates are ready. It is -// crucial that the administrator monitors the logs and is -// notified of any errors so that corrective action can be -// taken as soon as possible. Any errors returned from this -// method occurred before ACME transactions started. -// -// As long as logs are monitored, this method is typically -// recommended for non-interactive environments. -// -// If there are failures loading, obtaining, or renewing a -// certificate, it will be retried with exponential backoff -// for up to about 30 days, with a maximum interval of about -// 24 hours. Cancelling ctx will cancel retries and shut down -// any goroutines spawned by ManageAsync. -func (cfg *Config) ManageAsync(ctx context.Context, domainNames []string) error { - return cfg.manageAll(ctx, domainNames, true) -} - func (cfg *Config) manageAll(ctx context.Context, domainNames []string, async bool) error { if ctx == nil { ctx = context.Background() @@ -863,20 +863,28 @@ func (cfg *Config) RevokeCert(ctx context.Context, domain string, reason int, in return nil } -// TLSConfig is an opinionated method that returns a -// recommended, modern TLS configuration that can be -// used to configure TLS listeners, which also supports -// the TLS-ALPN challenge and serves up certificates -// managed by cfg. +// TLSConfig is an opinionated method that returns a recommended, modern +// TLS configuration that can be used to configure TLS listeners. Aside +// from safe, modern defaults, this method sets two critical fields on the +// TLS config which are required to enable automatic certificate +// management: GetCertificate and NextProtos. // -// Unlike the package TLS() function, this method does -// not, by itself, enable certificate management for -// any domain names. +// The GetCertificate field is necessary to get certificates from memory +// or storage, including both manual and automated certificates. You +// should only change this field if you know what you are doing. // -// Feel free to further customize the returned tls.Config, -// but do not mess with the GetCertificate or NextProtos -// fields unless you know what you're doing, as they're -// necessary to solve the TLS-ALPN challenge. +// The NextProtos field is pre-populated with a special value to enable +// solving the TLS-ALPN ACME challenge. Because this method does not +// assume any particular protocols after the TLS handshake is completed, +// you will likely need to customize the NextProtos field by prepending +// your application's protocols to the slice. For example, to serve +// HTTP, you will need to prepend "h2" and "http/1.1" values. Be sure to +// leave the acmez.ACMETLS1Protocol value intact, however, or TLS-ALPN +// challenges will fail (which may be acceptable if you are not using +// ACME, or specifically, the TLS-ALPN challenge). +// +// Unlike the package TLS() function, this method does not, by itself, +// enable certificate management for any domain names. func (cfg *Config) TLSConfig() *tls.Config { return &tls.Config{ // these two fields necessary for TLS-ALPN challenge diff --git a/vendor/github.com/caddyserver/certmagic/crypto.go b/vendor/github.com/caddyserver/certmagic/crypto.go index a705cdde2cdd..ee4671f5f59b 100644 --- a/vendor/github.com/caddyserver/certmagic/crypto.go +++ b/vendor/github.com/caddyserver/certmagic/crypto.go @@ -72,6 +72,10 @@ func encodePrivateKey(key crypto.PrivateKey) ([]byte, error) { func decodePrivateKey(keyPEMBytes []byte) (crypto.Signer, error) { keyBlockDER, _ := pem.Decode(keyPEMBytes) + if keyBlockDER == nil { + return nil, fmt.Errorf("failed to decode PEM block containing private key") + } + if keyBlockDER.Type != "PRIVATE KEY" && !strings.HasSuffix(keyBlockDER.Type, " PRIVATE KEY") { return nil, fmt.Errorf("unknown PEM header %q", keyBlockDER.Type) } @@ -142,14 +146,14 @@ func (cfg *Config) saveCertResource(issuer Issuer, cert CertificateResource) err certKey := cert.NamesKey() all := []keyValue{ - { - key: StorageKeys.SiteCert(issuerKey, certKey), - value: cert.CertificatePEM, - }, { key: StorageKeys.SitePrivateKey(issuerKey, certKey), value: cert.PrivateKeyPEM, }, + { + key: StorageKeys.SiteCert(issuerKey, certKey), + value: cert.CertificatePEM, + }, { key: StorageKeys.SiteMeta(issuerKey, certKey), value: metaBytes, diff --git a/vendor/github.com/caddyserver/certmagic/go.mod b/vendor/github.com/caddyserver/certmagic/go.mod index 42665bf1b320..a9267715b640 100644 --- a/vendor/github.com/caddyserver/certmagic/go.mod +++ b/vendor/github.com/caddyserver/certmagic/go.mod @@ -3,10 +3,10 @@ module github.com/caddyserver/certmagic go 1.14 require ( - github.com/klauspost/cpuid/v2 v2.0.6 + github.com/klauspost/cpuid/v2 v2.0.9 github.com/libdns/libdns v0.2.1 - github.com/mholt/acmez v0.1.3 - github.com/miekg/dns v1.1.42 + github.com/mholt/acmez v1.0.1 + github.com/miekg/dns v1.1.43 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 1251ac84f0ce..d9512a8062a8 100644 --- a/vendor/github.com/caddyserver/certmagic/go.sum +++ b/vendor/github.com/caddyserver/certmagic/go.sum @@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI= -github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -13,10 +13,10 @@ 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.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.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY= -github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/mholt/acmez v1.0.1 h1:J7uquHOKEmo71UDnVApy1sSLA0oF/r+NtVrNzMKKA9I= +github.com/mholt/acmez v1.0.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/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= diff --git a/vendor/github.com/caddyserver/certmagic/handshake.go b/vendor/github.com/caddyserver/certmagic/handshake.go index 5506719c2b2b..e57a3d168301 100644 --- a/vendor/github.com/caddyserver/certmagic/handshake.go +++ b/vendor/github.com/caddyserver/certmagic/handshake.go @@ -125,23 +125,6 @@ func (cfg *Config) getCertificate(hello *tls.ClientHelloInfo) (cert Certificate, return } } - - // check the certCache directly to see if the SNI name is - // already the key of the certificate it wants; this implies - // that the SNI can contain the hash of a specific cert - // (chain) it wants and we will still be able to serve it up - // (this behavior, by the way, could be controversial as to - // whether it complies with RFC 6066 about SNI, but I think - // it does, soooo...) - // (this is how we solved the former ACME TLS-SNI challenge) - cfg.certCache.mu.RLock() - directCert, ok := cfg.certCache.cache[name] - cfg.certCache.mu.RUnlock() - if ok { - cert = directCert - matched = true - return - } } // otherwise, we're bingo on ammo; see issues @@ -162,18 +145,48 @@ func (cfg *Config) getCertificate(hello *tls.ClientHelloInfo) (cert Certificate, // then all certificates in the cache will be passed in // for the cfg.CertSelection to make the final decision. func (cfg *Config) selectCert(hello *tls.ClientHelloInfo, name string) (Certificate, bool) { + logger := loggerNamed(cfg.Logger, "handshake") choices := cfg.certCache.getAllMatchingCerts(name) if len(choices) == 0 { if cfg.CertSelection == nil { + if logger != nil { + logger.Debug("no matching certificates and no custom selection logic", zap.String("identifier", name)) + } return Certificate{}, false } + if logger != nil { + logger.Debug("no matching certificate; will choose from all certificates", zap.String("identifier", name)) + } choices = cfg.certCache.getAllCerts() } + if logger != nil { + logger.Debug("choosing certificate", + zap.String("identifier", name), + zap.Int("num_choices", len(choices))) + } if cfg.CertSelection == nil { cert, err := DefaultCertificateSelector(hello, choices) + if logger != nil { + logger.Debug("default certificate selection results", + zap.Error(err), + zap.String("identifier", name), + zap.Strings("subjects", cert.Names), + zap.Bool("managed", cert.managed), + zap.String("issuer_key", cert.issuerKey), + zap.String("hash", cert.hash)) + } return cert, err == nil } cert, err := cfg.CertSelection.SelectCertificate(hello, choices) + if logger != nil { + logger.Debug("custom certificate selection results", + zap.Error(err), + zap.String("identifier", name), + zap.Strings("subjects", cert.Names), + zap.Bool("managed", cert.managed), + zap.String("issuer_key", cert.issuerKey), + zap.String("hash", cert.hash)) + } return cert, err == nil } @@ -213,28 +226,54 @@ func DefaultCertificateSelector(hello *tls.ClientHelloInfo, choices []Certificat // // This function is safe for concurrent use. func (cfg *Config) getCertDuringHandshake(hello *tls.ClientHelloInfo, loadIfNecessary, obtainIfNecessary bool) (Certificate, error) { - log := loggerNamed(cfg.Logger, "on_demand") + log := loggerNamed(cfg.Logger, "handshake") // First check our in-memory cache to see if we've already loaded it cert, matched, defaulted := cfg.getCertificate(hello) if matched { + if log != nil { + log.Debug("matched certificate in cache", + zap.Strings("subjects", cert.Names), + zap.Bool("managed", cert.managed), + zap.Time("expiration", cert.Leaf.NotAfter), + zap.String("hash", cert.hash)) + } if cert.managed && cfg.OnDemand != nil && obtainIfNecessary { // It's been reported before that if the machine goes to sleep (or // suspends the process) that certs which are already loaded into // memory won't get renewed in the background, so we need to check // expiry on each handshake too, sigh: // https://caddy.community/t/local-certificates-not-renewing-on-demand/9482 - return cfg.optionalMaintenance(log, cert, hello) + return cfg.optionalMaintenance(loggerNamed(cfg.Logger, "on_demand"), cert, hello) } return cert, nil } name := cfg.getNameFromClientHello(hello) - // If OnDemand is enabled, then we might be able to load or - // obtain a needed certificate - if cfg.OnDemand != nil && loadIfNecessary { + // We might be able to load or obtain a needed certificate. Load from + // storage if OnDemand is enabled, or if there is the possibility that + // a statically-managed cert was evicted from a full cache. + cfg.certCache.mu.RLock() + cacheSize := len(cfg.certCache.cache) + cfg.certCache.mu.RUnlock() + + // A cert might have still been evicted from the cache even if the cache + // is no longer completely full; this happens if the newly-loaded cert is + // itself evicted (perhaps due to being expired or unmanaged at this point). + // Hence, we use an "almost full" metric to allow for the cache to not be + // 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 + // and caddyserver/caddy#4320. + cacheAlmostFull := float64(cacheSize) >= (float64(cfg.certCache.options.Capacity) * .9) + loadDynamically := cfg.OnDemand != nil || cacheAlmostFull + + if loadDynamically && loadIfNecessary { // Then check to see if we have one on disk + // TODO: As suggested here, https://caddy.community/t/error-tls-alert-internal-error-592-again/13272/30?u=matt, + // it might be a good idea to check with the DecisionFunc or allowlist first before even loading the certificate + // from storage, since if we can't renew it, why should we even try serving it (it will just get evicted after + // we get a return value of false anyway)? loadedCert, err := cfg.CacheManagedCertificate(name) if _, ok := err.(ErrNotExist); ok { // If no exact match, try a wildcard variant, which is something we can still use @@ -243,6 +282,13 @@ func (cfg *Config) getCertDuringHandshake(hello *tls.ClientHelloInfo, loadIfNece loadedCert, err = cfg.CacheManagedCertificate(strings.Join(labels, ".")) } if err == nil { + if log != nil { + log.Debug("loaded certificate from storage", + zap.Strings("subjects", loadedCert.Names), + zap.Bool("managed", loadedCert.managed), + zap.Time("expiration", loadedCert.Leaf.NotAfter), + zap.String("hash", loadedCert.hash)) + } loadedCert, err = cfg.handshakeMaintenance(hello, loadedCert) if err != nil { if log != nil { @@ -253,7 +299,7 @@ func (cfg *Config) getCertDuringHandshake(hello *tls.ClientHelloInfo, loadIfNece } return loadedCert, nil } - if obtainIfNecessary { + if cfg.OnDemand != nil && obtainIfNecessary { // By this point, we need to ask the CA for a certificate return cfg.obtainOnDemandCertificate(hello) } @@ -261,9 +307,28 @@ func (cfg *Config) getCertDuringHandshake(hello *tls.ClientHelloInfo, loadIfNece // Fall back to the default certificate if there is one if defaulted { + if log != nil { + log.Debug("fell back to default certificate", + zap.Strings("subjects", cert.Names), + zap.Bool("managed", cert.managed), + zap.Time("expiration", cert.Leaf.NotAfter), + zap.String("hash", cert.hash)) + } return cert, nil } + if log != nil { + log.Debug("no certificate matching TLS ClientHello", + zap.String("server_name", hello.ServerName), + zap.String("remote", hello.Conn.RemoteAddr().String()), + zap.String("identifier", name), + zap.Uint16s("cipher_suites", hello.CipherSuites), + zap.Float64("cert_cache_fill", float64(cacheSize)/float64(cfg.certCache.options.Capacity)), // may be approximate! because we are not within the lock + zap.Bool("load_if_necessary", loadIfNecessary), + zap.Bool("obtain_if_necessary", obtainIfNecessary), + zap.Bool("on_demand", cfg.OnDemand != nil)) + } + return Certificate{}, fmt.Errorf("no certificate available for '%s'", name) } @@ -371,7 +436,8 @@ func (cfg *Config) obtainOnDemandCertificate(hello *tls.ClientHelloInfo) (Certif } // TODO: use a proper context; we use one with timeout because retries are enabled because interactive is false - ctx, cancel := context.WithTimeout(context.TODO(), 90*time.Second) + // (timeout duration is based on https://caddy.community/t/zerossl-dns-challenge-failing-often-route53-plugin/13822/24?u=matt) + ctx, cancel := context.WithTimeout(context.TODO(), 180*time.Second) defer cancel() // Obtain the certificate @@ -459,7 +525,7 @@ func (cfg *Config) renewDynamicCertificate(hello *tls.ClientHelloInfo, currentCe // renewing it, so we might as well serve what we have without blocking if log != nil { log.Debug("certificate expires soon but is already being renewed; serving current certificate", - zap.Strings("identifiers", currentCert.Names), + zap.Strings("subjects", currentCert.Names), zap.Duration("remaining", timeLeft)) } return currentCert, nil @@ -470,7 +536,7 @@ func (cfg *Config) renewDynamicCertificate(hello *tls.ClientHelloInfo, currentCe if log != nil { log.Debug("certificate has expired, but is already being renewed; waiting for renewal to complete", - zap.Strings("identifiers", currentCert.Names), + zap.Strings("subjects", currentCert.Names), zap.Time("expired", currentCert.Leaf.NotAfter)) } @@ -501,7 +567,7 @@ func (cfg *Config) renewDynamicCertificate(hello *tls.ClientHelloInfo, currentCe if log != nil { log.Info("attempting certificate renewal", zap.String("server_name", name), - zap.Strings("identifiers", currentCert.Names), + zap.Strings("subjects", currentCert.Names), zap.Time("expiration", currentCert.Leaf.NotAfter), zap.Duration("remaining", timeLeft)) } diff --git a/vendor/github.com/caddyserver/certmagic/solvers.go b/vendor/github.com/caddyserver/certmagic/solvers.go index 8c7199581430..8cdaeaf839be 100644 --- a/vendor/github.com/caddyserver/certmagic/solvers.go +++ b/vendor/github.com/caddyserver/certmagic/solvers.go @@ -32,6 +32,7 @@ import ( "github.com/libdns/libdns" "github.com/mholt/acmez" "github.com/mholt/acmez/acme" + "github.com/miekg/dns" ) // httpSolver solves the HTTP challenge. It must be @@ -131,10 +132,12 @@ func (s *tlsALPNSolver) Present(ctx context.Context, chal acme.Challenge) error if err != nil { return err } + + key := challengeKey(chal) activeChallengesMu.Lock() - chalData := activeChallenges[chal.Identifier.Value] + chalData := activeChallenges[key] chalData.data = cert - activeChallenges[chal.Identifier.Value] = chalData + activeChallenges[key] = chalData activeChallengesMu.Unlock() // the rest of this function increments the @@ -215,10 +218,6 @@ func (*tlsALPNSolver) handleConn(conn net.Conn) { // CleanUp removes the challenge certificate from the cache, and if // it is the last one to finish, stops the TLS server. func (s *tlsALPNSolver) CleanUp(ctx context.Context, chal acme.Challenge) error { - s.config.certCache.mu.Lock() - delete(s.config.certCache.cache, tlsALPNCertKeyName(chal.Identifier.Value)) - s.config.certCache.mu.Unlock() - solversMu.Lock() defer solversMu.Unlock() si := getSolverInfo(s.address) @@ -236,14 +235,6 @@ func (s *tlsALPNSolver) CleanUp(ctx context.Context, chal acme.Challenge) error return nil } -// tlsALPNCertKeyName returns the key to use when caching a cert -// for use with the TLS-ALPN ACME challenge. It is simply to help -// avoid conflicts (although at time of writing, there shouldn't -// be, since the cert cache is keyed by hash of certificate chain). -func tlsALPNCertKeyName(sniName string) string { - return sniName + ":acme-tls-alpn" -} - // DNS01Solver is a type that makes libdns providers usable // as ACME dns-01 challenge solvers. // See https://github.com/libdns/libdns @@ -478,7 +469,7 @@ func (dhs distributedSolver) Present(ctx context.Context, chal acme.Challenge) e return err } - err = dhs.storage.Store(dhs.challengeTokensKey(chal.Identifier.Value), infoBytes) + err = dhs.storage.Store(dhs.challengeTokensKey(challengeKey(chal)), infoBytes) if err != nil { return err } @@ -501,7 +492,7 @@ func (dhs distributedSolver) Wait(ctx context.Context, challenge acme.Challenge) // CleanUp invokes the underlying solver's CleanUp method // and also cleans up any assets saved to storage. func (dhs distributedSolver) CleanUp(ctx context.Context, chal acme.Challenge) error { - err := dhs.storage.Delete(dhs.challengeTokensKey(chal.Identifier.Value)) + err := dhs.storage.Delete(dhs.challengeTokensKey(challengeKey(chal))) if err != nil { return err } @@ -648,6 +639,18 @@ type Challenge struct { data interface{} } +// challengeKey returns the map key for a given challenge; it is the identifier +// unless it is an IP address using the TLS-ALPN challenge. +func challengeKey(chal acme.Challenge) string { + if chal.Type == acme.ChallengeTypeTLSALPN01 && chal.Identifier.Type == "ip" { + reversed, err := dns.ReverseAddr(chal.Identifier.Value) + if err == nil { + return reversed[:len(reversed)-1] // strip off '.' + } + } + return chal.Identifier.Value +} + // solverWrapper should be used to wrap all challenge solvers so that // we can add the challenge info to memory; this makes challenges globally // solvable by a single HTTP or TLS server even if multiple servers with @@ -656,7 +659,7 @@ type solverWrapper struct{ acmez.Solver } func (sw solverWrapper) Present(ctx context.Context, chal acme.Challenge) error { activeChallengesMu.Lock() - activeChallenges[chal.Identifier.Value] = Challenge{Challenge: chal} + activeChallenges[challengeKey(chal)] = Challenge{Challenge: chal} activeChallengesMu.Unlock() return sw.Solver.Present(ctx, chal) } @@ -670,7 +673,7 @@ func (sw solverWrapper) Wait(ctx context.Context, chal acme.Challenge) error { func (sw solverWrapper) CleanUp(ctx context.Context, chal acme.Challenge) error { activeChallengesMu.Lock() - delete(activeChallenges, chal.Identifier.Value) + delete(activeChallenges, challengeKey(chal)) activeChallengesMu.Unlock() return sw.Solver.CleanUp(ctx, chal) } diff --git a/vendor/github.com/mholt/acmez/acme/certificate.go b/vendor/github.com/mholt/acmez/acme/certificate.go index a778280802bb..42bbba07e3df 100644 --- a/vendor/github.com/mholt/acmez/acme/certificate.go +++ b/vendor/github.com/mholt/acmez/acme/certificate.go @@ -111,7 +111,7 @@ func (c *Client) GetCertificateChain(ctx context.Context, account Account, certU // heuristics to decide which is optimal." §7.4.2 alternates := extractLinks(resp, "alternate") for _, altURL := range alternates { - resp, err = addChain(altURL) + _, err = addChain(altURL) if err != nil { return nil, fmt.Errorf("retrieving alternate certificate chain at %s: %w", altURL, err) } diff --git a/vendor/github.com/mholt/acmez/acme/http.go b/vendor/github.com/mholt/acmez/acme/http.go index a910d57e562d..63688013e943 100644 --- a/vendor/github.com/mholt/acmez/acme/http.go +++ b/vendor/github.com/mholt/acmez/acme/http.go @@ -117,8 +117,7 @@ func (c *Client) httpPostJWS(ctx context.Context, privateKey crypto.Signer, break } - return resp, fmt.Errorf("request to %s failed after %d attempts: %w", - endpoint, attempts, err) + return resp, fmt.Errorf("attempt %d: %s: %w", attempts, endpoint, err) } // httpReq robustly performs an HTTP request using the given method to the given endpoint, honoring @@ -272,8 +271,8 @@ func (c *Client) doHTTPRequest(req *http.Request, buf *bytes.Buffer) (resp *http zap.String("method", req.Method), zap.String("url", req.URL.String()), zap.Reflect("headers", req.Header), - zap.Int("status_code", resp.StatusCode), - zap.Reflect("response_headers", resp.Header)) + zap.Reflect("response_headers", resp.Header), + zap.Int("status_code", resp.StatusCode)) } // "The server MUST include a Replay-Nonce header field diff --git a/vendor/github.com/mholt/acmez/acme/problem.go b/vendor/github.com/mholt/acmez/acme/problem.go index 98fdb0095885..c5f1124649d5 100644 --- a/vendor/github.com/mholt/acmez/acme/problem.go +++ b/vendor/github.com/mholt/acmez/acme/problem.go @@ -14,7 +14,11 @@ package acme -import "fmt" +import ( + "fmt" + + "go.uber.org/zap/zapcore" +) // Problem carries the details of an error from HTTP APIs as // defined in RFC 7807: https://tools.ietf.org/html/rfc7807 @@ -77,6 +81,9 @@ func (p Problem) Error() string { if len(p.Subproblems) > 0 { for _, v := range p.Subproblems { s += fmt.Sprintf(", problem %q: %s", v.Type, v.Detail) + if v.Identifier.Type != "" || v.Identifier.Value != "" { + s += fmt.Sprintf(" (%s_identifier=%s)", v.Identifier.Type, v.Identifier.Value) + } } } if p.Instance != "" { @@ -85,6 +92,17 @@ func (p Problem) Error() string { return s } +// MarshalLogObject satisfies the zapcore.ObjectMarshaler interface. +// This allows problems to be serialized by the zap logger. +func (p Problem) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddString("type", p.Type) + enc.AddString("title", p.Title) + enc.AddString("detail", p.Detail) + enc.AddString("instance", p.Instance) + enc.AddArray("subproblems", loggableSubproblems(p.Subproblems)) + return nil +} + // Subproblem describes a more specific error in a problem according to // RFC 8555 §6.7.1: "An ACME problem document MAY contain the // 'subproblems' field, containing a JSON array of problem documents, @@ -97,6 +115,26 @@ type Subproblem struct { Identifier Identifier `json:"identifier,omitempty"` } +// MarshalLogObject satisfies the zapcore.ObjectMarshaler interface. +// This allows subproblems to be serialized by the zap logger. +func (sp Subproblem) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddString("identifier_type", sp.Identifier.Type) + enc.AddString("identifier", sp.Identifier.Value) + enc.AddObject("subproblem", sp.Problem) + return nil +} + +type loggableSubproblems []Subproblem + +// MarshalLogArray satisfies the zapcore.ArrayMarshaler interface. +// This allows a list of subproblems to be serialized by the zap logger. +func (ls loggableSubproblems) MarshalLogArray(enc zapcore.ArrayEncoder) error { + for _, sp := range ls { + enc.AppendObject(sp) + } + return nil +} + // Standard token values for the "type" field of problems, as defined // in RFC 8555 §6.7: https://tools.ietf.org/html/rfc8555#section-6.7 // diff --git a/vendor/github.com/mholt/acmez/client.go b/vendor/github.com/mholt/acmez/client.go index a4d0446bb882..3add982cac5b 100644 --- a/vendor/github.com/mholt/acmez/client.go +++ b/vendor/github.com/mholt/acmez/client.go @@ -134,16 +134,23 @@ func (c *Client) ObtainCertificateUsingCSR(ctx context.Context, account acme.Acc // for some errors, we can retry with different challenge types var problem acme.Problem if errors.As(err, &problem) { - authz := problem.Resource.(acme.Authorization) + authz, haveAuthz := problem.Resource.(acme.Authorization) if c.Logger != nil { - c.Logger.Error("validating authorization", - zap.String("identifier", authz.IdentifierValue()), - zap.Error(err), + l := c.Logger + if haveAuthz { + l = l.With(zap.String("identifier", authz.IdentifierValue())) + } + l.Error("validating authorization", + zap.Object("problem", problem), zap.String("order", order.Location), zap.Int("attempt", attempt), zap.Int("max_attempts", maxAttempts)) } - err = fmt.Errorf("solving challenge: %s: %w", authz.IdentifierValue(), err) + errStr := "solving challenge" + if haveAuthz { + errStr += ": " + authz.IdentifierValue() + } + err = fmt.Errorf("%s: %w", errStr, err) if errors.As(err, &retryableErr{}) { continue } @@ -505,9 +512,7 @@ func (c *Client) pollAuthorization(ctx context.Context, account acme.Account, au c.Logger.Error("challenge failed", zap.String("identifier", authz.IdentifierValue()), zap.String("challenge_type", authz.currentChallenge.Type), - zap.Int("status_code", problem.Status), - zap.String("problem_type", problem.Type), - zap.String("error", problem.Detail)) + zap.Object("problem", problem)) } failedChallengeTypes.rememberFailedChallenge(authz) diff --git a/vendor/modules.txt b/vendor/modules.txt index dfc355e9040a..23a59c18ac12 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -197,7 +197,7 @@ github.com/boombuler/barcode/utils # github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b ## explicit github.com/bradfitz/gomemcache/memcache -# github.com/caddyserver/certmagic v0.14.1 +# github.com/caddyserver/certmagic v0.15.2 ## explicit github.com/caddyserver/certmagic # github.com/cespare/xxhash/v2 v2.1.1 @@ -606,7 +606,7 @@ github.com/mattn/go-runewidth github.com/mattn/go-sqlite3 # github.com/matttproud/golang_protobuf_extensions v1.0.1 github.com/matttproud/golang_protobuf_extensions/pbutil -# github.com/mholt/acmez v0.1.3 +# github.com/mholt/acmez v1.0.1 github.com/mholt/acmez github.com/mholt/acmez/acme # github.com/mholt/archiver/v3 v3.5.0 @@ -617,7 +617,6 @@ github.com/mholt/archiver/v3 github.com/microcosm-cc/bluemonday github.com/microcosm-cc/bluemonday/css # github.com/miekg/dns v1.1.43 -## explicit github.com/miekg/dns # github.com/minio/md5-simd v1.1.2 ## explicit