@@ -6,11 +6,15 @@ import (
6
6
"fmt"
7
7
"net/http"
8
8
"path/filepath"
9
+ "time"
9
10
10
11
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/filemonitor"
11
12
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/profile"
12
13
"github.com/prometheus/client_golang/prometheus/promhttp"
13
14
"github.com/sirupsen/logrus"
15
+ "k8s.io/client-go/rest"
16
+ "sigs.k8s.io/controller-runtime/pkg/log"
17
+ "sigs.k8s.io/controller-runtime/pkg/metrics/filters"
14
18
)
15
19
16
20
// Option applies a configuration option to the given config.
@@ -43,11 +47,18 @@ func WithDebug(debug bool) Option {
43
47
}
44
48
}
45
49
50
+ func WithKubeConfig (config * rest.Config ) Option {
51
+ return func (sc * serverConfig ) {
52
+ sc .kubeConfig = config
53
+ }
54
+ }
55
+
46
56
type serverConfig struct {
47
57
logger * logrus.Logger
48
58
tlsCertPath * string
49
59
tlsKeyPath * string
50
60
clientCAPath * string
61
+ kubeConfig * rest.Config
51
62
debug bool
52
63
}
53
64
@@ -62,6 +73,7 @@ func defaultServerConfig() serverConfig {
62
73
tlsCertPath : nil ,
63
74
tlsKeyPath : nil ,
64
75
clientCAPath : nil ,
76
+ kubeConfig : nil ,
65
77
logger : nil ,
66
78
debug : false ,
67
79
}
@@ -90,12 +102,53 @@ func (sc serverConfig) getListenAndServeFunc() (func() error, error) {
90
102
}
91
103
92
104
mux := http .NewServeMux ()
93
- mux .Handle ("/metrics" , promhttp .Handler ())
94
105
mux .HandleFunc ("/healthz" , func (w http.ResponseWriter , r * http.Request ) {
95
106
w .WriteHeader (http .StatusOK )
96
107
})
97
108
profile .RegisterHandlers (mux , profile .WithTLS (tlsEnabled || ! sc .debug ))
98
109
110
+ // Set up authenticated metrics endpoint if kubeConfig is provided
111
+ sc .logger .Infof ("DEBUG: Checking authentication setup - kubeConfig != nil: %v, tlsEnabled: %v" , sc .kubeConfig != nil , tlsEnabled )
112
+ if sc .kubeConfig != nil && tlsEnabled {
113
+ sc .logger .Info ("DEBUG: Setting up authenticated metrics endpoint" )
114
+ // Create authentication filter using controller-runtime
115
+ sc .logger .Info ("DEBUG: Creating authentication filter with controller-runtime" )
116
+ filter , err := filters .WithAuthenticationAndAuthorization (sc .kubeConfig , & http.Client {
117
+ Timeout : 30 * time .Second ,
118
+ })
119
+ if err != nil {
120
+ sc .logger .Errorf ("DEBUG: Failed to create authentication filter: %v" , err )
121
+ return nil , fmt .Errorf ("failed to create authentication filter: %w" , err )
122
+ }
123
+ sc .logger .Info ("DEBUG: Authentication filter created successfully" )
124
+ // Create authenticated metrics handler
125
+ sc .logger .Info ("DEBUG: Wrapping metrics handler with authentication" )
126
+ logger := log .FromContext (context .Background ())
127
+ authenticatedMetricsHandler , err := filter (logger , promhttp .Handler ())
128
+ if err != nil {
129
+ sc .logger .Errorf ("DEBUG: Failed to wrap metrics handler: %v" , err )
130
+ return nil , fmt .Errorf ("failed to wrap metrics handler with authentication: %w" , err )
131
+ }
132
+ sc .logger .Info ("DEBUG: Metrics handler wrapped successfully" )
133
+ // Add debugging wrapper to log authentication attempts
134
+ debugAuthHandler := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
135
+ sc .logger .Infof ("DEBUG: Metrics request from %s, Auth header present: %v, User-Agent: %s" ,
136
+ r .RemoteAddr , r .Header .Get ("Authorization" ) != "" , r .Header .Get ("User-Agent" ))
137
+ authenticatedMetricsHandler .ServeHTTP (w , r )
138
+ })
139
+ mux .Handle ("/metrics" , debugAuthHandler )
140
+ sc .logger .Info ("Metrics endpoint configured with authentication and authorization" )
141
+ } else {
142
+ // Fallback to unprotected metrics (for development/testing)
143
+ sc .logger .Warnf ("DEBUG: Using unprotected metrics - kubeConfig != nil: %v, tlsEnabled: %v" , sc .kubeConfig != nil , tlsEnabled )
144
+ mux .Handle ("/metrics" , promhttp .Handler ())
145
+ if sc .kubeConfig == nil {
146
+ sc .logger .Warn ("No Kubernetes config provided - metrics endpoint will be unprotected" )
147
+ } else if ! tlsEnabled {
148
+ sc .logger .Warn ("TLS not enabled - metrics endpoint will be unprotected" )
149
+ }
150
+ }
151
+
99
152
s := http.Server {
100
153
Handler : mux ,
101
154
Addr : sc .getAddress (tlsEnabled ),
@@ -141,6 +194,7 @@ func (sc serverConfig) getListenAndServeFunc() (func() error, error) {
141
194
ClientAuth : tls .VerifyClientCertIfGiven ,
142
195
}, nil
143
196
},
197
+ NextProtos : []string {"http/1.1" }, // Disable HTTP/2 for security
144
198
}
145
199
return func () error {
146
200
return s .ListenAndServeTLS ("" , "" )
0 commit comments