forked from TrueCloudLab/lego
add issuer certificate to CertificateResource (#325)
* add issuer certificate to CertificateResource Also write it out to the file system when running "lego run" Removed caching of the issuer certificate inside the acme client, since it didn't appear to be used. * only append issuerCert to issuedCert in case of success Effectively a no-op since issuerCert will be nil on error, but it seems more correct to only do it if fetching the issuer succeeds.
This commit is contained in:
parent
d149f14b6b
commit
e9c3078492
3 changed files with 41 additions and 37 deletions
|
@ -49,12 +49,11 @@ type validateFunc func(j *jws, domain, uri string, chlng challenge) error
|
||||||
|
|
||||||
// Client is the user-friendy way to ACME
|
// Client is the user-friendy way to ACME
|
||||||
type Client struct {
|
type Client struct {
|
||||||
directory directory
|
directory directory
|
||||||
user User
|
user User
|
||||||
jws *jws
|
jws *jws
|
||||||
keyType KeyType
|
keyType KeyType
|
||||||
issuerCert []byte
|
solvers map[Challenge]solver
|
||||||
solvers map[Challenge]solver
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new ACME client on behalf of the user. The client will depend on
|
// NewClient creates a new ACME client on behalf of the user. The client will depend on
|
||||||
|
@ -634,24 +633,26 @@ func (c *Client) requestCertificateForCsr(authz []authorizationResource, bundle
|
||||||
cerRes.AccountRef = c.user.GetRegistration().URI
|
cerRes.AccountRef = c.user.GetRegistration().URI
|
||||||
|
|
||||||
issuedCert := pemEncode(derCertificateBytes(cert))
|
issuedCert := pemEncode(derCertificateBytes(cert))
|
||||||
// If bundle is true, we want to return a certificate bundle.
|
|
||||||
// To do this, we need the issuer certificate.
|
// The issuer certificate link is always supplied via an "up" link
|
||||||
if bundle {
|
// in the response headers of a new certificate.
|
||||||
// The issuer certificate link is always supplied via an "up" link
|
links := parseLinks(resp.Header["Link"])
|
||||||
// in the response headers of a new certificate.
|
issuerCert, err := c.getIssuerCertificate(links["up"])
|
||||||
links := parseLinks(resp.Header["Link"])
|
if err != nil {
|
||||||
issuerCert, err := c.getIssuerCertificate(links["up"])
|
// If we fail to acquire the issuer cert, return the issued certificate - do not fail.
|
||||||
if err != nil {
|
logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", commonName.Domain, err)
|
||||||
// If we fail to acquire the issuer cert, return the issued certificate - do not fail.
|
} else {
|
||||||
logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", commonName.Domain, err)
|
issuerCert = pemEncode(derCertificateBytes(issuerCert))
|
||||||
} else {
|
|
||||||
// Success - append the issuer cert to the issued cert.
|
// If bundle is true, we want to return a certificate bundle.
|
||||||
issuerCert = pemEncode(derCertificateBytes(issuerCert))
|
// To do this, we append the issuer cert to the issued cert.
|
||||||
|
if bundle {
|
||||||
issuedCert = append(issuedCert, issuerCert...)
|
issuedCert = append(issuedCert, issuerCert...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cerRes.Certificate = issuedCert
|
cerRes.Certificate = issuedCert
|
||||||
|
cerRes.IssuerCertificate = issuerCert
|
||||||
logf("[INFO][%s] Server responded with a certificate.", commonName.Domain)
|
logf("[INFO][%s] Server responded with a certificate.", commonName.Domain)
|
||||||
return cerRes, nil
|
return cerRes, nil
|
||||||
}
|
}
|
||||||
|
@ -679,14 +680,9 @@ func (c *Client) requestCertificateForCsr(authz []authorizationResource, bundle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getIssuerCertificate requests the issuer certificate and caches it for
|
// getIssuerCertificate requests the issuer certificate
|
||||||
// subsequent requests.
|
|
||||||
func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
|
func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
|
||||||
logf("[INFO] acme: Requesting issuer cert from %s", url)
|
logf("[INFO] acme: Requesting issuer cert from %s", url)
|
||||||
if c.issuerCert != nil {
|
|
||||||
return c.issuerCert, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := httpGet(url)
|
resp, err := httpGet(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -703,7 +699,6 @@ func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.issuerCert = issuerBytes
|
|
||||||
return issuerBytes, err
|
return issuerBytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,16 +94,17 @@ type revokeCertMessage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertificateResource represents a CA issued certificate.
|
// CertificateResource represents a CA issued certificate.
|
||||||
// PrivateKey and Certificate are both already PEM encoded
|
// PrivateKey, Certificate and IssuerCertificate are all
|
||||||
// and can be directly written to disk. Certificate may
|
// already PEM encoded and can be directly written to disk.
|
||||||
// be a certificate bundle, depending on the options supplied
|
// Certificate may be a certificate bundle, depending on the
|
||||||
// to create it.
|
// options supplied to create it.
|
||||||
type CertificateResource struct {
|
type CertificateResource struct {
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
CertURL string `json:"certUrl"`
|
CertURL string `json:"certUrl"`
|
||||||
CertStableURL string `json:"certStableUrl"`
|
CertStableURL string `json:"certStableUrl"`
|
||||||
AccountRef string `json:"accountRef,omitempty"`
|
AccountRef string `json:"accountRef,omitempty"`
|
||||||
PrivateKey []byte `json:"-"`
|
PrivateKey []byte `json:"-"`
|
||||||
Certificate []byte `json:"-"`
|
Certificate []byte `json:"-"`
|
||||||
CSR []byte `json:"-"`
|
IssuerCertificate []byte `json:"-"`
|
||||||
|
CSR []byte `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,12 +136,20 @@ func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
|
||||||
privOut := path.Join(conf.CertPath(), certRes.Domain+".key")
|
privOut := path.Join(conf.CertPath(), certRes.Domain+".key")
|
||||||
pemOut := path.Join(conf.CertPath(), certRes.Domain+".pem")
|
pemOut := path.Join(conf.CertPath(), certRes.Domain+".pem")
|
||||||
metaOut := path.Join(conf.CertPath(), certRes.Domain+".json")
|
metaOut := path.Join(conf.CertPath(), certRes.Domain+".json")
|
||||||
|
issuerOut := path.Join(conf.CertPath(), certRes.Domain+".issuer.crt")
|
||||||
|
|
||||||
err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
|
err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
|
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 certRes.PrivateKey != nil {
|
||||||
// if we were given a CSR, we don't know the private key
|
// if we were given a CSR, we don't know the private key
|
||||||
err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
|
err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
|
||||||
|
|
Loading…
Reference in a new issue