Skip to content

Commit a17ec67

Browse files
Add authorization for metric prometheus report (apache#15363)
* init * add test * Tan review * add base64 & optimize test
1 parent 923bb2c commit a17ec67

File tree

15 files changed

+296
-21
lines changed

15 files changed

+296
-21
lines changed

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppConfigNodeConfig.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,16 @@ public ConfigNodeConfig setMetricReporterType(List<String> metricReporterTypes)
5555
properties.setProperty("cn_metric_reporter_list", String.join(",", metricReporterTypes));
5656
return this;
5757
}
58+
59+
@Override
60+
public ConfigNodeConfig setMetricPrometheusReporterUsername(String username) {
61+
properties.setProperty("metric_prometheus_reporter_username", username);
62+
return this;
63+
}
64+
65+
@Override
66+
public ConfigNodeConfig setMetricPrometheusReporterPassword(String password) {
67+
properties.setProperty("metric_prometheus_reporter_password", password);
68+
return this;
69+
}
5870
}

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/config/MppDataNodeConfig.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ public DataNodeConfig setMetricReporterType(List<String> metricReporterTypes) {
5656
return this;
5757
}
5858

59+
@Override
60+
public DataNodeConfig setMetricPrometheusReporterUsername(String username) {
61+
properties.setProperty("metric_prometheus_reporter_username", username);
62+
return this;
63+
}
64+
65+
@Override
66+
public DataNodeConfig setMetricPrometheusReporterPassword(String password) {
67+
properties.setProperty("metric_prometheus_reporter_password", password);
68+
return this;
69+
}
70+
5971
@Override
6072
public DataNodeConfig setEnableRestService(boolean enableRestService) {
6173
properties.setProperty("enable_rest_service", String.valueOf(enableRestService));

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public ClusterConfig getConfig() {
118118
}
119119

120120
@Override
121-
public List<String> getMetricPrometheusReporterContents() {
121+
public List<String> getMetricPrometheusReporterContents(String authHeader) {
122122
final List<String> result = new ArrayList<>();
123123
// get all report content of confignodes
124124
for (final ConfigNodeWrapper configNode : this.configNodeWrapperList) {
@@ -128,7 +128,8 @@ public List<String> getMetricPrometheusReporterContents() {
128128
+ configNode.getIp()
129129
+ ":"
130130
+ configNode.getMetricPort()
131-
+ "/metrics");
131+
+ "/metrics",
132+
authHeader);
132133
result.add(configNodeMetricContent);
133134
}
134135
// get all report content of datanodes
@@ -139,7 +140,8 @@ public List<String> getMetricPrometheusReporterContents() {
139140
+ dataNode.getIp()
140141
+ ":"
141142
+ dataNode.getMetricPort()
142-
+ "/metrics");
143+
+ "/metrics",
144+
authHeader);
143145
result.add(dataNodeMetricContent);
144146
}
145147
return result;
@@ -1047,6 +1049,11 @@ public void shutdownAllConfigNodes() {
10471049
configNodeWrapperList.forEach(AbstractNodeWrapper::stop);
10481050
}
10491051

1052+
@Override
1053+
public void shutdownForciblyAllConfigNodes() {
1054+
configNodeWrapperList.forEach(AbstractNodeWrapper::stopForcibly);
1055+
}
1056+
10501057
@Override
10511058
public ConfigNodeWrapper getConfigNodeWrapper(final int index) {
10521059
return configNodeWrapperList.get(index);

integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteConfigNodeConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,14 @@ public class RemoteConfigNodeConfig implements ConfigNodeConfig {
2828
public ConfigNodeConfig setMetricReporterType(List<String> metricReporterTypes) {
2929
return this;
3030
}
31+
32+
@Override
33+
public ConfigNodeConfig setMetricPrometheusReporterUsername(String username) {
34+
return this;
35+
}
36+
37+
@Override
38+
public ConfigNodeConfig setMetricPrometheusReporterPassword(String password) {
39+
return this;
40+
}
3141
}

integration-test/src/main/java/org/apache/iotdb/it/env/remote/config/RemoteDataNodeConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ public DataNodeConfig setMetricReporterType(List<String> metricReporterTypes) {
2828
return this;
2929
}
3030

31+
@Override
32+
public DataNodeConfig setMetricPrometheusReporterUsername(String username) {
33+
return this;
34+
}
35+
36+
@Override
37+
public DataNodeConfig setMetricPrometheusReporterPassword(String password) {
38+
return this;
39+
}
40+
3141
@Override
3242
public DataNodeConfig setEnableRestService(boolean enableRestService) {
3343
return this;

integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,16 @@ public ClusterConfig getConfig() {
112112
}
113113

114114
@Override
115-
public List<String> getMetricPrometheusReporterContents() {
115+
public List<String> getMetricPrometheusReporterContents(String authHeader) {
116116
List<String> result = new ArrayList<>();
117117
result.add(
118118
getUrlContent(
119-
Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + configNodeMetricPort + "/metrics"));
119+
Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + configNodeMetricPort + "/metrics",
120+
authHeader));
120121
result.add(
121122
getUrlContent(
122-
Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + dataNodeMetricPort + "/metrics"));
123+
Config.IOTDB_HTTP_URL_PREFIX + ip_addr + ":" + dataNodeMetricPort + "/metrics",
124+
authHeader));
123125
return result;
124126
}
125127

