This is an automated email from the ASF dual-hosted git repository.
deardeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new c3c7af57fa4 [fix](be) Remove heartbeat tokens from logs and errors
(#69532)
c3c7af57fa4 is described below
commit c3c7af57fa4e018a2f4319bf60ce5f83ef503ad7
Author: deardeng <[email protected]>
AuthorDate: Mon Oct 26 11:59:16 2026 +0800
[fix](be) Remove heartbeat tokens from logs and errors (#69532)
Problem Summary: When a BE receives its cluster token or a new
authentication token, heartbeat INFO logs include the credential values.
A cluster-token mismatch also includes both tokens in the error
response, which can propagate to FE logs. Keep the heartbeat event
messages and invalid-token error while removing credential values. Add a
unit test covering initialization, repeated heartbeats, successive
authentication-token updates, and token mismatch, including checks that
logs and error responses do not contain the credentials.
---
be/src/agent/heartbeat_server.cpp | 10 ++--
be/test/agent/heartbeat_server_test.cpp | 91 +++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/be/src/agent/heartbeat_server.cpp
b/be/src/agent/heartbeat_server.cpp
index a3ee995020e..dd9ed4358a2 100644
--- a/be/src/agent/heartbeat_server.cpp
+++ b/be/src/agent/heartbeat_server.cpp
@@ -227,10 +227,9 @@ Status HeartbeatServer::_heartbeat(const TMasterInfo&
master_info) {
if (master_info.__isset.token) {
if (_cluster_info->token == "") {
_cluster_info->token = master_info.token;
- LOG(INFO) << "get token. token: " << _cluster_info->token;
+ LOG(INFO) << "get token";
} else if (_cluster_info->token != master_info.token) {
- return Status::InternalError("invalid token. local: {}, master:
{}",
- _cluster_info->token,
master_info.token);
+ return Status::InternalError("invalid token");
}
}
@@ -330,10 +329,9 @@ Status HeartbeatServer::_heartbeat(const TMasterInfo&
master_info) {
if (master_info.__isset.auth_token) {
if (_cluster_info->curr_auth_token == "") {
_cluster_info->curr_auth_token = master_info.auth_token;
- LOG(INFO) << "set new auth token: " << master_info.auth_token;
+ LOG(INFO) << "set new auth token";
} else if (_cluster_info->curr_auth_token != master_info.auth_token) {
- LOG(INFO) << "last auth token: " << _cluster_info->last_auth_token
- << "set new auth token: " << master_info.auth_token;
+ LOG(INFO) << "update auth token";
_cluster_info->last_auth_token = _cluster_info->curr_auth_token;
_cluster_info->curr_auth_token = master_info.auth_token;
}
diff --git a/be/test/agent/heartbeat_server_test.cpp
b/be/test/agent/heartbeat_server_test.cpp
new file mode 100644
index 00000000000..f71e5341f65
--- /dev/null
+++ b/be/test/agent/heartbeat_server_test.cpp
@@ -0,0 +1,91 @@
+// 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.
+
+#include "agent/heartbeat_server.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <string>
+
+#include "runtime/cluster_info.h"
+#include "runtime/exec_env.h"
+#include "storage/storage_engine.h"
+#include "util/defer_op.h"
+
+namespace doris {
+
+class HeartbeatLogSink : public google::LogSink {
+public:
+ void send(google::LogSeverity /*severity*/, const char* /*full_filename*/,
+ const char* /*base_filename*/, int /*line*/, const
google::LogMessageTime& /*time*/,
+ const char* message, std::size_t message_len) override {
+ messages.append(message, message_len);
+ }
+
+ std::string messages;
+};
+
+TEST(HeartbeatServerTest, DoesNotExposeTokens) {
+
ExecEnv::GetInstance()->set_storage_engine(std::make_unique<StorageEngine>(EngineOptions
{}));
+ Defer reset_engine([] {
ExecEnv::GetInstance()->set_storage_engine(nullptr); });
+ ClusterInfo cluster;
+ cluster.cluster_id = 7;
+ HeartbeatServer server(&cluster);
+ TMasterInfo master;
+ master.__set_cluster_id(7);
+ master.__set_epoch(10);
+ TNetworkAddress address;
+ address.__set_hostname("master-a");
+ address.__set_port(9020);
+ master.__set_network_address(address);
+ master.__set_token("heartbeat_cluster_secret");
+
+ HeartbeatLogSink log_sink;
+ google::AddLogSink(&log_sink);
+ Defer remove_log_sink([&] { google::RemoveLogSink(&log_sink); });
+
+ THeartbeatResult result;
+ for (const auto* token :
+ {"heartbeat_auth_secret_a", "heartbeat_auth_secret_b",
"heartbeat_auth_secret_c"}) {
+ master.__set_auth_token(token);
+ server.heartbeat(result, master);
+ ASSERT_EQ(TStatusCode::OK, result.status.status_code);
+ }
+
+ server.heartbeat(result, master);
+ ASSERT_EQ(TStatusCode::OK, result.status.status_code);
+ EXPECT_EQ("heartbeat_auth_secret_c", cluster.curr_auth_token);
+ EXPECT_EQ("heartbeat_auth_secret_b", cluster.last_auth_token);
+
+ master.__set_token("heartbeat_mismatched_secret");
+ server.heartbeat(result, master);
+ ASSERT_EQ(TStatusCode::INTERNAL_ERROR, result.status.status_code);
+ ASSERT_EQ(1, result.status.error_msgs.size());
+ EXPECT_NE(std::string::npos,
result.status.error_msgs.front().find("invalid token"));
+ EXPECT_EQ("heartbeat_cluster_secret", cluster.token);
+
+ for (const auto* secret :
+ {"heartbeat_cluster_secret", "heartbeat_mismatched_secret",
"heartbeat_auth_secret_a",
+ "heartbeat_auth_secret_b", "heartbeat_auth_secret_c"}) {
+ EXPECT_EQ(std::string::npos, log_sink.messages.find(secret));
+ EXPECT_EQ(std::string::npos,
result.status.error_msgs.front().find(secret));
+ }
+}
+
+} // namespace doris
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]