Refactor error code in obtain functions to return a canonical error

This commit is contained in:
xenolf 2018-04-17 01:30:54 +02:00
parent 94083744ee
commit 6e962fbfb3
2 changed files with 27 additions and 19 deletions

View file

@ -265,7 +265,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) {
// your issued certificate as a bundle. // your issued certificate as a bundle.
// This function will never return a partial certificate. If one domain in the list fails, // This function will never return a partial certificate. If one domain in the list fails,
// the whole certificate will fail. // the whole certificate will fail.
func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, map[string]error) { func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, error) {
// figure out what domains it concerns // figure out what domains it concerns
// start with the common name // start with the common name
domains := []string{csr.Subject.CommonName} domains := []string{csr.Subject.CommonName}
@ -292,11 +292,7 @@ DNSNames:
order, err := c.createOrderForIdentifiers(domains) order, err := c.createOrderForIdentifiers(domains)
if err != nil { if err != nil {
identErrors := make(map[string]error) return CertificateResource{}, err
for _, auth := range order.Identifiers {
identErrors[auth.Value] = err
}
return CertificateResource{}, identErrors
} }
authz, failures := c.getAuthzForOrder(order) authz, failures := c.getAuthzForOrder(order)
// If any challenge fails - return. Do not generate partial SAN certificates. // If any challenge fails - return. Do not generate partial SAN certificates.
@ -338,7 +334,11 @@ DNSNames:
// your issued certificate as a bundle. // your issued certificate as a bundle.
// This function will never return a partial certificate. If one domain in the list fails, // This function will never return a partial certificate. If one domain in the list fails,
// the whole certificate will fail. // the whole certificate will fail.
func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, map[string]error) { func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) {
if len(domains) == 0 {
return CertificateResource{}, errors.New("Passed no domains into ObtainCertificate")
}
if bundle { if bundle {
logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", ")) logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
} else { } else {
@ -347,11 +347,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
order, err := c.createOrderForIdentifiers(domains) order, err := c.createOrderForIdentifiers(domains)
if err != nil { if err != nil {
identErrors := make(map[string]error) return CertificateResource{}, err
for _, domain := range domains {
identErrors[domain] = err
}
return CertificateResource{}, identErrors
} }
authz, failures := c.getAuthzForOrder(order) authz, failures := c.getAuthzForOrder(order)
// If any challenge fails - return. Do not generate partial SAN certificates. // If any challenge fails - return. Do not generate partial SAN certificates.
@ -433,7 +429,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
return CertificateResource{}, err return CertificateResource{}, err
} }
newCert, failures := c.ObtainCertificateForCSR(*csr, bundle) newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
return newCert, failures[cert.Domain] return newCert, failures
} }
var privKey crypto.PrivateKey var privKey crypto.PrivateKey
@ -445,7 +441,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
} }
var domains []string var domains []string
var failures map[string]error
// check for SAN certificate // check for SAN certificate
if len(x509Cert.DNSNames) > 1 { if len(x509Cert.DNSNames) > 1 {
domains = append(domains, x509Cert.Subject.CommonName) domains = append(domains, x509Cert.Subject.CommonName)
@ -459,8 +454,8 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
domains = append(domains, x509Cert.Subject.CommonName) domains = append(domains, x509Cert.Subject.CommonName)
} }
newCert, failures := c.ObtainCertificate(domains, bundle, privKey, mustStaple) newCert, err := c.ObtainCertificate(domains, bundle, privKey, mustStaple)
return newCert, failures[cert.Domain] return newCert, err
} }
func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) { func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) {
@ -490,9 +485,9 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err
// Looks through the challenge combinations to find a solvable match. // Looks through the challenge combinations to find a solvable match.
// Then solves the challenges in series and returns. // Then solves the challenges in series and returns.
func (c *Client) solveChallengeForAuthz(authorizations []authorization) map[string]error { func (c *Client) solveChallengeForAuthz(authorizations []authorization) ObtainError {
// loop through the resources, basically through the domains. // loop through the resources, basically through the domains.
failures := make(map[string]error) failures := make(ObtainError)
for _, authz := range authorizations { for _, authz := range authorizations {
if authz.Status == "valid" { if authz.Status == "valid" {
// Boulder might recycle recent validated authz (see issue #267) // Boulder might recycle recent validated authz (see issue #267)
@ -528,7 +523,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) {
} }
// Get the challenges needed to proof our identifier to the ACME server. // Get the challenges needed to proof our identifier to the ACME server.
func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, map[string]error) { func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, ObtainError) {
resc, errc := make(chan authorization), make(chan domainError) resc, errc := make(chan authorization), make(chan domainError)
delay := time.Second / overallRequestLimit delay := time.Second / overallRequestLimit

View file

@ -1,6 +1,7 @@
package acme package acme
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -42,6 +43,18 @@ type domainError struct {
Error error Error error
} }
// ObtainError is returned when there are specific errors available
// per domain. For example in ObtainCertificate
type ObtainError map[string]error
func (e ObtainError) Error() string {
buffer := bytes.NewBufferString("acme: Error -> One or more domains had a problem:\n")
for dom, err := range e {
buffer.WriteString(fmt.Sprintf("[%s] %s\n", dom, err))
}
return buffer.String()
}
func handleHTTPError(resp *http.Response) error { func handleHTTPError(resp *http.Response) error {
var errorDetail RemoteError var errorDetail RemoteError