From 3577d696c757de9b3916209406af6dfdc2825069 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 10 Aug 2020 18:14:32 -0700 Subject: [PATCH] Use new x509util in tls_test.go --- authority/tls_test.go | 211 ++++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 98 deletions(-) diff --git a/authority/tls_test.go b/authority/tls_test.go index 47bc964d..dbbabd03 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -3,6 +3,8 @@ package authority import ( "context" "crypto" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/sha1" "crypto/x509" @@ -22,8 +24,8 @@ import ( "github.com/smallstep/certificates/errs" "github.com/smallstep/cli/crypto/keys" "github.com/smallstep/cli/crypto/pemutil" - "github.com/smallstep/cli/crypto/x509util" "github.com/smallstep/cli/jose" + "go.step.sm/crypto/x509util" "gopkg.in/square/go-jose.v2/jwt" ) @@ -51,10 +53,73 @@ func (m *certificateDurationEnforcer) Enforce(cert *x509.Certificate) error { return nil } -func withProvisionerOID(name, kid string) x509util.WithOption { - return func(p x509util.Profile) error { - crt := p.Subject() +func generateCertificate(t *testing.T, commonName string, sans []string, opts ...interface{}) *x509.Certificate { + t.Helper() + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + assert.FatalError(t, err) + + cr, err := x509util.CreateCertificateRequest(commonName, sans, priv) + assert.FatalError(t, err) + + template, err := x509util.NewCertificate(cr) + assert.FatalError(t, err) + + cert := template.GetCertificate() + for _, m := range opts { + switch m := m.(type) { + case provisioner.CertificateModifierFunc: + err = m.Modify(cert, provisioner.SignOptions{}) + assert.FatalError(t, err) + case signerFunc: + cert, err = m(cert, priv.Public()) + assert.FatalError(t, err) + default: + t.Fatalf("unknown type %T", m) + } + + } + return cert +} + +func generateRootCertificate(t *testing.T) (*x509.Certificate, crypto.Signer) { + t.Helper() + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + assert.FatalError(t, err) + + cr, err := x509util.CreateCertificateRequest("TestRootCA", nil, priv) + assert.FatalError(t, err) + + data := x509util.CreateTemplateData("TestRootCA", nil) + template, err := x509util.NewCertificate(cr, x509util.WithTemplate(x509util.DefaultRootTemplate, data)) + assert.FatalError(t, err) + + cert := template.GetCertificate() + cert, err = x509util.CreateCertificate(cert, cert, priv.Public(), priv) + assert.FatalError(t, err) + return cert, priv +} + +func generateIntermidiateCertificate(t *testing.T, issuer *x509.Certificate, signer crypto.Signer) (*x509.Certificate, crypto.Signer) { + t.Helper() + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + assert.FatalError(t, err) + + cr, err := x509util.CreateCertificateRequest("TestIntermediateCA", nil, priv) + assert.FatalError(t, err) + + data := x509util.CreateTemplateData("TestIntermediateCA", nil) + template, err := x509util.NewCertificate(cr, x509util.WithTemplate(x509util.DefaultRootTemplate, data)) + assert.FatalError(t, err) + + cert := template.GetCertificate() + cert, err = x509util.CreateCertificate(cert, issuer, priv.Public(), signer) + assert.FatalError(t, err) + return cert, priv +} + +func withProvisionerOID(name, kid string) provisioner.CertificateModifierFunc { + return func(crt *x509.Certificate, _ provisioner.SignOptions) error { b, err := asn1.Marshal(stepProvisionerASN1{ Type: provisionerTypeJWK, Name: []byte(name), @@ -68,11 +133,26 @@ func withProvisionerOID(name, kid string) x509util.WithOption { Critical: false, Value: b, }) - return nil } } +func withNotBeforeNotAfter(notBefore, notAfter time.Time) provisioner.CertificateModifierFunc { + return func(crt *x509.Certificate, _ provisioner.SignOptions) error { + crt.NotBefore = notBefore + crt.NotAfter = notAfter + return nil + } +} + +type signerFunc func(crt *x509.Certificate, pub crypto.PublicKey) (*x509.Certificate, error) + +func withSigner(issuer *x509.Certificate, signer crypto.Signer) signerFunc { + return func(crt *x509.Certificate, pub crypto.PublicKey) (*x509.Certificate, error) { + return x509util.CreateCertificate(crt, issuer, pub, signer) + } +} + func getCSR(t *testing.T, priv interface{}, opts ...func(*x509.CertificateRequest)) *x509.CertificateRequest { _csr := &x509.CertificateRequest{ Subject: pkix.Name{CommonName: "smallstep test"}, @@ -473,9 +553,6 @@ ZYtQ9Ot36qc= } func TestAuthority_Renew(t *testing.T) { - pub, _, err := keys.GenerateDefaultKeyPair() - assert.FatalError(t, err) - a := testAuthority(t) a.config.AuthorityConfig.Template = &ASN1DN{ Country: "Tazmania", @@ -486,13 +563,6 @@ func TestAuthority_Renew(t *testing.T) { CommonName: "renew", } - certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption { - return func(p x509util.Profile) error { - crt := p.Subject() - return m.Modify(crt, provisioner.SignOptions{}) - } - } - now := time.Now().UTC() nb1 := now.Add(-time.Minute * 7) na1 := now @@ -501,28 +571,17 @@ func TestAuthority_Renew(t *testing.T) { NotAfter: provisioner.NewTimeDuration(na1), } - leaf, err := x509util.NewLeafProfile("renew", a.x509Issuer, a.x509Signer, - x509util.WithNotBeforeAfterDuration(so.NotBefore.Time(), so.NotAfter.Time(), 0), - certModToWithOptions(withDefaultASN1DN(a.config.AuthorityConfig.Template)), - x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test"), - withProvisionerOID("Max", a.config.AuthorityConfig.Provisioners[0].(*provisioner.JWK).Key.KeyID)) - assert.FatalError(t, err) - certBytes, err := leaf.CreateCertificate() - assert.FatalError(t, err) - cert, err := x509.ParseCertificate(certBytes) - assert.FatalError(t, err) + cert := generateCertificate(t, "renew", []string{"test.smallstep.com", "test"}, + withNotBeforeNotAfter(so.NotBefore.Time(), so.NotAfter.Time()), + withDefaultASN1DN(a.config.AuthorityConfig.Template), + withProvisionerOID("Max", a.config.AuthorityConfig.Provisioners[0].(*provisioner.JWK).Key.KeyID), + withSigner(a.x509Issuer, a.x509Signer)) - leafNoRenew, err := x509util.NewLeafProfile("norenew", a.x509Issuer, a.x509Signer, - x509util.WithNotBeforeAfterDuration(so.NotBefore.Time(), so.NotAfter.Time(), 0), - certModToWithOptions(withDefaultASN1DN(a.config.AuthorityConfig.Template)), - x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test"), + certNoRenew := generateCertificate(t, "renew", []string{"test.smallstep.com", "test"}, + withNotBeforeNotAfter(so.NotBefore.Time(), so.NotAfter.Time()), + withDefaultASN1DN(a.config.AuthorityConfig.Template), withProvisionerOID("dev", a.config.AuthorityConfig.Provisioners[2].(*provisioner.JWK).Key.KeyID), - ) - assert.FatalError(t, err) - certBytesNoRenew, err := leafNoRenew.CreateCertificate() - assert.FatalError(t, err) - certNoRenew, err := x509.ParseCertificate(certBytesNoRenew) - assert.FatalError(t, err) + withSigner(a.x509Issuer, a.x509Signer)) type renewTest struct { auth *Authority @@ -555,24 +614,12 @@ func TestAuthority_Renew(t *testing.T) { }, nil }, "ok/success-new-intermediate": func() (*renewTest, error) { - newRootProfile, err := x509util.NewRootProfile("new-root") - assert.FatalError(t, err) - newRootBytes, err := newRootProfile.CreateCertificate() - assert.FatalError(t, err) - newRootCert, err := x509.ParseCertificate(newRootBytes) - assert.FatalError(t, err) - - newIntermediateProfile, err := x509util.NewIntermediateProfile("new-intermediate", - newRootCert, newRootProfile.SubjectPrivateKey()) - assert.FatalError(t, err) - newIntermediateBytes, err := newIntermediateProfile.CreateCertificate() - assert.FatalError(t, err) - newIntermediateCert, err := x509.ParseCertificate(newIntermediateBytes) - assert.FatalError(t, err) + rootCert, rootSigner := generateRootCertificate(t) + intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner) _a := testAuthority(t) - _a.x509Signer = newIntermediateProfile.SubjectPrivateKey().(crypto.Signer) - _a.x509Issuer = newIntermediateCert + _a.x509Signer = intSigner + _a.x509Issuer = intCert return &renewTest{ auth: _a, cert: cert, @@ -634,7 +681,7 @@ func TestAuthority_Renew(t *testing.T) { []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}) assert.Equals(t, leaf.DNSNames, []string{"test.smallstep.com", "test"}) - subjectKeyID, err := generateSubjectKeyID(pub) + subjectKeyID, err := generateSubjectKeyID(leaf.PublicKey) assert.FatalError(t, err) assert.Equals(t, leaf.SubjectKeyId, subjectKeyID) @@ -700,8 +747,6 @@ func TestAuthority_Renew(t *testing.T) { func TestAuthority_Rekey(t *testing.T) { pub, _, err := keys.GenerateDefaultKeyPair() assert.FatalError(t, err) - pub1, _, err := keys.GenerateDefaultKeyPair() - assert.FatalError(t, err) a := testAuthority(t) a.config.AuthorityConfig.Template = &ASN1DN{ @@ -713,13 +758,6 @@ func TestAuthority_Rekey(t *testing.T) { CommonName: "renew", } - certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption { - return func(p x509util.Profile) error { - crt := p.Subject() - return m.Modify(crt, provisioner.SignOptions{}) - } - } - now := time.Now().UTC() nb1 := now.Add(-time.Minute * 7) na1 := now @@ -728,28 +766,17 @@ func TestAuthority_Rekey(t *testing.T) { NotAfter: provisioner.NewTimeDuration(na1), } - leaf, err := x509util.NewLeafProfile("renew", a.x509Issuer, a.x509Signer, - x509util.WithNotBeforeAfterDuration(so.NotBefore.Time(), so.NotAfter.Time(), 0), - certModToWithOptions(withDefaultASN1DN(a.config.AuthorityConfig.Template)), - x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test"), - withProvisionerOID("Max", a.config.AuthorityConfig.Provisioners[0].(*provisioner.JWK).Key.KeyID)) - assert.FatalError(t, err) - certBytes, err := leaf.CreateCertificate() - assert.FatalError(t, err) - cert, err := x509.ParseCertificate(certBytes) - assert.FatalError(t, err) + cert := generateCertificate(t, "renew", []string{"test.smallstep.com", "test"}, + withNotBeforeNotAfter(so.NotBefore.Time(), so.NotAfter.Time()), + withDefaultASN1DN(a.config.AuthorityConfig.Template), + withProvisionerOID("Max", a.config.AuthorityConfig.Provisioners[0].(*provisioner.JWK).Key.KeyID), + withSigner(a.x509Issuer, a.x509Signer)) - leafNoRenew, err := x509util.NewLeafProfile("norenew", a.x509Issuer, a.x509Signer, - x509util.WithNotBeforeAfterDuration(so.NotBefore.Time(), so.NotAfter.Time(), 0), - certModToWithOptions(withDefaultASN1DN(a.config.AuthorityConfig.Template)), - x509util.WithPublicKey(pub), x509util.WithHosts("test.smallstep.com,test"), + certNoRenew := generateCertificate(t, "renew", []string{"test.smallstep.com", "test"}, + withNotBeforeNotAfter(so.NotBefore.Time(), so.NotAfter.Time()), + withDefaultASN1DN(a.config.AuthorityConfig.Template), withProvisionerOID("dev", a.config.AuthorityConfig.Provisioners[2].(*provisioner.JWK).Key.KeyID), - ) - assert.FatalError(t, err) - certBytesNoRenew, err := leafNoRenew.CreateCertificate() - assert.FatalError(t, err) - certNoRenew, err := x509.ParseCertificate(certBytesNoRenew) - assert.FatalError(t, err) + withSigner(a.x509Issuer, a.x509Signer)) type renewTest struct { auth *Authority @@ -786,28 +813,16 @@ func TestAuthority_Rekey(t *testing.T) { return &renewTest{ auth: a, cert: cert, - pk: pub1, + pk: pub, }, nil }, "ok/renew/success-new-intermediate": func() (*renewTest, error) { - newRootProfile, err := x509util.NewRootProfile("new-root") - assert.FatalError(t, err) - newRootBytes, err := newRootProfile.CreateCertificate() - assert.FatalError(t, err) - newRootCert, err := x509.ParseCertificate(newRootBytes) - assert.FatalError(t, err) - - newIntermediateProfile, err := x509util.NewIntermediateProfile("new-intermediate", - newRootCert, newRootProfile.SubjectPrivateKey()) - assert.FatalError(t, err) - newIntermediateBytes, err := newIntermediateProfile.CreateCertificate() - assert.FatalError(t, err) - newIntermediateCert, err := x509.ParseCertificate(newIntermediateBytes) - assert.FatalError(t, err) + rootCert, rootSigner := generateRootCertificate(t) + intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner) _a := testAuthority(t) - _a.x509Signer = newIntermediateProfile.SubjectPrivateKey().(crypto.Signer) - _a.x509Issuer = newIntermediateCert + _a.x509Signer = intSigner + _a.x509Issuer = intCert return &renewTest{ auth: _a, cert: cert,