forked from TrueCloudLab/lego
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.
This commit is contained in:
parent
71624f607a
commit
e32b9abfb2
2 changed files with 11 additions and 95 deletions
|
@ -176,56 +176,12 @@ func (c *Client) AgreeToTOS() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObtainCertificates tries to obtain certificates from the CA server
|
// ObtainCertificate tries to obtain a single certificate using all domains passed into it.
|
||||||
// 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.
|
|
||||||
// The first domain in domains is used for the CommonName field of the certificate, all other
|
// 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.
|
// domains are added using the Subject Alternate Names extension.
|
||||||
// If bundle is true, the []byte contains both the issuer certificate and
|
// If bundle is true, the []byte contains both the issuer certificate and
|
||||||
// your issued certificate as a bundle.
|
// 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 {
|
if bundle {
|
||||||
logf("[INFO] acme: Obtaining bundled SAN certificate for %v", strings.Join(domains, ", "))
|
logf("[INFO] acme: Obtaining bundled SAN certificate for %v", strings.Join(domains, ", "))
|
||||||
} else {
|
} 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.
|
// 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
|
// If bundle is true, the []byte contains both the issuer certificate and
|
||||||
// your issued certificate as a bundle.
|
// 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
|
// 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.
|
// cert later on in the renewal process. The input may be a bundle or a single certificate.
|
||||||
certificates, err := parsePEMBundle(cert.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)
|
// TODO: Further test if we can actually use the new certificate (Our private key works)
|
||||||
if !x509Cert.Equal(serverCert) {
|
if !x509Cert.Equal(serverCert) {
|
||||||
logf("[INFO] acme: [%s] Server responded with renewed certificate", cert.Domain)
|
logf("[INFO] acme: [%s] Server responded with renewed certificate", cert.Domain)
|
||||||
if revokeOld {
|
|
||||||
c.RevokeCertificate(cert.Certificate)
|
|
||||||
}
|
|
||||||
issuedCert := pemEncode(derCertificateBytes(serverCertBytes))
|
issuedCert := pemEncode(derCertificateBytes(serverCertBytes))
|
||||||
// If bundle is true, we want to return a certificate bundle.
|
// If bundle is true, we want to return a certificate bundle.
|
||||||
// To do this, we need the issuer certificate.
|
// To do this, we need the issuer certificate.
|
||||||
|
@ -345,16 +298,8 @@ func (c *Client) RenewCertificate(cert CertificateResource, revokeOld bool, bund
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
newCerts, failures := c.ObtainCertificates([]string{cert.Domain}, bundle)
|
newCert, failures := c.ObtainCertificate([]string{cert.Domain}, bundle)
|
||||||
if len(failures) > 0 {
|
return newCert, failures[cert.Domain]
|
||||||
return CertificateResource{}, failures[cert.Domain]
|
|
||||||
}
|
|
||||||
|
|
||||||
if revokeOld {
|
|
||||||
c.RevokeCertificate(cert.Certificate)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCerts[0], nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Looks through the challenge combinations to find a solvable match.
|
// 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
|
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) {
|
func (c *Client) requestCertificate(authz []authorizationResource, bundle bool) (CertificateResource, error) {
|
||||||
if len(authz) == 0 {
|
if len(authz) == 0 {
|
||||||
return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!")
|
return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!")
|
||||||
|
|
|
@ -125,7 +125,7 @@ func run(c *cli.Context) {
|
||||||
logger().Fatal("Please specify --domains")
|
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 {
|
if len(failures) > 0 {
|
||||||
for k, v := range failures {
|
for k, v := range failures {
|
||||||
logger().Printf("[%s] Could not obtain certificates\n\t%v", k, v)
|
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.PrivateKey = keyBytes
|
||||||
certRes.Certificate = certBytes
|
certRes.Certificate = certBytes
|
||||||
|
|
||||||
newCert, err := client.RenewCertificate(certRes, true, true)
|
newCert, err := client.RenewCertificate(certRes, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger().Printf("%v", err)
|
logger().Printf("%v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := client.RevokeCertificate(certBytes); err != nil {
|
||||||
|
logger().Printf("%v (ignored)", err)
|
||||||
|
}
|
||||||
|
|
||||||
saveCertRes(newCert, conf)
|
saveCertRes(newCert, conf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue