package observability import ( "crypto/subtle" "net/http" "os" "strings" ) // ProtectMetrics wraps the Prometheus handler. When EVOBGP_METRICS_TOKEN is set, // scrapes must send Authorization: Bearer (constant-time compare). // Empty token keeps /metrics open (dev / private network). func ProtectMetrics(next http.Handler) http.Handler { token := strings.TrimSpace(os.Getenv("EVOBGP_METRICS_TOKEN")) if token == "" { return next } want := []byte(token) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h := r.Header.Get("Authorization") const p = "Bearer " got := "" if strings.HasPrefix(h, p) { got = strings.TrimSpace(h[len(p):]) } if subtle.ConstantTimeCompare([]byte(got), want) != 1 { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) }