Add JWK as an issuer for stepcas.

pull/510/head
Mariano Cano 3 years ago
parent ce3e6bfdf6
commit 80542d6d9a

@ -1,12 +1,36 @@
package stepcas
import (
"net/url"
"strings"
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/cas/apiv1"
)
type stepIssuer interface {
SignToken(subject string, sans []string) (string, error)
RevokeToken(subject string) (string, error)
Lifetime(d time.Duration) time.Duration
}
// newStepIssuer returns the configured step issuer.
func newStepIssuer(caURL *url.URL, iss *apiv1.CertificateIssuer) (stepIssuer, error) {
if err := validateCertificateIssuer(iss); err != nil {
return nil, err
}
switch strings.ToLower(iss.Type) {
case "x5c":
return newX5CIssuer(caURL, iss)
case "jwk":
return newJWKIssuer(caURL, iss)
default:
return nil, errors.Errorf("stepCAS `certificateIssuer.type` %s is not supported", iss.Type)
}
}
// validateCertificateIssuer validates the configuration of the certificate
// issuer.
func validateCertificateIssuer(iss *apiv1.CertificateIssuer) error {
@ -20,6 +44,8 @@ func validateCertificateIssuer(iss *apiv1.CertificateIssuer) error {
switch strings.ToLower(iss.Type) {
case "x5c":
return validateX5CIssuer(iss)
case "jwk":
return validateJWKIssuer(iss)
default:
return errors.Errorf("stepCAS `certificateIssuer.type` %s is not supported", iss.Type)
}
@ -38,3 +64,15 @@ func validateX5CIssuer(iss *apiv1.CertificateIssuer) error {
return nil
}
}
// validateJWKIssuer validates the configuration of jwk issuer.
func validateJWKIssuer(iss *apiv1.CertificateIssuer) error {
switch {
case iss.Key == "":
return errors.New("stepCAS `certificateIssuer.key` cannot be empty")
case iss.Provisioner == "":
return errors.New("stepCAS `certificateIssuer.provisioner` cannot be empty")
default:
return nil
}
}

@ -0,0 +1,80 @@
package stepcas
import (
"net/url"
"reflect"
"testing"
"time"
"github.com/smallstep/certificates/cas/apiv1"
)
type mockErrIssuer struct{}
func (m mockErrIssuer) SignToken(subject string, sans []string) (string, error) {
return "", apiv1.ErrNotImplemented{}
}
func (m mockErrIssuer) RevokeToken(subject string) (string, error) {
return "", apiv1.ErrNotImplemented{}
}
func (m mockErrIssuer) Lifetime(d time.Duration) time.Duration {
return d
}
func Test_newStepIssuer(t *testing.T) {
caURL, err := url.Parse("https://ca.smallstep.com")
if err != nil {
t.Fatal(err)
}
type args struct {
caURL *url.URL
iss *apiv1.CertificateIssuer
}
tests := []struct {
name string
args args
want stepIssuer
wantErr bool
}{
{"x5c", args{caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
}}, &x5cIssuer{
caURL: caURL,
certFile: testX5CPath,
keyFile: testX5CKeyPath,
issuer: "X5C",
}, false},
{"jwk", args{caURL, &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "ra@doe.org",
Key: testX5CKeyPath,
}}, &jwkIssuer{
caURL: caURL,
keyFile: testX5CKeyPath,
issuer: "ra@doe.org",
}, false},
{"fail", args{caURL, &apiv1.CertificateIssuer{
Type: "unknown",
Provisioner: "ra@doe.org",
Key: testX5CKeyPath,
}}, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := newStepIssuer(tt.args.caURL, tt.args.iss)
if (err != nil) != tt.wantErr {
t.Errorf("newStepIssuer() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("newStepIssuer() = %v, want %v", got, tt.want)
}
})
}
}

