From b815478981c2c062096834717c17c1f300aa1278 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Fri, 26 Mar 2021 15:44:45 +0100 Subject: [PATCH] Make serving SCEP endpoints optional Only when a SCEP provisioner is enabled, the SCEP endpoints will now be available. The SCEP endpoints will be served on an "insecure" server, without TLS, only when an additional "insecureAddress" and a SCEP provisioner are configured for the CA. --- authority/authority.go | 2 ++ ca/ca.go | 72 ++++++++++++++++++++++++++---------------- scep/scep.go | 1 - 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/authority/authority.go b/authority/authority.go index e5b62602..a2dca6e0 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -440,6 +440,8 @@ func (a *Authority) CloseForReload() { // requiresDecrypter returns whether the Authority // requires a KMS that provides a crypto.Decrypter +// Currently this is only required when SCEP is +// enabled. func (a *Authority) requiresDecrypter() bool { return a.requiresSCEPService() } diff --git a/ca/ca.go b/ca/ca.go index b6b1fc7f..84545f57 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -115,6 +115,7 @@ func (ca *CA) Init(config *authority.Config) (*CA, error) { if err != nil { return nil, err } + ca.auth = auth tlsConfig, err := ca.getTLSConfig(auth) if err != nil { @@ -166,29 +167,35 @@ func (ca *CA) Init(config *authority.Config) (*CA, error) { acmeRouterHandler.Route(r) }) - scepPrefix := "scep" - scepAuthority, err := scep.New(auth, scep.AuthorityOptions{ - Service: auth.GetSCEPService(), - DNS: dns, - Prefix: scepPrefix, - }) - if err != nil { - return nil, errors.Wrap(err, "error creating SCEP authority") - } - scepRouterHandler := scepAPI.New(scepAuthority) - mux.Route("/"+scepPrefix, func(r chi.Router) { - scepRouterHandler.Route(r) - }) + if ca.shouldServeSCEPEndpoints() { + scepPrefix := "scep" + scepAuthority, err := scep.New(auth, scep.AuthorityOptions{ + Service: auth.GetSCEPService(), + DNS: dns, + Prefix: scepPrefix, + }) + if err != nil { + return nil, errors.Wrap(err, "error creating SCEP authority") + } + scepRouterHandler := scepAPI.New(scepAuthority) - // According to the RFC (https://tools.ietf.org/html/rfc8894#section-7.10), - // SCEP operations are performed using HTTP, so that's why the API is mounted - // to the insecure mux. To my current understanding there's no strong reason - // to not use HTTPS also, so that's why I've kept the API endpoints in both - // muxes and both HTTP as well as HTTPS can be used to request certificates - // using SCEP. - insecureMux.Route("/"+scepPrefix, func(r chi.Router) { - scepRouterHandler.Route(r) - }) + // According to the RFC (https://tools.ietf.org/html/rfc8894#section-7.10), + // SCEP operations are performed using HTTP, so that's why the API is mounted + // to the insecure mux. + insecureMux.Route("/"+scepPrefix, func(r chi.Router) { + scepRouterHandler.Route(r) + }) + + // The RFC also mentions usage of HTTPS, but seems to advise + // against it, because of potential interoperability issues. + // Currently I think it's not bad to use HTTPS also, so that's + // why I've kept the API endpoints in both muxes and both HTTP + // as well as HTTPS can be used to request certificates + // using SCEP. + mux.Route("/"+scepPrefix, func(r chi.Router) { + scepRouterHandler.Route(r) + }) + } // helpful routine for logging all routes //dumpRoutes(mux) @@ -213,14 +220,15 @@ func (ca *CA) Init(config *authority.Config) (*CA, error) { insecureHandler = logger.Middleware(insecureHandler) } - ca.auth = auth ca.srv = server.New(config.Address, handler, tlsConfig) - // TODO: instead opt for having a single server.Server but two - // http.Servers handling the HTTP and HTTPS handler? The latter - // will probably introduce more complexity in terms of graceful - // reload. - if config.InsecureAddress != "" { + // only start the insecure server if the insecure address is configured + // and, currently, also only when it should serve SCEP endpoints. + if ca.shouldServeSCEPEndpoints() && config.InsecureAddress != "" { + // TODO: instead opt for having a single server.Server but two + // http.Servers handling the HTTP and HTTPS handler? The latter + // will probably introduce more complexity in terms of graceful + // reload. ca.insecureSrv = server.New(config.InsecureAddress, insecureHandler, nil) } @@ -375,6 +383,14 @@ func (ca *CA) getTLSConfig(auth *authority.Authority) (*tls.Config, error) { return tlsConfig, nil } +// shouldMountSCEPEndpoints returns if the CA should be +// configured with endpoints for SCEP. This is assumed to be +// true if a SCEPService exists, which is true in case a +// SCEP provisioner was configured. +func (ca *CA) shouldServeSCEPEndpoints() bool { + return ca.auth.GetSCEPService() != nil +} + //nolint // ignore linters to allow keeping this function around for debugging func dumpRoutes(mux chi.Routes) { // helpful routine for logging all routes // diff --git a/scep/scep.go b/scep/scep.go index f56176d7..3323ac1d 100644 --- a/scep/scep.go +++ b/scep/scep.go @@ -33,7 +33,6 @@ var ( oidSCEPtransactionID = asn1.ObjectIdentifier{2, 16, 840, 1, 113733, 1, 9, 7} oidSCEPfailInfoText = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 24} //oidChallengePassword = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 7} - ) // PKIMessage defines the possible SCEP message types