forked from TrueCloudLab/certificates
Merge pull request #440 from mkkeffeler/smallstep-by-provisioner-appendedcert
Begins to fix issue 87
This commit is contained in:
commit
00c6f08612
8 changed files with 54 additions and 60 deletions
|
@ -164,7 +164,7 @@ func (a *Authority) init() error {
|
||||||
|
|
||||||
// Read intermediate and create X509 signer for default CAS.
|
// Read intermediate and create X509 signer for default CAS.
|
||||||
if options.Is(casapi.SoftCAS) {
|
if options.Is(casapi.SoftCAS) {
|
||||||
options.Issuer, err = pemutil.ReadCertificate(a.config.IntermediateCert)
|
options.CertificateChain, err = pemutil.ReadCertificateBundle(a.config.IntermediateCert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ func WithX509Signer(crt *x509.Certificate, s crypto.Signer) Option {
|
||||||
return func(a *Authority) error {
|
return func(a *Authority) error {
|
||||||
srv, err := cas.New(context.Background(), casapi.Options{
|
srv, err := cas.New(context.Background(), casapi.Options{
|
||||||
Type: casapi.SoftCAS,
|
Type: casapi.SoftCAS,
|
||||||
Issuer: crt,
|
|
||||||
Signer: s,
|
Signer: s,
|
||||||
|
CertificateChain: []*x509.Certificate{crt},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -56,7 +56,7 @@ func (m *certificateDurationEnforcer) Enforce(cert *x509.Certificate) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultIssuer(a *Authority) *x509.Certificate {
|
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 {
|
func getDefaultSigner(a *Authority) crypto.Signer {
|
||||||
|
@ -671,7 +671,7 @@ func TestAuthority_Renew(t *testing.T) {
|
||||||
intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner)
|
intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner)
|
||||||
|
|
||||||
_a := testAuthority(t)
|
_a := testAuthority(t)
|
||||||
_a.x509CAService.(*softcas.SoftCAS).Issuer = intCert
|
_a.x509CAService.(*softcas.SoftCAS).CertificateChain = []*x509.Certificate{intCert}
|
||||||
_a.x509CAService.(*softcas.SoftCAS).Signer = intSigner
|
_a.x509CAService.(*softcas.SoftCAS).Signer = intSigner
|
||||||
return &renewTest{
|
return &renewTest{
|
||||||
auth: _a,
|
auth: _a,
|
||||||
|
@ -878,7 +878,7 @@ func TestAuthority_Rekey(t *testing.T) {
|
||||||
intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner)
|
intCert, intSigner := generateIntermidiateCertificate(t, rootCert, rootSigner)
|
||||||
|
|
||||||
_a := testAuthority(t)
|
_a := testAuthority(t)
|
||||||
_a.x509CAService.(*softcas.SoftCAS).Issuer = intCert
|
_a.x509CAService.(*softcas.SoftCAS).CertificateChain = []*x509.Certificate{intCert}
|
||||||
_a.x509CAService.(*softcas.SoftCAS).Signer = intSigner
|
_a.x509CAService.(*softcas.SoftCAS).Signer = intSigner
|
||||||
return &renewTest{
|
return &renewTest{
|
||||||
auth: _a,
|
auth: _a,
|
||||||
|
|
|
@ -21,9 +21,9 @@ type Options struct {
|
||||||
// `projects/*/locations/*/certificateAuthorities/*`.
|
// `projects/*/locations/*/certificateAuthorities/*`.
|
||||||
CertificateAuthority string `json:"certificateAuthority"`
|
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.
|
// They are configured in ca.json crt and key properties.
|
||||||
Issuer *x509.Certificate `json:"-"`
|
CertificateChain []*x509.Certificate
|
||||||
Signer crypto.Signer `json:"-"`
|
Signer crypto.Signer `json:"-"`
|
||||||
|
|
||||||
// IsCreator is set to true when we're creating a certificate authority. Is
|
// IsCreator is set to true when we're creating a certificate authority. Is
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestOptions_Validate(t *testing.T) {
|
||||||
Type: tt.fields.Type,
|
Type: tt.fields.Type,
|
||||||
CredentialsFile: tt.fields.CredentialsFile,
|
CredentialsFile: tt.fields.CredentialsFile,
|
||||||
CertificateAuthority: tt.fields.CertificateAuthority,
|
CertificateAuthority: tt.fields.CertificateAuthority,
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
}
|
}
|
||||||
if err := o.Validate(); (err != nil) != tt.wantErr {
|
if err := o.Validate(); (err != nil) != tt.wantErr {
|
||||||
|
@ -120,7 +120,7 @@ func TestOptions_Is(t *testing.T) {
|
||||||
Type: tt.fields.Type,
|
Type: tt.fields.Type,
|
||||||
CredentialsFile: tt.fields.CredentialsFile,
|
CredentialsFile: tt.fields.CredentialsFile,
|
||||||
CertificateAuthority: tt.fields.CertificateAuthority,
|
CertificateAuthority: tt.fields.CertificateAuthority,
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
}
|
}
|
||||||
if got := o.Is(tt.args.t); got != tt.want {
|
if got := o.Is(tt.args.t); got != tt.want {
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (m *mockCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
expected := &softcas.SoftCAS{
|
expected := &softcas.SoftCAS{
|
||||||
Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}},
|
CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}},
|
||||||
Signer: ed25519.PrivateKey{},
|
Signer: ed25519.PrivateKey{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,17 +50,17 @@ func TestNew(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{"ok default", args{context.Background(), apiv1.Options{
|
{"ok default", args{context.Background(), apiv1.Options{
|
||||||
Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}},
|
CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}},
|
||||||
Signer: ed25519.PrivateKey{},
|
Signer: ed25519.PrivateKey{},
|
||||||
}}, expected, false},
|
}}, expected, false},
|
||||||
{"ok softcas", args{context.Background(), apiv1.Options{
|
{"ok softcas", args{context.Background(), apiv1.Options{
|
||||||
Type: "softcas",
|
Type: "softcas",
|
||||||
Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}},
|
CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}},
|
||||||
Signer: ed25519.PrivateKey{},
|
Signer: ed25519.PrivateKey{},
|
||||||
}}, expected, false},
|
}}, expected, false},
|
||||||
{"ok SoftCAS", args{context.Background(), apiv1.Options{
|
{"ok SoftCAS", args{context.Background(), apiv1.Options{
|
||||||
Type: "SoftCAS",
|
Type: "SoftCAS",
|
||||||
Issuer: &x509.Certificate{Subject: pkix.Name{CommonName: "Test Issuer"}},
|
CertificateChain: []*x509.Certificate{{Subject: pkix.Name{CommonName: "Test Issuer"}}},
|
||||||
Signer: ed25519.PrivateKey{},
|
Signer: ed25519.PrivateKey{},
|
||||||
}}, expected, false},
|
}}, expected, false},
|
||||||
{"fail empty", args{context.Background(), apiv1.Options{}}, (*softcas.SoftCAS)(nil), true},
|
{"fail empty", args{context.Background(), apiv1.Options{}}, (*softcas.SoftCAS)(nil), true},
|
||||||
|
|
|
@ -26,7 +26,7 @@ var now = func() time.Time {
|
||||||
// SoftCAS implements a Certificate Authority Service using Golang or KMS
|
// SoftCAS implements a Certificate Authority Service using Golang or KMS
|
||||||
// crypto. This is the default CAS used in step-ca.
|
// crypto. This is the default CAS used in step-ca.
|
||||||
type SoftCAS struct {
|
type SoftCAS struct {
|
||||||
Issuer *x509.Certificate
|
CertificateChain []*x509.Certificate
|
||||||
Signer crypto.Signer
|
Signer crypto.Signer
|
||||||
KeyManager kms.KeyManager
|
KeyManager kms.KeyManager
|
||||||
}
|
}
|
||||||
|
@ -36,14 +36,14 @@ type SoftCAS struct {
|
||||||
func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) {
|
func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) {
|
||||||
if !opts.IsCreator {
|
if !opts.IsCreator {
|
||||||
switch {
|
switch {
|
||||||
case opts.Issuer == nil:
|
case len(opts.CertificateChain) == 0:
|
||||||
return nil, errors.New("softCAS 'issuer' cannot be nil")
|
return nil, errors.New("softCAS 'CertificateChain' cannot be nil")
|
||||||
case opts.Signer == nil:
|
case opts.Signer == nil:
|
||||||
return nil, errors.New("softCAS 'signer' cannot be nil")
|
return nil, errors.New("softCAS 'signer' cannot be nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &SoftCAS{
|
return &SoftCAS{
|
||||||
Issuer: opts.Issuer,
|
CertificateChain: opts.CertificateChain,
|
||||||
Signer: opts.Signer,
|
Signer: opts.Signer,
|
||||||
KeyManager: opts.KeyManager,
|
KeyManager: opts.KeyManager,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -66,18 +66,16 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
|
||||||
if req.Template.NotAfter.IsZero() {
|
if req.Template.NotAfter.IsZero() {
|
||||||
req.Template.NotAfter = t.Add(req.Lifetime)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &apiv1.CreateCertificateResponse{
|
return &apiv1.CreateCertificateResponse{
|
||||||
Certificate: cert,
|
Certificate: cert,
|
||||||
CertificateChain: []*x509.Certificate{
|
CertificateChain: c.CertificateChain,
|
||||||
c.Issuer,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,18 +91,16 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R
|
||||||
t := now()
|
t := now()
|
||||||
req.Template.NotBefore = t.Add(-1 * req.Backdate)
|
req.Template.NotBefore = t.Add(-1 * req.Backdate)
|
||||||
req.Template.NotAfter = t.Add(req.Lifetime)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &apiv1.RenewCertificateResponse{
|
return &apiv1.RenewCertificateResponse{
|
||||||
Certificate: cert,
|
Certificate: cert,
|
||||||
CertificateChain: []*x509.Certificate{
|
CertificateChain: c.CertificateChain,
|
||||||
c.Issuer,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,9 +110,7 @@ func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.R
|
||||||
func (c *SoftCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) {
|
func (c *SoftCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) {
|
||||||
return &apiv1.RevokeCertificateResponse{
|
return &apiv1.RevokeCertificateResponse{
|
||||||
Certificate: req.Certificate,
|
Certificate: req.Certificate,
|
||||||
CertificateChain: []*x509.Certificate{
|
CertificateChain: c.CertificateChain,
|
||||||
c.Issuer,
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,9 +182,9 @@ func TestNew(t *testing.T) {
|
||||||
want *SoftCAS
|
want *SoftCAS
|
||||||
wantErr bool
|
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 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 {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -208,11 +208,11 @@ func TestNew_register(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
want := &SoftCAS{
|
want := &SoftCAS{
|
||||||
Issuer: testIssuer,
|
CertificateChain: []*x509.Certificate{testIssuer},
|
||||||
Signer: testSigner,
|
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 {
|
if err != nil {
|
||||||
t.Errorf("New() error = %v", err)
|
t.Errorf("New() error = %v", err)
|
||||||
return
|
return
|
||||||
|
@ -286,7 +286,7 @@ func TestSoftCAS_CreateCertificate(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := &SoftCAS{
|
c := &SoftCAS{
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
}
|
}
|
||||||
got, err := c.CreateCertificate(tt.args.req)
|
got, err := c.CreateCertificate(tt.args.req)
|
||||||
|
@ -342,7 +342,7 @@ func TestSoftCAS_RenewCertificate(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := &SoftCAS{
|
c := &SoftCAS{
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
}
|
}
|
||||||
got, err := c.RenewCertificate(tt.args.req)
|
got, err := c.RenewCertificate(tt.args.req)
|
||||||
|
@ -395,7 +395,7 @@ func TestSoftCAS_RevokeCertificate(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := &SoftCAS{
|
c := &SoftCAS{
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
}
|
}
|
||||||
got, err := c.RevokeCertificate(tt.args.req)
|
got, err := c.RevokeCertificate(tt.args.req)
|
||||||
|
@ -524,7 +524,7 @@ func TestSoftCAS_CreateCertificateAuthority(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := &SoftCAS{
|
c := &SoftCAS{
|
||||||
Issuer: tt.fields.Issuer,
|
CertificateChain: []*x509.Certificate{tt.fields.Issuer},
|
||||||
Signer: tt.fields.Signer,
|
Signer: tt.fields.Signer,
|
||||||
KeyManager: tt.fields.KeyManager,
|
KeyManager: tt.fields.KeyManager,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue