Skip to content

Commit 1c3e4dd

Browse files
committed
ZOOKEEPER-5029: Port unification for PrometheusMetricsProvider
1 parent 6c4fabf commit 1c3e4dd

3 files changed

Lines changed: 73 additions & 17 deletions

File tree

zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/main/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProvider.java

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
import org.apache.zookeeper.metrics.MetricsProviderLifeCycleException;
4242
import org.apache.zookeeper.metrics.Summary;
4343
import org.apache.zookeeper.metrics.SummarySet;
44+
import org.apache.zookeeper.server.admin.UnifiedConnectionFactory;
45+
import org.eclipse.jetty.http.HttpVersion;
46+
import org.eclipse.jetty.server.HttpConfiguration;
47+
import org.eclipse.jetty.server.HttpConnectionFactory;
48+
import org.eclipse.jetty.server.SecureRequestCustomizer;
4449
import org.eclipse.jetty.server.Server;
4550
import org.eclipse.jetty.server.ServerConnector;
4651
import org.eclipse.jetty.servlet.ServletContextHandler;
@@ -84,6 +89,7 @@ public class PrometheusMetricsProvider implements MetricsProvider {
8489
private boolean wantClientAuth = true; // Secure default
8590
private String enabledProtocols;
8691
private String cipherSuites;
92+
private int httpVersion;
8793

8894
// Constants for configuration
8995
public static final String HTTP_HOST = "httpHost";
@@ -101,7 +107,10 @@ public class PrometheusMetricsProvider implements MetricsProvider {
101107
public static final String SSL_WANT_CLIENT_AUTH = "ssl.want.client.auth";
102108
public static final String SSL_ENABLED_PROTOCOLS = "ssl.enabledProtocols";
103109
public static final String SSL_ENABLED_CIPHERS = "ssl.ciphersuites";
110+
public static final String HTTP_VERSION = "httpVersion";
104111
public static final int SCAN_INTERVAL = 60 * 10; // 10 minutes
112+
public static final int DEFAULT_HTTP_VERSION = 11; // based on HttpVersion.java in jetty
113+
public static final int DEFAULT_STS_MAX_AGE = 1 * 24 * 60 * 60; // seconds in a day
105114

106115
/**
107116
* Custom servlet to disable the TRACE method for security reasons.
@@ -139,6 +148,7 @@ public void configure(Properties configuration) throws MetricsProviderLifeCycleE
139148
this.wantClientAuth = Boolean.parseBoolean(configuration.getProperty(SSL_WANT_CLIENT_AUTH, "true"));
140149
this.enabledProtocols = configuration.getProperty(SSL_ENABLED_PROTOCOLS);
141150
this.cipherSuites = configuration.getProperty(SSL_ENABLED_CIPHERS);
151+
this.httpVersion = Integer.getInteger(HTTP_VERSION, DEFAULT_HTTP_VERSION);
142152
}
143153

144154
// Validate that at least one port is configured.
@@ -171,23 +181,47 @@ public void start() throws MetricsProviderLifeCycleException {
171181
int acceptors = 1;
172182
int selectors = 1;
173183

174-
// Configure HTTP connector if enabled
175-
if (this.httpPort != -1) {
176-
ServerConnector httpConnector = new ServerConnector(server, acceptors, selectors);
177-
httpConnector.setPort(this.httpPort);
178-
httpConnector.setHost(this.host);
179-
server.addConnector(httpConnector);
180-
}
184+
ServerConnector connector = null;
185+
186+
if (this.httpPort != -1 && this.httpsPort != -1 && this.httpPort == this.httpsPort) {
187+
SecureRequestCustomizer customizer = new SecureRequestCustomizer();
188+
customizer.setStsMaxAge(DEFAULT_STS_MAX_AGE);
189+
customizer.setStsIncludeSubDomains(true);
190+
191+
HttpConfiguration config = new HttpConfiguration();
192+
config.setSecureScheme("https");
193+
config.addCustomizer(customizer);
181194

182-
// Configure HTTPS connector if enabled
183-
if (this.httpsPort != -1) {
184195
SslContextFactory.Server sslContextFactory = createSslContextFactory();
185-
KeyStoreScanner keystoreScanner = new KeyStoreScanner(sslContextFactory);
186-
keystoreScanner.setScanInterval(SCAN_INTERVAL);
187-
server.addBean(keystoreScanner);
188-
server.addConnector(createSslConnector(server, acceptors, selectors, sslContextFactory));
196+
setKeyStoreScanner(sslContextFactory);
197+
198+
String nextProtocol = HttpVersion.fromVersion(httpVersion).asString();
199+
connector = new ServerConnector(server,
200+
new UnifiedConnectionFactory(sslContextFactory, nextProtocol),
201+
new HttpConnectionFactory(config));
202+
connector.setPort(this.httpPort);
203+
connector.setHost(this.host);
204+
LOG.debug("Created unified ServerConnector for host: {}, httpPort: {}", host, httpPort);
205+
} else {
206+
// Configure HTTP connector if enabled
207+
if (this.httpPort != -1) {
208+
connector = new ServerConnector(server, acceptors, selectors);
209+
connector.setPort(this.httpPort);
210+
connector.setHost(this.host);
211+
LOG.debug("Created ServerConnector for host: {}, httpPort: {}", host, httpPort);
212+
}
213+
214+
// Configure HTTPS connector if enabled
215+
if (this.httpsPort != -1) {
216+
SslContextFactory.Server sslContextFactory = createSslContextFactory();
217+
setKeyStoreScanner(sslContextFactory);
218+
connector = createSslConnector(server, acceptors, selectors, sslContextFactory);
219+
LOG.debug("Created HTTPS ServerConnector for host: {}, httpsPort: {}", host, httpsPort);
220+
}
189221
}
190222

223+
server.addConnector(connector);
224+
191225
// Set up the servlet context handler
192226
ServletContextHandler context = new ServletContextHandler();
193227
context.setContextPath("/");
@@ -207,6 +241,12 @@ public void start() throws MetricsProviderLifeCycleException {
207241
}
208242
}
209243

244+
private void setKeyStoreScanner(SslContextFactory.Server sslContextFactory) {
245+
KeyStoreScanner keystoreScanner = new KeyStoreScanner(sslContextFactory);
246+
keystoreScanner.setScanInterval(SCAN_INTERVAL);
247+
server.addBean(keystoreScanner);
248+
}
249+
210250
/**
211251
* Creates and configures the SslContextFactory for the server.
212252
*

zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusHttpsMetricsProviderTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
public class PrometheusHttpsMetricsProviderTest extends PrometheusMetricsTestBase {
4444

4545
private PrometheusMetricsProvider provider;
46-
private String httpHost = "127.0.0.1";
47-
private int httpsPort = 4443;
48-
private int httpPort = 4000;
49-
private String testDataPath = System.getProperty("test.data.dir", "src/test/resources/data");
46+
private final String httpHost = "127.0.0.1";
47+
private final int httpsPort = 4443;
48+
private final int httpPort = 4000;
49+
private final String testDataPath = System.getProperty("test.data.dir", "src/test/resources/data");
5050

5151
public void initializeProviderWithCustomConfig(Properties inputConfiguration) throws Exception {
5252
provider = new PrometheusMetricsProvider();

zookeeper-metrics-providers/zookeeper-prometheus-metrics/src/test/java/org/apache/zookeeper/metrics/prometheus/PrometheusMetricsProviderConfigTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,20 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) {
292292
}
293293
};
294294
}
295+
296+
@Test
297+
public void testPortUnification() throws Exception {
298+
int unifiedPort = 5400;
299+
Properties configuration = new Properties();
300+
configuration.setProperty("httpsPort", String.valueOf(unifiedPort));
301+
configuration.setProperty("httpPort", String.valueOf(unifiedPort));
302+
String testDataPath = System.getProperty("test.data.dir", "src/test/resources/data");
303+
configuration.setProperty("ssl.keyStore.location", testDataPath + "/ssl/server_keystore.jks");
304+
configuration.setProperty("ssl.keyStore.password", "testpass");
305+
configuration.setProperty("ssl.trustStore.location", testDataPath + "/ssl/server_truststore.jks");
306+
configuration.setProperty("ssl.trustStore.password", "testpass");
307+
PrometheusMetricsProvider provider = new PrometheusMetricsProvider();
308+
provider.configure(configuration);
309+
provider.start();
310+
}
295311
}

0 commit comments

Comments
 (0)