Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
Expand Down Expand Up @@ -136,7 +137,7 @@ protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws

@Override
public void configure(Properties configuration) throws MetricsProviderLifeCycleException {
LOG.info("Initializing Prometheus metrics with Jetty, configuration: {}", configuration);
LOG.info("Initializing Prometheus metrics with Jetty, configuration: {}", redactSensitiveValues(configuration));

this.host = configuration.getProperty(HTTP_HOST, "0.0.0.0");
this.httpPort = Integer.parseInt(configuration.getProperty(HTTP_PORT, "-1"));
Expand Down Expand Up @@ -528,13 +529,13 @@ public SummarySet getSummarySet(String name, DetailLevel detailLevel) {
return new PrometheusLabelledSummaryWrapper(prometheusSummary);
});
}

}

// --- Wrapper classes to adapt Prometheus metrics to ZooKeeper's metric interfaces ---

private static class PrometheusCounterWrapper implements Counter {
private final io.prometheus.metrics.core.metrics.Counter prometheusCounter;

private final io.prometheus.metrics.core.metrics.Counter prometheusCounter;
public PrometheusCounterWrapper(io.prometheus.metrics.core.metrics.Counter prometheusCounter) {
this.prometheusCounter = prometheusCounter;
}
Expand Down Expand Up @@ -602,4 +603,20 @@ public void add(String key, long value) {
this.prometheusSummary.labelValues(key).observe(value);
}
}

private static Properties redactSensitiveValues(Properties configuration) {
Properties redactedConfig = new Properties();
configuration.forEach((k, v) -> redactedConfig.put(k, logRedactor((String) k, (String) v)));
return redactedConfig;
}

private static String logRedactor(String key, String value) {
if (key == null) {
return value;
}
if (key.toLowerCase(Locale.ROOT).endsWith("password")) {
return "***";
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
Expand All @@ -36,6 +41,7 @@
import org.apache.zookeeper.metrics.Counter;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;

/**
* Tests about Prometheus Metrics Provider. Please note that we are not testing Prometheus but only our integration.
Expand Down Expand Up @@ -176,4 +182,39 @@ private void validateMetricResponse(String response) throws IOException {
assertThat(response, containsString("# TYPE cc_total counter"));
assertThat(response, containsString("cc_total 10.0"));
}

@Test
void testLogRedactorRedactsPasswords() throws Exception {
Logger logger = (Logger) LoggerFactory.getLogger(PrometheusMetricsProvider.class);
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
listAppender.start();
logger.addAppender(listAppender);

try {
provider = new PrometheusMetricsProvider();
Properties configuration = new Properties();
configuration.setProperty("httpPort", String.valueOf(httpPort));
configuration.setProperty("httpsPort", String.valueOf(httpsPort));
configuration.setProperty("ssl.keyStore.location", testDataPath + "/ssl/server_keystore.jks");
configuration.setProperty("ssl.keyStore.password", "SuperSecret123!");
configuration.setProperty("ssl.trustStore.location", testDataPath + "/ssl/server_truststore.jks");
configuration.setProperty("ssl.trustStore.password", "AnotherSecret456!");
provider.configure(configuration);

String logOutput = listAppender.list.stream()
.map(ILoggingEvent::getFormattedMessage)
.filter(msg -> msg.contains("configuration"))
.findFirst()
.orElse("");

assertFalse(logOutput.contains("SuperSecret123!"),
"Logs should not contain keyStore password");
assertFalse(logOutput.contains("AnotherSecret456!"),
"Logs should not contain trustStore password");
assertTrue(logOutput.contains(testDataPath + "/ssl/server_keystore.jks"),
"Logs should still contain non-sensitive config like keyStore location");
} finally {
logger.detachAppender(listAppender);
}
}
}
Loading