@@ -392,6 +394,11 @@ public void shutdownAllConfigNodes() {
392394
throw new UnsupportedOperationException();
393395
}
394396

397+
@Override
398+
public void shutdownForciblyAllConfigNodes() {
399+
throw new UnsupportedOperationException();
400+
}
401+
395402
@Override
396403
public void ensureNodeStatus(List<BaseNodeWrapper> nodes, List<NodeStatus> targetStatus) {
397404
throw new UnsupportedOperationException();

integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.apache.iotdb.jdbc.Constant;
3535
import org.apache.iotdb.rpc.IoTDBConnectionException;
3636

37+
import reactor.util.annotation.Nullable;
38+
3739
import java.io.BufferedReader;
3840
import java.io.IOException;
3941
import java.io.InputStream;
@@ -79,11 +81,14 @@ public interface BaseEnv {
7981
/** Return the {@link ClusterConfig} for developers to set values before test. */
8082
ClusterConfig getConfig();
8183

82-
default String getUrlContent(String urlStr) {
84+
default String getUrlContent(String urlStr, @Nullable String authHeader) {
8385
StringBuilder sb = new StringBuilder();
8486
try {
8587
URL url = new URL(urlStr);
8688
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
89+
if (authHeader != null) {
90+
httpConnection.setRequestProperty("Authorization", authHeader);
91+
}
8792
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
8893
InputStream in = httpConnection.getInputStream();
8994
InputStreamReader isr = new InputStreamReader(in);
@@ -105,7 +110,7 @@ default String getUrlContent(String urlStr) {
105110
}
106111

107112
/** Return the content of prometheus */
108-
List<String> getMetricPrometheusReporterContents();
113+
List<String> getMetricPrometheusReporterContents(String authHeader);
109114

110115
default Connection getConnection() throws SQLException {
111116
return getConnection(
@@ -243,6 +248,8 @@ default IConfigNodeRPCService.Iface getConfigNodeConnection(int index) throws Ex
243248
/** Shutdown all existed ConfigNodes. */
244249
void shutdownAllConfigNodes();
245250

251+
void shutdownForciblyAllConfigNodes();
252+
246253
/**
247254
* Ensure all the nodes being in the corresponding status.
248255
*

integration-test/src/main/java/org/apache/iotdb/itbase/env/ConfigNodeConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@
2323

2424
/** This interface is used to handle properties in iotdb-confignode.properties. */
2525
public interface ConfigNodeConfig {
26+
2627
ConfigNodeConfig setMetricReporterType(List<String> metricReporterTypes);
28+
29+
ConfigNodeConfig setMetricPrometheusReporterUsername(String username);
30+
31+
ConfigNodeConfig setMetricPrometheusReporterPassword(String password);
2732
}

integration-test/src/main/java/org/apache/iotdb/itbase/env/DataNodeConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
public interface DataNodeConfig {
2626
DataNodeConfig setMetricReporterType(List<String> metricReporterTypes);
2727

28+
DataNodeConfig setMetricPrometheusReporterUsername(String username);
29+
30+
DataNodeConfig setMetricPrometheusReporterPassword(String password);
31+
2832
DataNodeConfig setEnableRestService(boolean enableRestService);
2933

3034
DataNodeConfig setConnectionTimeoutInMS(int connectionTimeoutInMS);

integration-test/src/test/java/org/apache/iotdb/db/it/metric/IoTDBMetricIT.java

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@
2323
import org.apache.iotdb.it.framework.IoTDBTestRunner;
2424
import org.apache.iotdb.itbase.category.ClusterIT;
2525
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
26+
import org.apache.iotdb.metrics.reporter.prometheus.PrometheusReporter;
2627

27-
import org.junit.AfterClass;
28+
import org.junit.After;
2829
import org.junit.Assert;
29-
import org.junit.BeforeClass;
30+
import org.junit.Before;
3031
import org.junit.Test;
3132
import org.junit.experimental.categories.Category;
3233
import org.junit.runner.RunWith;
3334
import org.slf4j.Logger;
3435
import org.slf4j.LoggerFactory;
3536

37+
import java.nio.charset.StandardCharsets;
38+
import java.util.Base64;
3639
import java.util.Collections;
3740
import java.util.List;
3841
import java.util.regex.Pattern;
@@ -65,7 +68,13 @@ public class IoTDBMetricIT {
6568
private static final String VALID_LOG_STRING =
6669
"This line {} is invalid in prometheus line protocol";
6770

68-
public static boolean isValidPrometheusTextFormat(String metrics) {
71+
private static final String TEST_USERNAME = "good";
72+
private static final String TEST_PASSWORD = "??";
73+
74+
private static final String WRONG_USERNAME = "bad";
75+
private static final String WRONG_PASSWORD = "!!";
76+
77+
private static boolean isValidPrometheusTextFormat(String metrics) {
6978
String[] lines = metrics.split("\\n");
7079
boolean valid = true;
7180

@@ -107,8 +116,8 @@ private static boolean isValidTypeLine(String line) {
107116
return Pattern.matches(TYPE_REGEX, line.trim());
108117
}
109118

110-
@BeforeClass
111-
public static void setUp() throws Exception {
119+
@Before
120+
public void setUp() throws Exception {
112121
// Start ConfigNode with Prometheus reporter up
113122
EnvFactory.getEnv()
114123
.getConfig()
@@ -119,21 +128,86 @@ public static void setUp() throws Exception {
119128
.getConfig()
120129
.getDataNodeConfig()
121130
.setMetricReporterType(Collections.singletonList("PROMETHEUS"));
122-
EnvFactory.getEnv().initClusterEnvironment();
123131
}
124132

125-
@AfterClass
126-
public static void tearDown() throws Exception {
133+
@After
134+
public void tearDown() throws Exception {
127135
EnvFactory.getEnv().cleanClusterEnvironment();
128136
}
129137

138+
@Test
139+
public void testPrometheusReporterWithoutAuth() {
140+
EnvFactory.getEnv().initClusterEnvironment();
141+
142+
List<String> metricContents = EnvFactory.getEnv().getMetricPrometheusReporterContents(null);
143+
for (String metricContent : metricContents) {
144+
Assert.assertNotNull(metricContent);
145+
Assert.assertNotEquals(0, metricContent.length());
146+
Assert.assertTrue(isValidPrometheusTextFormat(metricContent));
147+
}
148+
}
149+
130150
@Test
131151
public void testPrometheusReporter() {
132-
List<String> metricContents = EnvFactory.getEnv().getMetricPrometheusReporterContents();
152+
EnvFactory.getEnv()
153+
.getConfig()
154+
.getConfigNodeConfig()
155+
.setMetricPrometheusReporterUsername(base64Encode(TEST_USERNAME))
156+
.setMetricPrometheusReporterPassword(base64Encode(TEST_PASSWORD));
157+
EnvFactory.getEnv()
158+
.getConfig()
159+
.getDataNodeConfig()
160+
.setMetricPrometheusReporterUsername(base64Encode(TEST_USERNAME))
161+
.setMetricPrometheusReporterPassword(base64Encode(TEST_PASSWORD));
162+
EnvFactory.getEnv().initClusterEnvironment();
163+
164+
wrongUsernameTest();
165+
wrongPasswordTest();
166+
correctUsernameAndPasswordTest();
167+
}
168+
169+
private void wrongUsernameTest() {
170+
List<String> metricContents =
171+
EnvFactory.getEnv()
172+
.getMetricPrometheusReporterContents(
173+
buildPrometheusReporterAuthHeader(WRONG_USERNAME, TEST_PASSWORD));
174+
for (String metricContent : metricContents) {
175+
Assert.assertNull(metricContent);
176+
}
177+
}
178+
179+
private void wrongPasswordTest() {
180+
List<String> metricContents =
181+
EnvFactory.getEnv()
182+
.getMetricPrometheusReporterContents(
183+
buildPrometheusReporterAuthHeader(TEST_USERNAME, WRONG_PASSWORD));
184+
for (String metricContent : metricContents) {
185+
Assert.assertNull(metricContent);
186+
}
187+
}
188+
189+
private void correctUsernameAndPasswordTest() {
190+
List<String> metricContents =
191+
EnvFactory.getEnv()
192+
.getMetricPrometheusReporterContents(
193+
buildPrometheusReporterAuthHeader(TEST_USERNAME, TEST_PASSWORD));
133194
for (String metricContent : metricContents) {
134195
Assert.assertNotNull(metricContent);
135196
Assert.assertNotEquals(0, metricContent.length());
136197
Assert.assertTrue(isValidPrometheusTextFormat(metricContent));
137198
}
138199
}
200+
201+
private String buildPrometheusReporterAuthHeader(String username, String password) {
202+
if (username == null || username.isEmpty()) {
203+
return null;
204+
}
205+
String raw = username + PrometheusReporter.DIVIDER_BETWEEN_USERNAME_AND_DIVIDER + password;
206+
String base64 = Base64.getEncoder().encodeToString(raw.getBytes(StandardCharsets.UTF_8));
207+
return PrometheusReporter.BASIC_AUTH_PREFIX + base64;
208+
}
209+
210+
private static String base64Encode(String raw) {
211+
return Base64.getEncoder().encodeToString(raw.getBytes(StandardCharsets.UTF_8));
212+
}
139213
}

0 commit comments

Comments
 (0)