This is an automated email from the ASF dual-hosted git repository.
liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new 42f0a74edf [fix] adding trusted domain verification (#3866)
42f0a74edf is described below
commit 42f0a74edf9282457c321eecb4563db642b06747
Author: Duansg <[email protected]>
AuthorDate: Thu Nov 27 20:38:00 2025 +0800
[fix] adding trusted domain verification (#3866)
Co-authored-by: aias00 <[email protected]>
---
.../impl/HuaweiCloudExternAlertService.java | 61 ++++++++++++++++++++++
.../service/HuaweiCloudExternAlertServiceTest.java | 37 ++++++++++++-
2 files changed, 97 insertions(+), 1 deletion(-)
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/HuaweiCloudExternAlertService.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/HuaweiCloudExternAlertService.java
index 2c538aeb48..335426f5db 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/HuaweiCloudExternAlertService.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/HuaweiCloudExternAlertService.java
@@ -18,6 +18,7 @@
package org.apache.hertzbeat.alert.service.impl;
import com.fasterxml.jackson.databind.JsonNode;
+import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.hertzbeat.alert.dto.HuaweiCloudExternAlert;
@@ -43,6 +44,7 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.time.Instant;
+import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@@ -70,6 +72,8 @@ public class HuaweiCloudExternAlertService implements
ExternAlertService {
private static final String CHARSET_UTF8 = StandardCharsets.UTF_8.name();
+ private static final String SUBSCRIBE_URL_PREFIX =
"https://console.huaweicloud.com/smn/subscription/confirm";
+
private final AlarmCommonReduce alarmCommonReduce;
public HuaweiCloudExternAlertService(AlarmCommonReduce alarmCommonReduce) {
@@ -197,6 +201,9 @@ public class HuaweiCloudExternAlertService implements
ExternAlertService {
if (StringUtils.isBlank(subscribeUrl)) {
return;
}
+ if (!subscribeUrl.startsWith(SUBSCRIBE_URL_PREFIX)) {
+ throw new SecurityException("Untrusted domain: " + subscribeUrl);
+ }
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet(subscribeUrl);
try (CloseableHttpResponse response = httpClient.execute(httpGet))
{
@@ -303,6 +310,13 @@ public class HuaweiCloudExternAlertService implements
ExternAlertService {
*/
private X509Certificate getCertificate(String signCertUrl) throws
Exception {
URL url = new URL(signCertUrl);
+ if (!"https".equalsIgnoreCase(url.getProtocol())) {
+ throw new SecurityException("Only HTTPS is allowed");
+ }
+ boolean trusted = Arrays.stream(Region.values()).anyMatch(ep ->
ep.getEndpoint().equals(url.getHost()));
+ if (!trusted) {
+ throw new SecurityException("Untrusted domain: " + url.getHost());
+ }
try (InputStream in = url.openStream()) {
CertificateFactory cf =
CertificateFactory.getInstance(CERTIFICATE_TYPE);
return (X509Certificate) cf.generateCertificate(in);
@@ -340,4 +354,51 @@ public class HuaweiCloudExternAlertService implements
ExternAlertService {
return "huaweicloud-ces";
}
+
+ /**
+ * doc: <a
href="https://console.huaweicloud.com/apiexplorer/#/endpoint/SMN">SMN API</a>
+ */
+ @Getter
+ private enum Region {
+
+ AE_AD_1("ae-ad-1", "smn.ae-ad-1.myhuaweicloud.com"),
+ AF_SOUTH_1("af-south-1", "smn.af-south-1.myhuaweicloud.com"),
+ AP_SOUTHEAST_1("ap-southeast-1",
"smn.ap-southeast-1.myhuaweicloud.com"),
+ AP_SOUTHEAST_2("ap-southeast-2",
"smn.ap-southeast-2.myhuaweicloud.com"),
+ AP_SOUTHEAST_3("ap-southeast-3",
"smn.ap-southeast-3.myhuaweicloud.com"),
+ AP_SOUTHEAST_4("ap-southeast-4",
"smn.ap-southeast-4.myhuaweicloud.com"),
+ CN_EAST_2("cn-east-2", "smn.cn-east-2.myhuaweicloud.com"),
+ CN_EAST_3("cn-east-3", "smn.cn-east-3.myhuaweicloud.com"),
+ CN_EAST_4("cn-east-4", "smn.cn-east-4.myhuaweicloud.com"),
+ CN_EAST_5("cn-east-5", "smn.cn-east-5.myhuaweicloud.com"),
+ CN_NORTH_1("cn-north-1", "smn.cn-north-1.myhuaweicloud.com"),
+ CN_NORTH_11("cn-north-11", "smn.cn-north-11.myhuaweicloud.com"),
+ CN_NORTH_12("cn-north-12", "smn.cn-north-12.myhuaweicloud.com"),
+ CN_NORTH_2("cn-north-2", "smn.cn-north-2.myhuaweicloud.cn"),
+ CN_NORTH_4("cn-north-4", "smn.cn-north-4.myhuaweicloud.com"),
+ CN_NORTH_9("cn-north-9", "smn.cn-north-9.myhuaweicloud.com"),
+ CN_SOUTH_1("cn-south-1", "smn.cn-south-1.myhuaweicloud.com"),
+ CN_SOUTH_2("cn-south-2", "smn.cn-south-2.myhuaweicloud.com"),
+ CN_SOUTH_4("cn-south-4", "smn.cn-south-4.myhuaweicloud.com"),
+ CN_SOUTHWEST_2("cn-southwest-2",
"smn.cn-southwest-2.myhuaweicloud.com"),
+ CN_SOUTHWEST_3("cn-southwest-3",
"smn.cn-southwest-3.myhuaweicloud.com"),
+ EU_WEST_0("eu-west-0", "smn.eu-west-0.myhuaweicloud.com"),
+ LA_NORTH_2("la-north-2", "smn.la-north-2.myhuaweicloud.com"),
+ LA_SOUTH_2("la-south-2", "smn.la-south-2.myhuaweicloud.com"),
+ MY_KUALALUMPUR_1("my-kualalumpur-1",
"smn.my-kualalumpur-1.myhuaweicloud.com"),
+ NA_MEXICO_1("na-mexico-1", "smn.na-mexico-1.myhuaweicloud.com"),
+ RU_MOSCOW_1("ru-moscow-1", "smn.ru-moscow-1.myhuaweicloud.com"),
+ SA_BRAZIL_1("sa-brazil-1", "smn.sa-brazil-1.myhuaweicloud.com"),
+ TR_WEST_1("tr-west-1", "smn.tr-west-1.myhuaweicloud.com"),
+ EU_WEST_101("eu-west-101", "smn.eu-west-101.myhuaweicloud.eu");
+
+ private final String id;
+
+ private final String endpoint;
+
+ Region(String id, String endpoint) {
+ this.id = id;
+ this.endpoint = endpoint;
+ }
+ }
}
\ No newline at end of file
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/HuaweiCloudExternAlertServiceTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/HuaweiCloudExternAlertServiceTest.java
index b29b948251..3859303c7e 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/HuaweiCloudExternAlertServiceTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/HuaweiCloudExternAlertServiceTest.java
@@ -146,7 +146,42 @@ public class HuaweiCloudExternAlertServiceTest {
verify(alarmCommonReduce,
never()).reduceAndSendAlarm(any(SingleAlert.class));
}
+ @Test
+ void testSubscriptionUrlFail() {
+ HuaweiCloudExternAlert externAlert = new HuaweiCloudExternAlert();
+
externAlert.setSubscribeUrl("https://console.huaweicloud.com/smn/subscription/confirm?token=477a784601d744e4ab9ab83986502d31c4b938"
+ +
"0ec0b64392b134e517c3aa17eb7b3a12dc9f3b4ab495e61c4dee654b435d7223ea934345bf8ae8901cef912b1d&topic_urn=urn:smn:cn-north-4"
+ +
":477a784601d744e4ab9ab83986502d31:CES_notification_group_bngJ2aMpX®ion=cn-north-4");
+
externAlert.setSignature("ottf37C/2RdDgqimRQMIBU6i7XjUfPPMU760jJn71wwP3825YPoIT22uw2A9399rkm9Jrt1qUEFrDLuA5yHFLd5n/XoM4FghIgyFn7VIfgpuVM31a+co78s"
+ +
"YBiZ1egOCE/AwFm2oygRhfIceUj9Kw9vmc06el9TXY6RtE5tAEF6qEmICtTh45KwtCO/WRs3DY72dQi5hm0w7/tktS4WFZ1iP4LHt5eCwFvnH0u29Y96cJNI0fLUQxI5MkhgjK"
+ +
"77JkFK7UT6ZYJZhzgSp/B7OQGStOQx+3Duvx4T4CzccZQM3sca81Z0B0GFGWeVXuEHyCPLsayY/Iz+5Tco51elT8w==");
+
externAlert.setTopicUrn("urn:smn:cn-north-4:477a784601d744e4ab9ab83986502d31:CES_notification_group_bngJ2aMpX");
+ externAlert.setMessageId("242fac183d3a4936b5ead6c725a32ed0");
+ externAlert.setType("SubscriptionConfirmation");
+ externAlert.setMessage("You are invited to subscribe to topic:
urn:smn:cn-north-4:477a784601d744e4ab9ab83986502d31:"
+ + "CES_notification_group_bngJ2aMpX. To confirm this
subscription, please visit the subscribe_url included in this message. The
subscribe_url is valid only within 48 hours.");
+
externAlert.setSigningCertUrl("https://xxxx.myhuaweicloud.com/smn/SMN_cn-north-4_b98100ca131b4116ab8ee7ccedbaae99.pem");
+ externAlert.setTimestamp("2025-06-07T15:07:14Z");
+ externAlertService.addExternAlert(JsonUtil.toJson(externAlert));
+ verify(alarmCommonReduce,
never()).reduceAndSendAlarm(any(SingleAlert.class));
+ }
-
+ @Test
+ void testCertUrlFailed() {
+ HuaweiCloudExternAlert externAlert = new HuaweiCloudExternAlert();
+
externAlert.setSignature("TImrLoeb0tV1JZJSPyA0rpC9mNqH3MmhwQ4tgpuHHa+JztfGVZFvkU//OthKKhzpDAoYiXOYG9DbzXCLb"
+ +
"vaGePIRITakoynYyYr9zZIpdx9jXhQNlgF8np1+t0JxNeoIq0DYWgH52tsodwqOm+OnmkcHwCRo/1rFv85KrKAaX2gy3sNwX"
+ +
"w1hKnAwAw0mJlxHHSf/N3+7j6GoxCNV7fN9K4CpJiLMGNvUa7zVmG0U9mPvt/7Lac155kPPQ9lYyeL7vVI0e4sfRbuQruz3E"
+ +
"0ZP40TKx0afoeR0/Bx/IoZzRP1La7pKlbEISvkcM7TqW/IOGQTkhVsQ32RFRxZWO2snw==");
+ externAlert.setSubject("DCS Redis “dcs-h4tv” ");
+
externAlert.setTopicUrn("urn:smn:cn-north-4:477a784601d744e4ab9ab83986502d31:CES_notification_group_bngJ2aMpX");
+ externAlert.setMessageId("d3672d737bb742cf8c2aa3f0fd72d4d1");
+ externAlert.setType("Notification");
+ externAlert.setMessage("{}");
+
externAlert.setSigningCertUrl("https://xxx.myhuaweicloud.com/failedUrl");
+ externAlert.setTimestamp("2025-06-07T15:12:09Z");
+ externAlertService.addExternAlert(JsonUtil.toJson(externAlert));
+ verify(alarmCommonReduce,
never()).reduceAndSendAlarm(any(SingleAlert.class));
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]