forked from TrueCloudLab/certificates
Added RenewOrRekey function based on @maraino suggestion. RenewOrReky is called from Renew.
This commit is contained in:
parent
3813f57b1a
commit
8f504483ce
3 changed files with 19 additions and 92 deletions
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
|
@ -35,7 +36,7 @@ type Authority interface {
|
|||
Root(shasum string) (*x509.Certificate, error)
|
||||
Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
|
||||
Renew(peer *x509.Certificate) ([]*x509.Certificate, error)
|
||||
Rekey(peer *x509.Certificate, csr *x509.CertificateRequest) ([]*x509.Certificate, error)
|
||||
RenewOrRekey(peer *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error)
|
||||
LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error)
|
||||
LoadProvisionerByID(string) (provisioner.Interface, error)
|
||||
GetProvisioners(cursor string, limit int) (provisioner.List, string, error)
|
||||
|
|
12
api/rekey.go
12
api/rekey.go
|
@ -34,17 +34,17 @@ func (h *caHandler) Rekey(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := body.Validate(); err != nil {
|
||||
WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 {
|
||||
WriteError(w, errs.BadRequest("missing peer certificate"))
|
||||
return
|
||||
}
|
||||
|
||||
certChain, err := h.Authority.Rekey(r.TLS.PeerCertificates[0],body.CsrPEM.CertificateRequest)
|
||||
if err := body.Validate(); err != nil {
|
||||
WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
certChain, err := h.Authority.RenewOrRekey(r.TLS.PeerCertificates[0],body.CsrPEM.CertificateRequest.PublicKey)
|
||||
if err != nil {
|
||||
WriteError(w, errs.Wrap(http.StatusInternalServerError, err, "cahandler.Rekey"))
|
||||
return
|
||||
|
|
104
authority/tls.go
104
authority/tls.go
|
@ -2,6 +2,7 @@ package authority
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
|
@ -135,20 +136,28 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Opti
|
|||
// Renew creates a new Certificate identical to the old certificate, except
|
||||
// with a validity window that begins 'now'.
|
||||
func (a *Authority) Renew(oldCert *x509.Certificate) ([]*x509.Certificate, error) {
|
||||
return a.RenewOrRekey(oldCert, oldCert.PublicKey)
|
||||
}
|
||||
|
||||
// Rekey is similar to renew except that the certificate will be renewed with new key.
|
||||
// Function does rekeying if a new public key is passed as pk else if same key is passed, certificate will be just renewed.
|
||||
func (a *Authority) RenewOrRekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error) {
|
||||
opts := []interface{}{errs.WithKeyVal("serialNumber", oldCert.SerialNumber.String())}
|
||||
|
||||
// Check step provisioner extensions
|
||||
if err := a.authorizeRenew(oldCert); err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew", opts...)
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.RenewOrRekey", opts...)
|
||||
}
|
||||
|
||||
|
||||
// Durations
|
||||
backdate := a.config.AuthorityConfig.Backdate.Duration
|
||||
duration := oldCert.NotAfter.Sub(oldCert.NotBefore)
|
||||
now := time.Now().UTC()
|
||||
|
||||
|
||||
newCert := &x509.Certificate{
|
||||
PublicKey: oldCert.PublicKey,
|
||||
PublicKey: pk,
|
||||
Issuer: a.x509Issuer.Subject,
|
||||
Subject: oldCert.Subject,
|
||||
NotBefore: now.Add(-1 * backdate),
|
||||
|
@ -191,106 +200,23 @@ func (a *Authority) Renew(oldCert *x509.Certificate) ([]*x509.Certificate, error
|
|||
|
||||
leaf, err := x509util.NewLeafProfileWithTemplate(newCert, a.x509Issuer, a.x509Signer)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew", opts...)
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.RenewOrRekey", opts...)
|
||||
}
|
||||
crtBytes, err := leaf.CreateCertificate()
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Renew; error renewing certificate from existing server certificate", opts...)
|
||||
"authority.RenewOrRenew; error renewing certificate from existing server certificate", opts...)
|
||||
}
|
||||
|
||||
serverCert, err := x509.ParseCertificate(crtBytes)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Renew; error parsing new server certificate", opts...)
|
||||
"authority.RenewOrRekey; error parsing new server certificate", opts...)
|
||||
}
|
||||
|
||||
if err = a.db.StoreCertificate(serverCert); err != nil {
|
||||
if err != db.ErrNotImplemented {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew; error storing certificate in db", opts...)
|
||||
}
|
||||
}
|
||||
|
||||
return []*x509.Certificate{serverCert, a.x509Issuer}, nil
|
||||
}
|
||||
|
||||
// Rekey is similar to renew except that the certificate will be renewed with new key from csr argument.
|
||||
func (a *Authority) Rekey(oldCert *x509.Certificate, csr *x509.CertificateRequest) ([]*x509.Certificate, error) {
|
||||
opts := []interface{}{errs.WithKeyVal("serialNumber", oldCert.SerialNumber.String())}
|
||||
|
||||
// Check step provisioner extensions
|
||||
if err := a.authorizeRenew(oldCert); err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew", opts...)
|
||||
}
|
||||
|
||||
|
||||
// Durations
|
||||
backdate := a.config.AuthorityConfig.Backdate.Duration
|
||||
duration := oldCert.NotAfter.Sub(oldCert.NotBefore)
|
||||
now := time.Now().UTC()
|
||||
|
||||
|
||||
newCert := &x509.Certificate{
|
||||
PublicKey: csr.PublicKey,
|
||||
Issuer: a.x509Issuer.Subject,
|
||||
Subject: oldCert.Subject,
|
||||
NotBefore: now.Add(-1 * backdate),
|
||||
NotAfter: now.Add(duration - backdate),
|
||||
KeyUsage: oldCert.KeyUsage,
|
||||
UnhandledCriticalExtensions: oldCert.UnhandledCriticalExtensions,
|
||||
ExtKeyUsage: oldCert.ExtKeyUsage,
|
||||
UnknownExtKeyUsage: oldCert.UnknownExtKeyUsage,
|
||||
BasicConstraintsValid: oldCert.BasicConstraintsValid,
|
||||
IsCA: oldCert.IsCA,
|
||||
MaxPathLen: oldCert.MaxPathLen,
|
||||
MaxPathLenZero: oldCert.MaxPathLenZero,
|
||||
OCSPServer: oldCert.OCSPServer,
|
||||
IssuingCertificateURL: oldCert.IssuingCertificateURL,
|
||||
PermittedDNSDomainsCritical: oldCert.PermittedDNSDomainsCritical,
|
||||
PermittedEmailAddresses: oldCert.PermittedEmailAddresses,
|
||||
DNSNames: oldCert.DNSNames,
|
||||
EmailAddresses: oldCert.EmailAddresses,
|
||||
IPAddresses: oldCert.IPAddresses,
|
||||
URIs: oldCert.URIs,
|
||||
PermittedDNSDomains: oldCert.PermittedDNSDomains,
|
||||
ExcludedDNSDomains: oldCert.ExcludedDNSDomains,
|
||||
PermittedIPRanges: oldCert.PermittedIPRanges,
|
||||
ExcludedIPRanges: oldCert.ExcludedIPRanges,
|
||||
ExcludedEmailAddresses: oldCert.ExcludedEmailAddresses,
|
||||
PermittedURIDomains: oldCert.PermittedURIDomains,
|
||||
ExcludedURIDomains: oldCert.ExcludedURIDomains,
|
||||
CRLDistributionPoints: oldCert.CRLDistributionPoints,
|
||||
PolicyIdentifiers: oldCert.PolicyIdentifiers,
|
||||
}
|
||||
|
||||
// Copy all extensions except for Authority Key Identifier. This one might
|
||||
// be different if we rotate the intermediate certificate and it will cause
|
||||
// a TLS bad certificate error.
|
||||
for _, ext := range oldCert.Extensions {
|
||||
if !ext.Id.Equal(oidAuthorityKeyIdentifier) {
|
||||
newCert.ExtraExtensions = append(newCert.ExtraExtensions, ext)
|
||||
}
|
||||
}
|
||||
|
||||
leaf, err := x509util.NewLeafProfileWithTemplate(newCert, a.x509Issuer, a.x509Signer)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew", opts...)
|
||||
}
|
||||
crtBytes, err := leaf.CreateCertificate()
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Renew; error renewing certificate from existing server certificate", opts...)
|
||||
}
|
||||
|
||||
serverCert, err := x509.ParseCertificate(crtBytes)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Renew; error parsing new server certificate", opts...)
|
||||
}
|
||||
|
||||
if err = a.db.StoreCertificate(serverCert); err != nil {
|
||||
if err != db.ErrNotImplemented {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Renew; error storing certificate in db", opts...)
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.RenewOrRekey; error storing certificate in db", opts...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue