From d1d9ae42d6141cf85284a35b6dd2c76f6793245d Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 7 Jul 2020 19:01:47 -0700 Subject: [PATCH] Use certificates x509util instead of cli for certificate signing. --- authority/tls.go | 68 ++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/authority/tls.go b/authority/tls.go index 7a8d1947..7b0d061d 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -16,6 +16,7 @@ import ( "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/db" "github.com/smallstep/certificates/errs" + x509cert "github.com/smallstep/certificates/x509util" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/tlsutil" "github.com/smallstep/cli/crypto/x509util" @@ -63,65 +64,80 @@ func withDefaultASN1DN(def *x509util.ASN1DN) x509util.WithOption { // Sign creates a signed certificate from a certificate signing request. func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { var ( - opts = []interface{}{errs.WithKeyVal("csr", csr), errs.WithKeyVal("signOptions", signOpts)} - mods = []x509util.WithOption{withDefaultASN1DN(a.config.AuthorityConfig.Template)} - certValidators = []provisioner.CertificateValidator{} - forcedModifiers = []provisioner.CertificateEnforcer{provisioner.ExtraExtsEnforcer{}} + certOptions []x509cert.Option + certValidators []provisioner.CertificateValidator + certModifiers []provisioner.CertificateModifier + certEnforcers []provisioner.CertificateEnforcer ) + opts := []interface{}{errs.WithKeyVal("csr", csr), errs.WithKeyVal("signOptions", signOpts)} + if err := csr.CheckSignature(); err != nil { + return nil, errs.Wrap(http.StatusBadRequest, err, "authority.Sign; invalid certificate request", opts...) + } + // Set backdate with the configured value signOpts.Backdate = a.config.AuthorityConfig.Backdate.Duration for _, op := range extraOpts { switch k := op.(type) { - case provisioner.CertificateValidator: - certValidators = append(certValidators, k) + // Adds new options to NewCertificate + case provisioner.CertificateOptions: + certOptions = append(certOptions, k.Options(signOpts)...) + + // Validate tie given certificate request. case provisioner.CertificateRequestValidator: if err := k.Valid(csr); err != nil { return nil, errs.Wrap(http.StatusUnauthorized, err, "authority.Sign", opts...) } - case provisioner.ProfileModifier: - mods = append(mods, k.Option(signOpts)) + + // Validates the unsigned certificate template. + case provisioner.CertificateValidator: + certValidators = append(certValidators, k) + + // Modifies a certificate before validating it. + case provisioner.CertificateModifier: + certModifiers = append(certModifiers, k) + + // Modifies a certificate after validating it. case provisioner.CertificateEnforcer: - forcedModifiers = append(forcedModifiers, k) + certEnforcers = append(certEnforcers, k) + default: return nil, errs.InternalServer("authority.Sign; invalid extra option type %T", append([]interface{}{k}, opts...)...) } } - if err := csr.CheckSignature(); err != nil { - return nil, errs.Wrap(http.StatusBadRequest, err, "authority.Sign; invalid certificate request", opts...) - } - - leaf, err := x509util.NewLeafProfileWithCSR(csr, a.x509Issuer, a.x509Signer, mods...) + cert, err := x509cert.NewCertificate(csr, certOptions...) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign", opts...) } - // Certificate validation + // Certificate modifiers before validation + leaf := cert.GetCertificate() + for _, m := range certModifiers { + if err := m.Modify(leaf, signOpts); err != nil { + return nil, errs.Wrap(http.StatusUnauthorized, err, "authority.Sign", opts...) + } + } + + // Certificate validation. for _, v := range certValidators { - if err := v.Valid(leaf.Subject(), signOpts); err != nil { + if err := v.Valid(leaf, signOpts); err != nil { return nil, errs.Wrap(http.StatusUnauthorized, err, "authority.Sign", opts...) } } // Certificate modifiers after validation - for _, m := range forcedModifiers { - if err := m.Enforce(leaf.Subject()); err != nil { + for _, m := range certEnforcers { + if err := m.Enforce(leaf); err != nil { return nil, errs.Wrap(http.StatusUnauthorized, err, "authority.Sign", opts...) } } - crtBytes, err := leaf.CreateCertificate() + serverCert, err := x509cert.CreateCertificate(leaf, a.x509Issuer, csr.PublicKey, a.x509Signer) if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, - "authority.Sign; error creating new leaf certificate", opts...) - } - - serverCert, err := x509.ParseCertificate(crtBytes) - if err != nil { - return nil, errs.Wrap(http.StatusInternalServerError, err, - "authority.Sign; error parsing new leaf certificate", opts...) + "authority.Sign; error creating certificate", opts...) } if err = a.db.StoreCertificate(serverCert); err != nil {