This is an automated email from the ASF dual-hosted git repository.

liyuheng pushed a commit to branch Working/prometheus-add-auth
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit f74e7904fa189d283398c44a644715d5ab9637e9
Author: liyuheng <[email protected]>
AuthorDate: Fri Apr 18 12:10:48 2025 +0800

    add test
---
 .../it/env/cluster/config/MppConfigNodeConfig.java | 12 +++++
 .../it/env/cluster/config/MppDataNodeConfig.java   | 12 +++++
 .../iotdb/it/env/cluster/env/AbstractEnv.java      |  8 +--
 .../env/remote/config/RemoteConfigNodeConfig.java  | 10 ++++
 .../it/env/remote/config/RemoteDataNodeConfig.java | 10 ++++
 .../iotdb/it/env/remote/env/RemoteServerEnv.java   |  8 +--
 .../java/org/apache/iotdb/itbase/env/BaseEnv.java  |  9 +++-
 .../apache/iotdb/itbase/env/ConfigNodeConfig.java  |  5 ++
 .../apache/iotdb/itbase/env/DataNodeConfig.java    |  4 ++
 .../apache/iotdb/db/it/metric/IoTDBMetricIT.java   | 56 +++++++++++++++++++--
 .../apache/iotdb/metrics/config/MetricConfig.java  |  2 +-
 .../metrics/config/MetricConfigDescriptor.java     | 21 ++++++--
 .../reporter/prometheus/PrometheusReporter.java    | 57 +++++++++++++---------
 .../conf/iotdb-system.properties.template          | 14 +++---
 14 files changed, 184 insertions(+), 44 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppConfigNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppConfigNodeConfig.java
index 62ccbb0aa4f..8e4a6def365 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppConfigNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppConfigNodeConfig.java
@@ -55,4 +55,16 @@ public class MppConfigNodeConfig extends MppBaseConfig 
implements ConfigNodeConf
     properties.setProperty("cn_metric_reporter_list", String.join(",", 
metricReporterTypes));
     return this;
   }
+
+  @Override
+  public ConfigNodeConfig setMetricPrometheusReporterUsername(String username) 
{
+    properties.setProperty("metric_prometheus_reporter_username", username);
+    return this;
+  }
+
+  @Override
+  public ConfigNodeConfig setMetricPrometheusReporterPassword(String password) 
{
+    properties.setProperty("metric_prometheus_reporter_password", password);
+    return this;
+  }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppDataNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppDataNodeConfig.java
index 19dada3d06a..5f51e486dd8 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppDataNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppDataNodeConfig.java
@@ -56,6 +56,18 @@ public class MppDataNodeConfig extends MppBaseConfig 
implements DataNodeConfig {
     return this;
   }
 
