From bc6074f596d9852134663ae6fc98075500c3ea1c Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 9 Oct 2019 21:57:12 +0200 Subject: [PATCH] Change api of functions Authority.Sign, Authority.Renew Returns certificate chain instead of 2 members. Implements #126 --- acme/common.go | 2 +- acme/order.go | 6 ++--- acme/order_test.go | 12 +++++----- api/api.go | 54 +++++++++++++++++++++++++++++-------------- api/api_test.go | 18 +++++++-------- authority/tls.go | 36 ++++++++++++++--------------- authority/tls_test.go | 12 ++++++---- ca/bootstrap_test.go | 6 ++--- ca/client_test.go | 8 +++++++ ca/tls_test.go | 16 +++++++++++++ 10 files changed, 109 insertions(+), 61 deletions(-) diff --git a/acme/common.go b/acme/common.go index 577c35cd..71e10cb6 100644 --- a/acme/common.go +++ b/acme/common.go @@ -12,7 +12,7 @@ import ( // SignAuthority is the interface implemented by a CA authority. type SignAuthority interface { - Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) + Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) LoadProvisionerByID(string) (provisioner.Interface, error) } diff --git a/acme/order.go b/acme/order.go index 5133ca1b..8d22b7db 100644 --- a/acme/order.go +++ b/acme/order.go @@ -274,7 +274,7 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut } // Create and store a new certificate. - leaf, inter, err := auth.Sign(csr, provisioner.Options{ + certChain, err := auth.Sign(csr, provisioner.Options{ NotBefore: provisioner.NewTimeDuration(o.NotBefore), NotAfter: provisioner.NewTimeDuration(o.NotAfter), }, signOps...) @@ -285,8 +285,8 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut cert, err := newCert(db, CertOptions{ AccountID: o.AccountID, OrderID: o.ID, - Leaf: leaf, - Intermediates: []*x509.Certificate{inter}, + Leaf: certChain[0], + Intermediates: certChain[1:], }) if err != nil { return nil, err diff --git a/acme/order_test.go b/acme/order_test.go index 31601fae..18a46589 100644 --- a/acme/order_test.go +++ b/acme/order_test.go @@ -789,19 +789,19 @@ func TestOrderUpdateStatus(t *testing.T) { } type mockSignAuth struct { - sign func(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) + sign func(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) loadProvisionerByID func(string) (provisioner.Interface, error) ret1, ret2 interface{} err error } -func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) { +func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { if m.sign != nil { return m.sign(csr, signOpts, extraOpts...) } else if m.err != nil { - return nil, nil, m.err + return nil, m.err } - return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err + return []*x509.Certificate{m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate)}, m.err } func (m *mockSignAuth) LoadProvisionerByID(id string) (provisioner.Interface, error) { @@ -1082,9 +1082,9 @@ func TestOrderFinalize(t *testing.T) { res: clone, csr: csr, sa: &mockSignAuth{ - sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) { + sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { assert.Equals(t, len(signOps), 4) - return crt, inter, nil + return []*x509.Certificate{crt, inter}, nil }, }, db: &db.MockNoSQLDB{ diff --git a/api/api.go b/api/api.go index 3850d921..d1ff7d1d 100644 --- a/api/api.go +++ b/api/api.go @@ -33,8 +33,8 @@ type Authority interface { AuthorizeSign(ott string) ([]provisioner.SignOption, error) GetTLSOptions() *tlsutil.TLSOptions Root(shasum string) (*x509.Certificate, error) - Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) - Renew(peer *x509.Certificate) (*x509.Certificate, *x509.Certificate, error) + Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) + Renew(peer *x509.Certificate) ([]*x509.Certificate, error) LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error) LoadProvisionerByID(string) (provisioner.Interface, error) GetProvisioners(cursor string, limit int) (provisioner.List, string, error) @@ -211,10 +211,11 @@ func (s *SignRequest) Validate() error { // SignResponse is the response object of the certificate signature request. type SignResponse struct { - ServerPEM Certificate `json:"crt"` - CaPEM Certificate `json:"ca"` - TLSOptions *tlsutil.TLSOptions `json:"tlsOptions,omitempty"` - TLS *tls.ConnectionState `json:"-"` + ServerPEM Certificate `json:"crt"` + CaPEM Certificate `json:"ca"` + CertChainPEM []Certificate `json:"certChain"` + TLSOptions *tlsutil.TLSOptions `json:"tlsOptions,omitempty"` + TLS *tls.ConnectionState `json:"-"` } // RootsResponse is the response object of the roots request. @@ -275,6 +276,14 @@ func (h *caHandler) Root(w http.ResponseWriter, r *http.Request) { JSON(w, &RootResponse{RootPEM: Certificate{cert}}) } +func certChainToPEM(certChain []*x509.Certificate) []Certificate { + certChainPEM := make([]Certificate, 0, len(certChain)) + for _, c := range certChain { + certChainPEM = append(certChainPEM, Certificate{c}) + } + return certChainPEM +} + // Sign is an HTTP handler that reads a certificate request and an // one-time-token (ott) from the body and creates a new certificate with the // information in the certificate request. @@ -302,17 +311,22 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { return } - cert, root, err := h.Authority.Sign(body.CsrPEM.CertificateRequest, opts, signOpts...) + certChain, err := h.Authority.Sign(body.CsrPEM.CertificateRequest, opts, signOpts...) if err != nil { WriteError(w, Forbidden(err)) return } - - logCertificate(w, cert) + certChainPEM := certChainToPEM(certChain) + var caPEM Certificate + if len(certChainPEM) > 0 { + caPEM = certChainPEM[1] + } + logCertificate(w, certChain[0]) JSONStatus(w, &SignResponse{ - ServerPEM: Certificate{cert}, - CaPEM: Certificate{root}, - TLSOptions: h.Authority.GetTLSOptions(), + ServerPEM: certChainPEM[0], + CaPEM: caPEM, + CertChainPEM: certChainPEM, + TLSOptions: h.Authority.GetTLSOptions(), }, http.StatusCreated) } @@ -324,17 +338,23 @@ func (h *caHandler) Renew(w http.ResponseWriter, r *http.Request) { return } - cert, root, err := h.Authority.Renew(r.TLS.PeerCertificates[0]) + certChain, err := h.Authority.Renew(r.TLS.PeerCertificates[0]) if err != nil { WriteError(w, Forbidden(err)) return } + certChainPEM := certChainToPEM(certChain) + var caPEM Certificate + if len(certChainPEM) > 0 { + caPEM = certChainPEM[1] + } - logCertificate(w, cert) + logCertificate(w, certChain[0]) JSONStatus(w, &SignResponse{ - ServerPEM: Certificate{cert}, - CaPEM: Certificate{root}, - TLSOptions: h.Authority.GetTLSOptions(), + ServerPEM: certChainPEM[0], + CaPEM: caPEM, + CertChainPEM: certChainPEM, + TLSOptions: h.Authority.GetTLSOptions(), }, http.StatusCreated) } diff --git a/api/api_test.go b/api/api_test.go index d141247c..a253f4cd 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -501,10 +501,10 @@ type mockAuthority struct { authorizeSign func(ott string) ([]provisioner.SignOption, error) getTLSOptions func() *tlsutil.TLSOptions root func(shasum string) (*x509.Certificate, error) - sign func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) + sign func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) signSSH func(key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) signSSHAddUser func(key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) - renew func(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error) + renew func(cert *x509.Certificate) ([]*x509.Certificate, error) loadProvisionerByCertificate func(cert *x509.Certificate) (provisioner.Interface, error) loadProvisionerByID func(provID string) (provisioner.Interface, error) getProvisioners func(nextCursor string, limit int) (provisioner.List, string, error) @@ -540,11 +540,11 @@ func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) { return m.ret1.(*x509.Certificate), m.err } -func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) { +func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { if m.sign != nil { return m.sign(cr, opts, signOpts...) } - return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err + return []*x509.Certificate{m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate)}, m.err } func (m *mockAuthority) SignSSH(key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { @@ -561,11 +561,11 @@ func (m *mockAuthority) SignSSHAddUser(key ssh.PublicKey, cert *ssh.Certificate) return m.ret1.(*ssh.Certificate), m.err } -func (m *mockAuthority) Renew(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error) { +func (m *mockAuthority) Renew(cert *x509.Certificate) ([]*x509.Certificate, error) { if m.renew != nil { return m.renew(cert) } - return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err + return []*x509.Certificate{m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate)}, m.err } func (m *mockAuthority) GetProvisioners(nextCursor string, limit int) (provisioner.List, string, error) { @@ -724,8 +724,8 @@ func Test_caHandler_Sign(t *testing.T) { t.Fatal(err) } - expected1 := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"}`) - expected2 := []byte(`{"crt":"` + strings.Replace(stepCertPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"}`) + expected1 := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) + expected2 := []byte(`{"crt":"` + strings.Replace(stepCertPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(stepCertPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) tests := []struct { name string @@ -798,7 +798,7 @@ func Test_caHandler_Renew(t *testing.T) { {"renew error", cs, nil, nil, fmt.Errorf("an error"), http.StatusForbidden}, } - expected := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"}`) + expected := []byte(`{"crt":"` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","ca":"` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n","certChain":["` + strings.Replace(certPEM, "\n", `\n`, -1) + `\n","` + strings.Replace(rootPEM, "\n", `\n`, -1) + `\n"]}`) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/tls.go b/authority/tls.go index 84227667..eb20639e 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -56,7 +56,7 @@ 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, *x509.Certificate, error) { +func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { var ( errContext = apiCtx{"csr": csr, "signOptions": signOpts} mods = []x509util.WithOption{withDefaultASN1DN(a.config.AuthorityConfig.Template)} @@ -69,66 +69,66 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Opti certValidators = append(certValidators, k) case provisioner.CertificateRequestValidator: if err := k.Valid(csr); err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign"), http.StatusUnauthorized, errContext} + return nil, &apiError{errors.Wrap(err, "sign"), http.StatusUnauthorized, errContext} } case provisioner.ProfileModifier: mods = append(mods, k.Option(signOpts)) default: - return nil, nil, &apiError{errors.Errorf("sign: invalid extra option type %T", k), + return nil, &apiError{errors.Errorf("sign: invalid extra option type %T", k), http.StatusInternalServerError, errContext} } } if err := csr.CheckSignature(); err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign: invalid certificate request"), + return nil, &apiError{errors.Wrap(err, "sign: invalid certificate request"), http.StatusBadRequest, errContext} } leaf, err := x509util.NewLeafProfileWithCSR(csr, issIdentity.Crt, issIdentity.Key, mods...) if err != nil { - return nil, nil, &apiError{errors.Wrapf(err, "sign"), http.StatusInternalServerError, errContext} + return nil, &apiError{errors.Wrapf(err, "sign"), http.StatusInternalServerError, errContext} } for _, v := range certValidators { if err := v.Valid(leaf.Subject()); err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign"), http.StatusUnauthorized, errContext} + return nil, &apiError{errors.Wrap(err, "sign"), http.StatusUnauthorized, errContext} } } crtBytes, err := leaf.CreateCertificate() if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign: error creating new leaf certificate"), + return nil, &apiError{errors.Wrap(err, "sign: error creating new leaf certificate"), http.StatusInternalServerError, errContext} } serverCert, err := x509.ParseCertificate(crtBytes) if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign: error parsing new leaf certificate"), + return nil, &apiError{errors.Wrap(err, "sign: error parsing new leaf certificate"), http.StatusInternalServerError, errContext} } caCert, err := x509.ParseCertificate(issIdentity.Crt.Raw) if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "sign: error parsing intermediate certificate"), + return nil, &apiError{errors.Wrap(err, "sign: error parsing intermediate certificate"), http.StatusInternalServerError, errContext} } if err = a.db.StoreCertificate(serverCert); err != nil { if err != db.ErrNotImplemented { - return nil, nil, &apiError{errors.Wrap(err, "sign: error storing certificate in db"), + return nil, &apiError{errors.Wrap(err, "sign: error storing certificate in db"), http.StatusInternalServerError, errContext} } } - return serverCert, caCert, nil + return []*x509.Certificate{serverCert, caCert}, nil } // 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, *x509.Certificate, error) { +func (a *Authority) Renew(oldCert *x509.Certificate) ([]*x509.Certificate, error) { // Check step provisioner extensions if err := a.authorizeRenewal(oldCert); err != nil { - return nil, nil, err + return nil, err } // Issuer @@ -181,26 +181,26 @@ func (a *Authority) Renew(oldCert *x509.Certificate) (*x509.Certificate, *x509.C leaf, err := x509util.NewLeafProfileWithTemplate(newCert, issIdentity.Crt, issIdentity.Key) if err != nil { - return nil, nil, &apiError{err, http.StatusInternalServerError, apiCtx{}} + return nil, &apiError{err, http.StatusInternalServerError, apiCtx{}} } crtBytes, err := leaf.CreateCertificate() if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "error renewing certificate from existing server certificate"), + return nil, &apiError{errors.Wrap(err, "error renewing certificate from existing server certificate"), http.StatusInternalServerError, apiCtx{}} } serverCert, err := x509.ParseCertificate(crtBytes) if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "error parsing new server certificate"), + return nil, &apiError{errors.Wrap(err, "error parsing new server certificate"), http.StatusInternalServerError, apiCtx{}} } caCert, err := x509.ParseCertificate(issIdentity.Crt.Raw) if err != nil { - return nil, nil, &apiError{errors.Wrap(err, "error parsing intermediate certificate"), + return nil, &apiError{errors.Wrap(err, "error parsing intermediate certificate"), http.StatusInternalServerError, apiCtx{}} } - return serverCert, caCert, nil + return []*x509.Certificate{serverCert, caCert}, nil } // RevokeOptions are the options for the Revoke API. diff --git a/authority/tls_test.go b/authority/tls_test.go index 8d443fd4..3ad796c0 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -276,7 +276,7 @@ ttnEF4Rq8zqzr4fbv+AF451Mx36AkfgZr9XWGzxidrH+fBCNWXWNR+ymhrL6UFTG t.Run(name, func(t *testing.T) { tc := genTestCase(t) - leaf, intermediate, err := tc.auth.Sign(tc.csr, tc.signOpts, tc.extraOpts...) + certChain, err := tc.auth.Sign(tc.csr, tc.signOpts, tc.extraOpts...) if err != nil { if assert.NotNil(t, tc.err) { switch v := err.(type) { @@ -289,6 +289,8 @@ ttnEF4Rq8zqzr4fbv+AF451Mx36AkfgZr9XWGzxidrH+fBCNWXWNR+ymhrL6UFTG } } } else { + leaf := certChain[0] + intermediate := certChain[1] if assert.Nil(t, tc.err) { assert.Equals(t, leaf.NotBefore, signOpts.NotBefore.Time().Truncate(time.Second)) assert.Equals(t, leaf.NotAfter, signOpts.NotAfter.Time().Truncate(time.Second)) @@ -453,11 +455,11 @@ func TestRenew(t *testing.T) { tc, err := genTestCase() assert.FatalError(t, err) - var leaf, intermediate *x509.Certificate + var certChain []*x509.Certificate if tc.auth != nil { - leaf, intermediate, err = tc.auth.Renew(tc.crt) + certChain, err = tc.auth.Renew(tc.crt) } else { - leaf, intermediate, err = a.Renew(tc.crt) + certChain, err = a.Renew(tc.crt) } if err != nil { if assert.NotNil(t, tc.err) { @@ -471,6 +473,8 @@ func TestRenew(t *testing.T) { } } } else { + leaf := certChain[0] + intermediate := certChain[1] if assert.Nil(t, tc.err) { assert.Equals(t, leaf.NotAfter.Sub(leaf.NotBefore), tc.crt.NotAfter.Sub(crt.NotBefore)) diff --git a/ca/bootstrap_test.go b/ca/bootstrap_test.go index baa23d7e..3449b45a 100644 --- a/ca/bootstrap_test.go +++ b/ca/bootstrap_test.go @@ -303,7 +303,7 @@ func TestBootstrapClient(t *testing.T) { t.Errorf("BootstrapClient() error reading response: %v", err) return } - if renewal.CaPEM.Certificate == nil || renewal.ServerPEM.Certificate == nil { + if renewal.CaPEM.Certificate == nil || renewal.ServerPEM.Certificate == nil || len(renewal.CertChainPEM) == 0 { t.Errorf("BootstrapClient() invalid renewal response: %v", renewal) } } @@ -375,7 +375,7 @@ func TestBootstrapClientServerRotation(t *testing.T) { if err := readJSON(resp.Body, &renew); err != nil { return errors.Wrap(err, "client.Post() error reading response") } - if renew.ServerPEM.Certificate == nil || renew.CaPEM.Certificate == nil { + if renew.ServerPEM.Certificate == nil || renew.CaPEM.Certificate == nil || len(renew.CertChainPEM) == 0 { return errors.New("client.Post() unexpected response found") } // test with bootstrap server @@ -492,7 +492,7 @@ func TestBootstrapClientServerFederation(t *testing.T) { if err := readJSON(resp.Body, &renew); err != nil { return errors.Wrap(err, "client.Post() error reading response") } - if renew.ServerPEM.Certificate == nil || renew.CaPEM.Certificate == nil { + if renew.ServerPEM.Certificate == nil || renew.CaPEM.Certificate == nil || len(renew.CertChainPEM) == 0 { return errors.New("client.Post() unexpected response found") } // test with bootstrap server diff --git a/ca/client_test.go b/ca/client_test.go index 1c90e52b..dd9f7228 100644 --- a/ca/client_test.go +++ b/ca/client_test.go @@ -253,6 +253,10 @@ func TestClient_Sign(t *testing.T) { ok := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: parseCertificate(certPEM)}, CaPEM: api.Certificate{Certificate: parseCertificate(rootPEM)}, + CertChainPEM: []api.Certificate{ + {Certificate: parseCertificate(certPEM)}, + {Certificate: parseCertificate(rootPEM)}, + }, } request := &api.SignRequest{ CsrPEM: api.CertificateRequest{CertificateRequest: parseCertificateRequest(csrPEM)}, @@ -406,6 +410,10 @@ func TestClient_Renew(t *testing.T) { ok := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: parseCertificate(certPEM)}, CaPEM: api.Certificate{Certificate: parseCertificate(rootPEM)}, + CertChainPEM: []api.Certificate{ + {Certificate: parseCertificate(certPEM)}, + {Certificate: parseCertificate(rootPEM)}, + }, } unauthorized := api.Unauthorized(fmt.Errorf("Unauthorized")) badRequest := api.BadRequest(fmt.Errorf("Bad Request")) diff --git a/ca/tls_test.go b/ca/tls_test.go index b88e825a..bf29e9a6 100644 --- a/ca/tls_test.go +++ b/ca/tls_test.go @@ -417,6 +417,10 @@ func TestCertificate(t *testing.T) { ok := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: cert}, CaPEM: api.Certificate{Certificate: parseCertificate(rootPEM)}, + CertChainPEM: []api.Certificate{ + {Certificate: cert}, + {Certificate: parseCertificate(rootPEM)}, + }, } tests := []struct { name string @@ -446,6 +450,10 @@ func TestIntermediateCertificate(t *testing.T) { ok := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: parseCertificate(certPEM)}, CaPEM: api.Certificate{Certificate: intermediate}, + CertChainPEM: []api.Certificate{ + {Certificate: parseCertificate(certPEM)}, + {Certificate: intermediate}, + }, } tests := []struct { name string @@ -475,6 +483,10 @@ func TestRootCertificateCertificate(t *testing.T) { ok := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: parseCertificate(certPEM)}, CaPEM: api.Certificate{Certificate: parseCertificate(rootPEM)}, + CertChainPEM: []api.Certificate{ + {Certificate: parseCertificate(certPEM)}, + {Certificate: parseCertificate(rootPEM)}, + }, TLS: &tls.ConnectionState{VerifiedChains: [][]*x509.Certificate{ {root, root}, }}, @@ -482,6 +494,10 @@ func TestRootCertificateCertificate(t *testing.T) { noTLS := &api.SignResponse{ ServerPEM: api.Certificate{Certificate: parseCertificate(certPEM)}, CaPEM: api.Certificate{Certificate: parseCertificate(rootPEM)}, + CertChainPEM: []api.Certificate{ + {Certificate: parseCertificate(certPEM)}, + {Certificate: parseCertificate(rootPEM)}, + }, } tests := []struct { name string