Merge pull request #440 from mkkeffeler/smallstep-by-provisioner-appendedcert

Begins to fix issue 87
This commit is contained in:
Mariano Cano 2020-12-28 17:49:00 -08:00 committed by GitHub
commit 00c6f08612
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 54 additions and 60 deletions

View file

@ -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
}

View file

@ -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

View file

@ -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,

View file

@ -21,10 +21,10 @@ 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.
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.

View file

@ -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 {

View file

@ -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},

View file

@ -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 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")
}
}
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
}

View file

@ -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 {