From 491c2b8d939cdf09c9e7d7aec773dbc688fb8662 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Fri, 12 Mar 2021 15:49:39 +0100 Subject: [PATCH] Improve initialization of SCEP authority --- authority/authority.go | 8 +++++--- cas/apiv1/registry.go | 2 +- scep/authority.go | 23 +++++------------------ scep/service.go | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index 32d26470..67fccf53 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -347,10 +347,12 @@ func (a *Authority) init() error { } } - a.scepService = &scep.Service{ - Signer: options.Signer, - Decrypter: options.Decrypter, + a.scepService, err = scep.NewService(context.Background(), options) + if err != nil { + return err } + + // TODO: mimick the x509CAService GetCertificateAuthority here too? } // Read root certificates and store them in the certificates map. diff --git a/cas/apiv1/registry.go b/cas/apiv1/registry.go index b74103b7..5876e9d7 100644 --- a/cas/apiv1/registry.go +++ b/cas/apiv1/registry.go @@ -18,7 +18,7 @@ func Register(t Type, fn CertificateAuthorityServiceNewFunc) { registry.Store(t.String(), fn) } -// LoadCertificateAuthorityServiceNewFunc returns the function initialize a KayManager. +// LoadCertificateAuthorityServiceNewFunc returns the function to initialize a KeyManager. func LoadCertificateAuthorityServiceNewFunc(t Type) (CertificateAuthorityServiceNewFunc, bool) { v, ok := registry.Load(t.String()) if !ok { diff --git a/scep/authority.go b/scep/authority.go index 69d83554..03bd6919 100644 --- a/scep/authority.go +++ b/scep/authority.go @@ -11,8 +11,6 @@ import ( "github.com/smallstep/certificates/authority/provisioner" database "github.com/smallstep/certificates/db" - "go.step.sm/crypto/pemutil" - "github.com/smallstep/nosql" microx509util "github.com/micromdm/scep/crypto/x509util" @@ -59,10 +57,8 @@ type Authority struct { // AuthorityOptions required to create a new SCEP Authority. type AuthorityOptions struct { - IntermediateCertificatePath string - + // Service provides the SCEP functions to Authority Service Service - // Backdate Backdate provisioner.Duration // DB is the database used by nosql. @@ -96,21 +92,12 @@ func New(signAuth SignAuthority, ops AuthorityOptions) (*Authority, error) { } } - // TODO: the below is a bit similar as what happens in the core Authority class, which - // creates the full x509 service. However, those aren't accessible directly, which is - // why I reimplemented this (for now). There might be an alternative that I haven't - // found yet. - certificateChain, err := pemutil.ReadCertificateBundle(ops.IntermediateCertificatePath) - if err != nil { - return nil, err - } - return &Authority{ backdate: ops.Backdate, db: ops.DB, prefix: ops.Prefix, dns: ops.DNS, - intermediateCertificate: certificateChain[0], + intermediateCertificate: ops.Service.certificateChain[0], service: ops.Service, signAuth: signAuth, }, nil @@ -208,7 +195,7 @@ func (a *Authority) DecryptPKIEnvelope(ctx context.Context, msg *PKIMessage) err return err } - envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.Decrypter) + envelope, err := p7c.Decrypt(a.intermediateCertificate, a.service.decrypter) if err != nil { return err } @@ -351,7 +338,7 @@ func (a *Authority) SignCSR(ctx context.Context, csr *x509.CertificateRequest, m authCert := a.intermediateCertificate // sign the attributes - if err := signedData.AddSigner(authCert, a.service.Signer, config); err != nil { + if err := signedData.AddSigner(authCert, a.service.signer, config); err != nil { return nil, err } @@ -430,7 +417,7 @@ func (a *Authority) CreateFailureResponse(ctx context.Context, csr *x509.Certifi } // sign the attributes - if err := signedData.AddSigner(a.intermediateCertificate, a.service.Signer, config); err != nil { + if err := signedData.AddSigner(a.intermediateCertificate, a.service.signer, config); err != nil { return nil, err } diff --git a/scep/service.go b/scep/service.go index 1d743dd6..0b37716d 100644 --- a/scep/service.go +++ b/scep/service.go @@ -1,9 +1,36 @@ package scep -import "crypto" +import ( + "context" + "crypto" + "crypto/x509" + "strings" -// Service is a (temporary?) wrapper for signer/decrypters + "github.com/smallstep/certificates/cas/apiv1" +) + +// Service is a wrapper for crypto.Signer and crypto.Decrypter type Service struct { - Signer crypto.Signer - Decrypter crypto.Decrypter + certificateChain []*x509.Certificate + signer crypto.Signer + decrypter crypto.Decrypter +} + +func NewService(ctx context.Context, opts apiv1.Options) (*Service, error) { + + if err := opts.Validate(); err != nil { + return nil, err + } + + t := apiv1.Type(strings.ToLower(opts.Type)) + if t == apiv1.DefaultCAS { + t = apiv1.SoftCAS + } + + // TODO: should this become similar to the New CertificateAuthorityService as in x509CAService? + return &Service{ + chain: opts.CertificateChain, + signer: opts.Signer, + decrypter: opts.Decrypter, + }, nil }