This is an automated email from the ASF dual-hosted git repository.

andor pushed a commit to branch branch-3.8
in repository https://gitbox.apache.org/repos/asf/zookeeper.git


The following commit(s) were added to refs/heads/branch-3.8 by this push:
     new 54da69219 ZOOKEEPER-3731: Disable HTTP TRACE Method (branch-3.8)
54da69219 is described below

commit 54da69219cc0adcc5cecf8e5f755fd93e464a0d5
Author: Andor Molnár <an...@apache.org>
AuthorDate: Thu May 22 18:40:10 2025 -0500

    ZOOKEEPER-3731: Disable HTTP TRACE Method (branch-3.8)
    
    ZOOKEEPER-3731: Disallow HTTP TRACE method on PrometheusMetrics Server 
(#1682)
    Author: anmolnar
    Closes #2262 from anmolnar/ZOOKEEPER-3731_38
---
 .../prometheus/PrometheusMetricsProvider.java      | 23 +++++++++++++++++++++
 .../prometheus/PrometheusMetricsProviderTest.java  | 24 ++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git 
a/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/main/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProvider.java
 
b/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/main/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProvider.java
index e17b09785..af4bff9d2 100644
--- 
a/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/main/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProvider.java
+++ 
b/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/main/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProvider.java
@@ -52,9 +52,12 @@
 import org.apache.zookeeper.metrics.Summary;
 import org.apache.zookeeper.metrics.SummarySet;
 import org.apache.zookeeper.server.RateLogger;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.security.Constraint;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -134,6 +137,7 @@ public void start() throws 
MetricsProviderLifeCycleException {
             server = new Server(new InetSocketAddress(host, port));
             ServletContextHandler context = new ServletContextHandler();
             context.setContextPath("/");
+            constrainTraceMethod(context);
             server.setHandler(context);
             context.addServlet(new ServletHolder(servlet), "/metrics");
             server.start();
@@ -235,6 +239,25 @@ public void resetAllValues() {
         // not supported on Prometheus
     }
 
+    /**
+     * Add constraint to a given context to disallow TRACE method.
+     * @param ctxHandler the context to modify
+     */
+    private void constrainTraceMethod(ServletContextHandler ctxHandler) {
+        Constraint c = new Constraint();
+        c.setAuthenticate(true);
+
+        ConstraintMapping cmt = new ConstraintMapping();
+        cmt.setConstraint(c);
+        cmt.setMethod("TRACE");
+        cmt.setPathSpec("/*");
+
+        ConstraintSecurityHandler securityHandler = new 
ConstraintSecurityHandler();
+        securityHandler.setConstraintMappings(new ConstraintMapping[] {cmt});
+
+        ctxHandler.setSecurityHandler(securityHandler);
+    }
+
     private class Context implements MetricsContext {
 
         private final ConcurrentMap<String, PrometheusGaugeWrapper> gauges = 
new ConcurrentHashMap<>();
diff --git 
a/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProviderTest.java
 
b/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProviderTest.java
index 9284f52bb..eb9cf8bd2 100644
--- 
a/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProviderTest.java
+++ 
b/zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProviderTest.java
@@ -31,6 +31,9 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -50,7 +53,10 @@
 import org.apache.zookeeper.metrics.Summary;
 import org.apache.zookeeper.metrics.SummarySet;
 import org.apache.zookeeper.server.util.QuotaMetricsUtils;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
 import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -61,6 +67,7 @@
  */
 public class PrometheusMetricsProviderTest {
 
+    private static final String URL_FORMAT = "http://localhost:%d/metrics";;
     private PrometheusMetricsProvider provider;
 
     @BeforeEach
@@ -395,6 +402,23 @@ public void testAdvancedSummary() throws Exception {
         assertThat(res, CoreMatchers.containsString("cc{quantile=\"0.99\",} 
10.0"));
     }
 
+    /**
+     * Using TRACE method to visit metrics provider, the response should be 
403 forbidden.
+     */
+    @Test
+    public void testTraceCall() throws IOException, IllegalAccessException, 
NoSuchFieldException {
+        Field privateServerField = 
provider.getClass().getDeclaredField("server");
+        privateServerField.setAccessible(true);
+        Server server = (Server) privateServerField.get(provider);
+        int port = ((ServerConnector) 
server.getConnectors()[0]).getLocalPort();
+
+        String metricsUrl = String.format(URL_FORMAT, port);
+        HttpURLConnection conn = (HttpURLConnection) new 
URL(metricsUrl).openConnection();
+        conn.setRequestMethod("TRACE");
+        conn.connect();
+        Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, 
conn.getResponseCode());
+    }
+
     @Test
     public void testSummary_asyncAndExceedMaxQueueSize() throws Exception {
         final Properties config = new Properties();

Reply via email to