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

cyyang 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 0b0fac4a41 [bugfix] fix the collector aes decode with secret error 
(#3652)
0b0fac4a41 is described below

commit 0b0fac4a411bfa9ed1a8111b3f23251a01a5b79a
Author: tomsun28 <[email protected]>
AuthorDate: Sun Aug 10 22:34:10 2025 +0800

    [bugfix] fix the collector aes decode with secret error (#3652)
    
    Signed-off-by: tomsun28 <[email protected]>
---
 .../entrance/processor/GoOnlineProcessor.java      | 13 ++++++
 .../hertzbeat/common/entity/dto/ServerInfo.java    | 40 ++++++++++++++++++
 .../org/apache/hertzbeat/common/util/AesUtil.java  | 12 ++++--
 .../apache/hertzbeat/common/util/AesUtilTest.java  |  2 +-
 .../manager/config/ConfigInitializer.java          | 48 ++++++++++++----------
 .../manager/scheduler/CollectorJobScheduler.java   |  4 ++
 .../netty/process/CollectorOnlineProcessor.java    | 11 ++++-
 .../remoting/netty/NettyRemotingAbstract.java      | 14 +++++--
 8 files changed, 113 insertions(+), 31 deletions(-)

diff --git 
a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/entrance/processor/GoOnlineProcessor.java
 
b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/entrance/processor/GoOnlineProcessor.java
index 1337001082..34dda15197 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/entrance/processor/GoOnlineProcessor.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-common/src/main/java/org/apache/hertzbeat/collector/dispatch/entrance/processor/GoOnlineProcessor.java
@@ -22,8 +22,11 @@ import io.netty.channel.ChannelHandlerContext;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.collector.timer.TimerDispatch;
 import org.apache.hertzbeat.common.constants.CommonConstants;
+import org.apache.hertzbeat.common.entity.dto.ServerInfo;
 import org.apache.hertzbeat.common.entity.message.ClusterMsg;
 import org.apache.hertzbeat.common.support.SpringContextHolder;
+import org.apache.hertzbeat.common.util.AesUtil;
+import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.remoting.netty.NettyRemotingProcessor;
 
 /**
@@ -40,6 +43,16 @@ public class GoOnlineProcessor implements 
NettyRemotingProcessor {
         if (this.timerDispatch == null) {
             this.timerDispatch = 
SpringContextHolder.getBean(TimerDispatch.class);
         }
+        if (message.getMsg().isEmpty()) {
+            log.warn("The message that server response to collector is empty, 
please upgrade server");
+        } else {
+            ServerInfo serverInfo = 
JsonUtil.fromJson(message.getMsg().toStringUtf8(), ServerInfo.class);
+            if (serverInfo == null || serverInfo.getAesSecret() == null) {
+                log.warn("The message that server response to collector has 
not secret empty, please check");
+            } else {
+                AesUtil.setDefaultSecretKey(serverInfo.getAesSecret());
+            }
+        }
         timerDispatch.goOnline();
         log.info("receive online message and handle success");
         return ClusterMsg.Message.newBuilder()
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ServerInfo.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ServerInfo.java
new file mode 100644
index 0000000000..4b3fe8a4fc
--- /dev/null
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ServerInfo.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.common.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * collector info
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "manager server info")
+public class ServerInfo {
+
+    /**
+     * the aes secret key value for aes encode decode
+     */
+    private String aesSecret;
+}
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/AesUtil.java 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/AesUtil.java
index 0ec608fb39..fd1279b809 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/AesUtil.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/util/AesUtil.java
@@ -37,7 +37,7 @@ public final class AesUtil {
      *  Default encryption key The AES encryption key is 16 bits by default.
      *  If the AES encryption key is larger than or smaller than 16 bits, an 
error message is displayed
      */
-    public static final String ENCODE_RULES = "tomSun28HaHaHaHa";
+    public static final String DEFAULT_ENCODE_RULES = "tomSun28HaHaHaHa";
 
     /**
      * Default algorithm
@@ -50,13 +50,17 @@ public final class AesUtil {
      * Encryption key The AES encryption key is 16 bits.
      * If the AES encryption key is larger than 16 bits, an error message is 
displayed
      */
-    private static String secretKey = ENCODE_RULES;
+    private static String secretKey = DEFAULT_ENCODE_RULES;
 
     private AesUtil() {}
 
     public static void setDefaultSecretKey(String secretKeyNow) {
         secretKey = secretKeyNow;
     }
+    
+    public static String getDefaultSecretKey() {
+        return secretKey;
+    }
 
     public static String aesEncode(String content) {
         return aesEncode(content, secretKey);
@@ -109,9 +113,9 @@ public final class AesUtil {
             byte[] byteDecode = getBytes(content, decryptKey);
             return new String(byteDecode, StandardCharsets.UTF_8);
         } catch (BadPaddingException e) {
-            if (!ENCODE_RULES.equals(decryptKey)) {
+            if (!DEFAULT_ENCODE_RULES.equals(decryptKey)) {
                 log.warn("There has default encode secret encode content, try 
to decode with default secret key");
-                return aesDecode(content, ENCODE_RULES);
+                return aesDecode(content, DEFAULT_ENCODE_RULES);
             }
             log.error("aes decode content error: {}, please config right 
common secret key", e.getMessage());
             return content;
diff --git 
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/AesUtilTest.java
 
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/AesUtilTest.java
index 40ec65cd01..9bff2d915c 100644
--- 
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/AesUtilTest.java
+++ 
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/AesUtilTest.java
@@ -95,7 +95,7 @@ class AesUtilTest {
         // Test with default key
         String originalText = "This is a secret message";
         // encode use default secret key
-        String encryptedText = aesEncode(originalText, AesUtil.ENCODE_RULES);
+        String encryptedText = aesEncode(originalText, 
AesUtil.DEFAULT_ENCODE_RULES);
         // decode use new secret key
         String decryptedText = aesDecode(encryptedText, "newkey1234567890");
         // old data can decode with default secret key
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/ConfigInitializer.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/ConfigInitializer.java
index 129d004ce4..35d48c0fa9 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/ConfigInitializer.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/ConfigInitializer.java
@@ -20,9 +20,9 @@ package org.apache.hertzbeat.manager.config;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.usthe.sureness.util.JsonWebTokenUtil;
 import jakarta.annotation.Resource;
+import java.security.SecureRandom;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
-import java.util.Random;
 import java.util.TimeZone;
 import lombok.SneakyThrows;
 import org.apache.commons.lang3.StringUtils;
@@ -63,7 +63,7 @@ public class ConfigInitializer implements SmartLifecycle {
     @Value("${sureness.jwt.secret:" + DEFAULT_JWT_SECRET + "}")
     private String currentJwtSecret;
 
-    @Value("${common.secret:" + AesUtil.ENCODE_RULES + "}")
+    @Value("${common.secret:" + AesUtil.DEFAULT_ENCODE_RULES + "}")
     private String currentAesSecret;
 
     @Resource
@@ -114,38 +114,40 @@ public class ConfigInitializer implements SmartLifecycle {
         // for template config, flush the template config in db to memory
         TemplateConfig templateConfig = templateConfigService.getConfig();
         appService.updateCustomTemplateConfig(templateConfig);
-        // for system secrets
+        // for system jwt secrets and aes secret
         boolean needUpdate = false;
-        SystemSecret.SystemSecretBuilder builder = SystemSecret.builder();
+        SystemSecret.SystemSecretBuilder systemSecretBuilder = 
SystemSecret.builder();
+        SystemSecret systemSecret = systemSecretService.getConfig();
+        if (systemSecret != null) {
+            systemSecretBuilder.jwtSecret(systemSecret.getJwtSecret());
+            systemSecretBuilder.aesSecret(systemSecret.getAesSecret());
+        }
         if (DEFAULT_JWT_SECRET.equals(currentJwtSecret)) {
             // use the random jwt secret
-            SystemSecret systemSecret = systemSecretService.getConfig();
             if (systemSecret == null || 
StringUtils.isBlank(systemSecret.getJwtSecret())) {
                 currentJwtSecret = randomizeSecret(DEFAULT_JWT_SECRET);
-                builder.jwtSecret(currentJwtSecret);
+                systemSecretBuilder.jwtSecret(currentJwtSecret);
                 needUpdate = true;
             } else {
                 currentJwtSecret = systemSecret.getJwtSecret();
             }
         }
-        // else use the user custom jwt secret
-        // set the jwt secret token in util
+        // else use the user custom jwt secret, set the jwt secret token in 
util
         JsonWebTokenUtil.setDefaultSecretKey(currentJwtSecret);
         // Aes secret config
-        if (AesUtil.ENCODE_RULES.equals(currentAesSecret)) {
+        if (AesUtil.DEFAULT_ENCODE_RULES.equals(currentAesSecret)) {
             // use the random aes secret
-            SystemSecret systemSecret = systemSecretService.getConfig();
             if (systemSecret == null || 
StringUtils.isBlank(systemSecret.getAesSecret())) {
-                currentAesSecret = randomizeSecret(AesUtil.ENCODE_RULES);
-                builder.aesSecret(currentAesSecret);
+                currentAesSecret = 
randomizeSecret(AesUtil.DEFAULT_ENCODE_RULES);
+                systemSecretBuilder.aesSecret(currentAesSecret);
+                needUpdate = true;
             } else {
                 currentAesSecret = systemSecret.getAesSecret();
             }
         }
         AesUtil.setDefaultSecretKey(currentAesSecret);
         if (needUpdate) {
-            SystemSecret systemSecret = builder.build();
-            systemSecretService.saveConfig(systemSecret);
+            systemSecretService.saveConfig(systemSecretBuilder.build());
         }
         // init web-app mute config
         MuteConfig muteConfig = muteGeneralConfigService.getConfig();
@@ -177,14 +179,16 @@ public class ConfigInitializer implements SmartLifecycle {
     }
 
     private String randomizeSecret(String secret) {
-        char[] chars = secret.toCharArray();
-        Random rand = new Random();
-        for (int i = 0; i < chars.length; i++) {
-            int index = rand.nextInt(chars.length);
-            char temp = chars[i];
-            chars[i] = chars[index];
-            chars[index] = temp;
+        SecureRandom random = new SecureRandom();
+        StringBuilder sb = new StringBuilder(secret.length());
+        for (int i = 0; i < secret.length(); i++) {
+            char ch;
+            do {
+                int codePoint = random.nextInt('z' - '0' + 1) + '0';
+                ch = (char) codePoint;
+            } while (!Character.isLetterOrDigit(ch));
+            sb.append(ch);
         }
-        return new String(chars);
+        return sb.toString();
     }
 }
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/CollectorJobScheduler.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/CollectorJobScheduler.java
index c0eed7aa9a..c939200e76 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/CollectorJobScheduler.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/CollectorJobScheduler.java
@@ -36,6 +36,7 @@ import 
org.apache.hertzbeat.collector.dispatch.entrance.internal.CollectJobServi
 import 
org.apache.hertzbeat.collector.dispatch.entrance.internal.CollectResponseEventListener;
 import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.dto.CollectorInfo;
+import org.apache.hertzbeat.common.entity.dto.ServerInfo;
 import org.apache.hertzbeat.common.entity.job.Configmap;
 import org.apache.hertzbeat.common.entity.job.Job;
 import org.apache.hertzbeat.common.entity.manager.Collector;
@@ -45,6 +46,7 @@ import org.apache.hertzbeat.common.entity.manager.Param;
 import org.apache.hertzbeat.common.entity.manager.ParamDefine;
 import org.apache.hertzbeat.common.entity.message.ClusterMsg;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
+import org.apache.hertzbeat.common.util.AesUtil;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.SnowFlakeIdGenerator;
 import org.apache.hertzbeat.manager.dao.CollectorDao;
@@ -261,9 +263,11 @@ public class CollectorJobScheduler implements 
CollectorScheduling, CollectJobSch
         if (Objects.isNull(collector)) {
             return false;
         }
+        ServerInfo serverInfo = 
ServerInfo.builder().aesSecret(AesUtil.getDefaultSecretKey()).build();
         ClusterMsg.Message message = ClusterMsg.Message.newBuilder()
                 .setType(ClusterMsg.MessageType.GO_ONLINE)
                 .setDirection(ClusterMsg.Direction.REQUEST)
+                .setMsg(ByteString.copyFromUtf8(JsonUtil.toJson(serverInfo)))
                 .setIdentity(identity)
                 .build();
         ClusterMsg.Message response = this.manageServer.sendMsgSync(identity, 
message);
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/netty/process/CollectorOnlineProcessor.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/netty/process/CollectorOnlineProcessor.java
index 0c54258632..9a7e4f4e08 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/netty/process/CollectorOnlineProcessor.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/netty/process/CollectorOnlineProcessor.java
@@ -17,12 +17,15 @@
 
 package org.apache.hertzbeat.manager.scheduler.netty.process;
 
+import com.google.protobuf.ByteString;
 import io.netty.channel.ChannelHandlerContext;
 import java.net.InetSocketAddress;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hertzbeat.common.entity.dto.CollectorInfo;
+import org.apache.hertzbeat.common.entity.dto.ServerInfo;
 import org.apache.hertzbeat.common.entity.message.ClusterMsg;
+import org.apache.hertzbeat.common.util.AesUtil;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.manager.scheduler.netty.ManageServer;
 import org.apache.hertzbeat.remoting.netty.NettyRemotingProcessor;
@@ -52,6 +55,12 @@ public class CollectorOnlineProcessor implements 
NettyRemotingProcessor {
         }
         this.manageServer.addChannel(collector, ctx.channel());
         
this.manageServer.getCollectorAndJobScheduler().collectorGoOnline(collector, 
collectorInfo);
-        return null;
+        ServerInfo serverInfo = 
ServerInfo.builder().aesSecret(AesUtil.getDefaultSecretKey()).build();
+        return ClusterMsg.Message.newBuilder()
+                .setIdentity(message.getIdentity())
+                .setDirection(ClusterMsg.Direction.RESPONSE)
+                .setMsg(ByteString.copyFromUtf8(JsonUtil.toJson(serverInfo)))
+                .setType(ClusterMsg.MessageType.GO_ONLINE)
+                .build();
     }
 }
diff --git 
a/hertzbeat-remoting/src/main/java/org/apache/hertzbeat/remoting/netty/NettyRemotingAbstract.java
 
b/hertzbeat-remoting/src/main/java/org/apache/hertzbeat/remoting/netty/NettyRemotingAbstract.java
index a9632d7c40..3d9390f467 100644
--- 
a/hertzbeat-remoting/src/main/java/org/apache/hertzbeat/remoting/netty/NettyRemotingAbstract.java
+++ 
b/hertzbeat-remoting/src/main/java/org/apache/hertzbeat/remoting/netty/NettyRemotingAbstract.java
@@ -59,7 +59,7 @@ public abstract class NettyRemotingAbstract implements 
RemotingService {
         if (ClusterMsg.Direction.REQUEST.equals(message.getDirection())) {
             this.processRequestMsg(ctx, message);
         } else {
-            this.processResponseMsg(message);
+            this.processResponseMsg(ctx, message);
         }
     }
 
@@ -86,12 +86,20 @@ public abstract class NettyRemotingAbstract implements 
RemotingService {
         }
     }
 
-    protected void processResponseMsg(ClusterMsg.Message response) {
+    protected void processResponseMsg(ChannelHandlerContext ctx, 
ClusterMsg.Message response) {
+        // for sync response
         if (this.responseTable.containsKey(response.getIdentity())) {
             ResponseFuture responseFuture = 
this.responseTable.get(response.getIdentity());
             responseFuture.putResponse(response);
         } else {
-            log.warn("receive response not in responseTable, identity: {}", 
response.getIdentity());
+            // async response
+            NettyRemotingProcessor processor = 
this.processorTable.get(response.getType());
+            if (processor != null) {
+                ClusterMsg.Message repMessage = processor.handle(ctx, 
response);
+                if (repMessage != null) {
+                    ctx.writeAndFlush(repMessage);
+                }
+            }   
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to