diff --git a/web/handler.go b/web/handler.go index 51da762c..fb88d174 100644 --- a/web/handler.go +++ b/web/handler.go @@ -37,14 +37,9 @@ var extraHTTPHeaders = map[string][]string{ "Content-Security-Policy": nil, } -func validateUsers(configPath string) error { - c, err := getConfig(configPath) - if err != nil { - return err - } - +func validateUsers(c *Config) error { for _, p := range c.Users { - _, err = bcrypt.Cost([]byte(p)) + _, err := bcrypt.Cost([]byte(p)) if err != nil { return err } @@ -77,6 +72,7 @@ HeadersLoop: type webHandler struct { tlsConfigPath string + config *Config handler http.Handler logger *slog.Logger cache *cache @@ -86,9 +82,23 @@ type webHandler struct { } func (u *webHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - c, err := getConfig(u.tlsConfigPath) + var c *Config + var err error + + if u.config == nil { + c, err = getConfig(u.tlsConfigPath) + if err != nil { + u.logger.Error("Unable to parse configuration", "err", err.Error()) + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + } else { + c = u.config + } + + err = ValidateWebConfig(c) if err != nil { - u.logger.Error("Unable to parse configuration", "err", err.Error()) + u.logger.Error("Invalid web configuration", "err", err.Error()) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } diff --git a/web/tls_config.go b/web/tls_config.go index 0730a938..1beeb6f2 100644 --- a/web/tls_config.go +++ b/web/tls_config.go @@ -64,7 +64,8 @@ type TLSConfig struct { type FlagConfig struct { WebListenAddresses *[]string WebSystemdSocket *bool - WebConfigFile *string + WebConfigFile *string // Optional: path to the TLS config file. Ether this or TLSConfig must be set. + WebConfig *Config // Optional: Configuration. If set, it overrides WebConfigFile. } // SetDirectory joins any relative file paths with dir. @@ -135,6 +136,11 @@ func getTLSConfig(configPath string) (*tls.Config, error) { if err != nil { return nil, err } + + if err := validateUsers(c); err != nil { + return nil, err + } + return ConfigToTLSConfig(&c.TLSConfig) } @@ -345,13 +351,28 @@ func parseVsockPort(address string) (uint32, error) { // WebConfigFile in the FlagConfig, TLS or basic auth could be enabled. func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger *slog.Logger) error { logger.Info("Listening on", "address", l.Addr().String()) - tlsConfigPath := *flags.WebConfigFile - if tlsConfigPath == "" { - logger.Info("TLS is disabled.", "http2", false, "address", l.Addr().String()) - return server.Serve(l) + var c *Config + var err error + + // WebConfig overrides WebConfigFile. If WebConfig field is not set, then WebConfigFile is used. + if flags.WebConfig == nil { + tlsConfigPath := *flags.WebConfigFile + if tlsConfigPath == "" { + logger.Info("TLS is disabled.", "http2", false, "address", l.Addr().String()) + return server.Serve(l) + } + + c, err = getConfig(tlsConfigPath) + if err != nil { + return err + } + } else { + // Use the provided config. + c = flags.WebConfig } - if err := validateUsers(tlsConfigPath); err != nil { + err = ValidateWebConfig(c) + if err != nil { return err } @@ -361,16 +382,11 @@ func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger *slog. handler = server.Handler } - c, err := getConfig(tlsConfigPath) - if err != nil { - return err - } - server.Handler = &webHandler{ - tlsConfigPath: tlsConfigPath, - logger: logger, - handler: handler, - cache: newCache(), + config: c, + logger: logger, + handler: handler, + cache: newCache(), } config, err := ConfigToTLSConfig(&c.TLSConfig) @@ -395,12 +411,29 @@ func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger *slog. // Set the GetConfigForClient method of the HTTPS server so that the config // and certs are reloaded on new connections. server.TLSConfig.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { - config, err := getTLSConfig(tlsConfigPath) - if err != nil { - return nil, err + var tlsConfig *tls.Config + var err error + // Config overrides WebConfigFile. If Config fiels is not set, then WebConfigFile is used. + if flags.WebConfig == nil { + tlsConfigPath := *flags.WebConfigFile + + tlsConfig, err = getTLSConfig(tlsConfigPath) + if err != nil { + return nil, err + } + } else { + err = ValidateWebConfig(flags.WebConfig) + if err != nil { + return nil, err + } + // Use the provided config. + tlsConfig, err = ConfigToTLSConfig(&flags.WebConfig.TLSConfig) + if err != nil { + return nil, err + } } - config.NextProtos = server.TLSConfig.NextProtos - return config, nil + tlsConfig.NextProtos = server.TLSConfig.NextProtos + return tlsConfig, nil } return server.ServeTLS(l, "", "") } @@ -410,13 +443,13 @@ func Validate(tlsConfigPath string) error { if tlsConfigPath == "" { return nil } - if err := validateUsers(tlsConfigPath); err != nil { - return err - } c, err := getConfig(tlsConfigPath) if err != nil { return err } + if err := validateUsers(c); err != nil { + return err + } _, err = ConfigToTLSConfig(&c.TLSConfig) if err == errNoTLSConfig { return nil @@ -424,6 +457,23 @@ func Validate(tlsConfigPath string) error { return err } +// ValidateWebConfig validates the web configuration, including the TLS config and HTTP headers. +func ValidateWebConfig(config *Config) error { + if config == nil { + return nil + } + if err := validateUsers(config); err != nil { + return err + } + if err := validateHeaderConfig(config.HTTPConfig.Header); err != nil { + return err + } + if _, err := ConfigToTLSConfig(&config.TLSConfig); err != nil && err != errNoTLSConfig { + return err + } + return nil +} + type Cipher uint16 func (c *Cipher) UnmarshalYAML(unmarshal func(interface{}) error) error { diff --git a/web/tls_config_test.go b/web/tls_config_test.go index b28c6671..064cefcd 100644 --- a/web/tls_config_test.go +++ b/web/tls_config_test.go @@ -30,6 +30,8 @@ import ( "sync" "testing" "time" + + "gopkg.in/yaml.v2" ) // Helpers for literal FlagConfig @@ -89,6 +91,7 @@ type TestInputs struct { Name string Server func() *http.Server YAMLConfigPath string + WebConfig bool ExpectedError *regexp.Regexp UseTLSClient bool ClientMaxTLSVersion uint16 @@ -106,6 +109,7 @@ func TestYAMLFiles(t *testing.T) { Name: `path to config yml invalid`, YAMLConfigPath: "somefile", ExpectedError: ErrorMap["No such file"], + WebConfig: false, }, { Name: `empty config yml`, @@ -196,6 +200,9 @@ func TestYAMLFiles(t *testing.T) { for _, testInputs := range testTables { t.Run("run/"+testInputs.Name, testInputs.Test) t.Run("validate/"+testInputs.Name, testInputs.TestValidate) + if testInputs.WebConfig { + t.Run("validateWebConfig/"+testInputs.Name, testInputs.TestValidateWebConfig) + } } } @@ -206,6 +213,10 @@ func TestServerBehaviour(t *testing.T) { YAMLConfigPath: "", ExpectedError: nil, }, + { + Name: `default client`, + ExpectedError: nil, + }, { Name: `empty string YAMLConfigPath and TLS client`, YAMLConfigPath: "", @@ -217,18 +228,38 @@ func TestServerBehaviour(t *testing.T) { YAMLConfigPath: "testdata/web_config_noAuth.good.yml", ExpectedError: ErrorMap["HTTP Request to HTTPS server"], }, + { + Name: `WebConfig: valid tls config and default client`, + YAMLConfigPath: "testdata/web_config_noAuth.good.yml", + WebConfig: true, + ExpectedError: ErrorMap["HTTP Request to HTTPS server"], + }, { Name: `valid tls config yml and tls client`, YAMLConfigPath: "testdata/web_config_noAuth.good.yml", UseTLSClient: true, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config and tls client`, + YAMLConfigPath: "testdata/web_config_noAuth.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: nil, + }, { Name: `valid tls config yml (cert and key inline) and tls client`, YAMLConfigPath: "testdata/web_config_noAuth_tlsInline.good.yml", UseTLSClient: true, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config (cert and key inline) and tls client`, + YAMLConfigPath: "testdata/web_config_noAuth_tlsInline.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: nil, + }, { Name: `valid tls config yml with TLS 1.1 client`, YAMLConfigPath: "testdata/web_config_noAuth.good.yml", @@ -236,12 +267,27 @@ func TestServerBehaviour(t *testing.T) { ClientMaxTLSVersion: tls.VersionTLS11, ExpectedError: ErrorMap["Incompatible TLS version"], }, + { + Name: `WebConfig: valid tls config with TLS 1.1 client`, + YAMLConfigPath: "testdata/web_config_noAuth.good.yml", + WebConfig: true, + UseTLSClient: true, + ClientMaxTLSVersion: tls.VersionTLS11, + ExpectedError: ErrorMap["Incompatible TLS version"], + }, { Name: `valid tls config yml with all ciphers`, YAMLConfigPath: "testdata/web_config_noAuth_allCiphers.good.yml", UseTLSClient: true, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with all ciphers`, + YAMLConfigPath: "testdata/web_config_noAuth_allCiphers.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: nil, + }, { Name: `valid tls config yml with some ciphers`, YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", @@ -249,6 +295,14 @@ func TestServerBehaviour(t *testing.T) { CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with some ciphers`, + YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", + WebConfig: true, + UseTLSClient: true, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + ExpectedError: nil, + }, { Name: `valid tls config yml with no common cipher`, YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", @@ -256,6 +310,14 @@ func TestServerBehaviour(t *testing.T) { CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, ExpectedError: ErrorMap["Handshake failure"], }, + { + Name: `WebConfig: valid tls config with no common cipher`, + YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", + WebConfig: true, + UseTLSClient: true, + CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, + ExpectedError: ErrorMap["Handshake failure"], + }, { Name: `valid tls config yml with multiple client ciphers`, YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", @@ -267,6 +329,18 @@ func TestServerBehaviour(t *testing.T) { ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with multiple client ciphers`, + YAMLConfigPath: "testdata/web_config_noAuth_someCiphers.good.yml", + WebConfig: true, + UseTLSClient: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + }, + ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + ExpectedError: nil, + }, { Name: `valid tls config yml with multiple client ciphers, client chooses cipher`, YAMLConfigPath: "testdata/web_config_noAuth_someCiphers_noOrder.good.yml", @@ -278,12 +352,31 @@ func TestServerBehaviour(t *testing.T) { ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with multiple client ciphers, client chooses cipher`, + YAMLConfigPath: "testdata/web_config_noAuth_someCiphers_noOrder.good.yml", + WebConfig: true, + UseTLSClient: true, + CipherSuites: []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + }, + ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + ExpectedError: nil, + }, { Name: `valid tls config yml with all curves`, YAMLConfigPath: "testdata/web_config_noAuth_allCurves.good.yml", UseTLSClient: true, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with all curves`, + YAMLConfigPath: "testdata/web_config_noAuth_allCurves.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: nil, + }, { Name: `valid tls config yml with some curves`, YAMLConfigPath: "testdata/web_config_noAuth_someCurves.good.yml", @@ -291,6 +384,14 @@ func TestServerBehaviour(t *testing.T) { CurvePreferences: []tls.CurveID{tls.CurveP521}, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with some curves`, + YAMLConfigPath: "testdata/web_config_noAuth_someCurves.good.yml", + WebConfig: true, + UseTLSClient: true, + CurvePreferences: []tls.CurveID{tls.CurveP521}, + ExpectedError: nil, + }, { Name: `valid tls config yml with no common curves`, YAMLConfigPath: "testdata/web_config_noAuth_someCurves.good.yml", @@ -298,37 +399,82 @@ func TestServerBehaviour(t *testing.T) { CurvePreferences: []tls.CurveID{tls.CurveP384}, ExpectedError: ErrorMap["Handshake failure"], }, + { + Name: `WebConfig: valid tls config with no common curves`, + YAMLConfigPath: "testdata/web_config_noAuth_someCurves.good.yml", + WebConfig: true, + UseTLSClient: true, + CurvePreferences: []tls.CurveID{tls.CurveP384}, + ExpectedError: ErrorMap["Handshake failure"], + }, { Name: `valid tls config yml with non-http2 ciphers`, YAMLConfigPath: "testdata/web_config_noAuth_noHTTP2.good.yml", UseTLSClient: true, ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config with non-http2 ciphers`, + YAMLConfigPath: "testdata/web_config_noAuth_noHTTP2.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: nil, + }, { Name: `valid tls config yml with non-http2 ciphers but http2 enabled`, YAMLConfigPath: "testdata/web_config_noAuth_noHTTP2Cipher.bad.yml", UseTLSClient: true, ExpectedError: ErrorMap["No HTTP2 cipher"], }, + { + Name: `WebConfig: valid tls config with non-http2 ciphers but http2 enabled`, + YAMLConfigPath: "testdata/web_config_noAuth_noHTTP2Cipher.bad.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: ErrorMap["No HTTP2 cipher"], + }, { Name: `valid headers config`, YAMLConfigPath: "testdata/web_config_headers.good.yml", }, + { + Name: `WebConfig: valid headers config`, + YAMLConfigPath: "testdata/web_config_headers.good.yml", + WebConfig: true, + }, { Name: `invalid X-Content-Type-Options headers config`, YAMLConfigPath: "testdata/web_config_headers_content_type_options.bad.yml", ExpectedError: ErrorMap["Invalid value"], }, + { + Name: `WebConfig: invalid X-Content-Type-Options headers config`, + YAMLConfigPath: "testdata/web_config_headers_content_type_options.bad.yml", + WebConfig: true, + ExpectedError: ErrorMap["Invalid value"], + }, { Name: `invalid X-Frame-Options headers config`, YAMLConfigPath: "testdata/web_config_headers_frame_options.bad.yml", ExpectedError: ErrorMap["Invalid value"], }, + { + Name: `WebConfig: invalid X-Frame-Options headers config`, + YAMLConfigPath: "testdata/web_config_headers_frame_options.bad.yml", + WebConfig: true, + ExpectedError: ErrorMap["Invalid value"], + }, { Name: `HTTP header that can not be overridden`, YAMLConfigPath: "testdata/web_config_headers_extra_header.bad.yml", ExpectedError: ErrorMap["Invalid header"], }, + { + Name: `WebConfig: HTTP header that can not be overridden`, + YAMLConfigPath: "testdata/web_config_headers_extra_header.bad.yml", + WebConfig: true, + ExpectedError: ErrorMap["Invalid header"], + }, { Name: `valid tls config yml and tls client with RequireAnyClientCert (present certificate)`, YAMLConfigPath: "testdata/tls_config_noAuth.requireanyclientcert.good.yml", @@ -336,6 +482,14 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client_selfsigned", ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config and tls client with RequireAnyClientCert (present certificate)`, + YAMLConfigPath: "testdata/tls_config_noAuth.requireanyclientcert.good.yml", + WebConfig: true, + UseTLSClient: true, + ClientCertificate: "client_selfsigned", + ExpectedError: nil, + }, { Name: `valid tls config yml (cert from file, key inline) and tls client with RequireAnyClientCert (present certificate)`, YAMLConfigPath: "testdata/tls_config_noAuth.requireanyclientcert.good.yml", @@ -343,6 +497,14 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client_selfsigned", ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config (cert from file, key inline) and tls client with RequireAnyClientCert (present certificate)`, + YAMLConfigPath: "testdata/tls_config_noAuth.requireanyclientcert.good.yml", + WebConfig: true, + UseTLSClient: true, + ClientCertificate: "client_selfsigned", + ExpectedError: nil, + }, { Name: `valid tls config yml and tls client with RequireAndVerifyClientCert (present certificate)`, YAMLConfigPath: "testdata/tls_config_noAuth.requireandverifyclientcert.good.yml", @@ -350,6 +512,14 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client_selfsigned", ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config and tls client with RequireAndVerifyClientCert (present certificate)`, + YAMLConfigPath: "testdata/tls_config_noAuth.requireandverifyclientcert.good.yml", + WebConfig: true, + UseTLSClient: true, + ClientCertificate: "client_selfsigned", + ExpectedError: nil, + }, { Name: `valid tls config yml and tls client with VerifyPeerCertificate (present good SAN DNS entry)`, YAMLConfigPath: "testdata/web_config_auth_client_san.good.yaml", @@ -357,6 +527,14 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client2_selfsigned", ExpectedError: nil, }, + { + Name: `WebConfig: valid tls config and tls client with VerifyPeerCertificate (present good SAN DNS entry)`, + YAMLConfigPath: "testdata/web_config_auth_client_san.good.yaml", + WebConfig: true, + UseTLSClient: true, + ClientCertificate: "client2_selfsigned", + ExpectedError: nil, + }, { Name: `valid tls config yml and tls client with VerifyPeerCertificate (present invalid SAN DNS entries)`, YAMLConfigPath: "testdata/web_config_auth_client_san.bad.yaml", @@ -364,6 +542,14 @@ func TestServerBehaviour(t *testing.T) { ClientCertificate: "client2_selfsigned", ExpectedError: ErrorMap["Invalid client cert"], }, + { + Name: `WebConfig: valid tls config and tls client with VerifyPeerCertificate (present invalid SAN DNS entries)`, + YAMLConfigPath: "testdata/web_config_auth_client_san.bad.yaml", + WebConfig: true, + UseTLSClient: true, + ClientCertificate: "client2_selfsigned", + ExpectedError: ErrorMap["Invalid client cert"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test) @@ -480,7 +666,15 @@ func (test *TestInputs) Test(t *testing.T) { flags := FlagConfig{ WebListenAddresses: &([]string{port}), WebSystemdSocket: OfBool(false), - WebConfigFile: &test.YAMLConfigPath, + } + if test.WebConfig { + webConfig, err := getConfig(test.YAMLConfigPath) + if err != nil { + recordConnectionError(errors.New(fmt.Sprintf("Could not parse configuration: %v", err))) + } + flags.WebConfig = webConfig + } else { + flags.WebConfigFile = &test.YAMLConfigPath } err := ListenAndServe(server, &flags, testlogger) recordConnectionError(err) @@ -572,6 +766,39 @@ func (test *TestInputs) TestValidate(t *testing.T) { } } +func (test *TestInputs) TestValidateWebConfig(t *testing.T) { + content, err := os.ReadFile(test.YAMLConfigPath) + if err != nil { + t.Fatalf("Could not read configuration file: %v", err) + } + c := &Config{ + TLSConfig: TLSConfig{ + MinVersion: tls.VersionTLS12, + MaxVersion: tls.VersionTLS13, + PreferServerCipherSuites: true, + }, + HTTPConfig: HTTPConfig{HTTP2: true}, + } + err = yaml.UnmarshalStrict(content, c) + if err != nil { + t.Fatalf("Could not parse configuration: %v", err) + } + validationErr := ValidateWebConfig(c) + if test.ExpectedError == nil { + if validationErr != nil { + t.Errorf("Expected no error, got error: %v", validationErr) + } + return + } + if validationErr == nil { + t.Errorf("Got no error, expected: %v", test.ExpectedError) + return + } + if !test.ExpectedError.MatchString(validationErr.Error()) { + t.Errorf("Expected error %v, got error: %v", test.ExpectedError, validationErr) + } +} + func (test *TestInputs) isCorrectError(returnedError error) bool { switch { case returnedError == nil && test.ExpectedError == nil: @@ -643,6 +870,12 @@ func TestUsers(t *testing.T) { YAMLConfigPath: "testdata/web_config_users_noTLS.good.yml", ExpectedError: ErrorMap["Unauthorized"], }, + { + Name: `WebConfig: without basic auth`, + YAMLConfigPath: "testdata/web_config_users_noTLS.good.yml", + WebConfig: true, + ExpectedError: ErrorMap["Unauthorized"], + }, { Name: `with correct basic auth`, YAMLConfigPath: "testdata/web_config_users_noTLS.good.yml", @@ -650,12 +883,27 @@ func TestUsers(t *testing.T) { Password: "dave123", ExpectedError: nil, }, + { + Name: `WebConfig: with correct basic auth`, + YAMLConfigPath: "testdata/web_config_users_noTLS.good.yml", + WebConfig: true, + Username: "dave", + Password: "dave123", + ExpectedError: nil, + }, { Name: `without basic auth and TLS`, YAMLConfigPath: "testdata/web_config_users.good.yml", UseTLSClient: true, ExpectedError: ErrorMap["Unauthorized"], }, + { + Name: `WebConfig: without basic auth and TLS`, + YAMLConfigPath: "testdata/web_config_users.good.yml", + WebConfig: true, + UseTLSClient: true, + ExpectedError: ErrorMap["Unauthorized"], + }, { Name: `with correct basic auth and TLS`, YAMLConfigPath: "testdata/web_config_users.good.yml", @@ -664,6 +912,15 @@ func TestUsers(t *testing.T) { Password: "dave123", ExpectedError: nil, }, + { + Name: `WebConfig: with correct basic auth and TLS`, + YAMLConfigPath: "testdata/web_config_users.good.yml", + WebConfig: true, + UseTLSClient: true, + Username: "dave", + Password: "dave123", + ExpectedError: nil, + }, { Name: `with another correct basic auth and TLS`, YAMLConfigPath: "testdata/web_config_users.good.yml", @@ -672,6 +929,15 @@ func TestUsers(t *testing.T) { Password: "carol123", ExpectedError: nil, }, + { + Name: `WebConfig: with another correct basic auth and TLS`, + YAMLConfigPath: "testdata/web_config_users.good.yml", + WebConfig: true, + UseTLSClient: true, + Username: "carol", + Password: "carol123", + ExpectedError: nil, + }, { Name: `with bad password and TLS`, YAMLConfigPath: "testdata/web_config_users.good.yml", @@ -680,6 +946,15 @@ func TestUsers(t *testing.T) { Password: "bad", ExpectedError: ErrorMap["Unauthorized"], }, + { + Name: `WebConfig: with bad password and TLS`, + YAMLConfigPath: "testdata/web_config_users.good.yml", + WebConfig: true, + UseTLSClient: true, + Username: "dave", + Password: "bad", + ExpectedError: ErrorMap["Unauthorized"], + }, { Name: `with bad username and TLS`, YAMLConfigPath: "testdata/web_config_users.good.yml", @@ -688,6 +963,15 @@ func TestUsers(t *testing.T) { Password: "nonexistent", ExpectedError: ErrorMap["Unauthorized"], }, + { + Name: `WebConfig: with bad username and TLS`, + YAMLConfigPath: "testdata/web_config_users.good.yml", + WebConfig: true, + UseTLSClient: true, + Username: "nonexistent", + Password: "nonexistent", + ExpectedError: ErrorMap["Unauthorized"], + }, } for _, testInputs := range testTables { t.Run(testInputs.Name, testInputs.Test)