From e2ba4159c3af6f559a148c793276bb17081b56f9 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Tue, 22 Dec 2020 16:39:39 -0600 Subject: [PATCH 1/8] Begins to fix issue 87 --- api/sign.go | 18 ++++++++------- authority/provisioner/sign_options.go | 9 ++++---- authority/tls.go | 33 +++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/api/sign.go b/api/sign.go index 69e9a1a5..7687015d 100644 --- a/api/sign.go +++ b/api/sign.go @@ -12,11 +12,12 @@ import ( // SignRequest is the request body for a certificate signature request. type SignRequest struct { - CsrPEM CertificateRequest `json:"csr"` - OTT string `json:"ott"` - NotAfter TimeDuration `json:"notAfter,omitempty"` - NotBefore TimeDuration `json:"notBefore,omitempty"` - TemplateData json.RawMessage `json:"templateData,omitempty"` + CsrPEM CertificateRequest `json:"csr"` + OTT string `json:"ott"` + NotAfter TimeDuration `json:"notAfter,omitempty"` + NotBefore TimeDuration `json:"notBefore,omitempty"` + AppendedCertsFile string `json:"AppendedCertsFile,omitempty"` + TemplateData json.RawMessage `json:"templateData,omitempty"` } // Validate checks the fields of the SignRequest and returns nil if they are ok @@ -61,9 +62,10 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { } opts := provisioner.SignOptions{ - NotBefore: body.NotBefore, - NotAfter: body.NotAfter, - TemplateData: body.TemplateData, + NotBefore: body.NotBefore, + NotAfter: body.NotAfter, + TemplateData: body.TemplateData, + AppendedCertsFile: body.AppendedCertsFile, } signOpts, err := h.Authority.AuthorizeSign(body.OTT) diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index 9bfe8529..b32b3c6c 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -23,10 +23,11 @@ const DefaultCertValidity = 24 * time.Hour // SignOptions contains the options that can be passed to the Sign method. Backdate // is automatically filled and can only be configured in the CA. type SignOptions struct { - NotAfter TimeDuration `json:"notAfter"` - NotBefore TimeDuration `json:"notBefore"` - TemplateData json.RawMessage `json:"templateData"` - Backdate time.Duration `json:"-"` + NotAfter TimeDuration `json:"notAfter"` + NotBefore TimeDuration `json:"notBefore"` + AppendedCertsFile string `json:"AppendedCertsFile"` + TemplateData json.RawMessage `json:"templateData"` + Backdate time.Duration `json:"-"` } // SignOption is the interface used to collect all extra options used in the diff --git a/authority/tls.go b/authority/tls.go index f22f4624..43a593f7 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -8,6 +8,8 @@ import ( "encoding/asn1" "encoding/base64" "encoding/pem" + "io/ioutil" + "log" "net/http" "time" @@ -67,7 +69,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign certModifiers []provisioner.CertificateModifier certEnforcers []provisioner.CertificateEnforcer ) - + var thecertfile = signOpts.AppendedCertsFile 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...) @@ -161,8 +163,35 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign "authority.Sign; error storing certificate in db", opts...) } } + //If the user defined a file to append to in ca.json + //log.Fatal(string(thecertfile)) + if thecertfile != "" { + content, err := ioutil.ReadFile(string(thecertfile)) + if err != nil { + log.Fatal(err) + } + block, _ := pem.Decode([]byte(content)) + if block == nil { + log.Fatal(err) + } + certs, err := x509.ParseCertificate(block.Bytes) + if err != nil { + log.Fatal(err) + } + var thecert = make([]*x509.Certificate, len(resp.CertificateChain)+1) + for i, aid := range resp.CertificateChain { + //log.wr(aid) + thecert[i] = aid + } + thecert[len(resp.CertificateChain)] = certs + return append([]*x509.Certificate{resp.Certificate}, thecert...), nil + } + var thecert = make([]*x509.Certificate, len(resp.CertificateChain)) + for i, aid := range resp.CertificateChain { + thecert[i] = aid + } + return append([]*x509.Certificate{resp.Certificate}, thecert...), nil - return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil } // Renew creates a new Certificate identical to the old certificate, except From 7545b4a625037b4c218289dc4166ced5cd78b898 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Wed, 23 Dec 2020 22:41:10 -0600 Subject: [PATCH 2/8] leverage intermediate_ca.crt for appending certs. --- authority/authority.go | 2 +- authority/options.go | 6 +++--- authority/tls_test.go | 6 +++--- cas/apiv1/options.go | 4 ++-- cas/apiv1/options_test.go | 4 ++-- cas/cas_test.go | 20 +++++++++--------- cas/softcas/softcas.go | 42 ++++++++++++++++--------------------- cas/softcas/softcas_test.go | 28 ++++++++++++------------- 8 files changed, 53 insertions(+), 59 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 98037cc0..4518abdf 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -164,7 +164,7 @@ func (a *Authority) init() error { // Read intermediate and create X509 signer for default CAS. if options.Is(casapi.SoftCAS) { - options.Issuer, err = pemutil.ReadCertificate(a.config.IntermediateCert) + options.CertificateChain, err = pemutil.ReadCertificateBundle(a.config.IntermediateCert) if err != nil { return err } diff --git a/authority/options.go b/authority/options.go index da5a8f88..9594f989 100644 --- a/authority/options.go +++ b/authority/options.go @@ -95,9 +95,9 @@ func WithKeyManager(k kms.KeyManager) Option { func WithX509Signer(crt *x509.Certificate, s crypto.Signer) Option { return func(a *Authority) error { srv, err := cas.New(context.Background(), casapi.Options{ - Type: casapi.SoftCAS, - Issuer: crt, - Signer: s, + Type: casapi.SoftCAS, + Signer: s, + CertificateChain: []*x509.Certificate{crt}, }) if err != nil { return err diff --git a/authority/tls_test.go b/authority/tls_test.go index 75f9e234..bf629a0d 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -56,7 +56,7 @@ func (m *certificateDurationEnforcer) Enforce(cert *x509.Certificate) error { } func getDefaultIssuer(a *Authority) *x509.Certificate { - return a.x509CAService.(*softcas.SoftCAS).Issuer + return a.x509CAService.(*softcas.SoftCAS).CertificateChain[len(a.x509CAService.(*softcas.SoftCAS).CertificateChain)-1] } func getDefaultSigner(a *Authority) crypto.Signer { @@ -671,7 +671,7 @@ func TestAuthority_Renew(t *testing.T) { intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner) _a := testAuthority(t) - _a.x509CAService.(*softcas.SoftCAS).Issuer = intCert + _a.x509CAService.(*softcas.SoftCAS).CertificateChain = []*x509.Certificate{intCert} _a.x509CAService.(*softcas.SoftCAS).Signer = intSigner return &renewTest{ auth: _a, @@ -878,7 +878,7 @@ func TestAuthority_Rekey(t *testing.T) { intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner) _a := testAuthority(t) - _a.x509CAService.(*softcas.SoftCAS).Issuer = intCert + _a.x509CAService.(*softcas.SoftCAS).CertificateChain = []*x509.Certificate{intCert} _a.x509CAService.(*softcas.SoftCAS).Signer = intSigner return &renewTest{ auth: _a, diff --git a/cas/apiv1/options.go b/cas/apiv1/options.go index e8072437..d185d71a 100644 --- a/cas/apiv1/options.go +++ b/cas/apiv1/options.go @@ -23,8 +23,8 @@ type Options struct { // Issuer and signer are the issuer certificate and signer used in SoftCAS. // They are configured in ca.json crt and key properties. - Issuer *x509.Certificate `json:"-"` - Signer crypto.Signer `json:"-"` + CertificateChain []*x509.Certificate + Signer crypto.Signer `json:"-"` // IsCreator is set to true when we're creating a certificate authority. Is // used to skip some validations when initializing a CertificateAuthority. diff --git a/cas/apiv1/options_test.go b/cas/apiv1/options_test.go index 6d601366..2442b0af 100644 --- a/cas/apiv1/options_test.go +++ b/cas/apiv1/options_test.go @@ -70,7 +70,7 @@ func TestOptions_Validate(t *testing.T) { Type: tt.fields.Type, CredentialsFile: tt.fields.CredentialsFile, CertificateAuthority: tt.fields.CertificateAuthority, - Issuer: tt.fields.Issuer, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, Signer: tt.fields.Signer, } if err := o.Validate(); (err != nil) != tt.wantErr { @@ -120,7 +120,7 @@ func TestOptions_Is(t *testing.T) { Type: tt.fields.Type, CredentialsFile: tt.fields.CredentialsFile, CertificateAuthority: tt.fields.CertificateAuthority, - Issuer: tt.fields.Issuer, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, Signer: tt.fields.Signer, } if got := o.Is(tt.args.t); got != tt.want { diff --git a/cas/cas_test.go b/cas/cas_test.go index 6c4c5c41..7b7b5976 100644 --- a/cas/cas_test.go +++ b/cas/cas_test.go @@ -31,8 +31,8 @@ func (m *mockCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1 func TestNew(t *testing.T) { expected := &softcas.SoftCAS{ - Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}}, - Signer: ed25519.PrivateKey{}, + CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}}, + Signer: ed25519.PrivateKey{}, } apiv1.Register(apiv1.Type("nockCAS"), func(ctx context.Context, opts apiv1.Options) (apiv1.CertificateAuthorityService, error) { @@ -50,18 +50,18 @@ func TestNew(t *testing.T) { wantErr bool }{ {"ok default", args{context.Background(), apiv1.Options{ - Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}}, - Signer: ed25519.PrivateKey{}, + CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}}, + Signer: ed25519.PrivateKey{}, }}, expected, false}, {"ok softcas", args{context.Background(), apiv1.Options{ - Type: "softcas", - Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}}, - Signer: ed25519.PrivateKey{}, + Type: "softcas", + CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}}, + Signer: ed25519.PrivateKey{}, }}, expected, false}, {"ok SoftCAS", args{context.Background(), apiv1.Options{ - Type: "SoftCAS", - Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}}, - Signer: ed25519.PrivateKey{}, + Type: "SoftCAS", + CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}}, + Signer: ed25519.PrivateKey{}, }}, expected, false}, {"fail empty", args{context.Background(), apiv1.Options{}}, (*softcas.SoftCAS)(nil), true}, {"fail type", args{context.Background(), apiv1.Options{Type: "FailCAS"}}, nil, true}, diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 4ece82d9..82a4a0a6 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -26,9 +26,9 @@ var now = func() time.Time { // SoftCAS implements a Certificate Authority Service using Golang or KMS // crypto. This is the default CAS used in step-ca. type SoftCAS struct { - Issuer *x509.Certificate - Signer crypto.Signer - KeyManager kms.KeyManager + CertificateChain []*x509.Certificate + Signer crypto.Signer + KeyManager kms.KeyManager } // New creates a new CertificateAuthorityService implementation using Golang or KMS @@ -36,16 +36,16 @@ type SoftCAS struct { func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) { if !opts.IsCreator { switch { - case opts.Issuer == nil: - return nil, errors.New("softCAS 'issuer' cannot be nil") + case opts.CertificateChain == nil: + return nil, errors.New("softCAS 'CertificateChain' cannot be nil") case opts.Signer == nil: return nil, errors.New("softCAS 'signer' cannot be nil") } } return &SoftCAS{ - Issuer: opts.Issuer, - Signer: opts.Signer, - KeyManager: opts.KeyManager, + CertificateChain: opts.CertificateChain, + Signer: opts.Signer, + KeyManager: opts.KeyManager, }, nil } @@ -66,18 +66,16 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 if req.Template.NotAfter.IsZero() { req.Template.NotAfter = t.Add(req.Lifetime) } - req.Template.Issuer = c.Issuer.Subject + req.Template.Issuer = c.CertificateChain[0].Subject - cert, err := x509util.CreateCertificate(req.Template, c.Issuer, req.Template.PublicKey, c.Signer) + cert, err := x509util.CreateCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) if err != nil { return nil, err } return &apiv1.CreateCertificateResponse{ - Certificate: cert, - CertificateChain: []*x509.Certificate{ - c.Issuer, - }, + Certificate: cert, + CertificateChain: c.CertificateChain, }, nil } @@ -93,18 +91,16 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R t := now() req.Template.NotBefore = t.Add(-1 * req.Backdate) req.Template.NotAfter = t.Add(req.Lifetime) - req.Template.Issuer = c.Issuer.Subject + req.Template.Issuer = c.CertificateChain[0].Subject - cert, err := x509util.CreateCertificate(req.Template, c.Issuer, req.Template.PublicKey, c.Signer) + cert, err := x509util.CreateCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer) if err != nil { return nil, err } return &apiv1.RenewCertificateResponse{ - Certificate: cert, - CertificateChain: []*x509.Certificate{ - c.Issuer, - }, + Certificate: cert, + CertificateChain: c.CertificateChain, }, nil } @@ -113,10 +109,8 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R // in the db. func (c *SoftCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) { return &apiv1.RevokeCertificateResponse{ - Certificate: req.Certificate, - CertificateChain: []*x509.Certificate{ - c.Issuer, - }, + Certificate: req.Certificate, + CertificateChain: c.CertificateChain, }, nil } diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index 258ebf5c..0a50a990 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -182,9 +182,9 @@ func TestNew(t *testing.T) { want *SoftCAS wantErr bool }{ - {"ok", args{context.Background(), apiv1.Options{Issuer: testIssuer, Signer: testSigner}}, &SoftCAS{Issuer: testIssuer, Signer: testSigner}, false}, + {"ok", args{context.Background(), apiv1.Options{CertificateChain: []*x509.Certificate{testIssuer}, Signer: testSigner}}, &SoftCAS{CertificateChain: []*x509.Certificate{testIssuer}, Signer: testSigner}, false}, {"fail no issuer", args{context.Background(), apiv1.Options{Signer: testSigner}}, nil, true}, - {"fail no signer", args{context.Background(), apiv1.Options{Issuer: testIssuer}}, nil, true}, + {"fail no signer", args{context.Background(), apiv1.Options{CertificateChain: []*x509.Certificate{testIssuer}}}, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -208,11 +208,11 @@ func TestNew_register(t *testing.T) { } want := &SoftCAS{ - Issuer: testIssuer, - Signer: testSigner, + CertificateChain: []*x509.Certificate{testIssuer}, + Signer: testSigner, } - got, err := newFn(context.Background(), apiv1.Options{Issuer: testIssuer, Signer: testSigner}) + got, err := newFn(context.Background(), apiv1.Options{CertificateChain: []*x509.Certificate{testIssuer}, Signer: testSigner}) if err != nil { t.Errorf("New() error = %v", err) return @@ -286,8 +286,8 @@ func TestSoftCAS_CreateCertificate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &SoftCAS{ - Issuer: tt.fields.Issuer, - Signer: tt.fields.Signer, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, + Signer: tt.fields.Signer, } got, err := c.CreateCertificate(tt.args.req) if (err != nil) != tt.wantErr { @@ -342,8 +342,8 @@ func TestSoftCAS_RenewCertificate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &SoftCAS{ - Issuer: tt.fields.Issuer, - Signer: tt.fields.Signer, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, + Signer: tt.fields.Signer, } got, err := c.RenewCertificate(tt.args.req) if (err != nil) != tt.wantErr { @@ -395,8 +395,8 @@ func TestSoftCAS_RevokeCertificate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &SoftCAS{ - Issuer: tt.fields.Issuer, - Signer: tt.fields.Signer, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, + Signer: tt.fields.Signer, } got, err := c.RevokeCertificate(tt.args.req) if (err != nil) != tt.wantErr { @@ -524,9 +524,9 @@ func TestSoftCAS_CreateCertificateAuthority(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &SoftCAS{ - Issuer: tt.fields.Issuer, - Signer: tt.fields.Signer, - KeyManager: tt.fields.KeyManager, + CertificateChain: []*x509.Certificate{tt.fields.Issuer}, + Signer: tt.fields.Signer, + KeyManager: tt.fields.KeyManager, } got, err := c.CreateCertificateAuthority(tt.args.req) if (err != nil) != tt.wantErr { From bfd13f1f72799a727f9c0ba7fb6ccf149fd0c6d8 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Wed, 23 Dec 2020 22:43:47 -0600 Subject: [PATCH 3/8] Revert "Begins to fix issue 87" This reverts commit e2ba4159c3af6f559a148c793276bb17081b56f9. --- api/sign.go | 18 +++++++-------- authority/provisioner/sign_options.go | 9 ++++---- authority/tls.go | 33 ++------------------------- 3 files changed, 14 insertions(+), 46 deletions(-) diff --git a/api/sign.go b/api/sign.go index 7687015d..69e9a1a5 100644 --- a/api/sign.go +++ b/api/sign.go @@ -12,12 +12,11 @@ import ( // SignRequest is the request body for a certificate signature request. type SignRequest struct { - CsrPEM CertificateRequest `json:"csr"` - OTT string `json:"ott"` - NotAfter TimeDuration `json:"notAfter,omitempty"` - NotBefore TimeDuration `json:"notBefore,omitempty"` - AppendedCertsFile string `json:"AppendedCertsFile,omitempty"` - TemplateData json.RawMessage `json:"templateData,omitempty"` + CsrPEM CertificateRequest `json:"csr"` + OTT string `json:"ott"` + NotAfter TimeDuration `json:"notAfter,omitempty"` + NotBefore TimeDuration `json:"notBefore,omitempty"` + TemplateData json.RawMessage `json:"templateData,omitempty"` } // Validate checks the fields of the SignRequest and returns nil if they are ok @@ -62,10 +61,9 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { } opts := provisioner.SignOptions{ - NotBefore: body.NotBefore, - NotAfter: body.NotAfter, - TemplateData: body.TemplateData, - AppendedCertsFile: body.AppendedCertsFile, + NotBefore: body.NotBefore, + NotAfter: body.NotAfter, + TemplateData: body.TemplateData, } signOpts, err := h.Authority.AuthorizeSign(body.OTT) diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index b32b3c6c..9bfe8529 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -23,11 +23,10 @@ const DefaultCertValidity = 24 * time.Hour // SignOptions contains the options that can be passed to the Sign method. Backdate // is automatically filled and can only be configured in the CA. type SignOptions struct { - NotAfter TimeDuration `json:"notAfter"` - NotBefore TimeDuration `json:"notBefore"` - AppendedCertsFile string `json:"AppendedCertsFile"` - TemplateData json.RawMessage `json:"templateData"` - Backdate time.Duration `json:"-"` + NotAfter TimeDuration `json:"notAfter"` + NotBefore TimeDuration `json:"notBefore"` + TemplateData json.RawMessage `json:"templateData"` + Backdate time.Duration `json:"-"` } // SignOption is the interface used to collect all extra options used in the diff --git a/authority/tls.go b/authority/tls.go index 43a593f7..f22f4624 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -8,8 +8,6 @@ import ( "encoding/asn1" "encoding/base64" "encoding/pem" - "io/ioutil" - "log" "net/http" "time" @@ -69,7 +67,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign certModifiers []provisioner.CertificateModifier certEnforcers []provisioner.CertificateEnforcer ) - var thecertfile = signOpts.AppendedCertsFile + 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...) @@ -163,35 +161,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign "authority.Sign; error storing certificate in db", opts...) } } - //If the user defined a file to append to in ca.json - //log.Fatal(string(thecertfile)) - if thecertfile != "" { - content, err := ioutil.ReadFile(string(thecertfile)) - if err != nil { - log.Fatal(err) - } - block, _ := pem.Decode([]byte(content)) - if block == nil { - log.Fatal(err) - } - certs, err := x509.ParseCertificate(block.Bytes) - if err != nil { - log.Fatal(err) - } - var thecert = make([]*x509.Certificate, len(resp.CertificateChain)+1) - for i, aid := range resp.CertificateChain { - //log.wr(aid) - thecert[i] = aid - } - thecert[len(resp.CertificateChain)] = certs - return append([]*x509.Certificate{resp.Certificate}, thecert...), nil - } - var thecert = make([]*x509.Certificate, len(resp.CertificateChain)) - for i, aid := range resp.CertificateChain { - thecert[i] = aid - } - return append([]*x509.Certificate{resp.Certificate}, thecert...), nil + return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil } // Renew creates a new Certificate identical to the old certificate, except From 21dc40638239447c7ad1815f8983c12567856bf6 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Tue, 22 Dec 2020 16:39:39 -0600 Subject: [PATCH 4/8] Begins to fix issue 87 --- api/sign.go | 18 ++++++++------- authority/provisioner/sign_options.go | 9 ++++---- authority/tls.go | 33 +++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/api/sign.go b/api/sign.go index 69e9a1a5..7687015d 100644 --- a/api/sign.go +++ b/api/sign.go @@ -12,11 +12,12 @@ import ( // SignRequest is the request body for a certificate signature request. type SignRequest struct { - CsrPEM CertificateRequest `json:"csr"` - OTT string `json:"ott"` - NotAfter TimeDuration `json:"notAfter,omitempty"` - NotBefore TimeDuration `json:"notBefore,omitempty"` - TemplateData json.RawMessage `json:"templateData,omitempty"` + CsrPEM CertificateRequest `json:"csr"` + OTT string `json:"ott"` + NotAfter TimeDuration `json:"notAfter,omitempty"` + NotBefore TimeDuration `json:"notBefore,omitempty"` + AppendedCertsFile string `json:"AppendedCertsFile,omitempty"` + TemplateData json.RawMessage `json:"templateData,omitempty"` } // Validate checks the fields of the SignRequest and returns nil if they are ok @@ -61,9 +62,10 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { } opts := provisioner.SignOptions{ - NotBefore: body.NotBefore, - NotAfter: body.NotAfter, - TemplateData: body.TemplateData, + NotBefore: body.NotBefore, + NotAfter: body.NotAfter, + TemplateData: body.TemplateData, + AppendedCertsFile: body.AppendedCertsFile, } signOpts, err := h.Authority.AuthorizeSign(body.OTT) diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index 9bfe8529..b32b3c6c 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -23,10 +23,11 @@ const DefaultCertValidity = 24 * time.Hour // SignOptions contains the options that can be passed to the Sign method. Backdate // is automatically filled and can only be configured in the CA. type SignOptions struct { - NotAfter TimeDuration `json:"notAfter"` - NotBefore TimeDuration `json:"notBefore"` - TemplateData json.RawMessage `json:"templateData"` - Backdate time.Duration `json:"-"` + NotAfter TimeDuration `json:"notAfter"` + NotBefore TimeDuration `json:"notBefore"` + AppendedCertsFile string `json:"AppendedCertsFile"` + TemplateData json.RawMessage `json:"templateData"` + Backdate time.Duration `json:"-"` } // SignOption is the interface used to collect all extra options used in the diff --git a/authority/tls.go b/authority/tls.go index f22f4624..43a593f7 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -8,6 +8,8 @@ import ( "encoding/asn1" "encoding/base64" "encoding/pem" + "io/ioutil" + "log" "net/http" "time" @@ -67,7 +69,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign certModifiers []provisioner.CertificateModifier certEnforcers []provisioner.CertificateEnforcer ) - + var thecertfile = signOpts.AppendedCertsFile 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...) @@ -161,8 +163,35 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign "authority.Sign; error storing certificate in db", opts...) } } + //If the user defined a file to append to in ca.json + //log.Fatal(string(thecertfile)) + if thecertfile != "" { + content, err := ioutil.ReadFile(string(thecertfile)) + if err != nil { + log.Fatal(err) + } + block, _ := pem.Decode([]byte(content)) + if block == nil { + log.Fatal(err) + } + certs, err := x509.ParseCertificate(block.Bytes) + if err != nil { + log.Fatal(err) + } + var thecert = make([]*x509.Certificate, len(resp.CertificateChain)+1) + for i, aid := range resp.CertificateChain { + //log.wr(aid) + thecert[i] = aid + } + thecert[len(resp.CertificateChain)] = certs + return append([]*x509.Certificate{resp.Certificate}, thecert...), nil + } + var thecert = make([]*x509.Certificate, len(resp.CertificateChain)) + for i, aid := range resp.CertificateChain { + thecert[i] = aid + } + return append([]*x509.Certificate{resp.Certificate}, thecert...), nil - return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil } // Renew creates a new Certificate identical to the old certificate, except From cf063d1f4a763120c4def4d78bf586419ee067c8 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Wed, 23 Dec 2020 22:43:47 -0600 Subject: [PATCH 5/8] Revert "Begins to fix issue 87" This reverts commit e2ba4159c3af6f559a148c793276bb17081b56f9. --- api/sign.go | 18 +++++++-------- authority/provisioner/sign_options.go | 9 ++++---- authority/tls.go | 33 ++------------------------- 3 files changed, 14 insertions(+), 46 deletions(-) diff --git a/api/sign.go b/api/sign.go index 7687015d..69e9a1a5 100644 --- a/api/sign.go +++ b/api/sign.go @@ -12,12 +12,11 @@ import ( // SignRequest is the request body for a certificate signature request. type SignRequest struct { - CsrPEM CertificateRequest `json:"csr"` - OTT string `json:"ott"` - NotAfter TimeDuration `json:"notAfter,omitempty"` - NotBefore TimeDuration `json:"notBefore,omitempty"` - AppendedCertsFile string `json:"AppendedCertsFile,omitempty"` - TemplateData json.RawMessage `json:"templateData,omitempty"` + CsrPEM CertificateRequest `json:"csr"` + OTT string `json:"ott"` + NotAfter TimeDuration `json:"notAfter,omitempty"` + NotBefore TimeDuration `json:"notBefore,omitempty"` + TemplateData json.RawMessage `json:"templateData,omitempty"` } // Validate checks the fields of the SignRequest and returns nil if they are ok @@ -62,10 +61,9 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { } opts := provisioner.SignOptions{ - NotBefore: body.NotBefore, - NotAfter: body.NotAfter, - TemplateData: body.TemplateData, - AppendedCertsFile: body.AppendedCertsFile, + NotBefore: body.NotBefore, + NotAfter: body.NotAfter, + TemplateData: body.TemplateData, } signOpts, err := h.Authority.AuthorizeSign(body.OTT) diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index b32b3c6c..9bfe8529 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -23,11 +23,10 @@ const DefaultCertValidity = 24 * time.Hour // SignOptions contains the options that can be passed to the Sign method. Backdate // is automatically filled and can only be configured in the CA. type SignOptions struct { - NotAfter TimeDuration `json:"notAfter"` - NotBefore TimeDuration `json:"notBefore"` - AppendedCertsFile string `json:"AppendedCertsFile"` - TemplateData json.RawMessage `json:"templateData"` - Backdate time.Duration `json:"-"` + NotAfter TimeDuration `json:"notAfter"` + NotBefore TimeDuration `json:"notBefore"` + TemplateData json.RawMessage `json:"templateData"` + Backdate time.Duration `json:"-"` } // SignOption is the interface used to collect all extra options used in the diff --git a/authority/tls.go b/authority/tls.go index 43a593f7..f22f4624 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -8,8 +8,6 @@ import ( "encoding/asn1" "encoding/base64" "encoding/pem" - "io/ioutil" - "log" "net/http" "time" @@ -69,7 +67,7 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign certModifiers []provisioner.CertificateModifier certEnforcers []provisioner.CertificateEnforcer ) - var thecertfile = signOpts.AppendedCertsFile + 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...) @@ -163,35 +161,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign "authority.Sign; error storing certificate in db", opts...) } } - //If the user defined a file to append to in ca.json - //log.Fatal(string(thecertfile)) - if thecertfile != "" { - content, err := ioutil.ReadFile(string(thecertfile)) - if err != nil { - log.Fatal(err) - } - block, _ := pem.Decode([]byte(content)) - if block == nil { - log.Fatal(err) - } - certs, err := x509.ParseCertificate(block.Bytes) - if err != nil { - log.Fatal(err) - } - var thecert = make([]*x509.Certificate, len(resp.CertificateChain)+1) - for i, aid := range resp.CertificateChain { - //log.wr(aid) - thecert[i] = aid - } - thecert[len(resp.CertificateChain)] = certs - return append([]*x509.Certificate{resp.Certificate}, thecert...), nil - } - var thecert = make([]*x509.Certificate, len(resp.CertificateChain)) - for i, aid := range resp.CertificateChain { - thecert[i] = aid - } - return append([]*x509.Certificate{resp.Certificate}, thecert...), nil + return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil } // Renew creates a new Certificate identical to the old certificate, except From f3396bf964a5e389a345b51057856236f3dcf4b7 Mon Sep 17 00:00:00 2001 From: Miclain K Keffeler Date: Mon, 28 Dec 2020 17:10:44 -0600 Subject: [PATCH 6/8] Update softcas.go --- cas/softcas/softcas.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 82a4a0a6..838dca9b 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -35,8 +35,8 @@ type SoftCAS struct { // crypto. func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) { if !opts.IsCreator { - switch { - case opts.CertificateChain == nil: + switch { + case len(opts.CertificateChain) == 0: return nil, errors.New("softCAS 'CertificateChain' cannot be nil") case opts.Signer == nil: return nil, errors.New("softCAS 'signer' cannot be nil") From 7a1eb43bb175332f5d11327ca121348929166286 Mon Sep 17 00:00:00 2001 From: Miclain K Keffeler Date: Mon, 28 Dec 2020 17:12:37 -0600 Subject: [PATCH 7/8] Update options.go --- cas/apiv1/options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cas/apiv1/options.go b/cas/apiv1/options.go index d185d71a..46efae3b 100644 --- a/cas/apiv1/options.go +++ b/cas/apiv1/options.go @@ -21,7 +21,7 @@ type Options struct { // `projects/*/locations/*/certificateAuthorities/*`. CertificateAuthority string `json:"certificateAuthority"` - // Issuer and signer are the issuer certificate and signer used in SoftCAS. + // Certificate and signer are the issuer certificate,along with any other bundled certificates to be returned in the chain for consumers, and signer used in SoftCAS. // They are configured in ca.json crt and key properties. CertificateChain []*x509.Certificate Signer crypto.Signer `json:"-"` From ffbfcfb1f2d4b95d866da46820a15f912b74aff1 Mon Sep 17 00:00:00 2001 From: Miclain Keffeler Date: Mon, 28 Dec 2020 18:46:21 -0600 Subject: [PATCH 8/8] format. --- cas/softcas/softcas.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 838dca9b..21760490 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -35,7 +35,7 @@ type SoftCAS struct { // crypto. func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) { if !opts.IsCreator { - switch { + switch { case len(opts.CertificateChain) == 0: return nil, errors.New("softCAS 'CertificateChain' cannot be nil") case opts.Signer == nil: