diff --git a/web/testdata/web_config_auth_client_common_name.bad.yaml b/web/testdata/web_config_auth_client_common_name.bad.yaml new file mode 100644 index 00000000..8ff979f3 --- /dev/null +++ b/web/testdata/web_config_auth_client_common_name.bad.yaml @@ -0,0 +1,6 @@ +tls_server_config: + cert_file: "server.crt" + key_file: "server.key" + client_auth_type: "RequireAndVerifyClientCert" + client_ca_file: "client_selfsigned.pem" + client_cert_allowed_cn: "bad" \ No newline at end of file diff --git a/web/testdata/web_config_auth_client_common_name.good.yaml b/web/testdata/web_config_auth_client_common_name.good.yaml new file mode 100644 index 00000000..54f636e2 --- /dev/null +++ b/web/testdata/web_config_auth_client_common_name.good.yaml @@ -0,0 +1,6 @@ +tls_server_config: + cert_file: "server.crt" + key_file: "server.key" + client_auth_type: "RequireAndVerifyClientCert" + client_ca_file: "client_selfsigned.pem" + client_cert_allowed_cn: "test" \ No newline at end of file diff --git a/web/tls_config.go b/web/tls_config.go index 328c5e0e..b97fd040 100644 --- a/web/tls_config.go +++ b/web/tls_config.go @@ -49,6 +49,7 @@ type TLSStruct struct { MinVersion tlsVersion `yaml:"min_version"` MaxVersion tlsVersion `yaml:"max_version"` PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"` + ClientCertAllowedCN string `yaml:"client_cert_allowed_cn"` } // SetDirectory joins any relative file paths with dir. @@ -155,6 +156,19 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { cfg.ClientCAs = clientCAPool } + if c.ClientCertAllowedCN != "" { + cfg.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + for _, chains := range verifiedChains { + if len(chains) != 0 { + if c.ClientCertAllowedCN == chains[0].Subject.CommonName { + return nil + } + } + } + return errors.New("CommonName authentication failed") + } + } + switch c.ClientAuth { case "RequestClientCert": cfg.ClientAuth = tls.RequestClientCert diff --git a/web/tls_config_test.go b/web/tls_config_test.go index 52f74676..9544a87c 100644 --- a/web/tls_config_test.go +++ b/web/tls_config_test.go @@ -57,6 +57,7 @@ var ( "Bad certificate": regexp.MustCompile(`bad certificate`), "Invalid value": regexp.MustCompile(`invalid value for`), "Invalid header": regexp.MustCompile(`HTTP header ".*" can not be configured`), + "Invalid common-name": regexp.MustCompile(`bad certificate`), } ) @@ -337,6 +338,20 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client2_selfsigned", ExpectedError: ErrorMap["Bad certificate"], }, + { + Name: `valid tls config yml and tls client with VerifyPeerCertificate (present good common-name)`, + YAMLConfigPath: "testdata/web_config_auth_client_common_name.good.yaml", + UseTLSClient: true, + ClientCertificate: "client_selfsigned", + ExpectedError: nil, + }, + { + Name: `valid tls config yml and tls client with VerifyPeerCertificate (present invalid common-name)`, + YAMLConfigPath: "testdata/web_config_auth_client_common_name.bad.yaml", + UseTLSClient: true, + ClientCertificate: "client_selfsigned", + ExpectedError: ErrorMap["Invalid common-name"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test)