Pass issuer and signer to softCAS options.
Remove commented code and initialize CAS properly. Minor fixes in CloudCAS.
This commit is contained in:
parent
c8d9cb0a1d
commit
aad8f9e582
10 changed files with 191 additions and 101 deletions
|
@ -148,18 +148,6 @@ func (a *Authority) init() error {
|
|||
}
|
||||
}
|
||||
|
||||
// Initialize the X.509 CA Service if it has not been set in the options
|
||||
if a.x509CAService == nil {
|
||||
var options casapi.Options
|
||||
if a.config.CAS != nil {
|
||||
options = *a.config.CAS
|
||||
}
|
||||
a.x509CAService, err = cas.New(context.Background(), options)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize step-ca Database if it's not already initialized with WithDB.
|
||||
// If a.config.DB is nil then a simple, barebones in memory DB will be used.
|
||||
if a.db == nil {
|
||||
|
@ -206,15 +194,51 @@ func (a *Authority) init() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{
|
||||
SigningKey: a.config.IntermediateKey,
|
||||
Password: []byte(a.config.Password),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.x509Signer = signer
|
||||
a.x509Issuer = crt
|
||||
|
||||
// Read signer only is the CAS is the default one.
|
||||
if a.config.CAS.HasType(casapi.SoftCAS) {
|
||||
signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{
|
||||
SigningKey: a.config.IntermediateKey,
|
||||
Password: []byte(a.config.Password),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.x509Signer = signer
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the X.509 CA Service if it has not been set in the options
|
||||
if a.x509CAService == nil {
|
||||
var options casapi.Options
|
||||
if a.config.CAS != nil {
|
||||
options = *a.config.CAS
|
||||
}
|
||||
|
||||
// Set issuer and signer for default CAS.
|
||||
if options.HasType(casapi.SoftCAS) {
|
||||
crt, err := pemutil.ReadCertificate(a.config.IntermediateCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
signer, err := a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{
|
||||
SigningKey: a.config.IntermediateKey,
|
||||
Password: []byte(a.config.Password),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options.Issuer = crt
|
||||
options.Signer = signer
|
||||
}
|
||||
|
||||
a.x509CAService, err = cas.New(context.Background(), options)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt and load SSH keys
|
||||
|
|
|
@ -187,7 +187,7 @@ func (c *Config) Validate() error {
|
|||
case c.IntermediateCert == "":
|
||||
return errors.New("crt cannot be empty")
|
||||
|
||||
case c.IntermediateKey == "":
|
||||
case c.IntermediateKey == "" && c.CAS.HasType(cas.SoftCAS):
|
||||
return errors.New("key cannot be empty")
|
||||
|
||||
case len(c.DNSNames) == 0:
|
||||
|
|
|
@ -145,32 +145,24 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign
|
|||
}
|
||||
}
|
||||
|
||||
lifetime := leaf.NotAfter.Sub(leaf.NotBefore.Add(-1 * signOpts.Backdate))
|
||||
lifetime := leaf.NotAfter.Sub(leaf.NotBefore.Add(signOpts.Backdate))
|
||||
resp, err := a.x509CAService.CreateCertificate(&casapi.CreateCertificateRequest{
|
||||
Template: leaf,
|
||||
Issuer: a.x509Issuer,
|
||||
Signer: a.x509Signer,
|
||||
Lifetime: lifetime,
|
||||
Backdate: signOpts.Backdate,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign; error creating certificate", opts...)
|
||||
}
|
||||
serverCert := resp.Certificate
|
||||
|
||||
// serverCert, err := x509util.CreateCertificate(leaf, a.x509Issuer, csr.PublicKey, a.x509Signer)
|
||||
// if err != nil {
|
||||
// return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
// "authority.Sign; error creating certificate", opts...)
|
||||
// }
|
||||
|
||||
if err = a.db.StoreCertificate(serverCert); err != nil {
|
||||
if err = a.db.StoreCertificate(resp.Certificate); err != nil {
|
||||
if err != db.ErrNotImplemented {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err,
|
||||
"authority.Sign; error storing certificate in db", opts...)
|
||||
}
|
||||
}
|
||||
|
||||
return []*x509.Certificate{serverCert, a.x509Issuer}, nil
|
||||
return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil
|
||||
}
|
||||
|
||||
// Renew creates a new Certificate identical to the old certificate, except
|
||||
|
@ -200,13 +192,12 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5
|
|||
// Durations
|
||||
backdate := a.config.AuthorityConfig.Backdate.Duration
|
||||
duration := oldCert.NotAfter.Sub(oldCert.NotBefore)
|
||||
now := time.Now().UTC()
|
||||
lifetime := duration - backdate
|
||||
|
||||
// Create new certificate from previous values.
|
||||
// Issuer, NotBefore, NotAfter and SubjectKeyId will be set by the CAS.
|
||||
newCert := &x509.Certificate{
|
||||
Issuer: a.x509Issuer.Subject,
|
||||
Subject: oldCert.Subject,
|
||||
NotBefore: now.Add(-1 * backdate),
|
||||
NotAfter: now.Add(duration - backdate),
|
||||
KeyUsage: oldCert.KeyUsage,
|
||||
UnhandledCriticalExtensions: oldCert.UnhandledCriticalExtensions,
|
||||
ExtKeyUsage: oldCert.ExtKeyUsage,
|
||||
|
@ -241,10 +232,14 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5
|
|||
}
|
||||
|
||||
// Copy all extensions except:
|
||||
// 1. Authority Key Identifier - This one might be different if we rotate the intermediate certificate
|
||||
// and it will cause a TLS bad certificate error.
|
||||
// 2. Subject Key Identifier, if rekey - For rekey, SubjectKeyIdentifier extension will be calculated
|
||||
// for the new public key by NewLeafProfilewithTemplate()
|
||||
//
|
||||
// 1. Authority Key Identifier - This one might be different if we rotate
|
||||
// the intermediate certificate and it will cause a TLS bad certificate
|
||||
// error.
|
||||
//
|
||||
// 2. Subject Key Identifier, if rekey - For rekey, SubjectKeyIdentifier
|
||||
// extension will be calculated for the new public key by
|
||||
// x509util.CreateCertificate()
|
||||
for _, ext := range oldCert.Extensions {
|
||||
if ext.Id.Equal(oidAuthorityKeyIdentifier) {
|
||||
continue
|
||||
|
@ -256,18 +251,22 @@ func (a *Authority) Rekey(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x5
|
|||
newCert.ExtraExtensions = append(newCert.ExtraExtensions, ext)
|
||||
}
|
||||
|
||||
serverCert, err := x509util.CreateCertificate(newCert, a.x509Issuer, newCert.PublicKey, a.x509Signer)
|
||||
resp, err := a.x509CAService.RenewCertificate(&casapi.RenewCertificateRequest{
|
||||
Template: newCert,
|
||||
Lifetime: lifetime,
|
||||
Backdate: backdate,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Rekey", opts...)
|
||||
}
|
||||
|
||||
if err = a.db.StoreCertificate(serverCert); err != nil {
|
||||
if err = a.db.StoreCertificate(resp.Certificate); err != nil {
|
||||
if err != db.ErrNotImplemented {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Rekey; error storing certificate in db", opts...)
|
||||
}
|
||||
}
|
||||
|
||||
return []*x509.Certificate{serverCert, a.x509Issuer}, nil
|
||||
return append([]*x509.Certificate{resp.Certificate}, resp.CertificateChain...), nil
|
||||
}
|
||||
|
||||
// RevokeOptions are the options for the Revoke API.
|
||||
|
@ -403,30 +402,36 @@ func (a *Authority) GetTLSCertificate() (*tls.Certificate, error) {
|
|||
certTpl.NotBefore = now.Add(-1 * time.Minute)
|
||||
certTpl.NotAfter = now.Add(24 * time.Hour)
|
||||
|
||||
cert, err := x509util.CreateCertificate(certTpl, a.x509Issuer, cr.PublicKey, a.x509Signer)
|
||||
resp, err := a.x509CAService.CreateCertificate(&casapi.CreateCertificateRequest{
|
||||
Template: certTpl,
|
||||
Lifetime: 24 * time.Hour,
|
||||
Backdate: 1 * time.Minute,
|
||||
})
|
||||
if err != nil {
|
||||
return fatal(err)
|
||||
}
|
||||
|
||||
// Generate PEM blocks to create tls.Certificate
|
||||
crtPEM := pem.EncodeToMemory(&pem.Block{
|
||||
pemBlocks := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
Bytes: resp.Certificate.Raw,
|
||||
})
|
||||
intermediatePEM, err := pemutil.Serialize(a.x509Issuer)
|
||||
if err != nil {
|
||||
return fatal(err)
|
||||
for _, crt := range resp.CertificateChain {
|
||||
pemBlocks = append(pemBlocks, pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: crt.Raw,
|
||||
})...)
|
||||
}
|
||||
keyPEM, err := pemutil.Serialize(priv)
|
||||
if err != nil {
|
||||
return fatal(err)
|
||||
}
|
||||
|
||||
tlsCrt, err := tls.X509KeyPair(append(crtPEM, pem.EncodeToMemory(intermediatePEM)...), pem.EncodeToMemory(keyPEM))
|
||||
tlsCrt, err := tls.X509KeyPair(pemBlocks, pem.EncodeToMemory(keyPEM))
|
||||
if err != nil {
|
||||
return fatal(err)
|
||||
}
|
||||
// Set leaf certificate
|
||||
tlsCrt.Leaf = cert
|
||||
tlsCrt.Leaf = resp.Certificate
|
||||
return &tlsCrt, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
oidStepRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64}
|
||||
oidStepCertificateAuthority = append(asn1.ObjectIdentifier(nil), append(oidStepRoot, 2)...)
|
||||
)
|
||||
|
||||
// CertificateAuthorityExtension is type used to encode the certificate
|
||||
// authority extension.
|
||||
type CertificateAuthorityExtension struct {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package apiv1
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -14,27 +15,36 @@ type Options struct {
|
|||
|
||||
// Path to the credentials file used in CloudCAS
|
||||
CredentialsFile string `json:"credentialsFile"`
|
||||
|
||||
// CertificateAuthority reference. In CloudCAS the format is
|
||||
// `projects/*/locations/*/certificateAuthorities/*`.
|
||||
Certificateauthority string `json:"certificateAuthority"`
|
||||
|
||||
// Issuer and signer are the issuer certificate and signer used in SoftCAS.
|
||||
// They are configured in ca.json crt and key properties.
|
||||
Issuer *x509.Certificate `json:"-"`
|
||||
Signer crypto.Signer `json:"-"`
|
||||
}
|
||||
|
||||
// Validate checks the fields in Options.
|
||||
func (o *Options) Validate() error {
|
||||
var typ Type
|
||||
if o == nil {
|
||||
return nil
|
||||
typ = Type(SoftCAS)
|
||||
} else {
|
||||
typ = Type(o.Type)
|
||||
}
|
||||
|
||||
switch Type(strings.ToLower(o.Type)) {
|
||||
case DefaultCAS, SoftCAS, CloudCAS:
|
||||
default:
|
||||
return errors.Errorf("unsupported kms type %s", o.Type)
|
||||
// Check that the type can be loaded.
|
||||
if _, ok := LoadCertificateAuthorityServiceNewFunc(typ); !ok {
|
||||
return errors.Errorf("unsupported cas type %s", typ)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasType returns if the options have the given type.
|
||||
func (o *Options) HasType(t Type) bool {
|
||||
if o == nil {
|
||||
return SoftCAS == t.String()
|
||||
return t.String() == SoftCAS
|
||||
}
|
||||
return Type(o.Type).String() == t.String()
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
var registry = new(sync.Map)
|
||||
var (
|
||||
registry = new(sync.Map)
|
||||
)
|
||||
|
||||
// CertificateAuthorityServiceNewFunc is the type that represents the method to initialize a new
|
||||
// CertificateAuthorityService.
|
||||
|
@ -13,12 +15,12 @@ type CertificateAuthorityServiceNewFunc func(ctx context.Context, opts Options)
|
|||
|
||||
// Register adds to the registry a method to create a KeyManager of type t.
|
||||
func Register(t Type, fn CertificateAuthorityServiceNewFunc) {
|
||||
registry.Store(t, fn)
|
||||
registry.Store(t.String(), fn)
|
||||
}
|
||||
|
||||
// LoadCertificateAuthorityServiceNewFunc returns the function initialize a KayManager.
|
||||
func LoadCertificateAuthorityServiceNewFunc(t Type) (CertificateAuthorityServiceNewFunc, bool) {
|
||||
v, ok := registry.Load(t)
|
||||
v, ok := registry.Load(t.String())
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
package apiv1
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CreateCertificateRequest struct {
|
||||
Template *x509.Certificate
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Lifetime time.Duration
|
||||
Backdate time.Duration
|
||||
RequestID string
|
||||
|
@ -21,8 +18,6 @@ type CreateCertificateResponse struct {
|
|||
|
||||
type RenewCertificateRequest struct {
|
||||
Template *x509.Certificate
|
||||
Issuer *x509.Certificate
|
||||
Signer crypto.Signer
|
||||
Lifetime time.Duration
|
||||
Backdate time.Duration
|
||||
RequestID string
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
package apiv1
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
oidStepRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64}
|
||||
oidStepCertificateAuthority = append(asn1.ObjectIdentifier(nil), append(oidStepRoot, 2)...)
|
||||
)
|
||||
|
||||
// CertificateAuthorityService is the interface implemented to support external
|
||||
// certificate authorities.
|
||||
type CertificateAuthorityService interface {
|
||||
|
@ -18,27 +12,24 @@ type CertificateAuthorityService interface {
|
|||
RevokeCertificate(req *RevokeCertificateRequest) (*RevokeCertificateResponse, error)
|
||||
}
|
||||
|
||||
// Type represents the KMS type used.
|
||||
// Type represents the CAS type used.
|
||||
type Type string
|
||||
|
||||
const (
|
||||
// DefaultCAS is a CertificateAuthorityService using software.
|
||||
DefaultCAS = ""
|
||||
// SoftCAS is a CertificateAuthorityService using software.
|
||||
SoftCAS = "SoftCAS"
|
||||
SoftCAS = "softcas"
|
||||
// CloudCAS is a CertificateAuthorityService using Google Cloud CAS.
|
||||
CloudCAS = "CloudCAS"
|
||||
CloudCAS = "cloudcas"
|
||||
)
|
||||
|
||||
// String returns the given type as a string. All the letters will be lowercase.
|
||||
// String returns a string from the type. It will always return the lower case
|
||||
// version of the Type, as we need a standard type to compare and use as the
|
||||
// registry key.
|
||||
func (t Type) String() string {
|
||||
if t == "" {
|
||||
return SoftCAS
|
||||
}
|
||||
for _, s := range []string{SoftCAS, CloudCAS} {
|
||||
if strings.EqualFold(s, string(t)) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return string(t)
|
||||
return strings.ToLower(string(t))
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@ type caClient interface{}
|
|||
// New creates a new CertificateAuthorityService implementation using Google
|
||||
// Cloud CAS.
|
||||
func New(ctx context.Context, opts apiv1.Options) (*CloudCAS, error) {
|
||||
if opts.Certificateauthority == "" {
|
||||
return nil, errors.New("cloudCAS 'certificateAuthority' cannot be empty")
|
||||
}
|
||||
|
||||
var cloudOpts []option.ClientOption
|
||||
if opts.CredentialsFile != "" {
|
||||
cloudOpts = append(cloudOpts, option.WithCredentialsFile(opts.CredentialsFile))
|
||||
|
@ -57,7 +61,7 @@ func New(ctx context.Context, opts apiv1.Options) (*CloudCAS, error) {
|
|||
|
||||
return &CloudCAS{
|
||||
client: client,
|
||||
certificateAuthority: "projects/smallstep-cas-test/locations/us-west1/certificateAuthorities/Smallstep-Test-Intermediate-CA",
|
||||
certificateAuthority: opts.Certificateauthority,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -87,9 +91,9 @@ func (c *CloudCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv
|
|||
func (c *CloudCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.RenewCertificateResponse, error) {
|
||||
switch {
|
||||
case req.Template == nil:
|
||||
return nil, errors.New("renewCertificate `template` cannot be nil")
|
||||
return nil, errors.New("renewCertificateRequest `template` cannot be nil")
|
||||
case req.Lifetime == 0:
|
||||
return nil, errors.New("renewCertificate `lifetime` cannot be 0")
|
||||
return nil, errors.New("renewCertificateRequest `lifetime` cannot be 0")
|
||||
}
|
||||
|
||||
cert, chain, err := c.createCertificate(req.Template, req.Lifetime, req.RequestID)
|
||||
|
@ -106,7 +110,7 @@ func (c *CloudCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.
|
|||
// RevokeCertificate a certificate using Google Cloud CAS.
|
||||
func (c *CloudCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) {
|
||||
if req.Certificate == nil {
|
||||
return nil, errors.New("revokeCertificate `certificate` cannot be nil")
|
||||
return nil, errors.New("revokeCertificateRequest `certificate` cannot be nil")
|
||||
}
|
||||
|
||||
ext, ok := apiv1.FindCertificateAuthorityExtension(req.Certificate)
|
||||
|
|
|
@ -2,8 +2,11 @@ package softcas
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/smallstep/certificates/cas/apiv1"
|
||||
"go.step.sm/crypto/x509util"
|
||||
|
@ -15,19 +18,47 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
// SoftCAS implements a Certificate Authority Service using Golang crypto.
|
||||
// This is the default CAS used in step-ca.
|
||||
type SoftCAS struct{}
|
||||
|
||||
// New creates a new CertificateAuthorityService implementation using Golang
|
||||
// crypto.
|
||||
func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) {
|
||||
return &SoftCAS{}, nil
|
||||
var now = func() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// CreateCertificate signs a new certificate using Golang crypto.
|
||||
// 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
|
||||
}
|
||||
|
||||
// New creates a new CertificateAuthorityService implementation using Golang or KMS
|
||||
// crypto.
|
||||
func New(ctx context.Context, opts apiv1.Options) (*SoftCAS, error) {
|
||||
switch {
|
||||
case opts.Issuer == nil:
|
||||
return nil, errors.New("softCAS 'issuer' cannot be nil")
|
||||
case opts.Signer == nil:
|
||||
return nil, errors.New("softCAS 'signer' cannot be nil")
|
||||
}
|
||||
return &SoftCAS{
|
||||
Issuer: opts.Issuer,
|
||||
Signer: opts.Signer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateCertificate signs a new certificate using Golang or KMS crypto.
|
||||
func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1.CreateCertificateResponse, error) {
|
||||
cert, err := x509util.CreateCertificate(req.Template, req.Issuer, req.Template.PublicKey, req.Signer)
|
||||
switch {
|
||||
case req.Template == nil:
|
||||
return nil, errors.New("createCertificateRequest `template` cannot be nil")
|
||||
case req.Lifetime == 0:
|
||||
return nil, errors.New("createCertificateRequest `lifetime` cannot be 0")
|
||||
}
|
||||
|
||||
t := now()
|
||||
req.Template.NotBefore = t.Add(-1 * req.Backdate)
|
||||
req.Template.NotAfter = t.Add(req.Lifetime)
|
||||
req.Template.Issuer = c.Issuer.Subject
|
||||
|
||||
cert, err := x509util.CreateCertificate(req.Template, c.Issuer, req.Template.PublicKey, c.Signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,13 +66,36 @@ func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
|
|||
return &apiv1.CreateCertificateResponse{
|
||||
Certificate: cert,
|
||||
CertificateChain: []*x509.Certificate{
|
||||
req.Issuer,
|
||||
c.Issuer,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RenewCertificate signs the given certificate template using Golang or KMS crypto.
|
||||
func (c *SoftCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.RenewCertificateResponse, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
switch {
|
||||
case req.Template == nil:
|
||||
return nil, errors.New("createCertificateRequest `template` cannot be nil")
|
||||
case req.Lifetime == 0:
|
||||
return nil, errors.New("createCertificateRequest `lifetime` cannot be 0")
|
||||
}
|
||||
|
||||
t := now()
|
||||
req.Template.NotBefore = t.Add(-1 * req.Backdate)
|
||||
req.Template.NotAfter = t.Add(req.Lifetime)
|
||||
req.Template.Issuer = c.Issuer.Subject
|
||||
|
||||
cert, err := x509util.CreateCertificate(req.Template, c.Issuer, req.Template.PublicKey, c.Signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &apiv1.RenewCertificateResponse{
|
||||
Certificate: cert,
|
||||
CertificateChain: []*x509.Certificate{
|
||||
c.Issuer,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RevokeCertificate revokes the given certificate in step-ca.
|
||||
|
|
Loading…
Add table
Reference in a new issue