diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dd76c35859..c2cb156b853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ * [ENHANCEMENT] Added `-ingest-storage.kafka.fetch-max-wait` configuration option to configure the maximum amount of time a Kafka broker waits for some records before a Fetch response is returned. #11012 * [ENHANCEMENT] Ingester: Add `cortex_ingester_tsdb_forced_compactions_in_progress` metric reporting a value of 1 when there's a forced TSDB head compaction in progress. #11006 * [ENHANCEMENT] Ingester: Add `cortex_ingest_storage_reader_records_batch_fetch_max_bytes` metric reporting the distribution of `MaxBytes` specified in the Fetch requests sent to Kafka. #11014 -* [ENHANCEMENT] All: Add experimental support for cluster validation in HTTP calls. When it is enabled, HTTP server verifies if a request coming from an HTTP client comes from an expected cluster. This validation can be configured by the following experimental configuration options: #11010 +* [ENHANCEMENT] All: Add experimental support for cluster validation in HTTP calls. When it is enabled, HTTP server verifies if a request coming from an HTTP client comes from an expected cluster. This validation can be configured by the following experimental configuration options: #11010 #11549 * `-server.cluster-validation.label` * `-server.cluster-validation.http.enabled` * `-server.cluster-validation.http.soft-validation` diff --git a/go.mod b/go.mod index 85a8de507f0..4c63d5da3c3 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/golang/snappy v1.0.0 github.com/google/gopacket v1.1.19 github.com/gorilla/mux v1.8.1 - github.com/grafana/dskit v0.0.0-20250508072153-10bc270c967b + github.com/grafana/dskit v0.0.0-20250527102949-18b79c4e9e07 github.com/grafana/e2e v0.1.2-0.20250428181430-708d63bcc673 github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/influxdata/influxdb/v2 v2.7.11 diff --git a/go.sum b/go.sum index 24bd443c57c..a88e9645584 100644 --- a/go.sum +++ b/go.sum @@ -532,8 +532,8 @@ github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc h1:PXZQA2WCxe85T github.com/grafana-tools/sdk v0.0.0-20220919052116-6562121319fc/go.mod h1:AHHlOEv1+GGQ3ktHMlhuTUwo3zljV3QJbC0+8o2kn+4= github.com/grafana/alerting v0.0.0-20250424095029-28f3388bdf46 h1:pd6zw/GgbFuVqKU4sBNuXY7c8jgsLJQWz3GjuTKlQOo= github.com/grafana/alerting v0.0.0-20250424095029-28f3388bdf46/go.mod h1:pMfhRxL2LZ3Pm8iy7VcVsb9CLYuBtjFYbf1oxgx7yFA= -github.com/grafana/dskit v0.0.0-20250508072153-10bc270c967b h1:CKhBTXihwq4FO+sbiSJ87A3Pf+bkFmSAVQTZeTkmfyM= -github.com/grafana/dskit v0.0.0-20250508072153-10bc270c967b/go.mod h1:aT6thv8yV0shmqbbRbtEwxK9a+H/8fWDOMm2IRx8xx0= +github.com/grafana/dskit v0.0.0-20250527102949-18b79c4e9e07 h1:KCS8hZ6JJ3pDmWtT+B9II8nqEPKQtZeyLmbDgvdVETM= +github.com/grafana/dskit v0.0.0-20250527102949-18b79c4e9e07/go.mod h1:aT6thv8yV0shmqbbRbtEwxK9a+H/8fWDOMm2IRx8xx0= github.com/grafana/e2e v0.1.2-0.20250428181430-708d63bcc673 h1:Va04sDlP33f1SFUHRTho4QJfDlGTz+/HnBIpYwlqV9Q= github.com/grafana/e2e v0.1.2-0.20250428181430-708d63bcc673/go.mod h1:JVmqPBe8A/pZWwRoJW5ZjyALeY5OXMzPl7LrVXOdZAI= github.com/grafana/goautoneg v0.0.0-20240607115440-f335c04c58ce h1:WI1olbgS+sEl77qxEYbmt9TgRUz7iLqmjh8lYPpGlKQ= diff --git a/pkg/frontend/frontend_test.go b/pkg/frontend/frontend_test.go index 38893b2698d..f5e44c8be23 100644 --- a/pkg/frontend/frontend_test.go +++ b/pkg/frontend/frontend_test.go @@ -152,7 +152,7 @@ func TestFrontend_ClusterValidationWhenDownstreamURLIsConfigured(t *testing.T) { expectedMetrics: ` # HELP cortex_client_invalid_cluster_validation_label_requests_total Number of requests with invalid cluster validation label. # TYPE cortex_client_invalid_cluster_validation_label_requests_total counter - cortex_client_invalid_cluster_validation_label_requests_total{client="querier",method="/api/v1/query_range",protocol="http"} 1 + cortex_client_invalid_cluster_validation_label_requests_total{client="querier",method="",protocol="http"} 1 `, }, "if client has no cluster validation label and soft cluster validation is enabled no error is returned": { diff --git a/vendor/github.com/grafana/dskit/middleware/http_cluster.go b/vendor/github.com/grafana/dskit/middleware/http_cluster.go index 9f20ca44885..d20a1b3c6a9 100644 --- a/vendor/github.com/grafana/dskit/middleware/http_cluster.go +++ b/vendor/github.com/grafana/dskit/middleware/http_cluster.go @@ -20,6 +20,7 @@ import ( type clusterValidationError struct { ClusterValidationErrorMessage string `json:"cluster_validation_error_message"` + Route string `json:"route"` } // writeAsJSON writes this error as JSON to the HTTP response. @@ -64,8 +65,8 @@ func ClusterValidationRoundTripper(cluster string, invalidClusterValidationRepor return resp, nil } msg := fmt.Sprintf("request rejected by the server: %s", clusterValidationErr.ClusterValidationErrorMessage) - invalidClusterValidationReporter(msg, req.URL.Path) - return nil, fmt.Errorf("%s", msg) + invalidClusterValidationReporter(msg, clusterValidationErr.Route) + return nil, errors.New(msg) } } @@ -98,8 +99,15 @@ func ClusterValidationMiddleware( return Func(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if err := checkClusterFromRequest(r, cluster, softValidation, reExcludedPath, invalidClusterRequests, logger); err != nil { - clusterValidationErr := clusterValidationError{ClusterValidationErrorMessage: err.Error()} + route := ExtractRouteName(r.Context()) + if route == "" { + route = "" + } + if err := checkClusterFromRequest(r, cluster, route, softValidation, reExcludedPath, invalidClusterRequests, logger); err != nil { + clusterValidationErr := clusterValidationError{ + ClusterValidationErrorMessage: err.Error(), + Route: route, + } clusterValidationErr.writeAsJSON(w) return } @@ -118,7 +126,7 @@ func validateClusterValidationMiddlewareInputParameters(cluster string, logger l } func checkClusterFromRequest( - r *http.Request, expectedCluster string, softValidationEnabled bool, reExcludedPath *regexp.Regexp, + r *http.Request, expectedCluster, route string, softValidationEnabled bool, reExcludedPath *regexp.Regexp, invalidClusterRequests *prometheus.CounterVec, logger log.Logger, ) error { if reExcludedPath != nil && reExcludedPath.MatchString(r.URL.Path) { @@ -148,7 +156,7 @@ func checkClusterFromRequest( wrongClusterErr = fmt.Errorf("rejected request with wrong cluster validation label %q - it should be %q", reqCluster, expectedCluster) } - invalidClusterRequests.WithLabelValues("http", r.URL.Path, expectedCluster, reqCluster).Inc() + invalidClusterRequests.WithLabelValues("http", route, expectedCluster, reqCluster).Inc() level.Warn(logger).Log("msg", "request with wrong cluster validation label", "request_cluster_validation_label", reqCluster) return wrongClusterErr } @@ -159,7 +167,7 @@ func checkClusterFromRequest( emptyClusterErr = fmt.Errorf("rejected request with empty cluster validation label - it should be %q", expectedCluster) } - invalidClusterRequests.WithLabelValues("http", r.URL.Path, expectedCluster, "").Inc() + invalidClusterRequests.WithLabelValues("http", route, expectedCluster, "").Inc() level.Warn(logger).Log("msg", "request with no cluster validation label") return emptyClusterErr } @@ -169,7 +177,7 @@ func checkClusterFromRequest( rejectedRequestErr = fmt.Errorf("rejected request: %w", err) } - invalidClusterRequests.WithLabelValues("http", r.URL.Path, expectedCluster, "").Inc() + invalidClusterRequests.WithLabelValues("http", route, expectedCluster, "").Inc() level.Warn(logger).Log("msg", "detected error during cluster validation label extraction", "err", err) return rejectedRequestErr } diff --git a/vendor/modules.txt b/vendor/modules.txt index bc9a027f2da..74075738ba1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -648,7 +648,7 @@ github.com/grafana/alerting/receivers/webhook github.com/grafana/alerting/receivers/wecom github.com/grafana/alerting/templates github.com/grafana/alerting/templates/gomplate -# github.com/grafana/dskit v0.0.0-20250508072153-10bc270c967b +# github.com/grafana/dskit v0.0.0-20250527102949-18b79c4e9e07 ## explicit; go 1.22.0 github.com/grafana/dskit/backoff github.com/grafana/dskit/ballast