+  @Override
+  public DataNodeConfig setMetricPrometheusReporterUsername(String username) {
+    properties.setProperty("metric_prometheus_reporter_username", username);
+    return this;
+  }
+
+  @Override
+  public DataNodeConfig setMetricPrometheusReporterPassword(String password) {
+    properties.setProperty("metric_prometheus_reporter_password", password);
+    return this;
+  }
+
   @Override
   public DataNodeConfig setEnableRestService(boolean enableRestService) {
     properties.setProperty("enable_rest_service", 
String.valueOf(enableRestService));
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
index a255dde2291..5511ecfc982 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java
@@ -118,7 +118,7 @@ public abstract class AbstractEnv implements BaseEnv {
   }
 
   @Override
-  public List<String> getMetricPrometheusReporterContents() {
+  public List<String> getMetricPrometheusReporterContents(String authHeader) {
     final List<String> result = new ArrayList<>();
     // get all report content of confignodes
     for (final ConfigNodeWrapper configNode : this.configNodeWrapperList) {
@@ -128,7 +128,8 @@ public abstract class AbstractEnv implements BaseEnv {
                   + configNode.getIp()
                   + ":"
                   + configNode.getMetricPort()
-                  + "/metrics");
+                  + "/metrics",
+              authHeader);
       result.add(configNodeMetricContent);
     }
     // get all report content of datanodes
@@ -139,7 +140,8 @@ public abstract class AbstractEnv implements BaseEnv {
                   + dataNode.getIp()
                   + ":"
                   + dataNode.getMetricPort()
-                  + "/metrics");
+                  + "/metrics",
+              authHeader);
       result.add(dataNodeMetricContent);
     }
     return result;
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteConfigNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteConfigNodeConfig.java
index 33a6bc48afd..ae8645eff52 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteConfigNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteConfigNodeConfig.java
@@ -28,4 +28,14 @@ public class RemoteConfigNodeConfig implements 
ConfigNodeConfig {
   public ConfigNodeConfig setMetricReporterType(List<String> 
metricReporterTypes) {
     return this;
   }
+
+  @Override
+  public ConfigNodeConfig setMetricPrometheusReporterUsername(String username) 
{
+    return this;
+  }
+
+  @Override
+  public ConfigNodeConfig setMetricPrometheusReporterPassword(String password) 
{
+    return this;
+  }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteDataNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteDataNodeConfig.java
index b109baa8203..c273daba49e 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteDataNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteDataNodeConfig.java
@@ -28,6 +28,16 @@ public class RemoteDataNodeConfig implements DataNodeConfig {
     return this;
   }
 
+  @Override
+  public DataNodeConfig setMetricPrometheusReporterUsername(String username) {
+    return this;
+  }
+
+  @Override
+  public DataNodeConfig setMetricPrometheusReporterPassword(String password) {
+    return this;
+  }
+
   @Override
   public DataNodeConfig setEnableRestService(boolean enableRestService) {
     return this;
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
index f0daa951e82..c47e5ce94c6 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java
@@ -112,14 +112,16 @@ public class RemoteServerEnv implements BaseEnv {
   }
 
   @Override
-  public List<String> getMetricPrometheusReporterContents() {
+  public List<String> getMetricPrometheusReporterContents(String authHeader) {
     List<String> result = new ArrayList<>();
     result.add(
         getUrlContent(
-            Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + 
configNodeMetricPort + "/metrics"));
+            Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + 
configNodeMetricPort + "/metrics",
+            authHeader));
     result.add(
         getUrlContent(
-            Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + dataNodeMetricPort 
+ "/metrics"));
+            Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + dataNodeMetricPort 
+ "/metrics",
+            authHeader));
     return result;
   }
 
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
index 0cae6d1fa25..c312d57b532 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
@@ -34,6 +34,8 @@ import org.apache.iotdb.jdbc.Config;
 import org.apache.iotdb.jdbc.Constant;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 
