From 701d1ab638b23c24877fc41824add66232446676 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 2 Feb 2017 09:32:00 -0500 Subject: Updating server dependancies (#5249) --- vendor/github.com/xenolf/lego/README.md | 2 +- vendor/github.com/xenolf/lego/acme/client.go | 149 ++++++++++++--------- vendor/github.com/xenolf/lego/acme/crypto.go | 2 +- vendor/github.com/xenolf/lego/acme/error.go | 15 +-- vendor/github.com/xenolf/lego/acme/jws.go | 12 +- vendor/github.com/xenolf/lego/acme/messages.go | 23 ++-- vendor/github.com/xenolf/lego/cli_handlers.go | 8 ++ .../xenolf/lego/providers/dns/azure/azure.go | 4 +- .../xenolf/lego/providers/dns/vultr/vultr.go | 14 +- 9 files changed, 128 insertions(+), 101 deletions(-) (limited to 'vendor/github.com/xenolf') diff --git a/vendor/github.com/xenolf/lego/README.md b/vendor/github.com/xenolf/lego/README.md index 136bc5548..9be562944 100644 --- a/vendor/github.com/xenolf/lego/README.md +++ b/vendor/github.com/xenolf/lego/README.md @@ -244,7 +244,7 @@ if err != nil { // The acme library takes care of completing the challenges to obtain the certificate(s). // The domains must resolve to this machine or you have to use the DNS challenge. bundle := false -certificates, failures := client.ObtainCertificate([]string{"mydomain.com"}, bundle, nil) +certificates, failures := client.ObtainCertificate([]string{"mydomain.com"}, bundle, nil, false) if len(failures) > 0 { log.Fatal(failures) } diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go index 9f837af36..e824f5080 100644 --- a/vendor/github.com/xenolf/lego/acme/client.go +++ b/vendor/github.com/xenolf/lego/acme/client.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "log" "net" + "net/http" "regexp" "strconv" "strings" @@ -22,6 +23,9 @@ var ( Logger *log.Logger ) +// maxBodySize is the maximum size of body that we will read. +const maxBodySize = 1024 * 1024 + // logf writes a log entry. It uses Logger if not // nil, otherwise it uses the default log.Logger. func logf(format string, args ...interface{}) { @@ -49,12 +53,11 @@ type validateFunc func(j *jws, domain, uri string, chlng challenge) error // Client is the user-friendy way to ACME type Client struct { - directory directory - user User - jws *jws - keyType KeyType - issuerCert []byte - solvers map[Challenge]solver + directory directory + user User + jws *jws + keyType KeyType + solvers map[Challenge]solver } // NewClient creates a new ACME client on behalf of the user. The client will depend on @@ -611,89 +614,108 @@ func (c *Client) requestCertificateForCsr(authz []authorizationResource, bundle return CertificateResource{}, err } - cerRes := CertificateResource{ + certRes := CertificateResource{ Domain: commonName.Domain, CertURL: resp.Header.Get("Location"), - PrivateKey: privateKeyPem} + PrivateKey: privateKeyPem, + } - for { - switch resp.StatusCode { - case 201, 202: - cert, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) - resp.Body.Close() - if err != nil { - return CertificateResource{}, err - } + maxChecks := 1000 + for i := 0; i < maxChecks; i++ { + done, err := c.checkCertResponse(resp, &certRes, bundle) + resp.Body.Close() + if err != nil { + return CertificateResource{}, err + } + if done { + break + } + if i == maxChecks-1 { + return CertificateResource{}, fmt.Errorf("polled for certificate %d times; giving up", i) + } + resp, err = httpGet(certRes.CertURL) + if err != nil { + return CertificateResource{}, err + } + } + + return certRes, nil +} + +// checkCertResponse checks resp to see if a certificate is contained in the +// response, and if so, loads it into certRes and returns true. If the cert +// is not yet ready, it returns false. This function honors the waiting period +// required by the Retry-After header of the response, if specified. This +// function may read from resp.Body but does NOT close it. The certRes input +// should already have the Domain (common name) field populated. If bundle is +// true, the certificate will be bundled with the issuer's cert. +func (c *Client) checkCertResponse(resp *http.Response, certRes *CertificateResource, bundle bool) (bool, error) { + switch resp.StatusCode { + case 201, 202: + cert, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) + if err != nil { + return false, err + } + + // The server returns a body with a length of zero if the + // certificate was not ready at the time this request completed. + // Otherwise the body is the certificate. + if len(cert) > 0 { + certRes.CertStableURL = resp.Header.Get("Content-Location") + certRes.AccountRef = c.user.GetRegistration().URI - // The server returns a body with a length of zero if the - // certificate was not ready at the time this request completed. - // Otherwise the body is the certificate. - if len(cert) > 0 { + issuedCert := pemEncode(derCertificateBytes(cert)) - cerRes.CertStableURL = resp.Header.Get("Content-Location") - cerRes.AccountRef = c.user.GetRegistration().URI + // The issuer certificate link is always supplied via an "up" link + // in the response headers of a new certificate. + links := parseLinks(resp.Header["Link"]) + issuerCert, err := c.getIssuerCertificate(links["up"]) + if err != nil { + // If we fail to acquire the issuer cert, return the issued certificate - do not fail. + logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err) + } else { + issuerCert = pemEncode(derCertificateBytes(issuerCert)) - issuedCert := pemEncode(derCertificateBytes(cert)) // If bundle is true, we want to return a certificate bundle. - // To do this, we need the issuer certificate. + // To do this, we append the issuer cert to the issued cert. if bundle { - // The issuer certificate link is always supplied via an "up" link - // in the response headers of a new certificate. - links := parseLinks(resp.Header["Link"]) - issuerCert, err := c.getIssuerCertificate(links["up"]) - if err != nil { - // If we fail to acquire the issuer cert, return the issued certificate - do not fail. - logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", commonName.Domain, err) - } else { - // Success - append the issuer cert to the issued cert. - issuerCert = pemEncode(derCertificateBytes(issuerCert)) - issuedCert = append(issuedCert, issuerCert...) - } + issuedCert = append(issuedCert, issuerCert...) } - - cerRes.Certificate = issuedCert - logf("[INFO][%s] Server responded with a certificate.", commonName.Domain) - return cerRes, nil - } - - // The certificate was granted but is not yet issued. - // Check retry-after and loop. - ra := resp.Header.Get("Retry-After") - retryAfter, err := strconv.Atoi(ra) - if err != nil { - return CertificateResource{}, err } - logf("[INFO][%s] acme: Server responded with status 202; retrying after %ds", commonName.Domain, retryAfter) - time.Sleep(time.Duration(retryAfter) * time.Second) - - break - default: - return CertificateResource{}, handleHTTPError(resp) + certRes.Certificate = issuedCert + certRes.IssuerCertificate = issuerCert + logf("[INFO][%s] Server responded with a certificate.", certRes.Domain) + return true, nil } - resp, err = httpGet(cerRes.CertURL) + // The certificate was granted but is not yet issued. + // Check retry-after and loop. + ra := resp.Header.Get("Retry-After") + retryAfter, err := strconv.Atoi(ra) if err != nil { - return CertificateResource{}, err + return false, err } + + logf("[INFO][%s] acme: Server responded with status 202; retrying after %ds", certRes.Domain, retryAfter) + time.Sleep(time.Duration(retryAfter) * time.Second) + + return false, nil + default: + return false, handleHTTPError(resp) } } -// getIssuerCertificate requests the issuer certificate and caches it for -// subsequent requests. +// getIssuerCertificate requests the issuer certificate func (c *Client) getIssuerCertificate(url string) ([]byte, error) { logf("[INFO] acme: Requesting issuer cert from %s", url) - if c.issuerCert != nil { - return c.issuerCert, nil - } - resp, err := httpGet(url) if err != nil { return nil, err } defer resp.Body.Close() - issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) + issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) if err != nil { return nil, err } @@ -703,7 +725,6 @@ func (c *Client) getIssuerCertificate(url string) ([]byte, error) { return nil, err } - c.issuerCert = issuerBytes return issuerBytes, err } diff --git a/vendor/github.com/xenolf/lego/acme/crypto.go b/vendor/github.com/xenolf/lego/acme/crypto.go index c63b23b99..fa868a90d 100644 --- a/vendor/github.com/xenolf/lego/acme/crypto.go +++ b/vendor/github.com/xenolf/lego/acme/crypto.go @@ -226,7 +226,7 @@ func generateCsr(privateKey crypto.PrivateKey, domain string, san []string, must } if mustStaple { - template.Extensions = append(template.Extensions, pkix.Extension{ + template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{ Id: tlsFeatureExtensionOID, Value: ocspMustStapleFeature, }) diff --git a/vendor/github.com/xenolf/lego/acme/error.go b/vendor/github.com/xenolf/lego/acme/error.go index 2aa690b33..6d7013cf1 100644 --- a/vendor/github.com/xenolf/lego/acme/error.go +++ b/vendor/github.com/xenolf/lego/acme/error.go @@ -8,9 +8,7 @@ import ( "strings" ) -const ( - tosAgreementError = "Must agree to subscriber agreement before any further actions" -) +const tosAgreementError = "Must agree to subscriber agreement before any further actions" // RemoteError is the base type for all errors specific to the ACME protocol. type RemoteError struct { @@ -54,20 +52,17 @@ func (c challengeError) Error() string { func handleHTTPError(resp *http.Response) error { var errorDetail RemoteError - contenType := resp.Header.Get("Content-Type") - // try to decode the content as JSON - if contenType == "application/json" || contenType == "application/problem+json" { - decoder := json.NewDecoder(resp.Body) - err := decoder.Decode(&errorDetail) + contentType := resp.Header.Get("Content-Type") + if contentType == "application/json" || contentType == "application/problem+json" { + err := json.NewDecoder(resp.Body).Decode(&errorDetail) if err != nil { return err } } else { - detailBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) + detailBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) if err != nil { return err } - errorDetail.Detail = string(detailBytes) } diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go index f70513e38..2a1fc244d 100644 --- a/vendor/github.com/xenolf/lego/acme/jws.go +++ b/vendor/github.com/xenolf/lego/acme/jws.go @@ -32,7 +32,9 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey { } } -// Posts a JWS signed message to the specified URL +// Posts a JWS signed message to the specified URL. +// It does NOT close the response body, so the caller must +// do that if no error was returned. func (j *jws) post(url string, content []byte) (*http.Response, error) { signedContent, err := j.signContent(content) if err != nil { @@ -44,6 +46,8 @@ func (j *jws) post(url string, content []byte) (*http.Response, error) { return nil, err } + j.Lock() + defer j.Unlock() j.getNonceFromResponse(resp) return resp, err @@ -77,8 +81,6 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { } func (j *jws) getNonceFromResponse(resp *http.Response) error { - j.Lock() - defer j.Unlock() nonce := resp.Header.Get("Replay-Nonce") if nonce == "" { return fmt.Errorf("Server did not respond with a proper nonce header.") @@ -98,6 +100,8 @@ func (j *jws) getNonce() error { } func (j *jws) Nonce() (string, error) { + j.Lock() + defer j.Unlock() nonce := "" if len(j.nonces) == 0 { err := j.getNonce() @@ -108,8 +112,6 @@ func (j *jws) Nonce() (string, error) { if len(j.nonces) == 0 { return "", fmt.Errorf("Can't get nonce") } - j.Lock() - defer j.Unlock() nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] return nonce, nil } diff --git a/vendor/github.com/xenolf/lego/acme/messages.go b/vendor/github.com/xenolf/lego/acme/messages.go index 0f6514c3f..36db3b217 100644 --- a/vendor/github.com/xenolf/lego/acme/messages.go +++ b/vendor/github.com/xenolf/lego/acme/messages.go @@ -94,16 +94,17 @@ type revokeCertMessage struct { } // CertificateResource represents a CA issued certificate. -// PrivateKey and Certificate are both already PEM encoded -// and can be directly written to disk. Certificate may -// be a certificate bundle, depending on the options supplied -// to create it. +// PrivateKey, Certificate and IssuerCertificate are all +// already PEM encoded and can be directly written to disk. +// Certificate may be a certificate bundle, depending on the +// options supplied to create it. type CertificateResource struct { - Domain string `json:"domain"` - CertURL string `json:"certUrl"` - CertStableURL string `json:"certStableUrl"` - AccountRef string `json:"accountRef,omitempty"` - PrivateKey []byte `json:"-"` - Certificate []byte `json:"-"` - CSR []byte `json:"-"` + Domain string `json:"domain"` + CertURL string `json:"certUrl"` + CertStableURL string `json:"certStableUrl"` + AccountRef string `json:"accountRef,omitempty"` + PrivateKey []byte `json:"-"` + Certificate []byte `json:"-"` + IssuerCertificate []byte `json:"-"` + CSR []byte `json:"-"` } diff --git a/vendor/github.com/xenolf/lego/cli_handlers.go b/vendor/github.com/xenolf/lego/cli_handlers.go index 858d71000..dad19a144 100644 --- a/vendor/github.com/xenolf/lego/cli_handlers.go +++ b/vendor/github.com/xenolf/lego/cli_handlers.go @@ -136,12 +136,20 @@ func saveCertRes(certRes acme.CertificateResource, conf *Configuration) { privOut := path.Join(conf.CertPath(), certRes.Domain+".key") pemOut := path.Join(conf.CertPath(), certRes.Domain+".pem") metaOut := path.Join(conf.CertPath(), certRes.Domain+".json") + issuerOut := path.Join(conf.CertPath(), certRes.Domain+".issuer.crt") err := ioutil.WriteFile(certOut, certRes.Certificate, 0600) if err != nil { logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error()) } + if certRes.IssuerCertificate != nil { + err = ioutil.WriteFile(issuerOut, certRes.IssuerCertificate, 0600) + if err != nil { + logger().Fatalf("Unable to save IssuerCertificate for domain %s\n\t%s", certRes.Domain, err.Error()) + } + } + if certRes.PrivateKey != nil { // if we were given a CSR, we don't know the private key err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600) diff --git a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go index 6742e4f56..9d281cd69 100644 --- a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go +++ b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go @@ -72,7 +72,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error { relative := toRelativeRecord(fqdn, acme.ToFqdn(zone)) rec := dns.RecordSet{ Name: &relative, - Properties: &dns.RecordSetProperties{ + RecordSetProperties: &dns.RecordSetProperties{ TTL: to.Int64Ptr(60), TXTRecords: &[]dns.TxtRecord{dns.TxtRecord{Value: &[]string{value}}}, }, @@ -103,7 +103,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { relative := toRelativeRecord(fqdn, acme.ToFqdn(zone)) rsc := dns.NewRecordSetsClient(c.subscriptionId) rsc.Authorizer, err = c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint) - _, err = rsc.Delete(c.resourceGroup, zone, relative, dns.TXT, "", "") + _, err = rsc.Delete(c.resourceGroup, zone, relative, dns.TXT, "") if err != nil { return err } diff --git a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go b/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go index 53804e270..bc2067579 100644 --- a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go +++ b/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go @@ -49,7 +49,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error { name := c.extractRecordName(fqdn, zoneDomain) - err = c.client.CreateDnsRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl) + err = c.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl) if err != nil { return fmt.Errorf("Vultr API call failed: %v", err) } @@ -67,7 +67,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { } for _, rec := range records { - err := c.client.DeleteDnsRecord(zoneDomain, rec.RecordID) + err := c.client.DeleteDNSRecord(zoneDomain, rec.RecordID) if err != nil { return err } @@ -76,12 +76,12 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { } func (c *DNSProvider) getHostedZone(domain string) (string, error) { - domains, err := c.client.GetDnsDomains() + domains, err := c.client.GetDNSDomains() if err != nil { return "", fmt.Errorf("Vultr API call failed: %v", err) } - var hostedDomain vultr.DnsDomain + var hostedDomain vultr.DNSDomain for _, d := range domains { if strings.HasSuffix(domain, d.Domain) { if len(d.Domain) > len(hostedDomain.Domain) { @@ -96,14 +96,14 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) { return hostedDomain.Domain, nil } -func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DnsRecord, error) { +func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) { zoneDomain, err := c.getHostedZone(domain) if err != nil { return "", nil, err } - var records []vultr.DnsRecord - result, err := c.client.GetDnsRecords(zoneDomain) + var records []vultr.DNSRecord + result, err := c.client.GetDNSRecords(zoneDomain) if err != nil { return "", records, fmt.Errorf("Vultr API call has failed: %v", err) } -- cgit v1.2.3-1-g7c22