mirror of
https://github.com/smallstep/certificates.git
synced 2024-10-31 03:20:16 +00:00
Add authority.WithX509SignerFunc
This change adds a new authority option that allows to pass a callback that returns the certificate chain and signer used to sign X.509 certificates. This option will be used by Caddy, they renew the intermediate certificate weekly and there's no other way to replace it without re-creating the embedded CA. Fixes #874
This commit is contained in:
parent
49de04661b
commit
955d4cf80d
@ -163,6 +163,22 @@ func WithX509Signer(crt *x509.Certificate, s crypto.Signer) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithX509SignerFunc defines the function used to get the chain of certificates
|
||||
// and signer used when we sign X.509 certificates.
|
||||
func WithX509SignerFunc(fn func() ([]*x509.Certificate, crypto.Signer, error)) Option {
|
||||
return func(a *Authority) error {
|
||||
srv, err := cas.New(context.Background(), casapi.Options{
|
||||
Type: casapi.SoftCAS,
|
||||
CertificateSigner: fn,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.x509CAService = srv
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSSHUserSigner defines the signer used to sign SSH user certificates.
|
||||
func WithSSHUserSigner(s crypto.Signer) Option {
|
||||
return func(a *Authority) error {
|
||||
|
@ -31,13 +31,18 @@ type Options struct {
|
||||
// https://cloud.google.com/docs/authentication.
|
||||
CredentialsFile string `json:"credentialsFile,omitempty"`
|
||||
|
||||
// Certificate and signer are the issuer certificate, along with any other
|
||||
// bundled certificates to be returned in the chain for consumers, and
|
||||
// CertificateChain 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 `json:"-"`
|
||||
Signer crypto.Signer `json:"-"`
|
||||
|
||||
// CertificateSigner combines CertificateChain and Signer in a callback that
|
||||
// returns the chain of certificate and signer used to sign X.509
|
||||
// certificates in SoftCAS.
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error) `json:"-"`
|
||||
|
||||
// IsCreator is set to true when we're creating a certificate authority. It
|
||||
// is used to skip some validations when initializing a
|
||||
// CertificateAuthority. This option is used on SoftCAS and CloudCAS.
|
||||
|
@ -24,9 +24,10 @@ var now = time.Now
|
||||
// SoftCAS implements a Certificate Authority Service using Golang or KMS
|
||||
// crypto. This is the default CAS used in step-ca.
|
||||
type SoftCAS struct {
|
||||
CertificateChain []*x509.Certificate
|
||||
Signer crypto.Signer
|
||||
KeyManager kms.KeyManager
|
||||
CertificateChain []*x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
KeyManager kms.KeyManager
|
||||
}
|
||||
|
||||
// New creates a new CertificateAuthorityService implementation using Golang or KMS
|
||||
@ -34,16 +35,17 @@ type SoftCAS struct {
|
||||
func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) {
|
||||
if !opts.IsCreator {
|
||||
switch {
|
||||
case len(opts.CertificateChain) == 0:
|
||||
case len(opts.CertificateChain) == 0 && opts.CertificateSigner == nil:
|
||||
return nil, errors.New("softCAS 'CertificateChain' cannot be nil")
|
||||
case opts.Signer == nil:
|
||||
case opts.Signer == nil && opts.CertificateSigner == nil:
|
||||
return nil, errors.New("softCAS 'signer' cannot be nil")
|
||||
}
|
||||
}
|
||||
return &SoftCAS{
|
||||
CertificateChain: opts.CertificateChain,
|
||||
Signer: opts.Signer,
|
||||
KeyManager: opts.KeyManager,
|
||||
CertificateChain: opts.CertificateChain,
|
||||
Signer: opts.Signer,
|
||||
CertificateSigner: opts.CertificateSigner,
|
||||
KeyManager: opts.KeyManager,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -57,6 +59,7 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
|
||||
}
|
||||
|
||||
t := now()
|
||||
|
||||
// Provisioners can also set specific values.
|
||||
if req.Template.NotBefore.IsZero() {
|
||||
req.Template.NotBefore = t.Add(-1 * req.Backdate)
|
||||
@ -64,16 +67,21 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
|
||||
if req.Template.NotAfter.IsZero() {
|
||||
req.Template.NotAfter = t.Add(req.Lifetime)
|
||||
}
|
||||
req.Template.Issuer = c.CertificateChain[0].Subject
|
||||
|
||||
cert, err := createCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer)
|
||||
chain, signer, err := c.getCertSigner()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Template.Issuer = chain[0].Subject
|
||||
|
||||
cert, err := createCertificate(req.Template, chain[0], req.Template.PublicKey, signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &apiv1.CreateCertificateResponse{
|
||||
Certificate: cert,
|
||||
CertificateChain: c.CertificateChain,
|
||||
CertificateChain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -89,16 +97,21 @@ 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.CertificateChain[0].Subject
|
||||
|
||||
cert, err := createCertificate(req.Template, c.CertificateChain[0], req.Template.PublicKey, c.Signer)
|
||||
chain, signer, err := c.getCertSigner()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Template.Issuer = chain[0].Subject
|
||||
|
||||
cert, err := createCertificate(req.Template, chain[0], req.Template.PublicKey, signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &apiv1.RenewCertificateResponse{
|
||||
Certificate: cert,
|
||||
CertificateChain: c.CertificateChain,
|
||||
CertificateChain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -106,9 +119,13 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R
|
||||
// operation is a no-op as the actual revoke will happen when we store the entry
|
||||
// in the db.
|
||||
func (c *SoftCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) {
|
||||
chain, _, err := c.getCertSigner()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &apiv1.RevokeCertificateResponse{
|
||||
Certificate: req.Certificate,
|
||||
CertificateChain: c.CertificateChain,
|
||||
CertificateChain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -179,7 +196,7 @@ func (c *SoftCAS) CreateCertificateAuthority(req *apiv1.CreateCertificateAuthori
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeKeyManager initiazes the default key manager if was not given.
|
||||
// initializeKeyManager initializes the default key manager if was not given.
|
||||
func (c *SoftCAS) initializeKeyManager() (err error) {
|
||||
if c.KeyManager == nil {
|
||||
c.KeyManager, err = kms.New(context.Background(), kmsapi.Options{
|
||||
@ -189,6 +206,15 @@ func (c *SoftCAS) initializeKeyManager() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// getCertSigner returns the certificate chain and signer to use.
|
||||
func (c *SoftCAS) getCertSigner() ([]*x509.Certificate, crypto.Signer, error) {
|
||||
if c.CertificateSigner != nil {
|
||||
return c.CertificateSigner()
|
||||
}
|
||||
return c.CertificateChain, c.Signer, nil
|
||||
|
||||
}
|
||||
|
||||
// createKey uses the configured kms to create a key.
|
||||
func (c *SoftCAS) createKey(req *kmsapi.CreateKeyRequest) (*kmsapi.CreateKeyResponse, error) {
|
||||
if err := c.initializeKeyManager(); err != nil {
|
||||
|
@ -73,6 +73,12 @@ var (
|
||||
testSignedTemplate = mustSign(testTemplate, testIssuer, testNow, testNow.Add(24*time.Hour))
|
||||
testSignedRootTemplate = mustSign(testRootTemplate, testRootTemplate, testNow, testNow.Add(24*time.Hour))
|
||||
testSignedIntermediateTemplate = mustSign(testIntermediateTemplate, testSignedRootTemplate, testNow, testNow.Add(24*time.Hour))
|
||||
testCertificateSigner = func() ([]*x509.Certificate, crypto.Signer, error) {
|
||||
return []*x509.Certificate{testIssuer}, testSigner, nil
|
||||
}
|
||||
testFailCertificateSigner = func() ([]*x509.Certificate, crypto.Signer, error) {
|
||||
return nil, nil, errTest
|
||||
}
|
||||
)
|
||||
|
||||
type signatureAlgorithmSigner struct {
|
||||
@ -186,6 +192,10 @@ func setTeeReader(t *testing.T, w *bytes.Buffer) {
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
assertEqual := func(x, y interface{}) bool {
|
||||
return reflect.DeepEqual(x, y) || fmt.Sprintf("%#v", x) == fmt.Sprintf("%#v", y)
|
||||
}
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
opts apiv1.Options
|
||||
@ -197,6 +207,7 @@ func TestNew(t *testing.T) {
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", args{context.Background(), apiv1.Options{CertificateChain: []*x509.Certificate{testIssuer}, Signer: testSigner}}, &SoftCAS{CertificateChain: []*x509.Certificate{testIssuer}, Signer: testSigner}, false},
|
||||
{"ok with callback", args{context.Background(), apiv1.Options{CertificateSigner: testCertificateSigner}}, &SoftCAS{CertificateSigner: testCertificateSigner}, false},
|
||||
{"fail no issuer", args{context.Background(), apiv1.Options{Signer: testSigner}}, nil, true},
|
||||
{"fail no signer", args{context.Background(), apiv1.Options{CertificateChain: []*x509.Certificate{testIssuer}}}, nil, true},
|
||||
}
|
||||
@ -207,7 +218,7 @@ func TestNew(t *testing.T) {
|
||||
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
if !assertEqual(got, tt.want) {
|
||||
t.Errorf("New() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
@ -265,8 +276,9 @@ func TestSoftCAS_CreateCertificate(t *testing.T) {
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
}
|
||||
type args struct {
|
||||
req *apiv1.CreateCertificateRequest
|
||||
@ -278,43 +290,53 @@ func TestSoftCAS_CreateCertificate(t *testing.T) {
|
||||
want *apiv1.CreateCertificateResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
{"ok", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.CreateCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok signature algorithm", fields{testIssuer, saSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
{"ok signature algorithm", fields{testIssuer, saSigner, nil}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: &saTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.CreateCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok with notBefore", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
{"ok with notBefore", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: &tmplNotBefore, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.CreateCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok with notBefore+notAfter", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
{"ok with notBefore+notAfter", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: &tmplWithLifetime, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.CreateCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"fail template", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{Lifetime: 24 * time.Hour}}, nil, true},
|
||||
{"fail lifetime", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{Template: testTemplate}}, nil, true},
|
||||
{"fail CreateCertificate", fields{testIssuer, testSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
{"ok with callback", fields{nil, nil, testCertificateSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.CreateCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"fail template", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{Lifetime: 24 * time.Hour}}, nil, true},
|
||||
{"fail lifetime", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{Template: testTemplate}}, nil, true},
|
||||
{"fail CreateCertificate", fields{testIssuer, testSigner, nil}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: &tmplNoSerial,
|
||||
Lifetime: 24 * time.Hour,
|
||||
}}, nil, true},
|
||||
{"fail with callback", fields{nil, nil, testFailCertificateSigner}, args{&apiv1.CreateCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, nil, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &SoftCAS{
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateSigner: tt.fields.CertificateSigner,
|
||||
}
|
||||
got, err := c.CreateCertificate(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
@ -345,8 +367,9 @@ func TestSoftCAS_RenewCertificate(t *testing.T) {
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
}
|
||||
type args struct {
|
||||
req *apiv1.RenewCertificateRequest
|
||||
@ -358,30 +381,40 @@ func TestSoftCAS_RenewCertificate(t *testing.T) {
|
||||
want *apiv1.RenewCertificateResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{
|
||||
{"ok", fields{testIssuer, testSigner, nil}, args{&apiv1.RenewCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.RenewCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok signature algorithm", fields{testIssuer, saSigner}, args{&apiv1.RenewCertificateRequest{
|
||||
{"ok signature algorithm", fields{testIssuer, saSigner, nil}, args{&apiv1.RenewCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.RenewCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"fail template", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{Lifetime: 24 * time.Hour}}, nil, true},
|
||||
{"fail lifetime", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{Template: testTemplate}}, nil, true},
|
||||
{"fail CreateCertificate", fields{testIssuer, testSigner}, args{&apiv1.RenewCertificateRequest{
|
||||
{"ok with callback", fields{nil, nil, testCertificateSigner}, args{&apiv1.RenewCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, &apiv1.RenewCertificateResponse{
|
||||
Certificate: testSignedTemplate,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"fail template", fields{testIssuer, testSigner, nil}, args{&apiv1.RenewCertificateRequest{Lifetime: 24 * time.Hour}}, nil, true},
|
||||
{"fail lifetime", fields{testIssuer, testSigner, nil}, args{&apiv1.RenewCertificateRequest{Template: testTemplate}}, nil, true},
|
||||
{"fail CreateCertificate", fields{testIssuer, testSigner, nil}, args{&apiv1.RenewCertificateRequest{
|
||||
Template: &tmplNoSerial,
|
||||
Lifetime: 24 * time.Hour,
|
||||
}}, nil, true},
|
||||
{"fail with callback", fields{nil, nil, testFailCertificateSigner}, args{&apiv1.RenewCertificateRequest{
|
||||
Template: testTemplate, Lifetime: 24 * time.Hour,
|
||||
}}, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &SoftCAS{
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateSigner: tt.fields.CertificateSigner,
|
||||
}
|
||||
got, err := c.RenewCertificate(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
@ -397,8 +430,9 @@ func TestSoftCAS_RenewCertificate(t *testing.T) {
|
||||
|
||||
func TestSoftCAS_RevokeCertificate(t *testing.T) {
|
||||
type fields struct {
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
}
|
||||
type args struct {
|
||||
req *apiv1.RevokeCertificateRequest
|
||||
@ -410,7 +444,7 @@ func TestSoftCAS_RevokeCertificate(t *testing.T) {
|
||||
want *apiv1.RevokeCertificateResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{testIssuer, testSigner}, args{&apiv1.RevokeCertificateRequest{
|
||||
{"ok", fields{testIssuer, testSigner, nil}, args{&apiv1.RevokeCertificateRequest{
|
||||
Certificate: &x509.Certificate{Subject: pkix.Name{CommonName: "fake"}},
|
||||
Reason: "test reason",
|
||||
ReasonCode: 1,
|
||||
@ -418,23 +452,37 @@ func TestSoftCAS_RevokeCertificate(t *testing.T) {
|
||||
Certificate: &x509.Certificate{Subject: pkix.Name{CommonName: "fake"}},
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok no cert", fields{testIssuer, testSigner}, args{&apiv1.RevokeCertificateRequest{
|
||||
{"ok no cert", fields{testIssuer, testSigner, nil}, args{&apiv1.RevokeCertificateRequest{
|
||||
Reason: "test reason",
|
||||
ReasonCode: 1,
|
||||
}}, &apiv1.RevokeCertificateResponse{
|
||||
Certificate: nil,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok empty", fields{testIssuer, testSigner}, args{&apiv1.RevokeCertificateRequest{}}, &apiv1.RevokeCertificateResponse{
|
||||
{"ok empty", fields{testIssuer, testSigner, nil}, args{&apiv1.RevokeCertificateRequest{}}, &apiv1.RevokeCertificateResponse{
|
||||
Certificate: nil,
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"ok with callback", fields{nil, nil, testCertificateSigner}, args{&apiv1.RevokeCertificateRequest{
|
||||
Certificate: &x509.Certificate{Subject: pkix.Name{CommonName: "fake"}},
|
||||
Reason: "test reason",
|
||||
ReasonCode: 1,
|
||||
}}, &apiv1.RevokeCertificateResponse{
|
||||
Certificate: &x509.Certificate{Subject: pkix.Name{CommonName: "fake"}},
|
||||
CertificateChain: []*x509.Certificate{testIssuer},
|
||||
}, false},
|
||||
{"fail with callback", fields{nil, nil, testFailCertificateSigner}, args{&apiv1.RevokeCertificateRequest{
|
||||
Certificate: &x509.Certificate{Subject: pkix.Name{CommonName: "fake"}},
|
||||
Reason: "test reason",
|
||||
ReasonCode: 1,
|
||||
}}, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &SoftCAS{
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||
Signer: tt.fields.Signer,
|
||||
CertificateSigner: tt.fields.CertificateSigner,
|
||||
}
|
||||
got, err := c.RevokeCertificate(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
@ -609,3 +657,56 @@ func TestSoftCAS_CreateCertificateAuthority(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSoftCAS_defaultKeyManager(t *testing.T) {
|
||||
mockNow(t)
|
||||
type args struct {
|
||||
req *apiv1.CreateCertificateAuthorityRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok root", args{&apiv1.CreateCertificateAuthorityRequest{
|
||||
Type: apiv1.RootCA,
|
||||
Template: &x509.Certificate{
|
||||
Subject: pkix.Name{CommonName: "Test Root CA"},
|
||||
KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
MaxPathLen: 1,
|
||||
SerialNumber: big.NewInt(1234),
|
||||
},
|
||||
Lifetime: 24 * time.Hour,
|
||||
}}, false},
|
||||
{"ok intermediate", args{&apiv1.CreateCertificateAuthorityRequest{
|
||||
Type: apiv1.IntermediateCA,
|
||||
Template: testIntermediateTemplate,
|
||||
Lifetime: 24 * time.Hour,
|
||||
Parent: &apiv1.CreateCertificateAuthorityResponse{
|
||||
Certificate: testSignedRootTemplate,
|
||||
Signer: testSigner,
|
||||
},
|
||||
}}, false},
|
||||
{"fail with default key manager", args{&apiv1.CreateCertificateAuthorityRequest{
|
||||
Type: apiv1.IntermediateCA,
|
||||
Template: testIntermediateTemplate,
|
||||
Lifetime: 24 * time.Hour,
|
||||
Parent: &apiv1.CreateCertificateAuthorityResponse{
|
||||
Certificate: testSignedRootTemplate,
|
||||
Signer: &badSigner{},
|
||||
},
|
||||
}}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &SoftCAS{}
|
||||
_, err := c.CreateCertificateAuthority(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("SoftCAS.CreateCertificateAuthority() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user