@ -0,0 +1,96 @@
package stepcas
import (
"crypto"
"net/url"
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/cas/apiv1"
"go.step.sm/crypto/jose"
"go.step.sm/crypto/pemutil"
"go.step.sm/crypto/randutil"
)
type jwkIssuer struct {
caURL *url.URL
keyFile string
issuer string
}
func newJWKIssuer(caURL *url.URL, cfg *apiv1.CertificateIssuer) (*jwkIssuer, error) {
_, err := newJWKSigner(cfg.Key)
if err != nil {
return nil, err
}
return &jwkIssuer{
caURL: caURL,
keyFile: cfg.Key,
issuer: cfg.Provisioner,
}, nil
}
func (i *jwkIssuer) SignToken(subject string, sans []string) (string, error) {
aud := i.caURL.ResolveReference(&url.URL{
Path: "/1.0/sign",
}).String()
return i.createToken(aud, subject, sans)
}
func (i *jwkIssuer) RevokeToken(subject string) (string, error) {
aud := i.caURL.ResolveReference(&url.URL{
Path: "/1.0/revoke",
}).String()
return i.createToken(aud, subject, nil)
}
func (i *jwkIssuer) Lifetime(d time.Duration) time.Duration {
return d
}
func (i *jwkIssuer) createToken(aud, sub string, sans []string) (string, error) {
signer, err := newJWKSigner(i.keyFile)
if err != nil {
return "", err
}
id, err := randutil.Hex(64) // 256 bits
if err != nil {
return "", err
}
claims := defaultClaims(i.issuer, sub, aud, id)
builder := jose.Signed(signer).Claims(claims)
if len(sans) > 0 {
builder = builder.Claims(map[string]interface{}{
"sans": sans,
})
}
tok, err := builder.CompactSerialize()
if err != nil {
return "", errors.Wrap(err, "error signing token")
}
return tok, nil
}
func newJWKSigner(keyFile string) (jose.Signer, error) {
key, err := pemutil.Read(keyFile)
if err != nil {
return nil, err
}
signer, ok := key.(crypto.Signer)
if !ok {
return nil, errors.New("key is not a crypto.Signer")
}
kid, err := jose.Thumbprint(&jose.JSONWebKey{Key: signer.Public()})
if err != nil {
return nil, err
}
so := new(jose.SignerOptions)
so.WithType("JWT")
so.WithHeader("kid", kid)
return newJoseSigner(signer, so)
}

@ -0,0 +1,172 @@
package stepcas
import (
"net/url"
"reflect"
"testing"
"time"
"go.step.sm/crypto/jose"
)
func Test_jwkIssuer_SignToken(t *testing.T) {
caURL, err := url.Parse("https://ca.smallstep.com")
if err != nil {
t.Fatal(err)
}
type fields struct {
caURL *url.URL
keyFile string
issuer string
}
type args struct {
subject string
sans []string
}
type claims struct {
Aud []string `json:"aud"`
Sub string `json:"sub"`
Sans []string `json:"sans"`
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{"ok", fields{caURL, testX5CKeyPath, "ra@doe.org"}, args{"doe", []string{"doe.org"}}, false},
{"fail key", fields{caURL, "", "ra@doe.org"}, args{"doe", []string{"doe.org"}}, true},
{"fail no signer", fields{caURL, testIssPath, "ra@doe.org"}, args{"doe", []string{"doe.org"}}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
i := &jwkIssuer{
caURL: tt.fields.caURL,
keyFile: tt.fields.keyFile,
issuer: tt.fields.issuer,
}
got, err := i.SignToken(tt.args.subject, tt.args.sans)
if (err != nil) != tt.wantErr {
t.Errorf("jwkIssuer.SignToken() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
jwt, err := jose.ParseSigned(got)
if err != nil {
t.Errorf("jose.ParseSigned() error = %v", err)
}
var c claims
want := claims{
Aud: []string{tt.fields.caURL.String() + "/1.0/sign"},
Sub: tt.args.subject,
Sans: tt.args.sans,
}
if err := jwt.Claims(testX5CKey.Public(), &c); err != nil {
t.Errorf("jwt.Claims() error = %v", err)
}
if !reflect.DeepEqual(c, want) {
t.Errorf("jwt.Claims() claims = %#v, want %#v", c, want)
}
}
})
}
}
func Test_jwkIssuer_RevokeToken(t *testing.T) {
caURL, err := url.Parse("https://ca.smallstep.com")
if err != nil {
t.Fatal(err)
}
type fields struct {
caURL *url.URL
keyFile string
issuer string
}
type args struct {
subject string
}
type claims struct {
Aud []string `json:"aud"`
Sub string `json:"sub"`
Sans []string `json:"sans"`
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{"ok", fields{caURL, testX5CKeyPath, "ra@smallstep.com"}, args{"doe"}, false},
{"fail key", fields{caURL, "", "ra@smallstep.com"}, args{"doe"}, true},
{"fail no signer", fields{caURL, testIssPath, "ra@smallstep.com"}, args{"doe"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
i := &jwkIssuer{
caURL: tt.fields.caURL,
keyFile: tt.fields.keyFile,
issuer: tt.fields.issuer,
}
got, err := i.RevokeToken(tt.args.subject)
if (err != nil) != tt.wantErr {
t.Errorf("jwkIssuer.RevokeToken() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
jwt, err := jose.ParseSigned(got)
if err != nil {
t.Errorf("jose.ParseSigned() error = %v", err)
}
var c claims
want := claims{
Aud: []string{tt.fields.caURL.String() + "/1.0/revoke"},
Sub: tt.args.subject,
}
if err := jwt.Claims(testX5CKey.Public(), &c); err != nil {
t.Errorf("jwt.Claims() error = %v", err)
}
if !reflect.DeepEqual(c, want) {
t.Errorf("jwt.Claims() claims = %#v, want %#v", c, want)
}
}
})
}
}
func Test_jwkIssuer_Lifetime(t *testing.T) {
caURL, err := url.Parse("https://ca.smallstep.com")
if err != nil {
t.Fatal(err)
}
type fields struct {
caURL *url.URL
keyFile string
issuer string
}
type args struct {
d time.Duration
}
tests := []struct {
name string
fields fields
args args
want time.Duration
}{
{"ok", fields{caURL, testX5CKeyPath, "ra@smallstep.com"}, args{time.Second}, time.Second},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
i := &jwkIssuer{
caURL: tt.fields.caURL,
keyFile: tt.fields.keyFile,
issuer: tt.fields.issuer,
}
if got := i.Lifetime(tt.args.d); got != tt.want {
t.Errorf("jwkIssuer.Lifetime() = %v, want %v", got, tt.want)
}
})
}
}

@ -21,7 +21,7 @@ func init() {
// StepCAS implements the cas.CertificateAuthorityService interface using
// another step-ca instance.
type StepCAS struct {
x5c *x5cIssuer
iss stepIssuer
client *ca.Client
fingerprint string
}
@ -40,24 +40,21 @@ func New(ctx context.Context, opts apiv1.Options) (*StepCAS, error) {
if err != nil {
return nil, errors.Wrap(err, "stepCAS `certificateAuthority` is not valid")
}
if err := validateCertificateIssuer(opts.CertificateIssuer); err != nil {
return nil, err
}
// Create client.
client, err := ca.NewClient(opts.CertificateAuthority, ca.WithRootSHA256(opts.CertificateAuthorityFingerprint))
// Create configured issuer
iss, err := newStepIssuer(caURL, opts.CertificateIssuer)
if err != nil {
return nil, err
}
// X5C is the only one supported at the moment.
x5c, err := newX5CIssuer(caURL, opts.CertificateIssuer)
// Create client.
client, err := ca.NewClient(opts.CertificateAuthority, ca.WithRootSHA256(opts.CertificateAuthorityFingerprint))
if err != nil {
return nil, err
}
return &StepCAS{
x5c: x5c,
iss: iss,
client: client,
fingerprint: opts.CertificateAuthorityFingerprint,
}, nil
@ -101,7 +98,7 @@ func (s *StepCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1
serialNumber = req.Certificate.SerialNumber.String()
}
token, err := s.revokeToken(serialNumber)
token, err := s.iss.RevokeToken(serialNumber)
if err != nil {
return nil, err
}
@ -151,7 +148,7 @@ func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.D
commonName = sans[0]
}
token, err := s.signToken(commonName, sans)
token, err := s.iss.SignToken(commonName, sans)
if err != nil {
return nil, nil, err
}
@ -174,27 +171,8 @@ func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.D
return cert, chain, nil
}
func (s *StepCAS) signToken(subject string, sans []string) (string, error) {
if s.x5c != nil {
return s.x5c.SignToken(subject, sans)
}
return "", errors.New("stepCAS does not have any provisioner configured")
}
func (s *StepCAS) revokeToken(subject string) (string, error) {
if s.x5c != nil {
return s.x5c.RevokeToken(subject)
}
return "", errors.New("stepCAS does not have any provisioner configured")
}
func (s *StepCAS) lifetime(d time.Duration) api.TimeDuration {
if s.x5c != nil {
d = s.x5c.Lifetime(d)
}
var td api.TimeDuration
td.SetDuration(d)
td.SetDuration(s.iss.Lifetime(d))
return td
}

@ -167,6 +167,33 @@ func testCAHelper(t *testing.T) (*url.URL, *ca.Client) {
return u, client
}
func testX5CIssuer(t *testing.T, caURL *url.URL) *x5cIssuer {
t.Helper()
x5c, err := newX5CIssuer(caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
return x5c
}
func testJWKIssuer(t *testing.T, caURL *url.URL) *jwkIssuer {
t.Helper()
x5c, err := newJWKIssuer(caURL, &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "ra@doe.org",
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
return x5c
}
func TestMain(m *testing.M) {
testRootCrt, testRootKey = mustSignCertificate("Test Root Certificate", nil, x509util.DefaultRootTemplate, nil, nil)
testIssCrt, testIssKey = mustSignCertificate("Test Intermediate Certificate", nil, x509util.DefaultIntermediateTemplate, testRootCrt, testRootKey)
@ -258,7 +285,7 @@ func TestNew(t *testing.T) {
Key: testX5CKeyPath,
},
}}, &StepCAS{
x5c: &x5cIssuer{
iss: &x5cIssuer{
caURL: caURL,
certFile: testX5CPath,
keyFile: testX5CKeyPath,
@ -267,6 +294,23 @@ func TestNew(t *testing.T) {
client: client,
fingerprint: testRootFingerprint,
}, false},
{"ok jwk", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
CertificateIssuer: &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "ra@doe.org",
Key: testX5CKeyPath,
},
}}, &StepCAS{
iss: &jwkIssuer{
caURL: caURL,
keyFile: testX5CKeyPath,
issuer: "ra@doe.org",
},
client: client,
fingerprint: testRootFingerprint,
}, false},
{"fail authority", args{context.TODO(), apiv1.Options{
CertificateAuthority: "",
CertificateAuthorityFingerprint: testRootFingerprint,
@ -307,6 +351,15 @@ func TestNew(t *testing.T) {
Key: testX5CKeyPath,
},
}}, nil, true},
{"fail provisioner jwk", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
CertificateIssuer: &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "",
Key: testX5CKeyPath,
},
}}, nil, true},
{"fail certificate", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
@ -327,6 +380,15 @@ func TestNew(t *testing.T) {
Key: "",
},
}}, nil, true},
{"fail key jwk", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
CertificateIssuer: &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "ra@smallstep.com",
Key: "",
},
}}, nil, true},
{"bad authority", args{context.TODO(), apiv1.Options{
CertificateAuthority: "https://foobar",
CertificateAuthorityFingerprint: testRootFingerprint,
@ -367,6 +429,15 @@ func TestNew(t *testing.T) {
Key: testX5CKeyPath,
},
}}, nil, true},
{"fail new jwk issuer", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
CertificateIssuer: &apiv1.CertificateIssuer{
Type: "jwk",
Provisioner: "ra@doe.org",
Key: testX5CKeyPath + ".missing",
},
}}, nil, true},
{"bad issuer", args{context.TODO(), apiv1.Options{
CertificateAuthority: caURL.String(),
CertificateAuthorityFingerprint: testRootFingerprint,
@ -402,18 +473,11 @@ func TestNew(t *testing.T) {
func TestStepCAS_CreateCertificate(t *testing.T) {
caURL, client := testCAHelper(t)
x5c, err := newX5CIssuer(caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
x5c := testX5CIssuer(t, caURL)
jwk := testJWKIssuer(t, caURL)
type fields struct {
x5c *x5cIssuer
iss stepIssuer
client *ca.Client
fingerprint string
}
@ -434,6 +498,13 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
Certificate: testCrt,
CertificateChain: []*x509.Certificate{testIssCrt},
}, false},
{"ok jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR,
Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{
Certificate: testCrt,
CertificateChain: []*x509.Certificate{testIssCrt},
}, false},
{"fail CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: nil,
Lifetime: time.Hour,
@ -442,7 +513,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
CSR: testCR,
Lifetime: 0,
}}, nil, true},
{"fail sign token", fields{nil, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
{"fail sign token", fields{mockErrIssuer{}, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR,
Lifetime: time.Hour,
}}, nil, true},
@ -454,7 +525,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &StepCAS{
x5c: tt.fields.x5c,
iss: tt.fields.iss,
client: tt.fields.client,
fingerprint: tt.fields.fingerprint,
}
@ -472,18 +543,11 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
func TestStepCAS_RenewCertificate(t *testing.T) {
caURL, client := testCAHelper(t)
x5c, err := newX5CIssuer(caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
x5c := testX5CIssuer(t, caURL)
jwk := testJWKIssuer(t, caURL)
type fields struct {
x5c *x5cIssuer
iss stepIssuer
client *ca.Client
fingerprint string
}
@ -501,11 +565,15 @@ func TestStepCAS_RenewCertificate(t *testing.T) {
CSR: testCR,
Lifetime: time.Hour,
}}, nil, true},
{"not implemented jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{
CSR: testCR,
Lifetime: time.Hour,
}}, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &StepCAS{
x5c: tt.fields.x5c,
iss: tt.fields.iss,
client: tt.fields.client,
fingerprint: tt.fields.fingerprint,
}
@ -523,18 +591,11 @@ func TestStepCAS_RenewCertificate(t *testing.T) {
func TestStepCAS_RevokeCertificate(t *testing.T) {
caURL, client := testCAHelper(t)
x5c, err := newX5CIssuer(caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
x5c := testX5CIssuer(t, caURL)
jwk := testJWKIssuer(t, caURL)
type fields struct {
x5c *x5cIssuer
iss stepIssuer
client *ca.Client
fingerprint string
}
@ -564,11 +625,27 @@ func TestStepCAS_RevokeCertificate(t *testing.T) {
}}, &apiv1.RevokeCertificateResponse{
Certificate: testCrt,
}, false},
{"ok serial number jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
SerialNumber: "ok",
Certificate: nil,
}}, &apiv1.RevokeCertificateResponse{}, false},
{"ok certificate jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
SerialNumber: "",
Certificate: testCrt,
}}, &apiv1.RevokeCertificateResponse{
Certificate: testCrt,
}, false},
{"ok both jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
SerialNumber: "ok",
Certificate: testCrt,
}}, &apiv1.RevokeCertificateResponse{
Certificate: testCrt,
}, false},
{"fail request", fields{x5c, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
SerialNumber: "",
Certificate: nil,
}}, nil, true},
{"fail revoke token", fields{nil, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
{"fail revoke token", fields{mockErrIssuer{}, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
SerialNumber: "ok",
}}, nil, true},
{"fail client revoke", fields{x5c, client, testRootFingerprint}, args{&apiv1.RevokeCertificateRequest{
@ -578,7 +655,7 @@ func TestStepCAS_RevokeCertificate(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &StepCAS{
x5c: tt.fields.x5c,
iss: tt.fields.iss,
client: tt.fields.client,
fingerprint: tt.fields.fingerprint,
}
@ -596,18 +673,11 @@ func TestStepCAS_RevokeCertificate(t *testing.T) {
func TestStepCAS_GetCertificateAuthority(t *testing.T) {
caURL, client := testCAHelper(t)
x5c, err := newX5CIssuer(caURL, &apiv1.CertificateIssuer{
Type: "x5c",
Provisioner: "X5C",
Certificate: testX5CPath,
Key: testX5CKeyPath,
})
if err != nil {
t.Fatal(err)
}
x5c := testX5CIssuer(t, caURL)
jwk := testJWKIssuer(t, caURL)
type fields struct {
x5c *x5cIssuer
iss stepIssuer
client *ca.Client
fingerprint string
}
@ -626,6 +696,11 @@ func TestStepCAS_GetCertificateAuthority(t *testing.T) {
}}, &apiv1.GetCertificateAuthorityResponse{
RootCertificate: testRootCrt,
}, false},
{"ok jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.GetCertificateAuthorityRequest{
Name: caURL.String(),
}}, &apiv1.GetCertificateAuthorityResponse{
RootCertificate: testRootCrt,
}, false},
{"fail fingerprint", fields{x5c, client, "fail"}, args{&apiv1.GetCertificateAuthorityRequest{
Name: caURL.String(),
}}, nil, true},
@ -633,7 +708,7 @@ func TestStepCAS_GetCertificateAuthority(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &StepCAS{
x5c: tt.fields.x5c,
iss: tt.fields.iss,
client: tt.fields.client,
fingerprint: tt.fields.fingerprint,
}

Loading…
Cancel
Save