diff --git a/acme/client.go b/acme/client.go index ef0f80b7..bcb84437 100644 --- a/acme/client.go +++ b/acme/client.go @@ -330,6 +330,10 @@ DNSNames: challenges, failures := c.getChallenges(domains) // If any challenge fails - return. Do not generate partial SAN certificates. if len(failures) > 0 { + for _, auth := range challenges { + c.disableAuthz(auth) + } + return CertificateResource{}, failures } @@ -373,6 +377,10 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto challenges, failures := c.getChallenges(domains) // If any challenge fails - return. Do not generate partial SAN certificates. if len(failures) > 0 { + for _, auth := range challenges { + c.disableAuthz(auth) + } + return CertificateResource{}, failures } @@ -493,10 +501,12 @@ func (c *Client) solveChallenges(challenges []authorizationResource) map[string] // TODO: do not immediately fail if one domain fails to validate. err := solver.Solve(authz.Body.Challenges[i], authz.Domain) if err != nil { + c.disableAuthz(authz) failures[authz.Domain] = err } } } else { + c.disableAuthz(authz) failures[authz.Domain] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Domain) } } @@ -586,6 +596,13 @@ func logAuthz(authz []authorizationResource) { } } +// cleanAuthz loops through the passed in slice and disables any auths which are not "valid" +func (c *Client) disableAuthz(auth authorizationResource) error { + var disabledAuth authorization + _, err := postJSON(c.jws, auth.AuthURL, deactivateAuthMessage{Resource: "authz", Status: "deactivated"}, &disabledAuth) + return err +} + func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) { if len(authz) == 0 { return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!") diff --git a/acme/messages.go b/acme/messages.go index 36db3b21..79ccf154 100644 --- a/acme/messages.go +++ b/acme/messages.go @@ -93,6 +93,11 @@ type revokeCertMessage struct { Certificate string `json:"certificate"` } +type deactivateAuthMessage struct { + Resource string `json:"resource,omitempty"` + Status string `jsom:"status"` +} + // CertificateResource represents a CA issued certificate. // PrivateKey, Certificate and IssuerCertificate are all // already PEM encoded and can be directly written to disk.