From b0f8fc7aaecb9ffc40d75df2a5a114bec3b50c10 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Wed, 25 Nov 2020 10:53:00 -0700 Subject: caddytls: Configure trusted CAs from PEM files (#3882) Closes #3563 --- modules/caddytls/connpolicy.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'modules/caddytls') diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index de929cc..ebf96e6 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -19,6 +19,7 @@ import ( "crypto/x509" "encoding/base64" "fmt" + "io/ioutil" "strings" "github.com/caddyserver/caddy/v2" @@ -286,6 +287,12 @@ type ClientAuthentication struct { // these CAs will be rejected. TrustedCACerts []string `json:"trusted_ca_certs,omitempty"` + // TrustedCACertPEMFiles is a list of PEM file names + // from which to load certificates of trusted CAs. + // Client certificates which are not signed by any of + // these CA certificates will be rejected. + TrustedCACertPEMFiles []string `json:"trusted_ca_certs_pem_files,omitempty"` + // A list of base64 DER-encoded client leaf certs // to accept. If this list is not empty, client certs // which are not in this list will be rejected. @@ -301,8 +308,8 @@ type ClientAuthentication struct { // `require_and_verify` | Require clients to present a valid certificate that is verified // // The default mode is `require_and_verify` if any - // TrustedCACerts or TrustedLeafCerts are provided; - // otherwise, the default mode is `require`. + // TrustedCACerts or TrustedCACertPEMFiles or TrustedLeafCerts + // are provided; otherwise, the default mode is `require`. Mode string `json:"mode,omitempty"` // state established with the last call to ConfigureTLSConfig @@ -312,7 +319,10 @@ type ClientAuthentication struct { // Active returns true if clientauth has an actionable configuration. func (clientauth ClientAuthentication) Active() bool { - return len(clientauth.TrustedCACerts) > 0 || len(clientauth.TrustedLeafCerts) > 0 || len(clientauth.Mode) > 0 + return len(clientauth.TrustedCACerts) > 0 || + len(clientauth.TrustedCACertPEMFiles) > 0 || + len(clientauth.TrustedLeafCerts) > 0 || + len(clientauth.Mode) > 0 } // ConfigureTLSConfig sets up cfg to enforce clientauth's configuration. @@ -339,7 +349,9 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro } } else { // otherwise, set a safe default mode - if len(clientauth.TrustedCACerts) > 0 || len(clientauth.TrustedLeafCerts) > 0 { + if len(clientauth.TrustedCACerts) > 0 || + len(clientauth.TrustedCACertPEMFiles) > 0 || + len(clientauth.TrustedLeafCerts) > 0 { cfg.ClientAuth = tls.RequireAndVerifyClientCert } else { cfg.ClientAuth = tls.RequireAnyClientCert @@ -347,7 +359,7 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro } // enforce CA verification by adding CA certs to the ClientCAs pool - if len(clientauth.TrustedCACerts) > 0 { + if len(clientauth.TrustedCACerts) > 0 || len(clientauth.TrustedCACertPEMFiles) > 0 { caPool := x509.NewCertPool() for _, clientCAString := range clientauth.TrustedCACerts { clientCA, err := decodeBase64DERCert(clientCAString) @@ -356,6 +368,13 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro } caPool.AddCert(clientCA) } + for _, pemFile := range clientauth.TrustedCACertPEMFiles { + pemContents, err := ioutil.ReadFile(pemFile) + if err != nil { + return fmt.Errorf("reading %s: %v", pemFile, err) + } + caPool.AppendCertsFromPEM(pemContents) + } cfg.ClientCAs = caPool } -- cgit v1.2.3