1
0
Fork 0
forked from forgejo/forgejo

[Vendor] update certmagic (#15590)

* update github.com/caddyserver/certmagic v0.12.0 -> v0.13.0

* migrate
This commit is contained in:
6543 2021-04-22 22:42:33 +02:00 committed by GitHub
parent e7fc078891
commit 8ea1d32bea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
177 changed files with 4725 additions and 1984 deletions

View file

@ -28,9 +28,12 @@ import (
"encoding/pem"
"fmt"
"hash/fnv"
"sort"
"strings"
"github.com/klauspost/cpuid"
"go.uber.org/zap"
"golang.org/x/net/idna"
)
// encodePrivateKey marshals a EC or RSA private key into a PEM-encoded array of bytes.
@ -129,13 +132,13 @@ func fastHash(input []byte) string {
// saveCertResource saves the certificate resource to disk. This
// includes the certificate file itself, the private key, and the
// metadata file.
func (cfg *Config) saveCertResource(cert CertificateResource) error {
func (cfg *Config) saveCertResource(issuer Issuer, cert CertificateResource) error {
metaBytes, err := json.MarshalIndent(cert, "", "\t")
if err != nil {
return fmt.Errorf("encoding certificate metadata: %v", err)
}
issuerKey := cfg.Issuer.IssuerKey()
issuerKey := issuer.IssuerKey()
certKey := cert.NamesKey()
all := []keyValue{
@ -156,20 +159,95 @@ func (cfg *Config) saveCertResource(cert CertificateResource) error {
return storeTx(cfg.Storage, all)
}
func (cfg *Config) loadCertResource(certNamesKey string) (CertificateResource, error) {
// loadCertResourceAnyIssuer loads and returns the certificate resource from any
// of the configured issuers. If multiple are found (e.g. if there are 3 issuers
// configured, and all 3 have a resource matching certNamesKey), then the newest
// (latest NotBefore date) resource will be chosen.
func (cfg *Config) loadCertResourceAnyIssuer(certNamesKey string) (CertificateResource, error) {
// we can save some extra decoding steps if there's only one issuer, since
// we don't need to compare potentially multiple available resources to
// select the best one, when there's only one choice anyway
if len(cfg.Issuers) == 1 {
return cfg.loadCertResource(cfg.Issuers[0], certNamesKey)
}
type decodedCertResource struct {
CertificateResource
issuer Issuer
decoded *x509.Certificate
}
var certResources []decodedCertResource
var lastErr error
// load and decode all certificate resources found with the
// configured issuers so we can sort by newest
for _, issuer := range cfg.Issuers {
certRes, err := cfg.loadCertResource(issuer, certNamesKey)
if err != nil {
if _, ok := err.(ErrNotExist); ok {
// not a problem, but we need to remember the error
// in case we end up not finding any cert resources
// since we'll need an error to return in that case
lastErr = err
continue
}
return CertificateResource{}, err
}
certs, err := parseCertsFromPEMBundle(certRes.CertificatePEM)
if err != nil {
return CertificateResource{}, err
}
certResources = append(certResources, decodedCertResource{
CertificateResource: certRes,
issuer: issuer,
decoded: certs[0],
})
}
if len(certResources) == 0 {
if lastErr == nil {
lastErr = fmt.Errorf("no certificate resources found") // just in case; e.g. no Issuers configured
}
return CertificateResource{}, lastErr
}
// sort by date so the most recently issued comes first
sort.Slice(certResources, func(i, j int) bool {
return certResources[j].decoded.NotBefore.Before(certResources[i].decoded.NotBefore)
})
if cfg.Logger != nil {
cfg.Logger.Debug("loading managed certificate",
zap.String("domain", certNamesKey),
zap.Time("expiration", certResources[0].decoded.NotAfter),
zap.String("issuer_key", certResources[0].issuer.IssuerKey()),
zap.Any("storage", cfg.Storage),
)
}
return certResources[0].CertificateResource, nil
}
// 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 := cfg.Issuer.IssuerKey()
certBytes, err := cfg.Storage.Load(StorageKeys.SiteCert(issuerKey, certNamesKey))
issuerKey := issuer.IssuerKey()
normalizedName, err := idna.ToASCII(certNamesKey)
if err != nil {
return certRes, fmt.Errorf("converting '%s' to ASCII: %v", certNamesKey, err)
}
certBytes, err := cfg.Storage.Load(StorageKeys.SiteCert(issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.CertificatePEM = certBytes
keyBytes, err := cfg.Storage.Load(StorageKeys.SitePrivateKey(issuerKey, certNamesKey))
keyBytes, err := cfg.Storage.Load(StorageKeys.SitePrivateKey(issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
certRes.PrivateKeyPEM = keyBytes
metaBytes, err := cfg.Storage.Load(StorageKeys.SiteMeta(issuerKey, certNamesKey))
metaBytes, err := cfg.Storage.Load(StorageKeys.SiteMeta(issuerKey, normalizedName))
if err != nil {
return CertificateResource{}, err
}
@ -178,50 +256,6 @@ func (cfg *Config) loadCertResource(certNamesKey string) (CertificateResource, e
return CertificateResource{}, fmt.Errorf("decoding certificate metadata: %v", err)
}
// TODO: July 2020 - transition to new ACME lib and cert resource structure;
// for a while, we will need to convert old cert resources to new structure
certRes, err = cfg.transitionCertMetaToACMEzJuly2020Format(certRes, metaBytes)
if err != nil {
return certRes, fmt.Errorf("one-time certificate resource transition: %v", err)
}
return certRes, nil
}
// TODO: this is a temporary transition helper starting July 2020.
// It can go away when we think enough time has passed that most active assets have transitioned.
func (cfg *Config) transitionCertMetaToACMEzJuly2020Format(certRes CertificateResource, metaBytes []byte) (CertificateResource, error) {
data, ok := certRes.IssuerData.(map[string]interface{})
if !ok {
return certRes, nil
}
if certURL, ok := data["url"].(string); ok && certURL != "" {
return certRes, nil
}
var oldCertRes struct {
SANs []string `json:"sans"`
IssuerData struct {
Domain string `json:"domain"`
CertURL string `json:"certUrl"`
CertStableURL string `json:"certStableUrl"`
} `json:"issuer_data"`
}
err := json.Unmarshal(metaBytes, &oldCertRes)
if err != nil {
return certRes, fmt.Errorf("decoding into old certificate resource type: %v", err)
}
data = map[string]interface{}{
"url": oldCertRes.IssuerData.CertURL,
}
certRes.IssuerData = data
err = cfg.saveCertResource(certRes)
if err != nil {
return certRes, fmt.Errorf("saving converted certificate resource: %v", err)
}
return certRes, nil
}