From 356528719610d72c1c517e2f3c5fb15caa8db0d2 Mon Sep 17 00:00:00 2001
From: Joel Takvorian <jtakvori@redhat.com>
Date: Mon, 6 Feb 2023 09:15:46 +0100
Subject: [PATCH] NETOBSERV-870 implement TokenReview

Requires operator PR to grant permission for TokenReviews

- 3 auth modes: check for cluster-admin, check for any user, no check
  (insecure; only for debugging/dev mode)
- add tests
- fix broken dev mode
---
 Makefile                                      |   2 +-
 cmd/plugin-backend.go                         |  14 +-
 go.mod                                        |   2 +-
 pkg/handler/auth/check_auth.go                |  66 ---
 pkg/handler/loki.go                           |   2 +-
 pkg/kubernetes/auth/check_auth.go             | 142 +++++
 pkg/kubernetes/auth/check_auth_test.go        | 207 +++++++
 pkg/kubernetes/client/client.go               |  38 ++
 pkg/server/routes.go                          |   2 +-
 pkg/server/server.go                          |   2 +-
 pkg/server/server_test.go                     |   4 +-
 .../prometheus/promhttp/delegator.go          | 368 -------------
 .../client_golang/prometheus/promhttp/http.go | 383 -------------
 .../prometheus/promhttp/instrument_client.go  | 235 --------
 .../prometheus/promhttp/instrument_server.go  | 517 ------------------
 .../prometheus/promhttp/option.go             |  31 --
 vendor/modules.txt                            |   1 -
 17 files changed, 406 insertions(+), 1610 deletions(-)
 delete mode 100644 pkg/handler/auth/check_auth.go
 create mode 100644 pkg/kubernetes/auth/check_auth.go
 create mode 100644 pkg/kubernetes/auth/check_auth_test.go
 create mode 100644 pkg/kubernetes/client/client.go
 delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
 delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
 delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
 delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
 delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go

diff --git a/Makefile b/Makefile
index 6aee16c72..cec8406d5 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ GOLANGCI_LINT_VERSION = v1.50.1
 COVERPROFILE = coverage.out
 NPM_INSTALL ?= install
 
-CMDLINE_ARGS ?= --loglevel trace --loki-tenant-id netobserv --frontend-config config/sample-frontend-config.yaml
+CMDLINE_ARGS ?= --loglevel trace --loki-tenant-id netobserv --frontend-config config/sample-frontend-config.yaml --auth-check none
 
 ifeq (,$(shell which podman 2>/dev/null))
 OCI_BIN ?= docker
diff --git a/cmd/plugin-backend.go b/cmd/plugin-backend.go
index 5775998fd..9e882423d 100644
--- a/cmd/plugin-backend.go
+++ b/cmd/plugin-backend.go
@@ -10,7 +10,7 @@ import (
 
 	"github.com/sirupsen/logrus"
 
-	"github.com/netobserv/network-observability-console-plugin/pkg/handler/auth"
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
 	"github.com/netobserv/network-observability-console-plugin/pkg/loki"
 	"github.com/netobserv/network-observability-console-plugin/pkg/server"
 )
@@ -39,6 +39,7 @@ var (
 	lokiMock             = flag.Bool("loki-mock", false, "Fake loki results using saved mocks")
 	logLevel             = flag.String("loglevel", "info", "log level (default: info)")
 	frontendConfig       = flag.String("frontend-config", "", "path to the console plugin config file")
+	authCheck            = flag.String("auth-check", "admin", "type of authentication check: authenticated, admin or none (default is admin)")
 	versionFlag          = flag.Bool("v", false, "print version")
 	log                  = logrus.WithField("module", "main")
 )
@@ -81,6 +82,15 @@ func main() {
 		log.Fatal("labels cannot be empty")
 	}
 
+	checkType := auth.CheckType(*authCheck)
+	if checkType == auth.CheckNone {
+		log.Warn("INSECURE: auth checker is disabled")
+	}
+	checker, err := auth.NewChecker(checkType)
+	if err != nil {
+		log.WithError(err).Fatal("auth checker error")
+	}
+
 	server.Start(&server.Config{
 		Port:             *port,
 		CertFile:         *cert,
@@ -91,5 +101,5 @@ func main() {
 		CORSMaxAge:       *corsMaxAge,
 		Loki:             loki.NewConfig(lURL, lStatusURL, *lokiTimeout, *lokiTenantID, *lokiTokenPath, *lokiForwardUserToken, *lokiSkipTLS, *lokiCAPath, *lokiMock, strings.Split(lLabels, ",")),
 		FrontendConfig:   *frontendConfig,
-	}, &auth.BearerTokenChecker{})
+	}, checker)
 }
diff --git a/go.mod b/go.mod
index a30e2f666..c1249ae1f 100644
--- a/go.mod
+++ b/go.mod
@@ -10,6 +10,7 @@ require (
 	github.com/sirupsen/logrus v1.8.1
 	github.com/stretchr/testify v1.8.0
 	gopkg.in/yaml.v3 v3.0.1
+	k8s.io/api v0.26.1
 	k8s.io/apimachinery v0.26.1
 	k8s.io/client-go v0.26.1
 )
@@ -48,7 +49,6 @@ require (
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
-	k8s.io/api v0.26.1 // indirect
 	k8s.io/klog/v2 v2.80.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
 	k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
diff --git a/pkg/handler/auth/check_auth.go b/pkg/handler/auth/check_auth.go
deleted file mode 100644
index cb4376289..000000000
--- a/pkg/handler/auth/check_auth.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package auth
-
-import (
-	"context"
-	"errors"
-	"net/http"
-	"strings"
-
-	"github.com/sirupsen/logrus"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/rest"
-)
-
-var hlog = logrus.WithField("module", "handler.auth")
-
-const AuthHeader = "Authorization"
-
-type Checker interface {
-	CheckAuth(ctx context.Context, header http.Header) error
-}
-
-type BearerTokenChecker struct {
-	Checker
-}
-
-func getUserToken(header http.Header) (string, error) {
-	authValue := header.Get(AuthHeader)
-	if authValue != "" {
-		parts := strings.Split(authValue, "Bearer ")
-		if len(parts) != 2 {
-			return "", errors.New("missing Bearer token in Authorization header")
-		}
-		return parts[1], nil
-	}
-	return "", errors.New("missing Authorization header")
-}
-
-func (b *BearerTokenChecker) CheckAuth(ctx context.Context, header http.Header) error {
-	hlog.Debug("Checking authenticated user")
-	token, err := getUserToken(header)
-	if err != nil {
-		return err
-	}
-	hlog.Debug("Checking auth: token found")
-	config, err := rest.InClusterConfig()
-	if err != nil {
-		return err
-	}
-	config.BearerToken = token
-	config.BearerTokenFile = ""
-
-	client, err := kubernetes.NewForConfig(config)
-	if err != nil {
-		return err
-	}
-	hlog.Debug("Checking auth: kube config created")
-
-	_, err = client.CoreV1().Namespaces().List(ctx, v1.ListOptions{})
-	if err != nil {
-		return err
-	}
-
-	hlog.Debug("Checking auth: passed")
-	return nil
-}
diff --git a/pkg/handler/loki.go b/pkg/handler/loki.go
index 02d716dc2..6b0c34038 100644
--- a/pkg/handler/loki.go
+++ b/pkg/handler/loki.go
@@ -12,9 +12,9 @@ import (
 	"github.com/sirupsen/logrus"
 	"gopkg.in/yaml.v3"
 
-	"github.com/netobserv/network-observability-console-plugin/pkg/handler/auth"
 	"github.com/netobserv/network-observability-console-plugin/pkg/handler/lokiclientmock"
 	"github.com/netobserv/network-observability-console-plugin/pkg/httpclient"
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
 	"github.com/netobserv/network-observability-console-plugin/pkg/loki"
 	"github.com/netobserv/network-observability-console-plugin/pkg/metrics"
 	"github.com/netobserv/network-observability-console-plugin/pkg/model"
diff --git a/pkg/kubernetes/auth/check_auth.go b/pkg/kubernetes/auth/check_auth.go
new file mode 100644
index 000000000..9a9f2fa0b
--- /dev/null
+++ b/pkg/kubernetes/auth/check_auth.go
@@ -0,0 +1,142 @@
+package auth
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/client"
+	"github.com/sirupsen/logrus"
+	authv1 "k8s.io/api/authentication/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var hlog = logrus.WithField("module", "handler.auth")
+
+type CheckType string
+
+const (
+	AuthHeader                   = "Authorization"
+	CheckAuthenticated CheckType = "authenticated"
+	CheckAdmin         CheckType = "admin"
+	CheckNone          CheckType = "none"
+)
+
+type Checker interface {
+	CheckAuth(ctx context.Context, header http.Header) error
+}
+
+func NewChecker(typez CheckType) (Checker, error) {
+	switch typez {
+	case CheckNone:
+		return &NoopChecker{}, nil
+	case CheckAuthenticated:
+		return &ValidBearerTokenChecker{apiProvider: client.NewInCluster}, nil
+	case CheckAdmin:
+		return &AdminBearerTokenChecker{apiProvider: client.NewInCluster}, nil
+	}
+	return nil, fmt.Errorf("auth checker type unknown: %s. Must be one of %s, %s, %s", typez, CheckAdmin, CheckAuthenticated, CheckNone)
+}
+
+type NoopChecker struct {
+	Checker
+}
+
+func (b *NoopChecker) CheckAuth(ctx context.Context, header http.Header) error {
+	hlog.Debug("noop auth checker: ignore auth")
+	return nil
+}
+
+func getUserToken(header http.Header) (string, error) {
+	authValue := header.Get(AuthHeader)
+	if authValue != "" {
+		parts := strings.Split(authValue, "Bearer ")
+		if len(parts) != 2 {
+			return "", errors.New("missing Bearer token in Authorization header")
+		}
+		return parts[1], nil
+	}
+	return "", errors.New("missing Authorization header")
+}
+
+func runTokenReview(ctx context.Context, apiProvider client.APIProvider, token string, preds []tokenReviewPredicate) error {
+	client, err := apiProvider()
+	if err != nil {
+		return err
+	}
+
+	rvw, err := client.CreateTokenReview(ctx, &authv1.TokenReview{
+		Spec: authv1.TokenReviewSpec{
+			Token: token,
+		},
+	}, &metav1.CreateOptions{})
+	if err != nil {
+		return err
+	}
+	for _, predFunc := range preds {
+		if err = predFunc(rvw); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+type tokenReviewPredicate func(*authv1.TokenReview) error
+
+func mustBeAuthenticated(rvw *authv1.TokenReview) error {
+	if !rvw.Status.Authenticated {
+		return errors.New("user not authenticated")
+	}
+	return nil
+}
+
+func mustBeClusterAdmin(rvw *authv1.TokenReview) error {
+	for _, group := range rvw.Status.User.Groups {
+		if group == "system:cluster-admins" {
+			return nil
+		}
+	}
+	return errors.New("user not in cluster-admins group")
+}
+
+type ValidBearerTokenChecker struct {
+	Checker
+	apiProvider client.APIProvider
+}
+
+func (c *ValidBearerTokenChecker) CheckAuth(ctx context.Context, header http.Header) error {
+	hlog.Debug("Checking authenticated user")
+	token, err := getUserToken(header)
+	if err != nil {
+		return err
+	}
+	hlog.Debug("Checking auth: token found")
+	if err = runTokenReview(ctx, c.apiProvider, token, []tokenReviewPredicate{mustBeAuthenticated}); err != nil {
+		return err
+	}
+
+	hlog.Debug("Checking auth: passed")
+	return nil
+}
+
+type AdminBearerTokenChecker struct {
+	Checker
+	apiProvider client.APIProvider
+}
+
+func (c *AdminBearerTokenChecker) CheckAuth(ctx context.Context, header http.Header) error {
+	hlog.Debug("Checking authenticated user")
+	token, err := getUserToken(header)
+	if err != nil {
+		return err
+	}
+	hlog.Debug("Checking auth: token found")
+	if err = runTokenReview(ctx, c.apiProvider, token, []tokenReviewPredicate{mustBeAuthenticated, mustBeClusterAdmin}); err != nil {
+		return err
+	}
+
+	hlog.Debug("Checking auth: passed")
+	return nil
+}
diff --git a/pkg/kubernetes/auth/check_auth_test.go b/pkg/kubernetes/auth/check_auth_test.go
new file mode 100644
index 000000000..975684910
--- /dev/null
+++ b/pkg/kubernetes/auth/check_auth_test.go
@@ -0,0 +1,207 @@
+package auth
+
+import (
+	"context"
+	"errors"
+	"net/http"
+	"testing"
+
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/client"
+	"github.com/stretchr/testify/mock"
+	"github.com/stretchr/testify/require"
+	authv1 "k8s.io/api/authentication/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestCheckAuth_NoAuth(t *testing.T) {
+	m := TokenReviewMock{}
+	m.mockNoAuth()
+
+	// Any user authenticated mode
+	checkAny := ValidBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err := checkAny.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkAny.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.Error(t, err)
+	require.Equal(t, "user not authenticated", err.Error())
+
+	// Admin mode
+	checkerAdmin := AdminBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.Error(t, err)
+	require.Equal(t, "user not authenticated", err.Error())
+
+	// Noop mode
+	checkerNoop := NoopChecker{}
+
+	// No header => success
+	err = checkerNoop.CheckAuth(context.TODO(), http.Header{})
+	require.NoError(t, err)
+}
+
+func TestCheckAuth_NormalUser(t *testing.T) {
+	m := TokenReviewMock{}
+	m.mockNormalUser()
+
+	// Any user authenticated mode
+	checkAny := ValidBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err := checkAny.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkAny.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.NoError(t, err)
+
+	// Admin mode
+	checkerAdmin := AdminBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.Error(t, err)
+	require.Equal(t, "user not in cluster-admins group", err.Error())
+
+	// Noop mode
+	checkerNoop := NoopChecker{}
+
+	// No header => success
+	err = checkerNoop.CheckAuth(context.TODO(), http.Header{})
+	require.NoError(t, err)
+}
+
+func TestCheckAuth_Admin(t *testing.T) {
+	m := TokenReviewMock{}
+	m.mockAdmin()
+
+	// Any user authenticated mode
+	checkAny := ValidBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err := checkAny.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkAny.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.NoError(t, err)
+
+	// Admin mode
+	checkerAdmin := AdminBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.NoError(t, err)
+
+	// Noop mode
+	checkerNoop := NoopChecker{}
+
+	// No header => success
+	err = checkerNoop.CheckAuth(context.TODO(), http.Header{})
+	require.NoError(t, err)
+}
+
+const fakeError = "an error occured"
+
+func TestCheckAuth_APIError(t *testing.T) {
+	m := TokenReviewMock{}
+	m.mockError()
+
+	// Any user authenticated mode
+	checkAny := ValidBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err := checkAny.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkAny.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.Error(t, err)
+	require.Equal(t, fakeError, err.Error())
+
+	// Admin mode
+	checkerAdmin := AdminBearerTokenChecker{apiProvider: func() (client.KubeAPI, error) { return &m, nil }}
+
+	// No header => fail
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{})
+	require.Error(t, err)
+	require.Equal(t, "missing Authorization header", err.Error())
+
+	err = checkerAdmin.CheckAuth(context.TODO(), http.Header{"Authorization": []string{"Bearer abcdef"}})
+	require.Error(t, err)
+	require.Equal(t, fakeError, err.Error())
+
+	// Noop mode
+	checkerNoop := NoopChecker{}
+
+	// No header => success
+	err = checkerNoop.CheckAuth(context.TODO(), http.Header{})
+	require.NoError(t, err)
+}
+
+type TokenReviewMock struct {
+	mock.Mock
+	client.KubeAPI
+}
+
+func (m *TokenReviewMock) CreateTokenReview(ctx context.Context, tr *authv1.TokenReview, opts *metav1.CreateOptions) (*authv1.TokenReview, error) {
+	args := m.Called(ctx, tr, opts)
+	return args.Get(0).(*authv1.TokenReview), args.Error(1)
+}
+
+func (m *TokenReviewMock) mockError() {
+	m.On("CreateTokenReview", mock.Anything, mock.Anything, mock.Anything).Return(&authv1.TokenReview{}, errors.New(fakeError))
+}
+
+func (m *TokenReviewMock) mockNoAuth() {
+	m.On("CreateTokenReview", mock.Anything, mock.Anything, mock.Anything).Return(&authv1.TokenReview{
+		Status: mockedTokenReviewStatus(false, true),
+	}, nil)
+}
+
+func (m *TokenReviewMock) mockNormalUser() {
+	m.On("CreateTokenReview", mock.Anything, mock.Anything, mock.Anything).Return(&authv1.TokenReview{
+		Status: mockedTokenReviewStatus(true, false),
+	}, nil)
+}
+
+func (m *TokenReviewMock) mockAdmin() {
+	m.On("CreateTokenReview", mock.Anything, mock.Anything, mock.Anything).Return(&authv1.TokenReview{
+		Status: mockedTokenReviewStatus(true, true),
+	}, nil)
+}
+
+func mockedTokenReviewStatus(isAuth, isAdmin bool) authv1.TokenReviewStatus {
+	st := authv1.TokenReviewStatus{
+		Authenticated: isAuth,
+		User: authv1.UserInfo{
+			Username: "user1",
+			Groups:   []string{"group1"},
+		},
+		Audiences: []string{"https://kubernetes.default.svc"},
+	}
+	if isAuth {
+		st.User.Groups = append(st.User.Groups, "system:authenticated")
+	}
+	if isAdmin {
+		st.User.Groups = append(st.User.Groups, "system:cluster-admins")
+	}
+	return st
+}
diff --git a/pkg/kubernetes/client/client.go b/pkg/kubernetes/client/client.go
new file mode 100644
index 000000000..80a3410cc
--- /dev/null
+++ b/pkg/kubernetes/client/client.go
@@ -0,0 +1,38 @@
+package client
+
+import (
+	"context"
+
+	authv1 "k8s.io/api/authentication/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+)
+
+// Interface for mocking
+type KubeAPI interface {
+	CreateTokenReview(ctx context.Context, tr *authv1.TokenReview, opts *metav1.CreateOptions) (*authv1.TokenReview, error)
+}
+
+type APIProvider func() (KubeAPI, error)
+
+type InCluster struct {
+	KubeAPI
+	client *kubernetes.Clientset
+}
+
+func (c *InCluster) CreateTokenReview(ctx context.Context, tr *authv1.TokenReview, opts *metav1.CreateOptions) (*authv1.TokenReview, error) {
+	return c.client.AuthenticationV1().TokenReviews().Create(ctx, tr, *opts)
+}
+
+func NewInCluster() (KubeAPI, error) {
+	config, err := rest.InClusterConfig()
+	if err != nil {
+		return nil, err
+	}
+	client, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+	return &InCluster{client: client}, nil
+}
diff --git a/pkg/server/routes.go b/pkg/server/routes.go
index a9aa2df30..9a4e7b889 100644
--- a/pkg/server/routes.go
+++ b/pkg/server/routes.go
@@ -8,7 +8,7 @@ import (
 	"github.com/sirupsen/logrus"
 
 	"github.com/netobserv/network-observability-console-plugin/pkg/handler"
-	"github.com/netobserv/network-observability-console-plugin/pkg/handler/auth"
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
 )
 
 func setupRoutes(cfg *Config, authChecker auth.Checker) *mux.Router {
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 85d8cb8a0..e9d7d4dcc 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -8,7 +8,7 @@ import (
 
 	"github.com/sirupsen/logrus"
 
-	"github.com/netobserv/network-observability-console-plugin/pkg/handler/auth"
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
 	"github.com/netobserv/network-observability-console-plugin/pkg/loki"
 )
 
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index 267d32486..20a19d099 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -27,7 +27,7 @@ import (
 	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/require"
 
-	"github.com/netobserv/network-observability-console-plugin/pkg/handler/auth"
+	"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
 	"github.com/netobserv/network-observability-console-plugin/pkg/loki"
 	"github.com/netobserv/network-observability-console-plugin/pkg/model"
 )
@@ -115,7 +115,7 @@ func TestServerUnauthorized(t *testing.T) {
 				URL: &url.URL{Scheme: "http", Host: "localhost:3100"},
 			},
 			Port: testPort,
-		}, &auth.BearerTokenChecker{})
+		}, &auth.AdminBearerTokenChecker{})
 	}()
 
 	t.Logf("Started test http server: %v", serverURL)
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
deleted file mode 100644
index e7c0d0546..000000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright 2017 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package promhttp
-
-import (
-	"bufio"
-	"io"
-	"net"
-	"net/http"
-)
-
-const (
-	closeNotifier = 1 << iota
-	flusher
-	hijacker
-	readerFrom
-	pusher
-)
-
-type delegator interface {
-	http.ResponseWriter
-
-	Status() int
-	Written() int64
-}
-
-type responseWriterDelegator struct {
-	http.ResponseWriter
-
-	status             int
-	written            int64
-	wroteHeader        bool
-	observeWriteHeader func(int)
-}
-
-func (r *responseWriterDelegator) Status() int {
-	return r.status
-}
-
-func (r *responseWriterDelegator) Written() int64 {
-	return r.written
-}
-
-func (r *responseWriterDelegator) WriteHeader(code int) {
-	if r.observeWriteHeader != nil && !r.wroteHeader {
-		// Only call observeWriteHeader for the 1st time. It's a bug if
-		// WriteHeader is called more than once, but we want to protect
-		// against it here. Note that we still delegate the WriteHeader
-		// to the original ResponseWriter to not mask the bug from it.
-		r.observeWriteHeader(code)
-	}
-	r.status = code
-	r.wroteHeader = true
-	r.ResponseWriter.WriteHeader(code)
-}
-
-func (r *responseWriterDelegator) Write(b []byte) (int, error) {
-	// If applicable, call WriteHeader here so that observeWriteHeader is
-	// handled appropriately.
-	if !r.wroteHeader {
-		r.WriteHeader(http.StatusOK)
-	}
-	n, err := r.ResponseWriter.Write(b)
-	r.written += int64(n)
-	return n, err
-}
-
-type closeNotifierDelegator struct{ *responseWriterDelegator }
-type flusherDelegator struct{ *responseWriterDelegator }
-type hijackerDelegator struct{ *responseWriterDelegator }
-type readerFromDelegator struct{ *responseWriterDelegator }
-type pusherDelegator struct{ *responseWriterDelegator }
-
-func (d closeNotifierDelegator) CloseNotify() <-chan bool {
-	//nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
-	return d.ResponseWriter.(http.CloseNotifier).CloseNotify()
-}
-func (d flusherDelegator) Flush() {
-	// If applicable, call WriteHeader here so that observeWriteHeader is
-	// handled appropriately.
-	if !d.wroteHeader {
-		d.WriteHeader(http.StatusOK)
-	}
-	d.ResponseWriter.(http.Flusher).Flush()
-}
-func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
-	return d.ResponseWriter.(http.Hijacker).Hijack()
-}
-func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) {
-	// If applicable, call WriteHeader here so that observeWriteHeader is
-	// handled appropriately.
-	if !d.wroteHeader {
-		d.WriteHeader(http.StatusOK)
-	}
-	n, err := d.ResponseWriter.(io.ReaderFrom).ReadFrom(re)
-	d.written += n
-	return n, err
-}
-func (d pusherDelegator) Push(target string, opts *http.PushOptions) error {
-	return d.ResponseWriter.(http.Pusher).Push(target, opts)
-}
-
-var pickDelegator = make([]func(*responseWriterDelegator) delegator, 32)
-
-func init() {
-	// TODO(beorn7): Code generation would help here.
-	pickDelegator[0] = func(d *responseWriterDelegator) delegator { // 0
-		return d
-	}
-	pickDelegator[closeNotifier] = func(d *responseWriterDelegator) delegator { // 1
-		return closeNotifierDelegator{d}
-	}
-	pickDelegator[flusher] = func(d *responseWriterDelegator) delegator { // 2
-		return flusherDelegator{d}
-	}
-	pickDelegator[flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 3
-		return struct {
-			*responseWriterDelegator
-			http.Flusher
-			http.CloseNotifier
-		}{d, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[hijacker] = func(d *responseWriterDelegator) delegator { // 4
-		return hijackerDelegator{d}
-	}
-	pickDelegator[hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 5
-		return struct {
-			*responseWriterDelegator
-			http.Hijacker
-			http.CloseNotifier
-		}{d, hijackerDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 6
-		return struct {
-			*responseWriterDelegator
-			http.Hijacker
-			http.Flusher
-		}{d, hijackerDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 7
-		return struct {
-			*responseWriterDelegator
-			http.Hijacker
-			http.Flusher
-			http.CloseNotifier
-		}{d, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[readerFrom] = func(d *responseWriterDelegator) delegator { // 8
-		return readerFromDelegator{d}
-	}
-	pickDelegator[readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 9
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.CloseNotifier
-		}{d, readerFromDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 10
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Flusher
-		}{d, readerFromDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 11
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Flusher
-			http.CloseNotifier
-		}{d, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 12
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Hijacker
-		}{d, readerFromDelegator{d}, hijackerDelegator{d}}
-	}
-	pickDelegator[readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 13
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Hijacker
-			http.CloseNotifier
-		}{d, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 14
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Hijacker
-			http.Flusher
-		}{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 15
-		return struct {
-			*responseWriterDelegator
-			io.ReaderFrom
-			http.Hijacker
-			http.Flusher
-			http.CloseNotifier
-		}{d, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher] = func(d *responseWriterDelegator) delegator { // 16
-		return pusherDelegator{d}
-	}
-	pickDelegator[pusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 17
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+flusher] = func(d *responseWriterDelegator) delegator { // 18
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Flusher
-		}{d, pusherDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[pusher+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 19
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Flusher
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+hijacker] = func(d *responseWriterDelegator) delegator { // 20
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Hijacker
-		}{d, pusherDelegator{d}, hijackerDelegator{d}}
-	}
-	pickDelegator[pusher+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 21
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Hijacker
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 22
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Hijacker
-			http.Flusher
-		}{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			http.Hijacker
-			http.Flusher
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom] = func(d *responseWriterDelegator) delegator { // 24
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-		}{d, pusherDelegator{d}, readerFromDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+closeNotifier] = func(d *responseWriterDelegator) delegator { // 25
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+flusher] = func(d *responseWriterDelegator) delegator { // 26
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Flusher
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 27
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Flusher
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+hijacker] = func(d *responseWriterDelegator) delegator { // 28
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Hijacker
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+hijacker+closeNotifier] = func(d *responseWriterDelegator) delegator { // 29
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Hijacker
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, closeNotifierDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+hijacker+flusher] = func(d *responseWriterDelegator) delegator { // 30
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Hijacker
-			http.Flusher
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}}
-	}
-	pickDelegator[pusher+readerFrom+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 31
-		return struct {
-			*responseWriterDelegator
-			http.Pusher
-			io.ReaderFrom
-			http.Hijacker
-			http.Flusher
-			http.CloseNotifier
-		}{d, pusherDelegator{d}, readerFromDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}, closeNotifierDelegator{d}}
-	}
-}
-
-func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator {
-	d := &responseWriterDelegator{
-		ResponseWriter:     w,
-		observeWriteHeader: observeWriteHeaderFunc,
-	}
-
-	id := 0
-	//nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users.
-	if _, ok := w.(http.CloseNotifier); ok {
-		id += closeNotifier
-	}
-	if _, ok := w.(http.Flusher); ok {
-		id += flusher
-	}
-	if _, ok := w.(http.Hijacker); ok {
-		id += hijacker
-	}
-	if _, ok := w.(io.ReaderFrom); ok {
-		id += readerFrom
-	}
-	if _, ok := w.(http.Pusher); ok {
-		id += pusher
-	}
-
-	return pickDelegator[id](d)
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
deleted file mode 100644
index d86d0cf4b..000000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright 2016 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package promhttp provides tooling around HTTP servers and clients.
-//
-// First, the package allows the creation of http.Handler instances to expose
-// Prometheus metrics via HTTP. promhttp.Handler acts on the
-// prometheus.DefaultGatherer. With HandlerFor, you can create a handler for a
-// custom registry or anything that implements the Gatherer interface. It also
-// allows the creation of handlers that act differently on errors or allow to
-// log errors.
-//
-// Second, the package provides tooling to instrument instances of http.Handler
-// via middleware. Middleware wrappers follow the naming scheme
-// InstrumentHandlerX, where X describes the intended use of the middleware.
-// See each function's doc comment for specific details.
-//
-// Finally, the package allows for an http.RoundTripper to be instrumented via
-// middleware. Middleware wrappers follow the naming scheme
-// InstrumentRoundTripperX, where X describes the intended use of the
-// middleware. See each function's doc comment for specific details.
-package promhttp
-
-import (
-	"compress/gzip"
-	"fmt"
-	"io"
-	"net/http"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/prometheus/common/expfmt"
-
-	"github.com/prometheus/client_golang/prometheus"
-)
-
-const (
-	contentTypeHeader     = "Content-Type"
-	contentEncodingHeader = "Content-Encoding"
-	acceptEncodingHeader  = "Accept-Encoding"
-)
-
-var gzipPool = sync.Pool{
-	New: func() interface{} {
-		return gzip.NewWriter(nil)
-	},
-}
-
-// Handler returns an http.Handler for the prometheus.DefaultGatherer, using
-// default HandlerOpts, i.e. it reports the first error as an HTTP error, it has
-// no error logging, and it applies compression if requested by the client.
-//
-// The returned http.Handler is already instrumented using the
-// InstrumentMetricHandler function and the prometheus.DefaultRegisterer. If you
-// create multiple http.Handlers by separate calls of the Handler function, the
-// metrics used for instrumentation will be shared between them, providing
-// global scrape counts.
-//
-// This function is meant to cover the bulk of basic use cases. If you are doing
-// anything that requires more customization (including using a non-default
-// Gatherer, different instrumentation, and non-default HandlerOpts), use the
-// HandlerFor function. See there for details.
-func Handler() http.Handler {
-	return InstrumentMetricHandler(
-		prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}),
-	)
-}
-
-// HandlerFor returns an uninstrumented http.Handler for the provided
-// Gatherer. The behavior of the Handler is defined by the provided
-// HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom
-// Gatherers, with non-default HandlerOpts, and/or with custom (or no)
-// instrumentation. Use the InstrumentMetricHandler function to apply the same
-// kind of instrumentation as it is used by the Handler function.
-func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
-	var (
-		inFlightSem chan struct{}
-		errCnt      = prometheus.NewCounterVec(
-			prometheus.CounterOpts{
-				Name: "promhttp_metric_handler_errors_total",
-				Help: "Total number of internal errors encountered by the promhttp metric handler.",
-			},
-			[]string{"cause"},
-		)
-	)
-
-	if opts.MaxRequestsInFlight > 0 {
-		inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
-	}
-	if opts.Registry != nil {
-		// Initialize all possibilities that can occur below.
-		errCnt.WithLabelValues("gathering")
-		errCnt.WithLabelValues("encoding")
-		if err := opts.Registry.Register(errCnt); err != nil {
-			if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
-				errCnt = are.ExistingCollector.(*prometheus.CounterVec)
-			} else {
-				panic(err)
-			}
-		}
-	}
-
-	h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
-		if inFlightSem != nil {
-			select {
-			case inFlightSem <- struct{}{}: // All good, carry on.
-				defer func() { <-inFlightSem }()
-			default:
-				http.Error(rsp, fmt.Sprintf(
-					"Limit of concurrent requests reached (%d), try again later.", opts.MaxRequestsInFlight,
-				), http.StatusServiceUnavailable)
-				return
-			}
-		}
-		mfs, err := reg.Gather()
-		if err != nil {
-			if opts.ErrorLog != nil {
-				opts.ErrorLog.Println("error gathering metrics:", err)
-			}
-			errCnt.WithLabelValues("gathering").Inc()
-			switch opts.ErrorHandling {
-			case PanicOnError:
-				panic(err)
-			case ContinueOnError:
-				if len(mfs) == 0 {
-					// Still report the error if no metrics have been gathered.
-					httpError(rsp, err)
-					return
-				}
-			case HTTPErrorOnError:
-				httpError(rsp, err)
-				return
-			}
-		}
-
-		var contentType expfmt.Format
-		if opts.EnableOpenMetrics {
-			contentType = expfmt.NegotiateIncludingOpenMetrics(req.Header)
-		} else {
-			contentType = expfmt.Negotiate(req.Header)
-		}
-		header := rsp.Header()
-		header.Set(contentTypeHeader, string(contentType))
-
-		w := io.Writer(rsp)
-		if !opts.DisableCompression && gzipAccepted(req.Header) {
-			header.Set(contentEncodingHeader, "gzip")
-			gz := gzipPool.Get().(*gzip.Writer)
-			defer gzipPool.Put(gz)
-
-			gz.Reset(w)
-			defer gz.Close()
-
-			w = gz
-		}
-
-		enc := expfmt.NewEncoder(w, contentType)
-
-		// handleError handles the error according to opts.ErrorHandling
-		// and returns true if we have to abort after the handling.
-		handleError := func(err error) bool {
-			if err == nil {
-				return false
-			}
-			if opts.ErrorLog != nil {
-				opts.ErrorLog.Println("error encoding and sending metric family:", err)
-			}
-			errCnt.WithLabelValues("encoding").Inc()
-			switch opts.ErrorHandling {
-			case PanicOnError:
-				panic(err)
-			case HTTPErrorOnError:
-				// We cannot really send an HTTP error at this
-				// point because we most likely have written
-				// something to rsp already. But at least we can
-				// stop sending.
-				return true
-			}
-			// Do nothing in all other cases, including ContinueOnError.
-			return false
-		}
-
-		for _, mf := range mfs {
-			if handleError(enc.Encode(mf)) {
-				return
-			}
-		}
-		if closer, ok := enc.(expfmt.Closer); ok {
-			// This in particular takes care of the final "# EOF\n" line for OpenMetrics.
-			if handleError(closer.Close()) {
-				return
-			}
-		}
-	})
-
-	if opts.Timeout <= 0 {
-		return h
-	}
-	return http.TimeoutHandler(h, opts.Timeout, fmt.Sprintf(
-		"Exceeded configured timeout of %v.\n",
-		opts.Timeout,
-	))
-}
-
-// InstrumentMetricHandler is usually used with an http.Handler returned by the
-// HandlerFor function. It instruments the provided http.Handler with two
-// metrics: A counter vector "promhttp_metric_handler_requests_total" to count
-// scrapes partitioned by HTTP status code, and a gauge
-// "promhttp_metric_handler_requests_in_flight" to track the number of
-// simultaneous scrapes. This function idempotently registers collectors for
-// both metrics with the provided Registerer. It panics if the registration
-// fails. The provided metrics are useful to see how many scrapes hit the
-// monitored target (which could be from different Prometheus servers or other
-// scrapers), and how often they overlap (which would result in more than one
-// scrape in flight at the same time). Note that the scrapes-in-flight gauge
-// will contain the scrape by which it is exposed, while the scrape counter will
-// only get incremented after the scrape is complete (as only then the status
-// code is known). For tracking scrape durations, use the
-// "scrape_duration_seconds" gauge created by the Prometheus server upon each
-// scrape.
-func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) http.Handler {
-	cnt := prometheus.NewCounterVec(
-		prometheus.CounterOpts{
-			Name: "promhttp_metric_handler_requests_total",
-			Help: "Total number of scrapes by HTTP status code.",
-		},
-		[]string{"code"},
-	)
-	// Initialize the most likely HTTP status codes.
-	cnt.WithLabelValues("200")
-	cnt.WithLabelValues("500")
-	cnt.WithLabelValues("503")
-	if err := reg.Register(cnt); err != nil {
-		if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
-			cnt = are.ExistingCollector.(*prometheus.CounterVec)
-		} else {
-			panic(err)
-		}
-	}
-
-	gge := prometheus.NewGauge(prometheus.GaugeOpts{
-		Name: "promhttp_metric_handler_requests_in_flight",
-		Help: "Current number of scrapes being served.",
-	})
-	if err := reg.Register(gge); err != nil {
-		if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
-			gge = are.ExistingCollector.(prometheus.Gauge)
-		} else {
-			panic(err)
-		}
-	}
-
-	return InstrumentHandlerCounter(cnt, InstrumentHandlerInFlight(gge, handler))
-}
-
-// HandlerErrorHandling defines how a Handler serving metrics will handle
-// errors.
-type HandlerErrorHandling int
-
-// These constants cause handlers serving metrics to behave as described if
-// errors are encountered.
-const (
-	// Serve an HTTP status code 500 upon the first error
-	// encountered. Report the error message in the body. Note that HTTP
-	// errors cannot be served anymore once the beginning of a regular
-	// payload has been sent. Thus, in the (unlikely) case that encoding the
-	// payload into the negotiated wire format fails, serving the response
-	// will simply be aborted. Set an ErrorLog in HandlerOpts to detect
-	// those errors.
-	HTTPErrorOnError HandlerErrorHandling = iota
-	// Ignore errors and try to serve as many metrics as possible.  However,
-	// if no metrics can be served, serve an HTTP status code 500 and the
-	// last error message in the body. Only use this in deliberate "best
-	// effort" metrics collection scenarios. In this case, it is highly
-	// recommended to provide other means of detecting errors: By setting an
-	// ErrorLog in HandlerOpts, the errors are logged. By providing a
-	// Registry in HandlerOpts, the exposed metrics include an error counter
-	// "promhttp_metric_handler_errors_total", which can be used for
-	// alerts.
-	ContinueOnError
-	// Panic upon the first error encountered (useful for "crash only" apps).
-	PanicOnError
-)
-
-// Logger is the minimal interface HandlerOpts needs for logging. Note that
-// log.Logger from the standard library implements this interface, and it is
-// easy to implement by custom loggers, if they don't do so already anyway.
-type Logger interface {
-	Println(v ...interface{})
-}
-
-// HandlerOpts specifies options how to serve metrics via an http.Handler. The
-// zero value of HandlerOpts is a reasonable default.
-type HandlerOpts struct {
-	// ErrorLog specifies an optional Logger for errors collecting and
-	// serving metrics. If nil, errors are not logged at all. Note that the
-	// type of a reported error is often prometheus.MultiError, which
-	// formats into a multi-line error string. If you want to avoid the
-	// latter, create a Logger implementation that detects a
-	// prometheus.MultiError and formats the contained errors into one line.
-	ErrorLog Logger
-	// ErrorHandling defines how errors are handled. Note that errors are
-	// logged regardless of the configured ErrorHandling provided ErrorLog
-	// is not nil.
-	ErrorHandling HandlerErrorHandling
-	// If Registry is not nil, it is used to register a metric
-	// "promhttp_metric_handler_errors_total", partitioned by "cause". A
-	// failed registration causes a panic. Note that this error counter is
-	// different from the instrumentation you get from the various
-	// InstrumentHandler... helpers. It counts errors that don't necessarily
-	// result in a non-2xx HTTP status code. There are two typical cases:
-	// (1) Encoding errors that only happen after streaming of the HTTP body
-	// has already started (and the status code 200 has been sent). This
-	// should only happen with custom collectors. (2) Collection errors with
-	// no effect on the HTTP status code because ErrorHandling is set to
-	// ContinueOnError.
-	Registry prometheus.Registerer
-	// If DisableCompression is true, the handler will never compress the
-	// response, even if requested by the client.
-	DisableCompression bool
-	// The number of concurrent HTTP requests is limited to
-	// MaxRequestsInFlight. Additional requests are responded to with 503
-	// Service Unavailable and a suitable message in the body. If
-	// MaxRequestsInFlight is 0 or negative, no limit is applied.
-	MaxRequestsInFlight int
-	// If handling a request takes longer than Timeout, it is responded to
-	// with 503 ServiceUnavailable and a suitable Message. No timeout is
-	// applied if Timeout is 0 or negative. Note that with the current
-	// implementation, reaching the timeout simply ends the HTTP requests as
-	// described above (and even that only if sending of the body hasn't
-	// started yet), while the bulk work of gathering all the metrics keeps
-	// running in the background (with the eventual result to be thrown
-	// away). Until the implementation is improved, it is recommended to
-	// implement a separate timeout in potentially slow Collectors.
-	Timeout time.Duration
-	// If true, the experimental OpenMetrics encoding is added to the
-	// possible options during content negotiation. Note that Prometheus
-	// 2.5.0+ will negotiate OpenMetrics as first priority. OpenMetrics is
-	// the only way to transmit exemplars. However, the move to OpenMetrics
-	// is not completely transparent. Most notably, the values of "quantile"
-	// labels of Summaries and "le" labels of Histograms are formatted with
-	// a trailing ".0" if they would otherwise look like integer numbers
-	// (which changes the identity of the resulting series on the Prometheus
-	// server).
-	EnableOpenMetrics bool
-}
-
-// gzipAccepted returns whether the client will accept gzip-encoded content.
-func gzipAccepted(header http.Header) bool {
-	a := header.Get(acceptEncodingHeader)
-	parts := strings.Split(a, ",")
-	for _, part := range parts {
-		part = strings.TrimSpace(part)
-		if part == "gzip" || strings.HasPrefix(part, "gzip;") {
-			return true
-		}
-	}
-	return false
-}
-
-// httpError removes any content-encoding header and then calls http.Error with
-// the provided error and http.StatusInternalServerError. Error contents is
-// supposed to be uncompressed plain text. Same as with a plain http.Error, this
-// must not be called if the header or any payload has already been sent.
-func httpError(rsp http.ResponseWriter, err error) {
-	rsp.Header().Del(contentEncodingHeader)
-	http.Error(
-		rsp,
-		"An error has occurred while serving metrics:\n\n"+err.Error(),
-		http.StatusInternalServerError,
-	)
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
deleted file mode 100644
index 861b4d21c..000000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2017 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package promhttp
-
-import (
-	"crypto/tls"
-	"net/http"
-	"net/http/httptrace"
-	"time"
-
-	"github.com/prometheus/client_golang/prometheus"
-)
-
-// The RoundTripperFunc type is an adapter to allow the use of ordinary
-// functions as RoundTrippers. If f is a function with the appropriate
-// signature, RountTripperFunc(f) is a RoundTripper that calls f.
-type RoundTripperFunc func(req *http.Request) (*http.Response, error)
-
-// RoundTrip implements the RoundTripper interface.
-func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
-	return rt(r)
-}
-
-// InstrumentRoundTripperInFlight is a middleware that wraps the provided
-// http.RoundTripper. It sets the provided prometheus.Gauge to the number of
-// requests currently handled by the wrapped http.RoundTripper.
-//
-// See the example for ExampleInstrumentRoundTripperDuration for example usage.
-func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc {
-	return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
-		gauge.Inc()
-		defer gauge.Dec()
-		return next.RoundTrip(r)
-	})
-}
-
-// InstrumentRoundTripperCounter is a middleware that wraps the provided
-// http.RoundTripper to observe the request result with the provided CounterVec.
-// The CounterVec must have zero, one, or two non-const non-curried labels. For
-// those, the only allowed label names are "code" and "method". The function
-// panics otherwise. For the "method" label a predefined default label value set
-// is used to filter given values. Values besides predefined values will count
-// as `unknown` method.`WithExtraMethods` can be used to add more
-// methods to the set. Partitioning of the CounterVec happens by HTTP status code
-// and/or HTTP method if the respective instance label names are present in the
-// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
-//
-// If the wrapped RoundTripper panics or returns a non-nil error, the Counter
-// is not incremented.
-//
-// See the example for ExampleInstrumentRoundTripperDuration for example usage.
-func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
-	rtOpts := &option{}
-	for _, o := range opts {
-		o(rtOpts)
-	}
-
-	code, method := checkLabels(counter)
-
-	return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
-		resp, err := next.RoundTrip(r)
-		if err == nil {
-			counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc()
-		}
-		return resp, err
-	})
-}
-
-// InstrumentRoundTripperDuration is a middleware that wraps the provided
-// http.RoundTripper to observe the request duration with the provided
-// ObserverVec.  The ObserverVec must have zero, one, or two non-const
-// non-curried labels. For those, the only allowed label names are "code" and
-// "method". The function panics otherwise. For the "method" label a predefined
-// default label value set is used to filter given values. Values besides
-// predefined values will count as `unknown` method. `WithExtraMethods`
-// can be used to add more methods to the set. The Observe method of the Observer
-// in the ObserverVec is called with the request duration in
-// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
-// respective instance label names are present in the ObserverVec. For
-// unpartitioned observations, use an ObserverVec with zero labels. Note that
-// partitioning of Histograms is expensive and should be used judiciously.
-//
-// If the wrapped RoundTripper panics or returns a non-nil error, no values are
-// reported.
-//
-// Note that this method is only guaranteed to never observe negative durations
-// if used with Go1.9+.
-func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc {
-	rtOpts := &option{}
-	for _, o := range opts {
-		o(rtOpts)
-	}
-
-	code, method := checkLabels(obs)
-
-	return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
-		start := time.Now()
-		resp, err := next.RoundTrip(r)
-		if err == nil {
-			obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds())
-		}
-		return resp, err
-	})
-}
-
-// InstrumentTrace is used to offer flexibility in instrumenting the available
-// httptrace.ClientTrace hook functions. Each function is passed a float64
-// representing the time in seconds since the start of the http request. A user
-// may choose to use separately buckets Histograms, or implement custom
-// instance labels on a per function basis.
-type InstrumentTrace struct {
-	GotConn              func(float64)
-	PutIdleConn          func(float64)
-	GotFirstResponseByte func(float64)
-	Got100Continue       func(float64)
-	DNSStart             func(float64)
-	DNSDone              func(float64)
-	ConnectStart         func(float64)
-	ConnectDone          func(float64)
-	TLSHandshakeStart    func(float64)
-	TLSHandshakeDone     func(float64)
-	WroteHeaders         func(float64)
-	Wait100Continue      func(float64)
-	WroteRequest         func(float64)
-}
-
-// InstrumentRoundTripperTrace is a middleware that wraps the provided
-// RoundTripper and reports times to hook functions provided in the
-// InstrumentTrace struct. Hook functions that are not present in the provided
-// InstrumentTrace struct are ignored. Times reported to the hook functions are
-// time since the start of the request. Only with Go1.9+, those times are
-// guaranteed to never be negative. (Earlier Go versions are not using a
-// monotonic clock.) Note that partitioning of Histograms is expensive and
-// should be used judiciously.
-//
-// For hook functions that receive an error as an argument, no observations are
-// made in the event of a non-nil error value.
-//
-// See the example for ExampleInstrumentRoundTripperDuration for example usage.
-func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc {
-	return RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
-		start := time.Now()
-
-		trace := &httptrace.ClientTrace{
-			GotConn: func(_ httptrace.GotConnInfo) {
-				if it.GotConn != nil {
-					it.GotConn(time.Since(start).Seconds())
-				}
-			},
-			PutIdleConn: func(err error) {
-				if err != nil {
-					return
-				}
-				if it.PutIdleConn != nil {
-					it.PutIdleConn(time.Since(start).Seconds())
-				}
-			},
-			DNSStart: func(_ httptrace.DNSStartInfo) {
-				if it.DNSStart != nil {
-					it.DNSStart(time.Since(start).Seconds())
-				}
-			},
-			DNSDone: func(_ httptrace.DNSDoneInfo) {
-				if it.DNSDone != nil {
-					it.DNSDone(time.Since(start).Seconds())
-				}
-			},
-			ConnectStart: func(_, _ string) {
-				if it.ConnectStart != nil {
-					it.ConnectStart(time.Since(start).Seconds())
-				}
-			},
-			ConnectDone: func(_, _ string, err error) {
-				if err != nil {
-					return
-				}
-				if it.ConnectDone != nil {
-					it.ConnectDone(time.Since(start).Seconds())
-				}
-			},
-			GotFirstResponseByte: func() {
-				if it.GotFirstResponseByte != nil {
-					it.GotFirstResponseByte(time.Since(start).Seconds())
-				}
-			},
-			Got100Continue: func() {
-				if it.Got100Continue != nil {
-					it.Got100Continue(time.Since(start).Seconds())
-				}
-			},
-			TLSHandshakeStart: func() {
-				if it.TLSHandshakeStart != nil {
-					it.TLSHandshakeStart(time.Since(start).Seconds())
-				}
-			},
-			TLSHandshakeDone: func(_ tls.ConnectionState, err error) {
-				if err != nil {
-					return
-				}
-				if it.TLSHandshakeDone != nil {
-					it.TLSHandshakeDone(time.Since(start).Seconds())
-				}
-			},
-			WroteHeaders: func() {
-				if it.WroteHeaders != nil {
-					it.WroteHeaders(time.Since(start).Seconds())
-				}
-			},
-			Wait100Continue: func() {
-				if it.Wait100Continue != nil {
-					it.Wait100Continue(time.Since(start).Seconds())
-				}
-			},
-			WroteRequest: func(_ httptrace.WroteRequestInfo) {
-				if it.WroteRequest != nil {
-					it.WroteRequest(time.Since(start).Seconds())
-				}
-			},
-		}
-		r = r.WithContext(httptrace.WithClientTrace(r.Context(), trace))
-
-		return next.RoundTrip(r)
-	})
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
deleted file mode 100644
index a23f0edc6..000000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright 2017 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package promhttp
-
-import (
-	"errors"
-	"net/http"
-	"strconv"
-	"strings"
-	"time"
-
-	dto "github.com/prometheus/client_model/go"
-
-	"github.com/prometheus/client_golang/prometheus"
-)
-
-// magicString is used for the hacky label test in checkLabels. Remove once fixed.
-const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa"
-
-// InstrumentHandlerInFlight is a middleware that wraps the provided
-// http.Handler. It sets the provided prometheus.Gauge to the number of
-// requests currently handled by the wrapped http.Handler.
-//
-// See the example for InstrumentHandlerDuration for example usage.
-func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		g.Inc()
-		defer g.Dec()
-		next.ServeHTTP(w, r)
-	})
-}
-
-// InstrumentHandlerDuration is a middleware that wraps the provided
-// http.Handler to observe the request duration with the provided ObserverVec.
-// The ObserverVec must have valid metric and label names and must have zero,
-// one, or two non-const non-curried labels. For those, the only allowed label
-// names are "code" and "method". The function panics otherwise. For the "method"
-// label a predefined default label value set is used to filter given values.
-// Values besides predefined values will count as `unknown` method.
-//`WithExtraMethods` can be used to add more methods to the set. The Observe
-// method of the Observer in the ObserverVec is called with the request duration
-// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
-// the respective instance label names are present in the ObserverVec. For
-// unpartitioned observations, use an ObserverVec with zero labels. Note that
-// partitioning of Histograms is expensive and should be used judiciously.
-//
-// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
-//
-// If the wrapped Handler panics, no values are reported.
-//
-// Note that this method is only guaranteed to never observe negative durations
-// if used with Go1.9+.
-func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
-	mwOpts := &option{}
-	for _, o := range opts {
-		o(mwOpts)
-	}
-
-	code, method := checkLabels(obs)
-
-	if code {
-		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			now := time.Now()
-			d := newDelegator(w, nil)
-			next.ServeHTTP(d, r)
-
-			obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
-		})
-	}
-
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		now := time.Now()
-		next.ServeHTTP(w, r)
-		obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
-	})
-}
-
-// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
-// to observe the request result with the provided CounterVec. The CounterVec
-// must have valid metric and label names and must have zero, one, or two
-// non-const non-curried labels. For those, the only allowed label names are
-// "code" and "method". The function panics otherwise. For the "method"
-// label a predefined default label value set is used to filter given values.
-// Values besides predefined values will count as `unknown` method.
-// `WithExtraMethods` can be used to add more methods to the set. Partitioning of the
-// CounterVec happens by HTTP status code and/or HTTP method if the respective
-// instance label names are present in the CounterVec. For unpartitioned
-// counting, use a CounterVec with zero labels.
-//
-// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
-//
-// If the wrapped Handler panics, the Counter is not incremented.
-//
-// See the example for InstrumentHandlerDuration for example usage.
-func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc {
-	mwOpts := &option{}
-	for _, o := range opts {
-		o(mwOpts)
-	}
-
-	code, method := checkLabels(counter)
-
-	if code {
-		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			d := newDelegator(w, nil)
-			next.ServeHTTP(d, r)
-			counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc()
-		})
-	}
-
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		next.ServeHTTP(w, r)
-		counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc()
-	})
-}
-
-// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
-// http.Handler to observe with the provided ObserverVec the request duration
-// until the response headers are written. The ObserverVec must have valid
-// metric and label names and must have zero, one, or two non-const non-curried
-// labels. For those, the only allowed label names are "code" and "method". The
-// function panics otherwise. For the "method" label a predefined default label
-// value set is used to filter given values. Values besides predefined values
-// will count as `unknown` method.`WithExtraMethods` can be used to add more
-// methods to the set. The Observe method of the Observer in the
-// ObserverVec is called with the request duration in seconds. Partitioning
-// happens by HTTP status code and/or HTTP method if the respective instance
-// label names are present in the ObserverVec. For unpartitioned observations,
-// use an ObserverVec with zero labels. Note that partitioning of Histograms is
-// expensive and should be used judiciously.
-//
-// If the wrapped Handler panics before calling WriteHeader, no value is
-// reported.
-//
-// Note that this method is only guaranteed to never observe negative durations
-// if used with Go1.9+.
-//
-// See the example for InstrumentHandlerDuration for example usage.
-func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
-	mwOpts := &option{}
-	for _, o := range opts {
-		o(mwOpts)
-	}
-
-	code, method := checkLabels(obs)
-
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		now := time.Now()
-		d := newDelegator(w, func(status int) {
-			obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds())
-		})
-		next.ServeHTTP(d, r)
-	})
-}
-
-// InstrumentHandlerRequestSize is a middleware that wraps the provided
-// http.Handler to observe the request size with the provided ObserverVec. The
-// ObserverVec must have valid metric and label names and must have zero, one,
-// or two non-const non-curried labels. For those, the only allowed label names
-// are "code" and "method". The function panics otherwise. For the "method"
-// label a predefined default label value set is used to filter given values.
-// Values besides predefined values will count as `unknown` method.
-// `WithExtraMethods` can be used to add more methods to the set. The Observe
-// method of the Observer in the ObserverVec is called with the request size in
-// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
-// respective instance label names are present in the ObserverVec. For
-// unpartitioned observations, use an ObserverVec with zero labels. Note that
-// partitioning of Histograms is expensive and should be used judiciously.
-//
-// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
-//
-// If the wrapped Handler panics, no values are reported.
-//
-// See the example for InstrumentHandlerDuration for example usage.
-func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc {
-	mwOpts := &option{}
-	for _, o := range opts {
-		o(mwOpts)
-	}
-
-	code, method := checkLabels(obs)
-
-	if code {
-		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			d := newDelegator(w, nil)
-			next.ServeHTTP(d, r)
-			size := computeApproximateRequestSize(r)
-			obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size))
-		})
-	}
-
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		next.ServeHTTP(w, r)
-		size := computeApproximateRequestSize(r)
-		obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size))
-	})
-}
-
-// InstrumentHandlerResponseSize is a middleware that wraps the provided
-// http.Handler to observe the response size with the provided ObserverVec. The
-// ObserverVec must have valid metric and label names and must have zero, one,
-// or two non-const non-curried labels. For those, the only allowed label names
-// are "code" and "method". The function panics otherwise. For the "method"
-// label a predefined default label value set is used to filter given values.
-// Values besides predefined values will count as `unknown` method.
-// `WithExtraMethods` can be used to add more methods to the set. The Observe
-// method of the Observer in the ObserverVec is called with the response size in
-// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
-// respective instance label names are present in the ObserverVec. For
-// unpartitioned observations, use an ObserverVec with zero labels. Note that
-// partitioning of Histograms is expensive and should be used judiciously.
-//
-// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
-//
-// If the wrapped Handler panics, no values are reported.
-//
-// See the example for InstrumentHandlerDuration for example usage.
-func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler {
-	mwOpts := &option{}
-	for _, o := range opts {
-		o(mwOpts)
-	}
-
-	code, method := checkLabels(obs)
-
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		d := newDelegator(w, nil)
-		next.ServeHTTP(d, r)
-		obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written()))
-	})
-}
-
-// checkLabels returns whether the provided Collector has a non-const,
-// non-curried label named "code" and/or "method". It panics if the provided
-// Collector does not have a Desc or has more than one Desc or its Desc is
-// invalid. It also panics if the Collector has any non-const, non-curried
-// labels that are not named "code" or "method".
-func checkLabels(c prometheus.Collector) (code bool, method bool) {
-	// TODO(beorn7): Remove this hacky way to check for instance labels
-	// once Descriptors can have their dimensionality queried.
-	var (
-		desc *prometheus.Desc
-		m    prometheus.Metric
-		pm   dto.Metric
-		lvs  []string
-	)
-
-	// Get the Desc from the Collector.
-	descc := make(chan *prometheus.Desc, 1)
-	c.Describe(descc)
-
-	select {
-	case desc = <-descc:
-	default:
-		panic("no description provided by collector")
-	}
-	select {
-	case <-descc:
-		panic("more than one description provided by collector")
-	default:
-	}
-
-	close(descc)
-
-	// Make sure the Collector has a valid Desc by registering it with a
-	// temporary registry.
-	prometheus.NewRegistry().MustRegister(c)
-
-	// Create a ConstMetric with the Desc. Since we don't know how many
-	// variable labels there are, try for as long as it needs.
-	for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {
-		m, err = prometheus.NewConstMetric(desc, prometheus.UntypedValue, 0, lvs...)
-	}
-
-	// Write out the metric into a proto message and look at the labels.
-	// If the value is not the magicString, it is a constLabel, which doesn't interest us.
-	// If the label is curried, it doesn't interest us.
-	// In all other cases, only "code" or "method" is allowed.
-	if err := m.Write(&pm); err != nil {
-		panic("error checking metric for labels")
-	}
-	for _, label := range pm.Label {
-		name, value := label.GetName(), label.GetValue()
-		if value != magicString || isLabelCurried(c, name) {
-			continue
-		}
-		switch name {
-		case "code":
-			code = true
-		case "method":
-			method = true
-		default:
-			panic("metric partitioned with non-supported labels")
-		}
-	}
-	return
-}
-
-func isLabelCurried(c prometheus.Collector, label string) bool {
-	// This is even hackier than the label test above.
-	// We essentially try to curry again and see if it works.
-	// But for that, we need to type-convert to the two
-	// types we use here, ObserverVec or *CounterVec.
-	switch v := c.(type) {
-	case *prometheus.CounterVec:
-		if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
-			return false
-		}
-	case prometheus.ObserverVec:
-		if _, err := v.CurryWith(prometheus.Labels{label: "dummy"}); err == nil {
-			return false
-		}
-	default:
-		panic("unsupported metric vec type")
-	}
-	return true
-}
-
-// emptyLabels is a one-time allocation for non-partitioned metrics to avoid
-// unnecessary allocations on each request.
-var emptyLabels = prometheus.Labels{}
-
-func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels {
-	if !(code || method) {
-		return emptyLabels
-	}
-	labels := prometheus.Labels{}
-
-	if code {
-		labels["code"] = sanitizeCode(status)
-	}
-	if method {
-		labels["method"] = sanitizeMethod(reqMethod, extraMethods...)
-	}
-
-	return labels
-}
-
-func computeApproximateRequestSize(r *http.Request) int {
-	s := 0
-	if r.URL != nil {
-		s += len(r.URL.String())
-	}
-
-	s += len(r.Method)
-	s += len(r.Proto)
-	for name, values := range r.Header {
-		s += len(name)
-		for _, value := range values {
-			s += len(value)
-		}
-	}
-	s += len(r.Host)
-
-	// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
-
-	if r.ContentLength != -1 {
-		s += int(r.ContentLength)
-	}
-	return s
-}
-
-// If the wrapped http.Handler has a known method, it will be sanitized and returned.
-// Otherwise, "unknown" will be returned. The known method list can be extended
-// as needed by using extraMethods parameter.
-func sanitizeMethod(m string, extraMethods ...string) string {
-	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for
-	// the methods chosen as default.
-	switch m {
-	case "GET", "get":
-		return "get"
-	case "PUT", "put":
-		return "put"
-	case "HEAD", "head":
-		return "head"
-	case "POST", "post":
-		return "post"
-	case "DELETE", "delete":
-		return "delete"
-	case "CONNECT", "connect":
-		return "connect"
-	case "OPTIONS", "options":
-		return "options"
-	case "NOTIFY", "notify":
-		return "notify"
-	case "TRACE", "trace":
-		return "trace"
-	case "PATCH", "patch":
-		return "patch"
-	default:
-		for _, method := range extraMethods {
-			if strings.EqualFold(m, method) {
-				return strings.ToLower(m)
-			}
-		}
-		return "unknown"
-	}
-}
-
-// If the wrapped http.Handler has not set a status code, i.e. the value is
-// currently 0, sanitizeCode will return 200, for consistency with behavior in
-// the stdlib.
-func sanitizeCode(s int) string {
-	// See for accepted codes https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
-	switch s {
-	case 100:
-		return "100"
-	case 101:
-		return "101"
-
-	case 200, 0:
-		return "200"
-	case 201:
-		return "201"
-	case 202:
-		return "202"
-	case 203:
-		return "203"
-	case 204:
-		return "204"
-	case 205:
-		return "205"
-	case 206:
-		return "206"
-
-	case 300:
-		return "300"
-	case 301:
-		return "301"
-	case 302:
-		return "302"
-	case 304:
-		return "304"
-	case 305:
-		return "305"
-	case 307:
-		return "307"
-
-	case 400:
-		return "400"
-	case 401:
-		return "401"
-	case 402:
-		return "402"
-	case 403:
-		return "403"
-	case 404:
-		return "404"
-	case 405:
-		return "405"
-	case 406:
-		return "406"
-	case 407:
-		return "407"
-	case 408:
-		return "408"
-	case 409:
-		return "409"
-	case 410:
-		return "410"
-	case 411:
-		return "411"
-	case 412:
-		return "412"
-	case 413:
-		return "413"
-	case 414:
-		return "414"
-	case 415:
-		return "415"
-	case 416:
-		return "416"
-	case 417:
-		return "417"
-	case 418:
-		return "418"
-
-	case 500:
-		return "500"
-	case 501:
-		return "501"
-	case 502:
-		return "502"
-	case 503:
-		return "503"
-	case 504:
-		return "504"
-	case 505:
-		return "505"
-
-	case 428:
-		return "428"
-	case 429:
-		return "429"
-	case 431:
-		return "431"
-	case 511:
-		return "511"
-
-	default:
-		if s >= 100 && s <= 599 {
-			return strconv.Itoa(s)
-		}
-		return "unknown"
-	}
-}
diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
deleted file mode 100644
index 35e41bd1e..000000000
--- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2022 The Prometheus Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package promhttp
-
-// Option are used to configure a middleware or round tripper..
-type Option func(*option)
-
-type option struct {
-	extraMethods []string
-}
-
-// WithExtraMethods adds additional HTTP methods to the list of allowed methods.
-// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list.
-//
-// See the example for ExampleInstrumentHandlerWithExtraMethods for example usage.
-func WithExtraMethods(methods ...string) Option {
-	return func(o *option) {
-		o.extraMethods = methods
-	}
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index eedf0e080..0ab7f5fd9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -86,7 +86,6 @@ github.com/pmezard/go-difflib/difflib
 github.com/prometheus/client_golang/prometheus
 github.com/prometheus/client_golang/prometheus/internal
 github.com/prometheus/client_golang/prometheus/promauto
-github.com/prometheus/client_golang/prometheus/promhttp
 # github.com/prometheus/client_model v0.2.0
 ## explicit; go 1.9
 github.com/prometheus/client_model/go