|
@ -19,6 +19,7 @@ import ( |
|
|
"crypto/x509" |
|
|
"crypto/x509" |
|
|
"encoding/base64" |
|
|
"encoding/base64" |
|
|
"fmt" |
|
|
"fmt" |
|
|
|
|
|
"io/ioutil" |
|
|
"strings" |
|
|
"strings" |
|
|
|
|
|
|
|
|
"github.com/caddyserver/caddy/v2" |
|
|
"github.com/caddyserver/caddy/v2" |
|
@ -286,6 +287,12 @@ type ClientAuthentication struct { |
|
|
// these CAs will be rejected.
|
|
|
// these CAs will be rejected.
|
|
|
TrustedCACerts []string `json:"trusted_ca_certs,omitempty"` |
|
|
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
|
|
|
// A list of base64 DER-encoded client leaf certs
|
|
|
// to accept. If this list is not empty, client certs
|
|
|
// to accept. If this list is not empty, client certs
|
|
|
// which are not in this list will be rejected.
|
|
|
// 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
|
|
|
// `require_and_verify` | Require clients to present a valid certificate that is verified
|
|
|
//
|
|
|
//
|
|
|
// The default mode is `require_and_verify` if any
|
|
|
// The default mode is `require_and_verify` if any
|
|
|
// TrustedCACerts or TrustedLeafCerts are provided;
|
|
|
// TrustedCACerts or TrustedCACertPEMFiles or TrustedLeafCerts
|
|
|
// otherwise, the default mode is `require`.
|
|
|
// are provided; otherwise, the default mode is `require`.
|
|
|
Mode string `json:"mode,omitempty"` |
|
|
Mode string `json:"mode,omitempty"` |
|
|
|
|
|
|
|
|
// state established with the last call to ConfigureTLSConfig
|
|
|
// state established with the last call to ConfigureTLSConfig
|
|
@ -312,7 +319,10 @@ type ClientAuthentication struct { |
|
|
|
|
|
|
|
|
// Active returns true if clientauth has an actionable configuration.
|
|
|
// Active returns true if clientauth has an actionable configuration.
|
|
|
func (clientauth ClientAuthentication) Active() bool { |
|
|
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.
|
|
|
// ConfigureTLSConfig sets up cfg to enforce clientauth's configuration.
|
|
@ -339,7 +349,9 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
// otherwise, set a safe default mode
|
|
|
// 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 |
|
|
cfg.ClientAuth = tls.RequireAndVerifyClientCert |
|
|
} else { |
|
|
} else { |
|
|
cfg.ClientAuth = tls.RequireAnyClientCert |
|
|
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
|
|
|
// 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() |
|
|
caPool := x509.NewCertPool() |
|
|
for _, clientCAString := range clientauth.TrustedCACerts { |
|
|
for _, clientCAString := range clientauth.TrustedCACerts { |
|
|
clientCA, err := decodeBase64DERCert(clientCAString) |
|
|
clientCA, err := decodeBase64DERCert(clientCAString) |
|
@ -356,6 +368,13 @@ func (clientauth *ClientAuthentication) ConfigureTLSConfig(cfg *tls.Config) erro |
|
|
} |
|
|
} |
|
|
caPool.AddCert(clientCA) |
|
|
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 |
|
|
cfg.ClientCAs = caPool |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|