Update dependencies

This commit is contained in:
Ken-Håvard Lieng 2020-06-15 11:05:32 +02:00
parent 6985dd16da
commit fcf0c17682
101 changed files with 7033 additions and 2205 deletions

View file

@ -17,7 +17,6 @@ package certmagic
import (
"context"
"crypto/tls"
"encoding/base64"
"fmt"
"log"
weakrand "math/rand"
@ -96,13 +95,6 @@ func (am *ACMEManager) newACMEClient(useTestCA, interactive bool) (*acmeClient,
var caURL string
if useTestCA {
caURL = am.TestCA
// only use the default test CA if the CA is also
// the default CA; no point in testing against
// Let's Encrypt's staging server if we are not
// using their production server too
if caURL == "" && am.CA == DefaultACME.CA {
caURL = DefaultACME.TestCA
}
}
if caURL == "" {
caURL = am.CA
@ -175,7 +167,7 @@ func (am *ACMEManager) newACMEClient(useTestCA, interactive bool) (*acmeClient,
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
TermsOfServiceAgreed: am.Agreed,
Kid: am.ExternalAccount.KeyID,
HmacEncoded: base64.StdEncoding.EncodeToString(am.ExternalAccount.HMAC),
HmacEncoded: am.ExternalAccount.HMAC,
})
} else {
reg, err = client.Registration.Register(registration.RegisterOptions{

View file

@ -108,7 +108,11 @@ func NewACMEManager(cfg *Config, template ACMEManager) *ACMEManager {
if template.CA == "" {
template.CA = DefaultACME.CA
}
if template.TestCA == "" {
if template.TestCA == "" && template.CA == DefaultACME.CA {
// only use the default test CA if the CA is also
// the default CA; no point in testing against
// Let's Encrypt's staging server if we are not
// using their production server too
template.TestCA = DefaultACME.TestCA
}
if template.Email == "" {
@ -332,7 +336,7 @@ func (am *ACMEManager) Revoke(ctx context.Context, cert CertificateResource) err
// binding an external account to an ACME account.
type ExternalAccountBinding struct {
KeyID string
HMAC []byte
HMAC string
}
// DefaultACME specifies the default settings

View file

@ -17,6 +17,7 @@ package certmagic
import (
"fmt"
"log"
weakrand "math/rand" // seeded elsewhere
"strings"
"sync"
"time"
@ -94,6 +95,9 @@ func NewCache(opts CacheOptions) *Cache {
if opts.RenewCheckInterval <= 0 {
opts.RenewCheckInterval = DefaultRenewCheckInterval
}
if opts.Capacity < 0 {
opts.Capacity = 0
}
// this must be set, because we cannot not
// safely assume that the Default Config
@ -110,7 +114,7 @@ func NewCache(opts CacheOptions) *Cache {
doneChan: make(chan struct{}),
}
go c.maintainAssets()
go c.maintainAssets(0)
return c
}
@ -153,6 +157,11 @@ type CacheOptions struct {
// How often to check certificates for renewal;
// if unset, DefaultRenewCheckInterval will be used.
RenewCheckInterval time.Duration
// Maximum number of certificates to allow in the cache.
// If reached, certificates will be randomly evicted to
// make room for new ones. 0 means unlimited.
Capacity int
}
// ConfigGetter is a function that returns a prepared,
@ -181,6 +190,25 @@ func (certCache *Cache) unsyncedCacheCertificate(cert Certificate) {
return
}
// if the cache is at capacity, make room for new cert
cacheSize := len(certCache.cache)
if certCache.options.Capacity > 0 && cacheSize >= certCache.options.Capacity {
// Go maps are "nondeterministic" but not actually random,
// so although we could just chop off the "front" of the
// map with less code, that is a heavily skewed eviction
// strategy; generating random numbers is cheap and
// ensures a much better distribution.
rnd := weakrand.Intn(cacheSize)
i := 0
for _, randomCert := range certCache.cache {
if i == rnd {
certCache.removeCertificate(randomCert)
break
}
i++
}
}
// store the certificate
certCache.cache[cert.hash] = cert

View file

@ -388,7 +388,7 @@ func (cfg *Config) obtainWithIssuer(ctx context.Context, issuer Issuer, name str
// ensure idempotency of the obtain operation for this name
lockKey := cfg.lockKey("cert_acme", name)
err := obtainLock(cfg.Storage, lockKey)
err := acquireLock(ctx, cfg.Storage, lockKey)
if err != nil {
return err
}
@ -474,7 +474,7 @@ func (cfg *Config) renewWithIssuer(ctx context.Context, issuer Issuer, name stri
// ensure idempotency of the renew operation for this name
lockKey := cfg.lockKey("cert_acme", name)
err := obtainLock(cfg.Storage, lockKey)
err := acquireLock(ctx, cfg.Storage, lockKey)
if err != nil {
return err
}

View file

@ -15,6 +15,7 @@
package certmagic
import (
"context"
"encoding/json"
"fmt"
"io"
@ -124,7 +125,7 @@ func (fs *FileStorage) Filename(key string) string {
// Lock obtains a lock named by the given key. It blocks
// until the lock can be obtained or an error is returned.
func (fs *FileStorage) Lock(key string) error {
func (fs *FileStorage) Lock(ctx context.Context, key string) error {
filename := fs.lockFilename(key)
for {
@ -168,8 +169,13 @@ func (fs *FileStorage) Lock(key string) error {
default:
// lockfile exists and is not stale;
// just wait a moment and try again
time.Sleep(fileLockPollInterval)
// just wait a moment and try again,
// or return if context cancelled
select {
case <-time.After(fileLockPollInterval):
case <-ctx.Done():
return ctx.Err()
}
}
}
}

View file

@ -1,6 +1,6 @@
module github.com/caddyserver/certmagic
go 1.13
go 1.14
require (
github.com/go-acme/lego/v3 v3.7.0

View file

@ -32,13 +32,19 @@ import (
// that loops indefinitely and, on a regular schedule, checks
// certificates for expiration and initiates a renewal of certs
// that are expiring soon. It also updates OCSP stapling. It
// should only be called once per cache. Panics are recovered.
func (certCache *Cache) maintainAssets() {
// should only be called once per cache. Panics are recovered,
// and if panicCount < 10, the function is called recursively,
// incrementing panicCount each time. Initial invocation should
// start panicCount at 0.
func (certCache *Cache) maintainAssets(panicCount int) {
defer func() {
if err := recover(); err != nil {
buf := make([]byte, stackTraceBufferSize)
buf = buf[:runtime.Stack(buf, false)]
log.Printf("panic: certificate maintenance: %v\n%s", err, buf)
if panicCount < 10 {
certCache.maintainAssets(panicCount + 1)
}
}
}()

View file

@ -15,6 +15,7 @@
package certmagic
import (
"context"
"log"
"path"
"regexp"
@ -86,8 +87,11 @@ type Locker interface {
// To prevent deadlocks, all implementations (where this concern
// is relevant) should put a reasonable expiration on the lock in
// case Unlock is unable to be called due to some sort of network
// failure or system crash.
Lock(key string) error
// failure or system crash. Additionally, implementations should
// honor context cancellation as much as possible (in case the
// caller wishes to give up and free resources before the lock
// can be obtained).
Lock(ctx context.Context, key string) error
// Unlock releases the lock for key. This method must ONLY be
// called after a successful call to Lock, and only after the
@ -223,8 +227,8 @@ func CleanUpOwnLocks() {
}
}
func obtainLock(storage Storage, lockKey string) error {
err := storage.Lock(lockKey)
func acquireLock(ctx context.Context, storage Storage, lockKey string) error {
err := storage.Lock(ctx, lockKey)
if err == nil {
locksMu.Lock()
locks[lockKey] = storage