Set SCEP authority options once

pull/1553/head
Herman Slatman 8 months ago
parent 15c46ebbaa
commit 4dc5a688fd
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -62,10 +62,9 @@ type Authority struct {
x509Enforcers []provisioner.CertificateEnforcer x509Enforcers []provisioner.CertificateEnforcer
// SCEP CA // SCEP CA
scepAuthority *scep.Authority scepOptions *scep.Options
scepCertificate *x509.Certificate validateSCEP bool
scepSigner crypto.Signer scepAuthority *scep.Authority
scepDecrypter crypto.Decrypter
// SSH CA // SSH CA
sshHostPassword []byte sshHostPassword []byte
@ -126,6 +125,7 @@ func New(cfg *config.Config, opts ...Option) (*Authority, error) {
var a = &Authority{ var a = &Authority{
config: cfg, config: cfg,
certificates: new(sync.Map), certificates: new(sync.Map),
validateSCEP: true,
} }
// Apply options. // Apply options.
@ -674,15 +674,12 @@ func (a *Authority) init() error {
// update that. // update that.
switch { switch {
case a.requiresSCEP() && a.GetSCEP() == nil: case a.requiresSCEP() && a.GetSCEP() == nil:
var options scep.Options if a.scepOptions == nil {
options.Roots = a.rootX509Certs options := &scep.Options{
options.Intermediates = a.intermediateX509Certs Roots: a.rootX509Certs,
options.SignerCert = options.Intermediates[0] Intermediates: a.intermediateX509Certs,
if a.scepSigner != nil { SignerCert: a.intermediateX509Certs[0],
options.Signer = a.scepSigner }
options.Decrypter = a.scepDecrypter
options.DecrypterCert = a.scepCertificate
} else {
if options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{ if options.Signer, err = a.keyManager.CreateSigner(&kmsapi.CreateSignerRequest{
SigningKey: a.config.IntermediateKey, SigningKey: a.config.IntermediateKey,
Password: a.password, Password: a.password,
@ -709,21 +706,25 @@ func (a *Authority) init() error {
options.DecrypterCert = options.Intermediates[0] options.DecrypterCert = options.Intermediates[0]
} }
} }
}
// provide the current SCEP provisioner names, so that the provisioners // provide the current SCEP provisioner names, so that the provisioners
// can be validated when the CA is started. // can be validated when the CA is started.
options.SCEPProvisionerNames = a.getSCEPProvisionerNames() options.SCEPProvisionerNames = a.getSCEPProvisionerNames()
a.scepOptions = options
}
// create a new SCEP authority // create a new SCEP authority
scepAuthority, err := scep.New(a, options) scepAuthority, err := scep.New(a, *a.scepOptions)
if err != nil { if err != nil {
return err return err
} }
// validate the SCEP authority if a.validateSCEP {
if err := scepAuthority.Validate(); err != nil { // validate the SCEP authority
a.initLogf("failed validating SCEP authority: %v", err) if err := scepAuthority.Validate(); err != nil {
a.initLogf("failed validating SCEP authority: %v", err)
}
} }
// set the SCEP authority // set the SCEP authority

@ -18,6 +18,7 @@ import (
"github.com/smallstep/certificates/cas" "github.com/smallstep/certificates/cas"
casapi "github.com/smallstep/certificates/cas/apiv1" casapi "github.com/smallstep/certificates/cas/apiv1"
"github.com/smallstep/certificates/db" "github.com/smallstep/certificates/db"
"github.com/smallstep/certificates/scep"
) )
// Option sets options to the Authority. // Option sets options to the Authority.
@ -205,11 +206,19 @@ func WithX509SignerFunc(fn func() ([]*x509.Certificate, crypto.Signer, error)) O
} }
} }
func WithSCEPOptions(crt *x509.Certificate, s crypto.Signer, d crypto.Decrypter) Option { // func WithSCEPOptions(crt *x509.Certificate, s crypto.Signer, d crypto.Decrypter) Option {
// return func(a *Authority) error {
// a.scepCertificate = crt
// a.scepSigner = s
// a.scepDecrypter = d
// return nil
// }
// }
func WithFullSCEPOptions(options *scep.Options) Option {
return func(a *Authority) error { return func(a *Authority) error {
a.scepCertificate = crt a.scepOptions = options
a.scepSigner = s a.validateSCEP = false
a.scepDecrypter = d
return nil return nil
} }
} }

@ -83,10 +83,7 @@ func New(signAuth SignAuthority, opts Options) (*Authority, error) {
// The validation includes a check if a decrypter is available, either // The validation includes a check if a decrypter is available, either
// an authority wide decrypter, or a provisioner specific decrypter. // an authority wide decrypter, or a provisioner specific decrypter.
func (a *Authority) Validate() error { func (a *Authority) Validate() error {
// TODO(hs): don't return early if a == nil {
return nil //nolint:revive // validation temporarily disabled
if a == nil { //nolint:govet // validation temporarily disabled
return nil return nil
} }

@ -2,6 +2,7 @@ package scep
import ( import (
"crypto" "crypto"
"crypto/rsa"
"crypto/x509" "crypto/x509"
"errors" "errors"
) )
@ -56,28 +57,27 @@ func (o *Options) Validate() error {
return nil return nil
} }
// TODO(hs): reenable this validation // If a decrypter is available, check that it's backed by an RSA key. According to the
// // If a decrypter is available, check that it's backed by an RSA key. According to the // RFC: https://tools.ietf.org/html/rfc8894#section-3.1, SCEP can be used with something
// // RFC: https://tools.ietf.org/html/rfc8894#section-3.1, SCEP can be used with something // different than RSA, but requires the encryption to be performed using the challenge
// // different than RSA, but requires the encryption to be performed using the challenge // password in that case. An older version of specification states that only RSA is
// // password in that case. An older version of specification states that only RSA is // supported: https://tools.ietf.org/html/draft-nourse-scep-23#section-2.1.1. Other
// // supported: https://tools.ietf.org/html/draft-nourse-scep-23#section-2.1.1. Other // algorithms do not seem to be supported in certnanny/sscep, but it might work
// // algorithms do not seem to be supported in certnanny/sscep, but it might work // in micromdm/scep. Currently only RSA is allowed, but it might be an option
// // in micromdm/scep. Currently only RSA is allowed, but it might be an option // to try other algorithms in the future.
// // to try other algorithms in the future. decrypterPublicKey, ok := o.Decrypter.Public().(*rsa.PublicKey)
// decrypterPublicKey, ok := o.Decrypter.Public().(*rsa.PublicKey) if !ok {
// if !ok { return errors.New("only RSA keys are (currently) supported as decrypters")
// return errors.New("only RSA keys are (currently) supported as decrypters") }
// }
// // check if intermediate public key is the same as the decrypter public key. // check if intermediate public key is the same as the decrypter public key.
// // In certnanny/sscep it's mentioned that the signing key can be different // In certnanny/sscep it's mentioned that the signing key can be different
// // from the decrypting (and encrypting) key. These options are only used and // from the decrypting (and encrypting) key. These options are only used and
// // validated when the intermediate CA is also used as the decrypter, though, // validated when the intermediate CA is also used as the decrypter, though,
// // so they should match. // so they should match.
// if !decrypterPublicKey.Equal(o.SignerCert.PublicKey) { if !decrypterPublicKey.Equal(o.SignerCert.PublicKey) {
// return errors.New("mismatch between certificate chain and decrypter public keys") return errors.New("mismatch between certificate chain and decrypter public keys")
// } }
return nil return nil
} }

Loading…
Cancel
Save