Update Vendor (#16325)

* Add Dependencie Update Script

* update gitea.com/lunny/levelqueue

* update github.com/PuerkitoBio/goquery

* update github.com/alecthomas/chroma

* update github.com/blevesearch/bleve/v2

* update github.com/caddyserver/certmagic

* update github.com/go-enry/go-enry/v2

* update github.com/go-redis/redis/v8

* update github.com/hashicorp/golang-lru

* update github.com/klauspost/compress

* update github.com/markbates/goth

* update github.com/mholt/archiver/v3

* update github.com/microcosm-cc/bluemonday

* update github.com/minio/minio-go/v7

* update github.com/olivere/elastic/v7

* update github.com/xanzy/go-gitlab

* update github.com/yuin/goldmark
This commit is contained in:
6543 2021-07-04 04:06:10 +02:00 committed by GitHub
parent 65ae46bc20
commit fae07cbc8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
319 changed files with 33568 additions and 21050 deletions

View file

@ -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))
err = cfg.deleteSiteAssets(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))
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 {