mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-21 21:43:01 +08:00
vendor: Update certmagic
This commit is contained in:
parent
393bc2992e
commit
598de9e6d9
12
vendor/github.com/mholt/certmagic/certmagic.go
generated
vendored
12
vendor/github.com/mholt/certmagic/certmagic.go
generated
vendored
|
@ -16,12 +16,12 @@
|
|||
// including TLS & HTTPS best practices such as robust OCSP stapling, caching,
|
||||
// HTTP->HTTPS redirects, and more.
|
||||
//
|
||||
// Its high-level API serves your HTTP handlers over HTTPS by simply giving
|
||||
// Its high-level API serves your HTTP handlers over HTTPS if you simply give
|
||||
// the domain name(s) and the http.Handler; CertMagic will create and run
|
||||
// the HTTPS server for you, fully managing certificates during the lifetime
|
||||
// of the server. Similarly, it can be used to start TLS listeners or return
|
||||
// a ready-to-use tls.Config -- whatever layer you need TLS for, CertMagic
|
||||
// makes it easy.
|
||||
// makes it easy. See the HTTPS, Listen, and TLS functions for that.
|
||||
//
|
||||
// If you need more control, create a Config using New() and then call
|
||||
// Manage() on the config; but you'll have to be sure to solve the HTTP
|
||||
|
@ -475,10 +475,14 @@ const (
|
|||
// forward packets from the defaults to whatever these
|
||||
// are set to; otherwise ACME challenges will fail.
|
||||
var (
|
||||
// HTTPPort is the port on which to serve HTTP.
|
||||
// HTTPPort is the port on which to serve HTTP
|
||||
// and, by extension, the HTTP challenge (unless
|
||||
// AltHTTPPort is set).
|
||||
HTTPPort = 80
|
||||
|
||||
// HTTPSPort is the port on which to serve HTTPS.
|
||||
// HTTPSPort is the port on which to serve HTTPS
|
||||
// and, by extension, the TLS-ALPN challenge
|
||||
// (unless AltTLSALPNPort is set).
|
||||
HTTPSPort = 443
|
||||
)
|
||||
|
||||
|
|
14
vendor/github.com/mholt/certmagic/client.go
generated
vendored
14
vendor/github.com/mholt/certmagic/client.go
generated
vendored
|
@ -142,6 +142,12 @@ func (cfg *Config) newACMEClient(interactive bool) (*acmeClient, error) {
|
|||
// figure out which ports we'll be serving the challenges on
|
||||
useHTTPPort := HTTPChallengePort
|
||||
useTLSALPNPort := TLSALPNChallengePort
|
||||
if HTTPPort > 0 && HTTPPort != HTTPChallengePort {
|
||||
useHTTPPort = HTTPPort
|
||||
}
|
||||
if HTTPSPort > 0 && HTTPSPort != TLSALPNChallengePort {
|
||||
useTLSALPNPort = HTTPSPort
|
||||
}
|
||||
if cfg.AltHTTPPort > 0 {
|
||||
useHTTPPort = cfg.AltHTTPPort
|
||||
}
|
||||
|
@ -333,7 +339,7 @@ func (c *acmeClient) Renew(name string) error {
|
|||
// Revoke revokes the certificate for name and deletes
|
||||
// it from storage.
|
||||
func (c *acmeClient) Revoke(name string) error {
|
||||
if !c.config.certCache.storage.Exists(prefixSiteKey(c.config.CA, name)) {
|
||||
if !c.config.certCache.storage.Exists(StorageKeys.SitePrivateKey(c.config.CA, name)) {
|
||||
return fmt.Errorf("private key not found for %s", name)
|
||||
}
|
||||
|
||||
|
@ -351,15 +357,15 @@ func (c *acmeClient) Revoke(name string) error {
|
|||
c.config.OnEvent("acme_cert_revoked", name)
|
||||
}
|
||||
|
||||
err = c.config.certCache.storage.Delete(prefixSiteCert(c.config.CA, name))
|
||||
err = c.config.certCache.storage.Delete(StorageKeys.SiteCert(c.config.CA, name))
|
||||
if err != nil {
|
||||
return fmt.Errorf("certificate revoked, but unable to delete certificate file: %v", err)
|
||||
}
|
||||
err = c.config.certCache.storage.Delete(prefixSiteKey(c.config.CA, name))
|
||||
err = c.config.certCache.storage.Delete(StorageKeys.SitePrivateKey(c.config.CA, name))
|
||||
if err != nil {
|
||||
return fmt.Errorf("certificate revoked, but unable to delete private key: %v", err)
|
||||
}
|
||||
err = c.config.certCache.storage.Delete(prefixSiteMeta(c.config.CA, name))
|
||||
err = c.config.certCache.storage.Delete(StorageKeys.SiteMeta(c.config.CA, name))
|
||||
if err != nil {
|
||||
return fmt.Errorf("certificate revoked, but unable to delete certificate metadata: %v", err)
|
||||
}
|
||||
|
|
2
vendor/github.com/mholt/certmagic/config.go
generated
vendored
2
vendor/github.com/mholt/certmagic/config.go
generated
vendored
|
@ -266,7 +266,7 @@ func (cfg *Config) ObtainCert(name string, interactive bool) error {
|
|||
|
||||
// we expect this to be a new site; if the
|
||||
// cert already exists, then no-op
|
||||
if cfg.certCache.storage.Exists(prefixSiteCert(cfg.CA, name)) {
|
||||
if cfg.certCache.storage.Exists(StorageKeys.SiteCert(cfg.CA, name)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
12
vendor/github.com/mholt/certmagic/crypto.go
generated
vendored
12
vendor/github.com/mholt/certmagic/crypto.go
generated
vendored
|
@ -104,15 +104,15 @@ func (cfg *Config) saveCertResource(cert *certificate.Resource) error {
|
|||
|
||||
all := []keyValue{
|
||||
{
|
||||
key: prefixSiteCert(cfg.CA, cert.Domain),
|
||||
key: StorageKeys.SiteCert(cfg.CA, cert.Domain),
|
||||
value: cert.Certificate,
|
||||
},
|
||||
{
|
||||
key: prefixSiteKey(cfg.CA, cert.Domain),
|
||||
key: StorageKeys.SitePrivateKey(cfg.CA, cert.Domain),
|
||||
value: cert.PrivateKey,
|
||||
},
|
||||
{
|
||||
key: prefixSiteMeta(cfg.CA, cert.Domain),
|
||||
key: StorageKeys.SiteMeta(cfg.CA, cert.Domain),
|
||||
value: metaBytes,
|
||||
},
|
||||
}
|
||||
|
@ -122,15 +122,15 @@ func (cfg *Config) saveCertResource(cert *certificate.Resource) error {
|
|||
|
||||
func (cfg *Config) loadCertResource(domain string) (certificate.Resource, error) {
|
||||
var certRes certificate.Resource
|
||||
certBytes, err := cfg.certCache.storage.Load(prefixSiteCert(cfg.CA, domain))
|
||||
certBytes, err := cfg.certCache.storage.Load(StorageKeys.SiteCert(cfg.CA, domain))
|
||||
if err != nil {
|
||||
return certRes, err
|
||||
}
|
||||
keyBytes, err := cfg.certCache.storage.Load(prefixSiteKey(cfg.CA, domain))
|
||||
keyBytes, err := cfg.certCache.storage.Load(StorageKeys.SitePrivateKey(cfg.CA, domain))
|
||||
if err != nil {
|
||||
return certRes, err
|
||||
}
|
||||
metaBytes, err := cfg.certCache.storage.Load(prefixSiteMeta(cfg.CA, domain))
|
||||
metaBytes, err := cfg.certCache.storage.Load(StorageKeys.SiteMeta(cfg.CA, domain))
|
||||
if err != nil {
|
||||
return certRes, err
|
||||
}
|
||||
|
|
18
vendor/github.com/mholt/certmagic/filestorage.go
generated
vendored
18
vendor/github.com/mholt/certmagic/filestorage.go
generated
vendored
|
@ -33,13 +33,13 @@ type FileStorage struct {
|
|||
|
||||
// Exists returns true if key exists in fs.
|
||||
func (fs FileStorage) Exists(key string) bool {
|
||||
_, err := os.Stat(fs.filename(key))
|
||||
_, err := os.Stat(fs.Filename(key))
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
// Store saves value at key.
|
||||
func (fs FileStorage) Store(key string, value []byte) error {
|
||||
filename := fs.filename(key)
|
||||
filename := fs.Filename(key)
|
||||
err := os.MkdirAll(filepath.Dir(filename), 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -49,7 +49,7 @@ func (fs FileStorage) Store(key string, value []byte) error {
|
|||
|
||||
// Load retrieves the value at key.
|
||||
func (fs FileStorage) Load(key string) ([]byte, error) {
|
||||
contents, err := ioutil.ReadFile(fs.filename(key))
|
||||
contents, err := ioutil.ReadFile(fs.Filename(key))
|
||||
if os.IsNotExist(err) {
|
||||
return nil, ErrNotExist(err)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func (fs FileStorage) Load(key string) ([]byte, error) {
|
|||
// Delete deletes the value at key.
|
||||
// TODO: Delete any empty folders caused by this operation
|
||||
func (fs FileStorage) Delete(key string) error {
|
||||
err := os.Remove(fs.filename(key))
|
||||
err := os.Remove(fs.Filename(key))
|
||||
if os.IsNotExist(err) {
|
||||
return ErrNotExist(err)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func (fs FileStorage) Delete(key string) error {
|
|||
|
||||
// List returns all keys that match prefix.
|
||||
func (fs FileStorage) List(prefix string) ([]string, error) {
|
||||
d, err := os.Open(fs.filename(prefix))
|
||||
d, err := os.Open(fs.Filename(prefix))
|
||||
if os.IsNotExist(err) {
|
||||
return nil, ErrNotExist(err)
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func (fs FileStorage) List(prefix string) ([]string, error) {
|
|||
|
||||
// Stat returns information about key.
|
||||
func (fs FileStorage) Stat(key string) (KeyInfo, error) {
|
||||
fi, err := os.Stat(fs.filename(key))
|
||||
fi, err := os.Stat(fs.Filename(key))
|
||||
if os.IsNotExist(err) {
|
||||
return KeyInfo{}, ErrNotExist(err)
|
||||
}
|
||||
|
@ -95,7 +95,9 @@ func (fs FileStorage) Stat(key string) (KeyInfo, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (fs FileStorage) filename(key string) string {
|
||||
// Filename returns the key as a path on the file
|
||||
// system prefixed by fs.Path.
|
||||
func (fs FileStorage) Filename(key string) string {
|
||||
return filepath.Join(fs.Path, filepath.FromSlash(key))
|
||||
}
|
||||
|
||||
|
@ -149,7 +151,7 @@ func (fs FileStorage) TryLock(key string) (Waiter, error) {
|
|||
}
|
||||
|
||||
fw = &fileStorageWaiter{
|
||||
filename: filepath.Join(lockDir, safeKey(key)+".lock"),
|
||||
filename: filepath.Join(lockDir, StorageKeys.safe(key)+".lock"),
|
||||
wg: new(sync.WaitGroup),
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/mholt/certmagic/ocsp.go
generated
vendored
2
vendor/github.com/mholt/certmagic/ocsp.go
generated
vendored
|
@ -52,7 +52,7 @@ func (certCache *Cache) stapleOCSP(cert *Certificate, pemBundle []byte) error {
|
|||
|
||||
// First try to load OCSP staple from storage and see if
|
||||
// we can still use it.
|
||||
ocspStapleKey := prefixOCSPStaple(cert, pemBundle)
|
||||
ocspStapleKey := StorageKeys.OCSPStaple(cert, pemBundle)
|
||||
cachedOCSP, err := certCache.storage.Load(ocspStapleKey)
|
||||
if err == nil {
|
||||
resp, err := ocsp.ParseResponse(cachedOCSP, nil)
|
||||
|
|
4
vendor/github.com/mholt/certmagic/solvers.go
generated
vendored
4
vendor/github.com/mholt/certmagic/solvers.go
generated
vendored
|
@ -134,13 +134,13 @@ func (dhs distributedSolver) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
// challengeTokensPrefix returns the key prefix for challenge info.
|
||||
func (dhs distributedSolver) challengeTokensPrefix() string {
|
||||
return filepath.Join(prefixCA(dhs.config.CA), "challenge_tokens")
|
||||
return filepath.Join(StorageKeys.CAPrefix(dhs.config.CA), "challenge_tokens")
|
||||
}
|
||||
|
||||
// challengeTokensKey returns the key to use to store and access
|
||||
// challenge info for domain.
|
||||
func (dhs distributedSolver) challengeTokensKey(domain string) string {
|
||||
return filepath.Join(dhs.challengeTokensPrefix(), safeKey(domain)+".json")
|
||||
return filepath.Join(dhs.challengeTokensPrefix(), StorageKeys.safe(domain)+".json")
|
||||
}
|
||||
|
||||
type challengeInfo struct {
|
||||
|
|
107
vendor/github.com/mholt/certmagic/storage.go
generated
vendored
107
vendor/github.com/mholt/certmagic/storage.go
generated
vendored
|
@ -117,91 +117,100 @@ type keyValue struct {
|
|||
value []byte
|
||||
}
|
||||
|
||||
const (
|
||||
prefixACME = "acme"
|
||||
prefixOCSP = "ocsp"
|
||||
)
|
||||
// KeyBuilder provides a namespace for methods that
|
||||
// build keys and key prefixes, for addressing items
|
||||
// in a Storage implementation.
|
||||
type KeyBuilder struct{}
|
||||
|
||||
func prefixCA(ca string) string {
|
||||
// CAPrefix returns the storage key prefix for
|
||||
// the given certificate authority URL.
|
||||
func (keys KeyBuilder) CAPrefix(ca string) string {
|
||||
caURL, err := url.Parse(ca)
|
||||
if err != nil {
|
||||
caURL = &url.URL{Host: ca}
|
||||
}
|
||||
return path.Join(prefixACME, safeKey(caURL.Host))
|
||||
return path.Join(prefixACME, keys.safe(caURL.Host))
|
||||
}
|
||||
|
||||
func prefixSite(ca, domain string) string {
|
||||
return path.Join(prefixCA(ca), "sites", safeKey(domain))
|
||||
// SitePrefix returns a key prefix for items associated with
|
||||
// the site using the given CA URL.
|
||||
func (keys KeyBuilder) SitePrefix(ca, domain string) string {
|
||||
return path.Join(keys.CAPrefix(ca), "sites", keys.safe(domain))
|
||||
}
|
||||
|
||||
// prefixSiteCert returns the path to the certificate file for domain.
|
||||
func prefixSiteCert(ca, domain string) string {
|
||||
return path.Join(prefixSite(ca, domain), safeKey(domain)+".crt")
|
||||
// SiteCert returns the path to the certificate file for domain.
|
||||
func (keys KeyBuilder) SiteCert(ca, domain string) string {
|
||||
return path.Join(keys.SitePrefix(ca, domain), keys.safe(domain)+".crt")
|
||||
}
|
||||
|
||||
// prefixSiteKey returns the path to domain's private key file.
|
||||
func prefixSiteKey(ca, domain string) string {
|
||||
return path.Join(prefixSite(ca, domain), safeKey(domain)+".key")
|
||||
// SitePrivateKey returns the path to domain's private key file.
|
||||
func (keys KeyBuilder) SitePrivateKey(ca, domain string) string {
|
||||
return path.Join(keys.SitePrefix(ca, domain), keys.safe(domain)+".key")
|
||||
}
|
||||
|
||||
// prefixSiteMeta returns the path to the domain's asset metadata file.
|
||||
func prefixSiteMeta(ca, domain string) string {
|
||||
return path.Join(prefixSite(ca, domain), safeKey(domain)+".json")
|
||||
// SiteMeta returns the path to the domain's asset metadata file.
|
||||
func (keys KeyBuilder) SiteMeta(ca, domain string) string {
|
||||
return path.Join(keys.SitePrefix(ca, domain), keys.safe(domain)+".json")
|
||||
}
|
||||
|
||||
func prefixUsers(ca string) string {
|
||||
return path.Join(prefixCA(ca), "users")
|
||||
// UsersPrefix returns a key prefix for items related to
|
||||
// users associated with the given CA URL.
|
||||
func (keys KeyBuilder) UsersPrefix(ca string) string {
|
||||
return path.Join(keys.CAPrefix(ca), "users")
|
||||
}
|
||||
|
||||
// prefixUser gets the account folder for the user with email
|
||||
func prefixUser(ca, email string) string {
|
||||
// UserPrefix returns a key prefix for items related to
|
||||
// the user with the given email for the given CA URL.
|
||||
func (keys KeyBuilder) UserPrefix(ca, email string) string {
|
||||
if email == "" {
|
||||
email = emptyEmail
|
||||
}
|
||||
return path.Join(prefixUsers(ca), safeKey(email))
|
||||
return path.Join(keys.UsersPrefix(ca), keys.safe(email))
|
||||
}
|
||||
|
||||
// prefixUserReg gets the path to the registration file for the user with the
|
||||
// given email address.
|
||||
func prefixUserReg(ca, email string) string {
|
||||
return safeUserKey(ca, email, "registration", ".json")
|
||||
// UserReg gets the path to the registration file for the user
|
||||
// with the given email address for the given CA URL.
|
||||
func (keys KeyBuilder) UserReg(ca, email string) string {
|
||||
return keys.safeUserKey(ca, email, "registration", ".json")
|
||||
}
|
||||
|
||||
// prefixUserKey gets the path to the private key file for the user with the
|
||||
// given email address.
|
||||
func prefixUserKey(ca, email string) string {
|
||||
return safeUserKey(ca, email, "private", ".key")
|
||||
// UserPrivateKey gets the path to the private key file for the
|
||||
// user with the given email address on the given CA URL.
|
||||
func (keys KeyBuilder) UserPrivateKey(ca, email string) string {
|
||||
return keys.safeUserKey(ca, email, "private", ".key")
|
||||
}
|
||||
|
||||
func prefixOCSPStaple(cert *Certificate, pemBundle []byte) string {
|
||||
// OCSPStaple returns a key for the OCSP staple associated
|
||||
// with the given certificate. If you have the PEM bundle
|
||||
// handy, pass that in to save an extra encoding step.
|
||||
func (keys KeyBuilder) OCSPStaple(cert *Certificate, pemBundle []byte) string {
|
||||
var ocspFileName string
|
||||
if len(cert.Names) > 0 {
|
||||
firstName := safeKey(cert.Names[0])
|
||||
firstName := keys.safe(cert.Names[0])
|
||||
ocspFileName = firstName + "-"
|
||||
}
|
||||
ocspFileName += fastHash(pemBundle)
|
||||
return path.Join(prefixOCSP, ocspFileName)
|
||||
}
|
||||
|
||||
// safeUserKey returns a key for the given email,
|
||||
// with the default filename, and the filename
|
||||
// ending in the given extension.
|
||||
func safeUserKey(ca, email, defaultFilename, extension string) string {
|
||||
// safeUserKey returns a key for the given email, with the default
|
||||
// filename, and the filename ending in the given extension.
|
||||
func (keys KeyBuilder) safeUserKey(ca, email, defaultFilename, extension string) string {
|
||||
if email == "" {
|
||||
email = emptyEmail
|
||||
}
|
||||
email = strings.ToLower(email)
|
||||
filename := emailUsername(email)
|
||||
filename := keys.emailUsername(email)
|
||||
if filename == "" {
|
||||
filename = defaultFilename
|
||||
}
|
||||
filename = safeKey(filename)
|
||||
return path.Join(prefixUser(ca, email), filename+extension)
|
||||
filename = keys.safe(filename)
|
||||
return path.Join(keys.UserPrefix(ca, email), filename+extension)
|
||||
}
|
||||
|
||||
// emailUsername returns the username portion of an email address (part before
|
||||
// '@') or the original input if it can't find the "@" symbol.
|
||||
func emailUsername(email string) string {
|
||||
func (keys KeyBuilder) emailUsername(email string) string {
|
||||
at := strings.Index(email, "@")
|
||||
if at == -1 {
|
||||
return email
|
||||
|
@ -211,8 +220,9 @@ func emailUsername(email string) string {
|
|||
return email[:at]
|
||||
}
|
||||
|
||||
// safeKey standardizes and sanitizes str for use in a file path.
|
||||
func safeKey(str string) string {
|
||||
// safe standardizes and sanitizes str for use as
|
||||
// a storage key. This method is idempotent.
|
||||
func (keys KeyBuilder) safe(str string) string {
|
||||
str = strings.ToLower(str)
|
||||
str = strings.TrimSpace(str)
|
||||
|
||||
|
@ -229,6 +239,19 @@ func safeKey(str string) string {
|
|||
return safeKeyRE.ReplaceAllLiteralString(str, "")
|
||||
}
|
||||
|
||||
// StorageKeys provides methods for accessing
|
||||
// keys and key prefixes for items in a Storage.
|
||||
// Typically, you will not need to use this
|
||||
// because accessing storage is abstracted away
|
||||
// for most cases. Only use this if you need to
|
||||
// directly access TLS assets in your application.
|
||||
var StorageKeys KeyBuilder
|
||||
|
||||
const (
|
||||
prefixACME = "acme"
|
||||
prefixOCSP = "ocsp"
|
||||
)
|
||||
|
||||
// safeKeyRE matches any undesirable characters in storage keys.
|
||||
// Note that this allows dots, so you'll have to strip ".." manually.
|
||||
var safeKeyRE = regexp.MustCompile(`[^\w@.-]`)
|
||||
|
|
14
vendor/github.com/mholt/certmagic/user.go
generated
vendored
14
vendor/github.com/mholt/certmagic/user.go
generated
vendored
|
@ -155,7 +155,7 @@ func (cfg *Config) getEmail(userPresent bool) (string, error) {
|
|||
func (cfg *Config) getUser(email string) (user, error) {
|
||||
var user user
|
||||
|
||||
regBytes, err := cfg.certCache.storage.Load(prefixUserReg(cfg.CA, email))
|
||||
regBytes, err := cfg.certCache.storage.Load(StorageKeys.UserReg(cfg.CA, email))
|
||||
if err != nil {
|
||||
if _, ok := err.(ErrNotExist); ok {
|
||||
// create a new user
|
||||
|
@ -163,7 +163,7 @@ func (cfg *Config) getUser(email string) (user, error) {
|
|||
}
|
||||
return user, err
|
||||
}
|
||||
keyBytes, err := cfg.certCache.storage.Load(prefixUserKey(cfg.CA, email))
|
||||
keyBytes, err := cfg.certCache.storage.Load(StorageKeys.UserPrivateKey(cfg.CA, email))
|
||||
if err != nil {
|
||||
if _, ok := err.(ErrNotExist); ok {
|
||||
// create a new user
|
||||
|
@ -197,11 +197,11 @@ func (cfg *Config) saveUser(user user) error {
|
|||
|
||||
all := []keyValue{
|
||||
{
|
||||
key: prefixUserReg(cfg.CA, user.Email),
|
||||
key: StorageKeys.UserReg(cfg.CA, user.Email),
|
||||
value: regBytes,
|
||||
},
|
||||
{
|
||||
key: prefixUserKey(cfg.CA, user.Email),
|
||||
key: StorageKeys.UserPrivateKey(cfg.CA, user.Email),
|
||||
value: keyBytes,
|
||||
},
|
||||
}
|
||||
|
@ -240,13 +240,13 @@ func (cfg *Config) askUserAgreement(agreementURL string) bool {
|
|||
// account, errors here are discarded to simplify code flow in
|
||||
// the caller, and errors are not important here anyway.
|
||||
func (cfg *Config) mostRecentUserEmail() string {
|
||||
userList, err := cfg.certCache.storage.List(prefixUsers(cfg.CA))
|
||||
userList, err := cfg.certCache.storage.List(StorageKeys.UsersPrefix(cfg.CA))
|
||||
if err != nil || len(userList) == 0 {
|
||||
return ""
|
||||
}
|
||||
sort.Slice(userList, func(i, j int) bool {
|
||||
iInfo, _ := cfg.certCache.storage.Stat(prefixUser(cfg.CA, userList[i]))
|
||||
jInfo, _ := cfg.certCache.storage.Stat(prefixUser(cfg.CA, userList[j]))
|
||||
iInfo, _ := cfg.certCache.storage.Stat(StorageKeys.UserPrefix(cfg.CA, userList[i]))
|
||||
jInfo, _ := cfg.certCache.storage.Stat(StorageKeys.UserPrefix(cfg.CA, userList[j]))
|
||||
return jInfo.Modified.Before(iInfo.Modified)
|
||||
})
|
||||
user, err := cfg.getUser(userList[0])
|
||||
|
|
2
vendor/manifest
vendored
2
vendor/manifest
vendored
|
@ -138,7 +138,7 @@
|
|||
"importpath": "github.com/mholt/certmagic",
|
||||
"repository": "https://github.com/mholt/certmagic",
|
||||
"vcs": "git",
|
||||
"revision": "8b6ddf223c912a863aaadd388bfdd29be295fb5d",
|
||||
"revision": "5b3085c491553887f36460365533eb5955fdeef0",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user