From cfa5a75104d104547d18895e832033ec61e5fa26 Mon Sep 17 00:00:00 2001 From: Chris Hodges Date: Wed, 1 Feb 2023 05:12:21 +0000 Subject: [PATCH] change config to regex Signed-off-by: chodges15 --- .../web_config_auth_client_san_dns.good.yaml | 2 +- .../web_config_auth_client_san_dns_regex.bad.yaml | 6 ++++++ .../web_config_auth_client_san_dns_regex.good.yaml | 6 ++++++ web/tls_config.go | 12 +++++++----- web/tls_config_test.go | 14 ++++++++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 web/testdata/web_config_auth_client_san_dns_regex.bad.yaml create mode 100644 web/testdata/web_config_auth_client_san_dns_regex.good.yaml diff --git a/web/testdata/web_config_auth_client_san_dns.good.yaml b/web/testdata/web_config_auth_client_san_dns.good.yaml index 72425ae6..588664c6 100644 --- a/web/testdata/web_config_auth_client_san_dns.good.yaml +++ b/web/testdata/web_config_auth_client_san_dns.good.yaml @@ -3,4 +3,4 @@ tls_server_config: key_file: "server.key" client_auth_type: "RequireAndVerifyClientCert" client_ca_file: "client2_selfsigned.pem" - client_cert_allowed_san_dns: "test3" \ No newline at end of file + client_cert_allowed_san_dns: "test3" diff --git a/web/testdata/web_config_auth_client_san_dns_regex.bad.yaml b/web/testdata/web_config_auth_client_san_dns_regex.bad.yaml new file mode 100644 index 00000000..249da8c4 --- /dev/null +++ b/web/testdata/web_config_auth_client_san_dns_regex.bad.yaml @@ -0,0 +1,6 @@ +tls_server_config: + cert_file: "server.crt" + key_file: "server.key" + client_auth_type: "RequireAndVerifyClientCert" + client_ca_file: "client2_selfsigned.pem" + client_cert_allowed_san_dns: ".+test.+" \ No newline at end of file diff --git a/web/testdata/web_config_auth_client_san_dns_regex.good.yaml b/web/testdata/web_config_auth_client_san_dns_regex.good.yaml new file mode 100644 index 00000000..e7d7c7ca --- /dev/null +++ b/web/testdata/web_config_auth_client_san_dns_regex.good.yaml @@ -0,0 +1,6 @@ +tls_server_config: + cert_file: "server.crt" + key_file: "server.key" + client_auth_type: "RequireAndVerifyClientCert" + client_ca_file: "client2_selfsigned.pem" + client_cert_allowed_san_dns: (test\d|dns) diff --git a/web/tls_config.go b/web/tls_config.go index 3d47869b..d5f04bf1 100644 --- a/web/tls_config.go +++ b/web/tls_config.go @@ -22,6 +22,7 @@ import ( "net/http" "os" "path/filepath" + "regexp" "github.com/coreos/go-systemd/v22/activation" "github.com/go-kit/log" @@ -51,7 +52,8 @@ type TLSConfig struct { MinVersion TLSVersion `yaml:"min_version"` MaxVersion TLSVersion `yaml:"max_version"` PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` - ClientCertAllowedSanDNS string `yaml:"client_cert_allowed_san_dns"` + // regular expression to match the SAN DNS entries of the client cert + ClientCertAllowedSanDNSRegex string `yaml:"client_cert_allowed_san_dns"` } type FlagConfig struct { @@ -67,7 +69,7 @@ func (t *TLSConfig) SetDirectory(dir string) { t.ClientCAs = config_util.JoinDir(dir, t.ClientCAs) } -// VerifyPeerCertificate will check the DNS SAN entries of the client cert if there is configuration for +// VerifyPeerCertificate will check the DNS SAN entries of the client cert if there is configuration for it func (t *TLSConfig) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { // sender cert comes first, see https://www.rfc-editor.org/rfc/rfc5246#section-7.4.2 cert, err := x509.ParseCertificate(rawCerts[0]) @@ -76,12 +78,12 @@ func (t *TLSConfig) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][] } for _, san := range cert.DNSNames { - if san == t.ClientCertAllowedSanDNS { + if matched, _ := regexp.MatchString(t.ClientCertAllowedSanDNSRegex, san); matched { return nil } } - return fmt.Errorf("could not find configured SAN DNS in client cert: %s", t.ClientCertAllowedSanDNS) + return fmt.Errorf("could not find configured SAN DNS in client cert: %s", t.ClientCertAllowedSanDNSRegex) } type HTTPConfig struct { @@ -181,7 +183,7 @@ func ConfigToTLSConfig(c *TLSConfig) (*tls.Config, error) { cfg.ClientCAs = clientCAPool } - if c.ClientCertAllowedSanDNS != "" { + if c.ClientCertAllowedSanDNSRegex != "" { // verify that the client cert contains the allowed domain name cfg.VerifyPeerCertificate = c.VerifyPeerCertificate } diff --git a/web/tls_config_test.go b/web/tls_config_test.go index 08faba01..dcc60d37 100644 --- a/web/tls_config_test.go +++ b/web/tls_config_test.go @@ -362,6 +362,20 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client2_selfsigned", ExpectedError: ErrorMap["Invalid client cert"], }, + { + Name: `valid tls config yml and tls client with VerifyPeerCertificate (present SAN DNS entry that matches configured regex)`, + YAMLConfigPath: "testdata/web_config_auth_client_san_dns_regex.good.yaml", + UseTLSClient: true, + ClientCertificate: "client2_selfsigned", + ExpectedError: nil, + }, + { + Name: `valid tls config yml and tls client with VerifyPeerCertificate (present SAN DNS entry that does not match configured regex)`, + YAMLConfigPath: "testdata/web_config_auth_client_san_dns_regex.bad.yaml", + UseTLSClient: true, + ClientCertificate: "client2_selfsigned", + ExpectedError: ErrorMap["Invalid client cert"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test)