diff --git a/vendor/github.com/mholt/certmagic/certmagic.go b/vendor/github.com/mholt/certmagic/certmagic.go index 5a356e2a1..cb480115f 100644 --- a/vendor/github.com/mholt/certmagic/certmagic.go +++ b/vendor/github.com/mholt/certmagic/certmagic.go @@ -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 ) diff --git a/vendor/github.com/mholt/certmagic/client.go b/vendor/github.com/mholt/certmagic/client.go index b909908a8..9589d0d8d 100644 --- a/vendor/github.com/mholt/certmagic/client.go +++ b/vendor/github.com/mholt/certmagic/client.go @@ -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) } diff --git a/vendor/github.com/mholt/certmagic/config.go b/vendor/github.com/mholt/certmagic/config.go index 3b2062122..1d0a7c8c4 100644 --- a/vendor/github.com/mholt/certmagic/config.go +++ b/vendor/github.com/mholt/certmagic/config.go @@ -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 } diff --git a/vendor/github.com/mholt/certmagic/crypto.go b/vendor/github.com/mholt/certmagic/crypto.go index eb7b52905..ec8080951 100644 --- a/vendor/github.com/mholt/certmagic/crypto.go +++ b/vendor/github.com/mholt/certmagic/crypto.go @@ -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 } diff --git a/vendor/github.com/mholt/certmagic/filestorage.go b/vendor/github.com/mholt/certmagic/filestorage.go index aa03058f9..0837f54cd 100644 --- a/vendor/github.com/mholt/certmagic/filestorage.go +++ b/vendor/github.com/mholt/certmagic/filestorage.go @@ -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), } diff --git a/vendor/github.com/mholt/certmagic/ocsp.go b/vendor/github.com/mholt/certmagic/ocsp.go index 5ee13fd4f..830d3d4b6 100644 --- a/vendor/github.com/mholt/certmagic/ocsp.go +++ b/vendor/github.com/mholt/certmagic/ocsp.go @@ -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) diff --git a/vendor/github.com/mholt/certmagic/solvers.go b/vendor/github.com/mholt/certmagic/solvers.go index 662647258..13f470f93 100644 --- a/vendor/github.com/mholt/certmagic/solvers.go +++ b/vendor/github.com/mholt/certmagic/solvers.go @@ -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 { diff --git a/vendor/github.com/mholt/certmagic/storage.go b/vendor/github.com/mholt/certmagic/storage.go index d3ac96608..3e20420bb 100644 --- a/vendor/github.com/mholt/certmagic/storage.go +++ b/vendor/github.com/mholt/certmagic/storage.go @@ -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@.-]`) diff --git a/vendor/github.com/mholt/certmagic/user.go b/vendor/github.com/mholt/certmagic/user.go index 642aa8b9e..b5116725a 100644 --- a/vendor/github.com/mholt/certmagic/user.go +++ b/vendor/github.com/mholt/certmagic/user.go @@ -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]) diff --git a/vendor/manifest b/vendor/manifest index 6d4f50dbd..a08ae9c99 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -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 },