Skip to content

Commit

Permalink
ZOOKEEPER-3731: Disallow HTTP TRACE method on PrometheusMetrics Server (
Browse files Browse the repository at this point in the history
  • Loading branch information
doxsch authored Mar 8, 2023
1 parent 1622746 commit f46b8fb
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -61,6 +67,7 @@
*/
public class PrometheusMetricsProviderTest {

private static final String URL_FORMAT = "http://localhost:%d/metrics";
private PrometheusMetricsProvider provider;

@BeforeEach
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit f46b8fb

Please sign in to comment.