Merge pull request #879 from smallstep/feat/WithX509SignerFunc
Add authority.WithX509SignerFunc
This commit is contained in:
commit
b42c1dfe64
4 changed files with 200 additions and 49 deletions
|
@ -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,21 @@ 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
|
||||
// signer used in SoftCAS. They are configured in ca.json crt and key
|
||||
// properties.
|
||||
// CertificateChain contains the issuer certificate, along with any other
|
||||
// bundled certificates to be returned in the chain for consumers. It is
|
||||
// used used in SoftCAS, and is configured in the crt property of the
|
||||
// ca.json.
|
||||
CertificateChain []*x509.Certificate `json:"-"`
|
||||
|
||||
// Signer is the private key or a KMS signer for the issuer certificate. It is used in
|
||||
// SoftCAS and it is configured in the key property of the ca.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.
|
||||
|
|
|
@ -26,6 +26,7 @@ var now = time.Now
|
|||
type SoftCAS struct {
|
||||
CertificateChain []*x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
KeyManager kms.KeyManager
|
||||
}
|
||||
|
||||
|
@ -34,15 +35,16 @@ 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,
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
@ -267,6 +278,7 @@ func TestSoftCAS_CreateCertificate(t *testing.T) {
|
|||
type fields struct {
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
CertificateSigner func() ([]*x509.Certificate, crypto.Signer, error)
|
||||
}
|
||||
type args struct {
|
||||
req *apiv1.CreateCertificateRequest
|
||||
|
@ -278,36 +290,45 @@ 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 {
|
||||
|
@ -315,6 +336,7 @@ func TestSoftCAS_CreateCertificate(t *testing.T) {
|
|||
c := &SoftCAS{
|
||||
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 {
|
||||
|
@ -347,6 +369,7 @@ func TestSoftCAS_RenewCertificate(t *testing.T) {
|
|||
type fields struct {
|
||||
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,
|
||||
CertificateSigner: tt.fields.CertificateSigner,
|
||||
}
|
||||
got, err := c.RenewCertificate(tt.args.req)
|
||||
if (err != nil) != tt.wantErr {
|
||||
|
@ -399,6 +432,7 @@ func TestSoftCAS_RevokeCertificate(t *testing.T) {
|
|||
type fields struct {
|
||||
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,
|
||||
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 a new issue