diff options
author | doxsch <28098153+doxsch@users.noreply.github.com> | 2023-03-08 14:08:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-08 14:08:29 +0100 |
commit | f46b8fb87ff3b06bab58bb6fcb73439a86bf9ab3 (patch) | |
tree | 6166578e3a090488dae4d622002de31791c27461 | |
parent | 16227468d64dd7e1744517a2e587099d5501c0c1 (diff) | |
download | zookeeper-f46b8fb87ff3b06bab58bb6fcb73439a86bf9ab3.tar.gz |
ZOOKEEPER-3731: Disallow HTTP TRACE method on PrometheusMetrics Server (#1682)
2 files changed, 47 insertions, 0 deletions
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.MetricsProviderLifeCycleException; 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 class PrometheusMetricsProvider implements MetricsProvider { 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 class PrometheusMetricsProvider implements MetricsProvider { // 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 io.prometheus.client.CollectorRegistry; 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.MetricsContext; 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 @@ import org.junit.jupiter.api.Test; */ public class PrometheusMetricsProviderTest { + private static final String URL_FORMAT = "http://localhost:%d/metrics"; private PrometheusMetricsProvider provider; @BeforeEach @@ -395,6 +402,23 @@ public class PrometheusMetricsProviderTest { 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(); |