This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new ff20bbf315d Metric connection security enhanced (#16379)
ff20bbf315d is described below
commit ff20bbf315d67fd8a1c5f311fa72b5488eb84ebd
Author: Haonan <[email protected]>
AuthorDate: Wed Sep 10 16:21:58 2025 +0800
Metric connection security enhanced (#16379)
* dev
* dev function
* function works
* dev
* finish config
* finish config
* remove switch
* fix pom issue
---
iotdb-core/metrics/interface/pom.xml | 4 ++
.../apache/iotdb/metrics/config/MetricConfig.java | 54 ++++++++++++++++++-
.../metrics/config/MetricConfigDescriptor.java | 13 +++++
.../reporter/iotdb/IoTDBSessionReporter.java | 22 +++++---
.../reporter/prometheus/PrometheusReporter.java | 63 ++++++++++++++++++++--
5 files changed, 145 insertions(+), 11 deletions(-)
diff --git a/iotdb-core/metrics/interface/pom.xml
b/iotdb-core/metrics/interface/pom.xml
index cb53d65b903..1e5028f6859 100644
--- a/iotdb-core/metrics/interface/pom.xml
+++ b/iotdb-core/metrics/interface/pom.xml
@@ -79,6 +79,10 @@
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-handler</artifactId>
+ </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
index 090ef3eae2c..317290e3435 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
@@ -79,6 +79,12 @@ public class MetricConfig {
private long upTimeInNs = 0;
private String internalDatabase = "root.__system";
+ private boolean enableSSL = false;
+ private String keyStorePath = "";
+ private String keyStorePassword = "";
+ private String trustStorePath = "";
+ private String trustStorePassword = "";
+
public MetricConfig() {
// try to get pid of iotdb instance
try {
@@ -95,7 +101,7 @@ public class MetricConfig {
public void setMetricReporterList(String metricReporterList) {
this.metricReporterList = new ArrayList<>();
for (String type : metricReporterList.split(",")) {
- if (type.trim().length() != 0) {
+ if (!type.trim().isEmpty()) {
this.metricReporterList.add(ReporterType.valueOf(type));
}
}
@@ -163,6 +169,46 @@ public class MetricConfig {
this.prometheusReporterPassword = prometheusReporterPassword;
}
+ public boolean isEnableSSL() {
+ return enableSSL;
+ }
+
+ public void setEnableSSL(boolean enableSSL) {
+ this.enableSSL = enableSSL;
+ }
+
+ public String getKeyStorePath() {
+ return keyStorePath;
+ }
+
+ public void setKeyStorePath(String keyStorePath) {
+ this.keyStorePath = keyStorePath;
+ }
+
+ public String getKeyStorePassword() {
+ return keyStorePassword;
+ }
+
+ public void setKeyStorePassword(String keyStorePassword) {
+ this.keyStorePassword = keyStorePassword;
+ }
+
+ public String getTrustStorePath() {
+ return trustStorePath;
+ }
+
+ public void setTrustStorePath(String trustStorePath) {
+ this.trustStorePath = trustStorePath;
+ }
+
+ public String getTrustStorePassword() {
+ return trustStorePassword;
+ }
+
+ public void setTrustStorePassword(String trustStorePassword) {
+ this.trustStorePassword = trustStorePassword;
+ }
+
public IoTDBReporterConfig getIoTDBReporterConfig() {
return iotdbReporterConfig;
}
@@ -221,6 +267,12 @@ public class MetricConfig {
prometheusReporterPassword =
newMetricConfig.getPrometheusReporterPassword();
internalReporterType = newMetricConfig.getInternalReportType();
+ enableSSL = newMetricConfig.isEnableSSL();
+ keyStorePath = newMetricConfig.getKeyStorePath();
+ keyStorePassword = newMetricConfig.getKeyStorePassword();
+ trustStorePath = newMetricConfig.getTrustStorePath();
+ trustStorePassword = newMetricConfig.getTrustStorePassword();
+
iotdbReporterConfig.copy(newMetricConfig.getIoTDBReporterConfig());
}
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
index 2cc5c2a986d..def3d1e50c0 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
@@ -124,6 +124,19 @@ public class MetricConfigDescriptor {
loadConfig.getPrometheusReporterPassword(),
properties));
+ loadConfig.setKeyStorePath(
+ getPropertyWithoutPrefix("key_store_path",
loadConfig.getKeyStorePath(), properties));
+
+ loadConfig.setKeyStorePassword(
+ getPropertyWithoutPrefix("key_store_pwd",
loadConfig.getKeyStorePassword(), properties));
+
+ loadConfig.setTrustStorePath(
+ getPropertyWithoutPrefix("trust_store_path",
loadConfig.getTrustStorePath(), properties));
+
+ loadConfig.setTrustStorePassword(
+ getPropertyWithoutPrefix(
+ "trust_store_pwd", loadConfig.getTrustStorePassword(),
properties));
+
IoTDBReporterConfig reporterConfig = loadConfig.getIoTDBReporterConfig();
reporterConfig.setHost(
getProperty(
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java
index b70ecebfff2..62392b8b124 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java
@@ -62,13 +62,21 @@ public class IoTDBSessionReporter extends IoTDBReporter {
public IoTDBSessionReporter(AbstractMetricManager metricManager) {
this.metricManager = metricManager;
- this.sessionPool =
- new SessionPool(
- ioTDBReporterConfig.getHost(),
- ioTDBReporterConfig.getPort(),
- ioTDBReporterConfig.getUsername(),
- ioTDBReporterConfig.getPassword(),
- ioTDBReporterConfig.getMaxConnectionNumber());
+ SessionPool.Builder sessionPoolBuilder =
+ new SessionPool.Builder()
+ .host(ioTDBReporterConfig.getHost())
+ .port(ioTDBReporterConfig.getPort())
+ .user(ioTDBReporterConfig.getUsername())
+ .password(ioTDBReporterConfig.getPassword())
+ .maxSize(ioTDBReporterConfig.getMaxConnectionNumber());
+ if (metricConfig.isEnableSSL()) {
+ sessionPoolBuilder =
+ sessionPoolBuilder
+ .useSSL(true)
+ .trustStore(metricConfig.getTrustStorePath())
+ .trustStorePwd(metricConfig.getTrustStorePassword());
+ }
+ this.sessionPool = sessionPoolBuilder.build();
try (SessionDataSetWrapper result =
this.sessionPool.executeQueryStatement(
"SHOW DATABASES " + metricConfig.getInternalDatabase())) {
diff --git
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
index 9bc8f2d9cae..1e0c33d61c2 100644
---
a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
+++
b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/prometheus/PrometheusReporter.java
@@ -39,6 +39,9 @@ import io.netty.channel.ChannelOption;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.ssl.ClientAuth;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,10 +51,15 @@ import reactor.netty.http.server.HttpServer;
import reactor.netty.http.server.HttpServerRequest;
import reactor.netty.http.server.HttpServerResponse;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
+import java.security.KeyStore;
import java.time.Duration;
import java.util.Base64;
import java.util.HashMap;
@@ -81,7 +89,7 @@ public class PrometheusReporter implements Reporter {
return false;
}
try {
- httpServer =
+ HttpServer serverTransport =
HttpServer.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
.channelGroup(new
DefaultChannelGroup(GlobalEventExecutor.INSTANCE))
@@ -97,8 +105,22 @@ public class PrometheusReporter implements Reporter {
}
return res.header(HttpHeaderNames.CONTENT_TYPE,
"text/plain")
.sendString(Mono.just(scrape()));
- }))
- .bindNow();
+ }));
+ if (METRIC_CONFIG.isEnableSSL()) {
+ SslContext sslContext;
+ try {
+ sslContext =
+ createSslContext(
+ METRIC_CONFIG.getKeyStorePath(),
+ METRIC_CONFIG.getKeyStorePassword(),
+ METRIC_CONFIG.getTrustStorePath(),
+ METRIC_CONFIG.getTrustStorePassword());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ serverTransport = serverTransport.secure(spec ->
spec.sslContext(sslContext));
+ }
+ httpServer = serverTransport.bindNow();
} catch (Throwable e) {
// catch Throwable rather than Exception here because the code above
might cause a
// NoClassDefFoundError
@@ -257,6 +279,41 @@ public class PrometheusReporter implements Reporter {
return result;
}
+ private SslContext createSslContext(
+ String keystorePath,
+ String keystorePassword,
+ String truststorePath,
+ String truststorePassword)
+ throws Exception {
+ SslContextBuilder sslContextBuilder = null;
+ if (keystorePath != null && keystorePassword != null) {
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(keystorePath)) {
+ keyStore.load(fis, keystorePassword.toCharArray());
+ }
+ KeyManagerFactory kmf =
+
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(keyStore, keystorePassword.toCharArray());
+ sslContextBuilder = SslContextBuilder.forServer(kmf);
+ }
+
+ if (sslContextBuilder != null && truststorePath != null &&
truststorePassword != null) {
+ KeyStore trustStore = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(truststorePath)) {
+ trustStore.load(fis, truststorePassword.toCharArray());
+ }
+ TrustManagerFactory tmf =
+
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(trustStore);
+ sslContextBuilder.trustManager(tmf);
+ }
+ if (sslContextBuilder == null) {
+ throw new Exception("Keystore or Truststore is null");
+ }
+ sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
+ return sslContextBuilder.build();
+ }
+
@Override
public boolean stop() {
if (httpServer != null) {