From e32b9abfb2808024f376a7241b6a362363503adf Mon Sep 17 00:00:00 2001 From: Tommie Gannert Date: Sat, 5 Dec 2015 22:07:12 +0000 Subject: [PATCH] Remove ObtainCertificates and rename ObtainSANCertificate to ObtainCertificate. Also removes revokation abilities from RenewCertificate. Makes the API more orthogonal. These things are not provided by the ACME protocol, but were convenience helpers. --- acme/client.go | 98 +++---------------------------------------------- cli_handlers.go | 8 +++- 2 files changed, 11 insertions(+), 95 deletions(-) diff --git a/acme/client.go b/acme/client.go index 025ae915..c37b7fe9 100644 --- a/acme/client.go +++ b/acme/client.go @@ -176,56 +176,12 @@ func (c *Client) AgreeToTOS() error { return err } -// ObtainCertificates tries to obtain certificates from the CA server -// using the challenges it has configured. The returned certificates are -// PEM encoded byte slices. -// If bundle is true, the []byte contains both the issuer certificate and -// your issued certificate as a bundle. -func (c *Client) ObtainCertificates(domains []string, bundle bool) ([]CertificateResource, map[string]error) { - if bundle { - logf("[INFO] acme: Obtaining bundled certificates for %v", strings.Join(domains, ", ")) - } else { - logf("[INFO] acme: Obtaining certificates for %v", strings.Join(domains, ", ")) - } - - challenges, failures := c.getChallenges(domains) - if len(challenges) == 0 { - return nil, failures - } - - err := c.solveChallenges(challenges) - for k, v := range err { - failures[k] = v - } - - if len(failures) == len(domains) { - return nil, failures - } - - // remove failed challenges from slice - var succeededChallenges []authorizationResource - for _, chln := range challenges { - if failures[chln.Domain] == nil { - succeededChallenges = append(succeededChallenges, chln) - } - } - - logf("[INFO] acme: Validations succeeded; requesting certificates") - - certs, err := c.requestCertificates(succeededChallenges, bundle) - for k, v := range err { - failures[k] = v - } - - return certs, failures -} - -// ObtainSANCertificate tries to obtain a single certificate using all domains passed into it. +// ObtainCertificate tries to obtain a single certificate using all domains passed into it. // The first domain in domains is used for the CommonName field of the certificate, all other // domains are added using the Subject Alternate Names extension. // If bundle is true, the []byte contains both the issuer certificate and // your issued certificate as a bundle. -func (c *Client) ObtainSANCertificate(domains []string, bundle bool) (CertificateResource, map[string]error) { +func (c *Client) ObtainCertificate(domains []string, bundle bool) (CertificateResource, map[string]error) { if bundle { logf("[INFO] acme: Obtaining bundled SAN certificate for %v", strings.Join(domains, ", ")) } else { @@ -281,7 +237,7 @@ func (c *Client) RevokeCertificate(certificate []byte) error { // this function will start a new-cert flow where a new certificate gets generated. // If bundle is true, the []byte contains both the issuer certificate and // your issued certificate as a bundle. -func (c *Client) RenewCertificate(cert CertificateResource, revokeOld bool, bundle bool) (CertificateResource, error) { +func (c *Client) RenewCertificate(cert CertificateResource, bundle bool) (CertificateResource, error) { // Input certificate is PEM encoded. Decode it here as we may need the decoded // cert later on in the renewal process. The input may be a bundle or a single certificate. certificates, err := parsePEMBundle(cert.Certificate) @@ -319,9 +275,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, revokeOld bool, bund // TODO: Further test if we can actually use the new certificate (Our private key works) if !x509Cert.Equal(serverCert) { logf("[INFO] acme: [%s] Server responded with renewed certificate", cert.Domain) - if revokeOld { - c.RevokeCertificate(cert.Certificate) - } issuedCert := pemEncode(derCertificateBytes(serverCertBytes)) // If bundle is true, we want to return a certificate bundle. // To do this, we need the issuer certificate. @@ -345,16 +298,8 @@ func (c *Client) RenewCertificate(cert CertificateResource, revokeOld bool, bund return cert, nil } - newCerts, failures := c.ObtainCertificates([]string{cert.Domain}, bundle) - if len(failures) > 0 { - return CertificateResource{}, failures[cert.Domain] - } - - if revokeOld { - c.RevokeCertificate(cert.Certificate) - } - - return newCerts[0], nil + newCert, failures := c.ObtainCertificate([]string{cert.Domain}, bundle) + return newCert, failures[cert.Domain] } // Looks through the challenge combinations to find a solvable match. @@ -449,39 +394,6 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s return challenges, failures } -// requestCertificates iterates all granted authorizations, creates RSA private keys and CSRs. -// It then uses these to request a certificate from the CA and returns the list of successfully -// granted certificates. -func (c *Client) requestCertificates(challenges []authorizationResource, bundle bool) ([]CertificateResource, map[string]error) { - resc, errc := make(chan CertificateResource), make(chan domainError) - for _, authz := range challenges { - go func(authz authorizationResource, resc chan CertificateResource, errc chan domainError) { - certRes, err := c.requestCertificate([]authorizationResource{authz}, bundle) - if err != nil { - errc <- domainError{Domain: authz.Domain, Error: err} - } else { - resc <- certRes - } - }(authz, resc, errc) - } - - var certs []CertificateResource - failures := make(map[string]error) - for i := 0; i < len(challenges); i++ { - select { - case res := <-resc: - certs = append(certs, res) - case err := <-errc: - failures[err.Domain] = err.Error - } - } - - close(resc) - close(errc) - - return certs, failures -} - func (c *Client) requestCertificate(authz []authorizationResource, bundle bool) (CertificateResource, error) { if len(authz) == 0 { return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!") diff --git a/cli_handlers.go b/cli_handlers.go index c6ff4f5e..5036ad73 100644 --- a/cli_handlers.go +++ b/cli_handlers.go @@ -125,7 +125,7 @@ func run(c *cli.Context) { logger().Fatal("Please specify --domains") } - cert, failures := client.ObtainSANCertificate(c.GlobalStringSlice("domains"), true) + cert, failures := client.ObtainCertificate(c.GlobalStringSlice("domains"), true) if len(failures) > 0 { for k, v := range failures { logger().Printf("[%s] Could not obtain certificates\n\t%v", k, v) @@ -203,12 +203,16 @@ func renew(c *cli.Context) { certRes.PrivateKey = keyBytes certRes.Certificate = certBytes - newCert, err := client.RenewCertificate(certRes, true, true) + newCert, err := client.RenewCertificate(certRes, true) if err != nil { logger().Printf("%v", err) return } + if err := client.RevokeCertificate(certBytes); err != nil { + logger().Printf("%v (ignored)", err) + } + saveCertRes(newCert, conf) } }