+import reactor.util.annotation.Nullable;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -79,11 +81,14 @@ public interface BaseEnv {
   /** Return the {@link ClusterConfig} for developers to set values before 
test. */
   ClusterConfig getConfig();
 
-  default String getUrlContent(String urlStr) {
+  default String getUrlContent(String urlStr, @Nullable String authHeader) {
     StringBuilder sb = new StringBuilder();
     try {
       URL url = new URL(urlStr);
       HttpURLConnection httpConnection = (HttpURLConnection) 
url.openConnection();
+      if (authHeader != null) {
+        httpConnection.setRequestProperty("Authorization", authHeader);
+      }
       if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
         InputStream in = httpConnection.getInputStream();
         InputStreamReader isr = new InputStreamReader(in);
@@ -105,7 +110,7 @@ public interface BaseEnv {
   }
 
   /** Return the content of prometheus */
-  List<String> getMetricPrometheusReporterContents();
+  List<String> getMetricPrometheusReporterContents(String authHeader);
 
   default Connection getConnection() throws SQLException {
     return getConnection(
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/ConfigNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/ConfigNodeConfig.java
index bf7179ef702..65a5a3271fc 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/ConfigNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/ConfigNodeConfig.java
@@ -23,5 +23,10 @@ import java.util.List;
 
 /** This interface is used to handle properties in 
iotdb-confignode.properties. */
 public interface ConfigNodeConfig {
+
   ConfigNodeConfig setMetricReporterType(List<String> metricReporterTypes);
+
+  ConfigNodeConfig setMetricPrometheusReporterUsername(String username);
+
+  ConfigNodeConfig setMetricPrometheusReporterPassword(String password);
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/DataNodeConfig.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/DataNodeConfig.java
index b8ad5c2f15b..b8c44423bf8 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/DataNodeConfig.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/DataNodeConfig.java
@@ -25,6 +25,10 @@ import java.util.List;
 public interface DataNodeConfig {
   DataNodeConfig setMetricReporterType(List<String> metricReporterTypes);
 
+  DataNodeConfig setMetricPrometheusReporterUsername(String username);
+
+  DataNodeConfig setMetricPrometheusReporterPassword(String password);
+
   DataNodeConfig setEnableRestService(boolean enableRestService);
 
   DataNodeConfig setConnectionTimeoutInMS(int connectionTimeoutInMS);
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/metric/IoTDBMetricIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/metric/IoTDBMetricIT.java
index 76e6ddce817..00d25f75085 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/metric/IoTDBMetricIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/metric/IoTDBMetricIT.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.metrics.reporter.prometheus.PrometheusReporter;
 
 import org.junit.AfterClass;
 import org.junit.Assert;
@@ -33,6 +34,8 @@ import org.junit.runner.RunWith;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
 import java.util.Collections;
 import java.util.List;
 import java.util.regex.Pattern;
@@ -65,6 +68,11 @@ public class IoTDBMetricIT {
   private static final String VALID_LOG_STRING =
       "This line {} is invalid in prometheus line protocol";
 
+  static final String TEST_USERNAME = "good";
+  static final String WRONG_USERNAME = "bad";
+  static final String TEST_PASSWORD = "??";
+  static final String WRONG_PASSWORD = "!!";
+
   public static boolean isValidPrometheusTextFormat(String metrics) {
     String[] lines = metrics.split("\\n");
     boolean valid = true;
@@ -113,12 +121,16 @@ public class IoTDBMetricIT {
     EnvFactory.getEnv()
         .getConfig()
         .getConfigNodeConfig()
-        .setMetricReporterType(Collections.singletonList("PROMETHEUS"));
+        .setMetricReporterType(Collections.singletonList("PROMETHEUS"))
+        .setMetricPrometheusReporterUsername(TEST_USERNAME)
+        .setMetricPrometheusReporterPassword(TEST_PASSWORD);
     // Start DataNode with Prometheus reporter up
     EnvFactory.getEnv()
         .getConfig()
         .getDataNodeConfig()
-        .setMetricReporterType(Collections.singletonList("PROMETHEUS"));
+        .setMetricReporterType(Collections.singletonList("PROMETHEUS"))
+        .setMetricPrometheusReporterUsername(TEST_USERNAME)
+        .setMetricPrometheusReporterPassword(TEST_PASSWORD);
     EnvFactory.getEnv().initClusterEnvironment();
   }
 
@@ -129,11 +141,49 @@ public class IoTDBMetricIT {
 
   @Test
   public void testPrometheusReporter() {
-    List<String> metricContents = 
EnvFactory.getEnv().getMetricPrometheusReporterContents();
+    wrongUsernameTest();
+    wrongPasswordTest();
+    correctUsernameAndPasswordTest();
+  }
+
+  private void wrongUsernameTest() {
+    List<String> metricContents =
+        EnvFactory.getEnv()
+            .getMetricPrometheusReporterContents(
+                buildPrometheusReporterAuthHeader(WRONG_USERNAME, 
TEST_PASSWORD));
+    for (String metricContent : metricContents) {
+      Assert.assertNull(metricContent);
+    }
+  }
+
+  private void wrongPasswordTest() {
+    List<String> metricContents =
+        EnvFactory.getEnv()
+            .getMetricPrometheusReporterContents(
+                buildPrometheusReporterAuthHeader(TEST_USERNAME, 
WRONG_PASSWORD));
+    for (String metricContent : metricContents) {
+      Assert.assertNull(metricContent);
+    }
+  }
+
+  private void correctUsernameAndPasswordTest() {
+    List<String> metricContents =
+        EnvFactory.getEnv()
+            .getMetricPrometheusReporterContents(
+                buildPrometheusReporterAuthHeader(TEST_USERNAME, 
TEST_PASSWORD));
     for (String metricContent : metricContents) {
       Assert.assertNotNull(metricContent);
       Assert.assertNotEquals(0, metricContent.length());
       Assert.assertTrue(isValidPrometheusTextFormat(metricContent));
     }
   }
+
+  private String buildPrometheusReporterAuthHeader(String username, String 
password) {
+    if (username == null || username.isEmpty()) {
+      return null;
+    }
+    String raw = username + 
PrometheusReporter.DIVIDER_BETWEEN_USERNAME_AND_DIVIDER + password;
+    String base64 = 
Base64.getEncoder().encodeToString(raw.getBytes(StandardCharsets.UTF_8));
+    return PrometheusReporter.BASIC_AUTH_PREFIX + base64;
+  }
 }
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 fcd1d8b3f14..593e36fbeca 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
@@ -132,7 +132,7 @@ public class MetricConfig {
   }
 
   public boolean prometheusNeedAuth() {
-    return !Objects.equals(prometheusReporterUsername, "") || 
!Objects.equals(prometheusReporterPassword, "");
+    return prometheusReporterUsername != null && 
!prometheusReporterUsername.isEmpty();
   }
 
   public String getPrometheusReporterUsername() {
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 b881ef31bd4..2cc5c2a986d 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
@@ -112,9 +112,17 @@ public class MetricConfigDescriptor {
                 properties,
                 isConfigNode)));
 
-    
loadConfig.setPrometheusReporterUsername(properties.getProperty("metric_prometheus_reporter_username",
 loadConfig.getPrometheusReporterUsername()));
-
-    
loadConfig.setPrometheusReporterPassword(properties.getProperty("metric_prometheus_reporter_password",
 loadConfig.getPrometheusReporterPassword()));
+    loadConfig.setPrometheusReporterUsername(
+        getPropertyWithoutPrefix(
+            "metric_prometheus_reporter_username",
+            loadConfig.getPrometheusReporterUsername(),
+            properties));
+
+    loadConfig.setPrometheusReporterPassword(
+        getPropertyWithoutPrefix(
+            "metric_prometheus_reporter_password",
+            loadConfig.getPrometheusReporterPassword(),
+            properties));
 
     IoTDBReporterConfig reporterConfig = loadConfig.getIoTDBReporterConfig();
     reporterConfig.setHost(
@@ -185,6 +193,13 @@ public class MetricConfigDescriptor {
         .orElse(defaultValue);
   }
 
+  private String getPropertyWithoutPrefix(
+      String target, String defaultValue, Properties properties) {
+    return Optional.ofNullable(properties.getProperty(target, defaultValue))
+        .map(String::trim)
+        .orElse(defaultValue);
+  }
+
   private static class MetricConfigDescriptorHolder {
     private static final MetricConfigDescriptor INSTANCE = new 
MetricConfigDescriptor();
   }
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 07ffc147600..0bc8bee164e 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
@@ -19,8 +19,6 @@
 
 package org.apache.iotdb.metrics.reporter.prometheus;
 
-import io.netty.handler.codec.http.HttpHeaderNames;
-import io.netty.handler.codec.http.HttpResponseStatus;
 import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfig;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
@@ -39,6 +37,8 @@ import org.apache.iotdb.metrics.utils.ReporterType;
 
 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.util.concurrent.GlobalEventExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,6 +66,8 @@ public class PrometheusReporter implements Reporter {
   private DisposableServer httpServer;
 
   private static final String REALM = "metrics";
+  public static final String BASIC_AUTH_PREFIX = "Basic ";
+  public static final char DIVIDER_BETWEEN_USERNAME_AND_DIVIDER = ':';
 
   public PrometheusReporter(AbstractMetricManager metricManager) {
     this.metricManager = metricManager;
@@ -84,13 +86,18 @@ public class PrometheusReporter implements Reporter {
               .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
               .channelGroup(new 
DefaultChannelGroup(GlobalEventExecutor.INSTANCE))
               .port(METRIC_CONFIG.getPrometheusReporterPort())
-                  .route(routes -> routes.get("/metrics", (req, res) -> {
-                    if (!authenticate(req, res)) {
-                      return Mono.empty();    // authenticate not pass
-                    }
-                    return res.header(HttpHeaderNames.CONTENT_TYPE, 
"text/plain")
-                            .sendString(Mono.just(scrape()));
-                  }))
+              .route(
+                  routes ->
+                      routes.get(
+                          "/metrics",
+                          (req, res) -> {
+                            if (!authenticate(req, res)) {
+                              // authenticate not pass
+                              return Mono.empty();
+                            }
+                            return res.header(HttpHeaderNames.CONTENT_TYPE, 
"text/plain")
+                                .sendString(Mono.just(scrape()));
+                          }))
               .bindNow();
     } catch (Throwable e) {
       // catch Throwable rather than Exception here because the code above 
might cause a
@@ -110,31 +117,37 @@ public class PrometheusReporter implements Reporter {
     }
 
     String header = req.requestHeaders().get(HttpHeaderNames.AUTHORIZATION);
-    if (header == null || !header.startsWith("Basic ")) {
+    if (header == null || !header.startsWith(BASIC_AUTH_PREFIX)) {
       return authenticateFailed(res);
     }
 
-    // base64String is expected like "Basic dXNlcjpwYXNzd29yZA=="
-    String base64String = header.substring("Basic ".length());
-    // decodedString is expected like "user:123456"
-    String decodedString = new 
String(Base64.getDecoder().decode(base64String), StandardCharsets.UTF_8);
-    int idx = decodedString.indexOf(':');
-    if (idx < 0) {
-      LOGGER.info("Unexpected auth string: {}", decodedString);
+    // base64 decoding
+    // base64String is expected as "Basic dXNlcjpwYXNzd29yZA=="
+    String base64String = header.substring(BASIC_AUTH_PREFIX.length());
+    // decodedString is expected as "username:password"
+    String decodedString =
+        new String(Base64.getDecoder().decode(base64String), 
StandardCharsets.UTF_8);
+    int dividerIndex = 
decodedString.indexOf(DIVIDER_BETWEEN_USERNAME_AND_DIVIDER);
+    if (dividerIndex < 0) {
+      LOGGER.warn("Unexpected auth string: {}", decodedString);
       return authenticateFailed(res);
     }
 
-    String username = decodedString.substring(0, idx);
-    String password  = decodedString.substring(idx + 1);
-    if (!METRIC_CONFIG.getPrometheusReporterUsername().equals(username) || 
!METRIC_CONFIG.getPrometheusReporterPassword().equals(password)) {
+    // check username and password
+    String username = decodedString.substring(0, dividerIndex);
+    String password = decodedString.substring(dividerIndex + 1);
+    if (!METRIC_CONFIG.getPrometheusReporterUsername().equals(username)
+        || !METRIC_CONFIG.getPrometheusReporterPassword().equals(password)) {
       return authenticateFailed(res);
     }
+
     return true;
   }
 
   private boolean authenticateFailed(HttpServerResponse response) {
-    response.status(HttpResponseStatus.UNAUTHORIZED)
-            .addHeader(HttpHeaderNames.WWW_AUTHENTICATE, "Basic realm=\"" + 
REALM + "\"");
+    response
+        .status(HttpResponseStatus.UNAUTHORIZED)
+        .addHeader(HttpHeaderNames.WWW_AUTHENTICATE, "Basic realm=\"" + REALM 
+ "\"");
     return false;
   }
 
diff --git 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
index e85d431595e..54ba688f76e 100644
--- 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
+++ 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
@@ -371,6 +371,13 @@ 
iot_consensus_v2_deletion_file_dir=data/datanode/system/pipe/consensus/deletion
 ### Metric Configuration
 ####################
 
+# The username for the prometheus port of both the ConfigNode and the DataNode.
+# If left unset, the prometheus port can be accessed without authentication.
+metric_prometheus_reporter_username=
+
+# The password for the prometheus port of both the ConfigNode and the DataNode.
+metric_prometheus_reporter_password=
+
 # The reporters of metric module to report metrics
 # If there are more than one reporter, please separate them by commas ",".
 # Options: [JMX, PROMETHEUS]
@@ -394,13 +401,6 @@ cn_metric_async_collect_period=5
 # Datatype: int
 cn_metric_prometheus_reporter_port=9091
 
-# The username for the Prometheus port of both the ConfigNode and the DataNode.
-# If left unset, the Prometheus port can be accessed without authentication.
-metric_prometheus_reporter_username=
-
-# The password for the Prometheus port of both the ConfigNode and the DataNode.
-metric_prometheus_reporter_password=
-
 # The reporters of metric module to report metrics
 # If there are more than one reporter, please separate them by commas ",".
 # Options: [JMX, PROMETHEUS]

Reply via email to