From 2c33506a7df9e24f973386d4ee1c574b374eac65 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Sat, 26 Dec 2020 15:23:10 +0100 Subject: [PATCH 1/3] Basic auth: add metrics Signed-off-by: Julien Pivotto --- go.mod | 1 + https/tls_config.go | 11 +++++++---- https/tls_config_test.go | 4 ++-- https/users.go | 24 +++++++++++++++++++++--- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index fe792bbf..71f34dd2 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.14 require ( github.com/go-kit/kit v0.10.0 github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.7.1 github.com/prometheus/common v0.15.0 golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 gopkg.in/alecthomas/kingpin.v2 v2.2.6 diff --git a/https/tls_config.go b/https/tls_config.go index 192e5338..d2b09e4e 100644 --- a/https/tls_config.go +++ b/https/tls_config.go @@ -26,6 +26,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" config_util "github.com/prometheus/common/config" "gopkg.in/yaml.v2" ) @@ -176,18 +177,18 @@ func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { // Listen starts the server on the given address. Based on the file // tlsConfigPath, TLS or basic auth could be enabled. -func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error { +func Listen(server *http.Server, tlsConfigPath string, logger log.Logger, r prometheus.Registerer) error { listener, err := net.Listen("tcp", server.Addr) if err != nil { return err } defer listener.Close() - return Serve(listener, server, tlsConfigPath, logger) + return Serve(listener, server, tlsConfigPath, logger, r) } // Server starts the server on the given listener. Based on the file // tlsConfigPath, TLS or basic auth could be enabled. -func Serve(l net.Listener, server *http.Server, tlsConfigPath string, logger log.Logger) error { +func Serve(l net.Listener, server *http.Server, tlsConfigPath string, logger log.Logger, r prometheus.Registerer) error { if tlsConfigPath == "" { level.Info(logger).Log("msg", "TLS is disabled.", "http2", false) return server.Serve(l) @@ -202,11 +203,13 @@ func Serve(l net.Listener, server *http.Server, tlsConfigPath string, logger log if server.Handler != nil { handler = server.Handler } - server.Handler = &userAuthRoundtrip{ + urt := &userAuthRoundtrip{ tlsConfigPath: tlsConfigPath, logger: logger, handler: handler, } + urt.instrument(r) + server.Handler = urt c, err := getConfig(tlsConfigPath) if err != nil { diff --git a/https/tls_config_test.go b/https/tls_config_test.go index d815a206..35d67862 100644 --- a/https/tls_config_test.go +++ b/https/tls_config_test.go @@ -319,7 +319,7 @@ func TestConfigReloading(t *testing.T) { recordConnectionError(errors.New("Panic starting server")) } }() - err := Listen(server, badYAMLPath, testlogger) + err := Listen(server, badYAMLPath, testlogger, nil) recordConnectionError(err) }() @@ -391,7 +391,7 @@ func (test *TestInputs) Test(t *testing.T) { recordConnectionError(errors.New("Panic starting server")) } }() - err := Listen(server, test.YAMLConfigPath, testlogger) + err := Listen(server, test.YAMLConfigPath, testlogger, nil) recordConnectionError(err) }() diff --git a/https/users.go b/https/users.go index 317b0e4f..e090e2cb 100644 --- a/https/users.go +++ b/https/users.go @@ -17,6 +17,7 @@ import ( "net/http" "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" "golang.org/x/crypto/bcrypt" ) @@ -37,14 +38,30 @@ func validateUsers(configPath string) error { } type userAuthRoundtrip struct { - tlsConfigPath string - handler http.Handler - logger log.Logger + tlsConfigPath string + handler http.Handler + logger log.Logger + failuresCounter prometheus.Counter +} + +func (u *userAuthRoundtrip) instrument(r prometheus.Registerer) { + u.failuresCounter = prometheus.NewCounter( + prometheus.CounterOpts{ + Namespace: "prometheus_toolkit", + Subsystem: "https", + Name: "request_basic_authentication_failures_total", + Help: "Total number of requests rejected by basic authentication because of wrong username, password, or configuration.", + }, + ) + if r != nil { + r.MustRegister(u.failuresCounter) + } } func (u *userAuthRoundtrip) ServeHTTP(w http.ResponseWriter, r *http.Request) { c, err := getConfig(u.tlsConfigPath) if err != nil { + u.failuresCounter.Inc() u.logger.Log("msg", "Unable to parse configuration", "err", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return @@ -65,6 +82,7 @@ func (u *userAuthRoundtrip) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } + u.failuresCounter.Inc() w.Header().Set("WWW-Authenticate", "Basic") http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } From c6524150450da19308c1374313888902f69ff394 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Sun, 27 Dec 2020 12:23:11 +0100 Subject: [PATCH 2/3] Rename metric Signed-off-by: Julien Pivotto --- https/users.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/https/users.go b/https/users.go index e090e2cb..fc578917 100644 --- a/https/users.go +++ b/https/users.go @@ -48,8 +48,7 @@ func (u *userAuthRoundtrip) instrument(r prometheus.Registerer) { u.failuresCounter = prometheus.NewCounter( prometheus.CounterOpts{ Namespace: "prometheus_toolkit", - Subsystem: "https", - Name: "request_basic_authentication_failures_total", + Name: "http_request_basic_authentication_failures_total", Help: "Total number of requests rejected by basic authentication because of wrong username, password, or configuration.", }, ) From bd4485b1f0077239821a02942d340bc2cc4c86a4 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Tue, 29 Dec 2020 01:47:35 +0100 Subject: [PATCH 3/3] Rename metric Signed-off-by: Julien Pivotto --- https/users.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/https/users.go b/https/users.go index fc578917..fc5a1a10 100644 --- a/https/users.go +++ b/https/users.go @@ -48,7 +48,8 @@ func (u *userAuthRoundtrip) instrument(r prometheus.Registerer) { u.failuresCounter = prometheus.NewCounter( prometheus.CounterOpts{ Namespace: "prometheus_toolkit", - Name: "http_request_basic_authentication_failures_total", + Subsystem: "https", + Name: "basic_authentication_failures_total", Help: "Total number of requests rejected by basic authentication because of wrong username, password, or configuration.", }, )