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

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 07d2425157b branch-3.1: [chore](sk) Encrypt `secret key` and hide 
`access key` for log #55241 (#55619)
07d2425157b is described below

commit 07d2425157bae51ccd3603e3a90bc01a9e22135b
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Sep 6 00:36:22 2025 +0800

    branch-3.1: [chore](sk) Encrypt `secret key` and hide `access key` for log 
#55241 (#55619)
    
    Cherry-picked from #55241
    
    Co-authored-by: Uniqueyou <[email protected]>
---
 be/src/cloud/cloud_meta_mgr.cpp                    |   9 ++
 be/src/util/s3_util.cpp                            |  26 +++++
 be/src/util/s3_util.h                              |   8 +-
 be/test/util/s3_util_test.cpp                      |  79 ++++++++++++++
 cloud/src/meta-service/meta_service.cpp            |  26 +++++
 cloud/src/meta-service/meta_service_helper.h       |  84 +++++++++++----
 cloud/src/meta-service/meta_service_http.cpp       |  11 +-
 cloud/src/meta-service/meta_service_resource.cpp   |  13 ++-
 cloud/src/resource-manager/resource_manager.cpp    |   6 +-
 cloud/test/meta_service_http_test.cpp              | 118 +++++++++++++++++++++
 .../doris/cloud/system/CloudSystemInfoService.java |  57 ++++++++++
 11 files changed, 405 insertions(+), 32 deletions(-)

diff --git a/be/src/cloud/cloud_meta_mgr.cpp b/be/src/cloud/cloud_meta_mgr.cpp
index 7e8f07d26cb..a05d9de402a 100644
--- a/be/src/cloud/cloud_meta_mgr.cpp
+++ b/be/src/cloud/cloud_meta_mgr.cpp
@@ -1271,6 +1271,15 @@ Status 
CloudMetaMgr::get_storage_vault_info(StorageVaultInfos* vault_infos, bool
         j->mutable_obj_info()->set_sk(j->obj_info().sk().substr(0, 2) + "xxx");
     }
 
+    for (int i = 0; i < resp.obj_info_size(); ++i) {
+        
resp.mutable_obj_info(i)->set_ak(hide_access_key(resp.obj_info(i).sk()));
+    }
+    for (int i = 0; i < resp.storage_vault_size(); ++i) {
+        auto* j = resp.mutable_storage_vault(i);
+        if (!j->has_obj_info()) continue;
+        j->mutable_obj_info()->set_sk(hide_access_key(j->obj_info().sk()));
+    }
+
     LOG(INFO) << "get storage vault, enable_storage_vault=" << *is_vault_mode
               << " response=" << resp.ShortDebugString();
     return Status::OK();
diff --git a/be/src/util/s3_util.cpp b/be/src/util/s3_util.cpp
index 174b6f8a5e6..d4c4e4e3d34 100644
--- a/be/src/util/s3_util.cpp
+++ b/be/src/util/s3_util.cpp
@@ -574,4 +574,30 @@ S3Conf S3Conf::get_s3_conf(const TS3StorageParam& param) {
     return ret;
 }
 
+std::string hide_access_key(const std::string& ak) {
+    std::string key = ak;
+    size_t key_len = key.length();
+    size_t reserved_count;
+    if (key_len > 7) {
+        reserved_count = 6;
+    } else if (key_len > 2) {
+        reserved_count = key_len - 2;
+    } else {
+        reserved_count = 0;
+    }
+
+    size_t x_count = key_len - reserved_count;
+    size_t left_x_count = (x_count + 1) / 2;
+
+    if (left_x_count > 0) {
+        key.replace(0, left_x_count, left_x_count, 'x');
+    }
+
+    if (x_count - left_x_count > 0) {
+        key.replace(key_len - (x_count - left_x_count), x_count - left_x_count,
+                    x_count - left_x_count, 'x');
+    }
+    return key;
+}
+
 } // end namespace doris
diff --git a/be/src/util/s3_util.h b/be/src/util/s3_util.h
index 8b96fb0776b..7f72bd3af26 100644
--- a/be/src/util/s3_util.h
+++ b/be/src/util/s3_util.h
@@ -61,6 +61,8 @@ extern bvar::LatencyRecorder s3_get_bucket_version_latency;
 extern bvar::LatencyRecorder s3_copy_object_latency;
 }; // namespace s3_bvar
 
+std::string hide_access_key(const std::string& ak);
+
 class S3URI;
 struct S3ClientConf {
     std::string endpoint;
@@ -107,9 +109,9 @@ struct S3ClientConf {
                 "(ak={}, token={}, endpoint={}, region={}, bucket={}, 
max_connections={}, "
                 "request_timeout_ms={}, connect_timeout_ms={}, 
use_virtual_addressing={}, "
                 "cred_provider_type={},role_arn={}, external_id={}",
-                ak, token, endpoint, region, bucket, max_connections, 
request_timeout_ms,
-                connect_timeout_ms, use_virtual_addressing, 
cred_provider_type, role_arn,
-                external_id);
+                hide_access_key(ak), token, endpoint, region, bucket, 
max_connections,
+                request_timeout_ms, connect_timeout_ms, 
use_virtual_addressing, cred_provider_type,
+                role_arn, external_id);
     }
 };
 
diff --git a/be/test/util/s3_util_test.cpp b/be/test/util/s3_util_test.cpp
new file mode 100644
index 00000000000..cd8eeb5cb68
--- /dev/null
+++ b/be/test/util/s3_util_test.cpp
@@ -0,0 +1,79 @@
+// 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 "util/s3_util.h"
+
+#include <gtest/gtest-test-part.h>
+
+#include <string>
+
+#include "gtest/gtest_pred_impl.h"
+#include "util/s3_uri.h"
+
+namespace doris {
+
+class S3UTILTest : public testing::Test {
+public:
+    S3UTILTest() = default;
+    ~S3UTILTest() = default;
+}; // end class S3UTILTest
+
+TEST_F(S3UTILTest, hide_access_key_empty) {
+    EXPECT_EQ("", hide_access_key(""));
+}
+
+TEST_F(S3UTILTest, hide_access_key_single_char) {
+    EXPECT_EQ("x", hide_access_key("A"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_two_chars) {
+    EXPECT_EQ("xx", hide_access_key("AB"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_three_chars) {
+    EXPECT_EQ("xBx", hide_access_key("ABC"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_four_chars) {
+    EXPECT_EQ("xBCx", hide_access_key("ABCD"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_six_chars) {
+    EXPECT_EQ("xBCDEx", hide_access_key("ABCDEF"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_seven_chars) {
+    EXPECT_EQ("xBCDEFx", hide_access_key("ABCDEFG"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_normal_length) {
+    EXPECT_EQ("xxxDEFGHIxxx", hide_access_key("ABCDEFGHIJKL"));
+}
+
+TEST_F(S3UTILTest, hide_access_key_long_key) {
+    std::string long_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+    std::string result = hide_access_key(long_key);
+    EXPECT_EQ("xxxxxxxxxxxxxxxPQRSTUxxxxxxxxxxxxxxx", result);
+}
+
+TEST_F(S3UTILTest, hide_access_key_typical_aws_key) {
+    std::string aws_key = "AKIAIOSFODNN7EXAMPLE";
+    std::string result = hide_access_key(aws_key);
+    EXPECT_EQ("xxxxxxxFODNN7xxxxxxx", result);
+}
+
+} // end namespace doris
diff --git a/cloud/src/meta-service/meta_service.cpp 
b/cloud/src/meta-service/meta_service.cpp
index c54c1e30b95..aeb3e46c7da 100644
--- a/cloud/src/meta-service/meta_service.cpp
+++ b/cloud/src/meta-service/meta_service.cpp
@@ -4401,4 +4401,30 @@ void 
MetaServiceImpl::get_schema_dict(::google::protobuf::RpcController* control
     response->mutable_schema_dict()->Swap(&schema_dict);
 }
 
+std::string hide_access_key(const std::string& ak) {
+    std::string key = ak;
+    size_t key_len = key.length();
+    size_t reserved_count;
+    if (key_len > 6) {
+        reserved_count = 6;
+    } else if (key_len > 2) {
+        reserved_count = key_len - 2;
+    } else {
+        reserved_count = 0;
+    }
+
+    size_t x_count = key_len - reserved_count;
+    size_t left_x_count = x_count / 2;
+
+    if (left_x_count > 0) {
+        key.replace(0, left_x_count, left_x_count, 'x');
+    }
+
+    if (x_count - left_x_count > 0) {
+        key.replace(key_len - (x_count - left_x_count), x_count - left_x_count,
+                    x_count - left_x_count, 'x');
+    }
+    return key;
+}
+
 } // namespace doris::cloud
diff --git a/cloud/src/meta-service/meta_service_helper.h 
b/cloud/src/meta-service/meta_service_helper.h
index c35873ed949..38f32b2d4f8 100644
--- a/cloud/src/meta-service/meta_service_helper.h
+++ b/cloud/src/meta-service/meta_service_helper.h
@@ -54,6 +54,45 @@ inline std::string md5(const std::string& str) {
     return ss.str();
 }
 
+std::string hide_access_key(const std::string& ak);
+
+// is_handle_sk: true for encrypting sk, false for hiding ak
+inline void process_ak_sk_pattern(std::string& str, const std::string& 
pattern, bool is_handle_sk) {
+    size_t pos = 0;
+    while ((pos = str.find(pattern, pos)) != std::string::npos) {
+        size_t colon_pos = str.find(':', pos);
+        if (colon_pos == std::string::npos) {
+            pos += pattern.length();
+            continue;
+        }
+
+        size_t quote_pos = str.find('\"', colon_pos);
+        if (quote_pos == std::string::npos) {
+            pos += pattern.length();
+            continue;
+        }
+
+        size_t value_start = quote_pos + 1;
+        size_t value_end = str.find('\"', value_start);
+        if (value_end == std::string::npos) {
+            pos = value_start;
+            continue;
+        }
+
+        std::string key_value = str.substr(value_start, value_end - 
value_start);
+
+        if (is_handle_sk) {
+            key_value = "md5: " + md5(key_value);
+        } else {
+            key_value = hide_access_key(key_value);
+        }
+
+        str.replace(value_start, value_end - value_start, key_value);
+
+        pos = value_end + (key_value.length() - key_value.length());
+    }
+};
+
 /**
  * Encrypts all "sk" values in the given debug string with MD5 hashes.
  * 
@@ -61,36 +100,26 @@ inline std::string md5(const std::string& str) {
  * - Input string contains one or more occurrences of "sk: " followed by a 
value in double quotes.
  * - An md5() function exists that takes a std::string and returns its MD5 
hash as a string.
  * 
- * @param debug_string Input string containing "sk: " fields to be encrypted.
+ * @param debug_string Input string containing "sk: " or ""sk": " fields to be 
encrypted.
  * @return A new string with all "sk" values replaced by their MD5 hashes.
  * 
- * Behavior:
+ * Behavior for "sk: " format:
  * 1. Searches for all occurrences of "sk: " in the input string.
  * 2. For each occurrence, extracts the value between double quotes.
  * 3. Replaces the original value with "md5: " followed by its MD5 hash.
  * 4. Returns the modified string with all "sk" values encrypted.
  */
 inline std::string encryt_sk(std::string debug_string) {
-    // Start position for searching "sk" fields
-    size_t pos = 0;
-    // Iterate through the string and find all occurrences of "sk: "
-    while ((pos = debug_string.find("sk: ", pos)) != std::string::npos) {
-        // Find the start and end of the "sk" value (assumed to be within 
quotes)
-        // Start after the quote
-        size_t sk_value_start = debug_string.find('\"', pos) + 1;
-        // End at the next quote
-        size_t sk_value_end = debug_string.find('\"', sk_value_start);
-
-        // Extract the "sk" value
-        std::string sk_value = debug_string.substr(sk_value_start, 
sk_value_end - sk_value_start);
-        // Encrypt the "sk" value with MD5
-        std::string encrypted_sk = "md5: " + md5(sk_value);
-
-        // Replace the original "sk" value with the encrypted MD5 value
-        debug_string.replace(sk_value_start, sk_value_end - sk_value_start, 
encrypted_sk);
-        // Move the position to the end of the current "sk" field and continue 
searching
-        pos = sk_value_end;
-    }
+    process_ak_sk_pattern(debug_string, "sk: ", true);
+    process_ak_sk_pattern(debug_string, "\"sk\"", true);
+
+    return debug_string;
+}
+
+inline std::string hide_ak(std::string debug_string) {
+    process_ak_sk_pattern(debug_string, "ak: ", false);
+    process_ak_sk_pattern(debug_string, "\"ak\"", false);
+
     return debug_string;
 }
 
@@ -134,6 +163,13 @@ void begin_rpc(std::string_view func_name, 
brpc::Controller* ctrl, const Request
                   << " lock_id=" << req->lock_id() << " initiator=" << 
req->initiator()
                   << " expiration=" << req->expiration()
                   << " require_compaction_stats=" << 
req->require_compaction_stats();
+    } else if constexpr (std::is_same_v<Request, CreateInstanceRequest> ||
+                         std::is_same_v<Request, CreateStageRequest>) {
+        std::string debug_string = encryt_sk(req->ShortDebugString());
+        debug_string = hide_ak(debug_string);
+        TEST_SYNC_POINT_CALLBACK("sk_begin_rpc", &debug_string);
+        LOG(INFO) << "begin " << func_name << " remote_caller=" << 
ctrl->remote_side()
+                  << " original_client_ip=" << req->request_ip() << " 
request=" << debug_string;
     } else {
         LOG(INFO) << "begin " << func_name << " remote_caller=" << 
ctrl->remote_side()
                   << " original_client_ip=" << req->request_ip()
@@ -179,8 +215,10 @@ void finish_rpc(std::string_view func_name, 
brpc::Controller* ctrl, const Reques
                   << " original_client_ip=" << req->request_ip()
                   << " status=" << res->status().ShortDebugString();
     } else if constexpr (std::is_same_v<Response, GetObjStoreInfoResponse> ||
-                         std::is_same_v<Response, GetStageResponse>) {
+                         std::is_same_v<Response, GetStageResponse> ||
+                         std::is_same_v<Response, GetInstanceResponse>) {
         std::string debug_string = encryt_sk(res->DebugString());
+        debug_string = hide_ak(debug_string);
         TEST_SYNC_POINT_CALLBACK("sk_finish_rpc", &debug_string);
         LOG(INFO) << "finish " << func_name << " remote_caller=" << 
ctrl->remote_side()
                   << " original_client_ip=" << req->request_ip() << " 
response=" << debug_string;
diff --git a/cloud/src/meta-service/meta_service_http.cpp 
b/cloud/src/meta-service/meta_service_http.cpp
index 8d7f6bba6e4..be4c643f7e5 100644
--- a/cloud/src/meta-service/meta_service_http.cpp
+++ b/cloud/src/meta-service/meta_service_http.cpp
@@ -48,6 +48,7 @@
 #include "common/configbase.h"
 #include "common/logging.h"
 #include "common/string_util.h"
+#include "meta-service/meta_service_helper.h"
 #include "meta-store/keys.h"
 #include "meta-store/txn_kv.h"
 #include "meta-store/txn_kv_error.h"
@@ -63,7 +64,7 @@ namespace doris::cloud {
         auto st = parse_json_message(unresolved_path, body, &req);             
                 \
         if (!st.ok()) {                                                        
                 \
             std::string msg = "parse http request '" + unresolved_path + "': " 
+ st.ToString(); \
-            LOG_WARNING(msg).tag("body", body);                                
                 \
+            LOG_WARNING(msg).tag("body", encryt_sk(body));                     
                 \
             return http_json_reply(MetaServiceCode::PROTOBUF_PARSE_ERR, msg);  
                 \
         }                                                                      
                 \
     } while (0)
@@ -86,7 +87,7 @@ static google::protobuf::util::Status 
parse_json_message(const std::string& unre
     if (!st.ok()) {
         std::string msg = "failed to strictly parse http request for '" + 
unresolved_path +
                           "' error: " + st.ToString();
-        LOG_WARNING(msg).tag("body", body);
+        LOG_WARNING(msg).tag("body", encryt_sk(hide_access_key(body)));
 
         // ignore unknown fields
         google::protobuf::util::JsonParseOptions json_parse_options;
@@ -776,6 +777,8 @@ void 
MetaServiceImpl::http(::google::protobuf::RpcController* controller,
     LOG(INFO) << "rpc from " << cntl->remote_side()
               << " request: " << cntl->http_request().uri().path();
     std::string http_request = format_http_request(cntl);
+    std::string http_request_for_log = encryt_sk(http_request);
+    http_request_for_log = hide_ak(http_request_for_log);
 
     // Auth
     auto token = http_query(cntl->http_request().uri(), "token");
@@ -786,7 +789,7 @@ void 
MetaServiceImpl::http(::google::protobuf::RpcController* controller,
         cntl->response_attachment().append(body);
         cntl->response_attachment().append("\n");
         LOG(WARNING) << "failed to handle http from " << cntl->remote_side()
-                     << " request: " << http_request << " msg: " << body;
+                     << " request: " << http_request_for_log << " msg: " << 
body;
         return;
     }
 
@@ -806,7 +809,7 @@ void 
MetaServiceImpl::http(::google::protobuf::RpcController* controller,
     int ret = cntl->http_response().status_code();
     LOG(INFO) << (ret == 200 ? "succ to " : "failed to ") << 
__PRETTY_FUNCTION__ << " "
               << cntl->remote_side() << " request=\n"
-              << http_request << "\n ret=" << ret << " msg=" << msg;
+              << http_request_for_log << "\n ret=" << ret << " msg=" << msg;
 }
 
 } // namespace doris::cloud
diff --git a/cloud/src/meta-service/meta_service_resource.cpp 
b/cloud/src/meta-service/meta_service_resource.cpp
index 9a45c7f6e9d..67bd81c10a6 100644
--- a/cloud/src/meta-service/meta_service_resource.cpp
+++ b/cloud/src/meta-service/meta_service_resource.cpp
@@ -76,7 +76,7 @@ static int encrypt_ak_sk_helper(const std::string plain_ak, 
const std::string pl
                                 MetaServiceCode& code, std::string& msg) {
     std::string key;
     int64_t key_id;
-    LOG_INFO("enter encrypt_ak_sk_helper, plain_ak {}", plain_ak);
+    LOG_INFO("enter encrypt_ak_sk_helper, plain_ak {}", 
hide_access_key(plain_ak));
     int ret = get_newest_encryption_key_for_ak_sk(&key_id, &key);
     TEST_SYNC_POINT_CALLBACK("encrypt_ak_sk:get_encryption_key", &ret, &key, 
&key_id);
     if (ret != 0) {
@@ -1661,7 +1661,10 @@ void 
MetaServiceImpl::create_instance(google::protobuf::RpcController* controlle
                                       const CreateInstanceRequest* request,
                                       CreateInstanceResponse* response,
                                       ::google::protobuf::Closure* done) {
+    TEST_SYNC_POINT_CALLBACK("create_instance_sk_request",
+                             const_cast<CreateInstanceRequest**>(&request));
     RPC_PREPROCESS(create_instance, get, put);
+    TEST_SYNC_POINT_RETURN_WITH_VOID("create_instance_sk_request_return");
     if (request->has_ram_user()) {
         auto& ram_user = request->ram_user();
         std::string ram_user_id = ram_user.has_user_id() ? ram_user.user_id() 
: "";
@@ -1739,6 +1742,10 @@ void 
MetaServiceImpl::create_instance(google::protobuf::RpcController* controlle
         return;
     }
 
+    for (auto& obj_info : *instance.mutable_obj_info()) {
+        obj_info.set_ak(hide_access_key(obj_info.ak()));
+    }
+
     LOG(INFO) << "xxx instance json=" << proto_to_json(instance);
 
     // Check existence before proceeding
@@ -1978,6 +1985,8 @@ void 
MetaServiceImpl::get_instance(google::protobuf::RpcController* controller,
                                    const GetInstanceRequest* request, 
GetInstanceResponse* response,
                                    ::google::protobuf::Closure* done) {
     RPC_PREPROCESS(get_instance, get);
+    TEST_SYNC_POINT_CALLBACK("get_instance_sk_response", &response);
+    TEST_SYNC_POINT_RETURN_WITH_VOID("get_instance_sk_response_return");
     std::string cloud_unique_id = request->has_cloud_unique_id() ? 
request->cloud_unique_id() : "";
     if (cloud_unique_id.empty()) {
         code = MetaServiceCode::INVALID_ARGUMENT;
@@ -2763,7 +2772,9 @@ void 
MetaServiceImpl::get_cluster(google::protobuf::RpcController* controller,
 void MetaServiceImpl::create_stage(::google::protobuf::RpcController* 
controller,
                                    const CreateStageRequest* request, 
CreateStageResponse* response,
                                    ::google::protobuf::Closure* done) {
+    TEST_SYNC_POINT_CALLBACK("create_stage_sk_request", 
const_cast<CreateStageRequest**>(&request));
     RPC_PREPROCESS(create_stage, get, put);
+    TEST_SYNC_POINT_RETURN_WITH_VOID("create_stage_sk_request_return");
     std::string cloud_unique_id = request->has_cloud_unique_id() ? 
request->cloud_unique_id() : "";
     if (cloud_unique_id.empty()) {
         code = MetaServiceCode::INVALID_ARGUMENT;
diff --git a/cloud/src/resource-manager/resource_manager.cpp 
b/cloud/src/resource-manager/resource_manager.cpp
index 7c5a95b4267..3aa7fcb99b3 100644
--- a/cloud/src/resource-manager/resource_manager.cpp
+++ b/cloud/src/resource-manager/resource_manager.cpp
@@ -519,8 +519,12 @@ std::pair<MetaServiceCode, std::string> 
ResourceManager::add_cluster(const std::
     }
 
     auto& req_cluster = cluster.cluster;
+    InstanceInfoPB instance_for_log {instance};
+    for (auto& obj_info : *instance_for_log.mutable_obj_info()) {
+        obj_info.set_ak(hide_access_key(obj_info.ak()));
+    }
     LOG(INFO) << "cluster to add json=" << proto_to_json(req_cluster);
-    LOG(INFO) << "json=" << proto_to_json(instance);
+    LOG(INFO) << "json=" << proto_to_json(instance_for_log);
 
     // Check id and name, they need to be unique
     // One cluster id per name, name is alias of cluster id
diff --git a/cloud/test/meta_service_http_test.cpp 
b/cloud/test/meta_service_http_test.cpp
index 082a7e3d974..9fb7abb04f3 100644
--- a/cloud/test/meta_service_http_test.cpp
+++ b/cloud/test/meta_service_http_test.cpp
@@ -1603,6 +1603,124 @@ TEST(MetaServiceHttpTest, 
get_obj_store_info_response_sk) {
     ms->get_obj_store_info(&cntl, &req1, &res1, nullptr);
 }
 
+TEST(MetaServiceHttpTest, get_instance_response_sk) {
+    auto sp = SyncPoint::get_instance();
+    sp->enable_processing();
+    DORIS_CLOUD_DEFER {
+        sp->disable_processing();
+    };
+
+    GetInstanceResponse res;
+    auto* obj_info = res.mutable_instance()->add_obj_info();
+    obj_info->set_ak("instance-ak");
+    obj_info->set_sk("instance-sk");
+    auto foo = [res](auto args) {
+        (*(try_any_cast<GetInstanceResponse**>(args[0])))->CopyFrom(res);
+    };
+    sp->set_call_back("get_instance_sk_response", foo);
+    sp->set_call_back("get_instance_sk_response_return",
+                      [](auto&& args) { *try_any_cast<bool*>(args.back()) = 
true; });
+
+    auto rate_limiter = std::make_shared<cloud::RateLimiter>();
+
+    auto ms = std::make_unique<cloud::MetaServiceImpl>(nullptr, nullptr, 
rate_limiter);
+
+    auto bar = [](auto args) {
+        std::cout << *try_any_cast<std::string*>(args[0]);
+
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0])).find("instance-sk") 
==
+                    std::string::npos);
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0]))
+                            .find("md5: 79d1924d669b7412019edc42db31bd92") != 
std::string::npos);
+    };
+    sp->set_call_back("sk_finish_rpc", bar);
+
+    GetInstanceResponse res1;
+    GetInstanceRequest req1;
+    brpc::Controller cntl;
+    ms->get_instance(&cntl, &req1, &res1, nullptr);
+}
+
+TEST(MetaServiceHttpTest, create_instance_request_sk) {
+    auto sp = SyncPoint::get_instance();
+    sp->enable_processing();
+    DORIS_CLOUD_DEFER {
+        sp->disable_processing();
+    };
+
+    CreateInstanceRequest req;
+    req.set_instance_id("get_value_instance_id");
+    req.set_user_id("test_user");
+    req.set_name("test_name");
+    ObjectStoreInfoPB obj;
+    obj.set_ak("instance-ak");
+    obj.set_sk("instance-sk");
+    req.mutable_obj_info()->CopyFrom(obj);
+
+    auto foo = [req](auto args) {
+        (*(try_any_cast<CreateInstanceRequest**>(args[0])))->CopyFrom(req);
+    };
+    sp->set_call_back("create_instance_sk_request", foo);
+    sp->set_call_back("create_instance_sk_request_return",
+                      [](auto&& args) { *try_any_cast<bool*>(args.back()) = 
true; });
+
+    auto rate_limiter = std::make_shared<cloud::RateLimiter>();
+
+    auto ms = std::make_unique<cloud::MetaServiceImpl>(nullptr, nullptr, 
rate_limiter);
+
+    auto bar = [](auto args) {
+        std::cout << *try_any_cast<std::string*>(args[0]) << '\n';
+
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0])).find("instance-sk") 
==
+                    std::string::npos);
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0]))
+                            .find("md5: 79d1924d669b7412019edc42db31bd92") != 
std::string::npos);
+    };
+    sp->set_call_back("sk_begin_rpc", bar);
+
+    CreateInstanceResponse res1;
+    CreateInstanceRequest req1;
+    brpc::Controller cntl;
+    ms->create_instance(&cntl, &req1, &res1, nullptr);
+}
+
+TEST(MetaServiceHttpTest, create_stage_request_sk) {
+    auto sp = SyncPoint::get_instance();
+    sp->enable_processing();
+    DORIS_CLOUD_DEFER {
+        sp->disable_processing();
+    };
+
+    CreateStageRequest req;
+    req.mutable_stage()->mutable_obj_info()->set_ak("stage-ak");
+    req.mutable_stage()->mutable_obj_info()->set_sk("stage-sk");
+
+    auto foo = [req](auto args) {
+        (*(try_any_cast<CreateStageRequest**>(args[0])))->CopyFrom(req);
+    };
+    sp->set_call_back("create_stage_sk_request", foo);
+    sp->set_call_back("create_stage_sk_request_return",
+                      [](auto&& args) { *try_any_cast<bool*>(args.back()) = 
true; });
+
+    auto rate_limiter = std::make_shared<cloud::RateLimiter>();
+
+    auto ms = std::make_unique<cloud::MetaServiceImpl>(nullptr, nullptr, 
rate_limiter);
+
+    auto bar = [](auto args) {
+        std::cout << *try_any_cast<std::string*>(args[0]) << '\n';
+
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0])).find("stage-sk") == 
std::string::npos);
+        EXPECT_TRUE((*try_any_cast<std::string*>(args[0]))
+                            .find("md5: f497d053066fa4b7d3b1f6564597d233") != 
std::string::npos);
+    };
+    sp->set_call_back("sk_begin_rpc", bar);
+
+    CreateStageResponse res1;
+    CreateStageRequest req1;
+    brpc::Controller cntl;
+    ms->create_stage(&cntl, &req1, &res1, nullptr);
+}
+
 TEST(MetaServiceHttpTest, AdjustRateLimit) {
     HttpContext ctx;
     {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/system/CloudSystemInfoService.java
 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/system/CloudSystemInfoService.java
index 81765e18029..10ad5c7ab66 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/system/CloudSystemInfoService.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/system/CloudSystemInfoService.java
@@ -26,6 +26,7 @@ import org.apache.doris.cloud.catalog.ComputeGroup;
 import org.apache.doris.cloud.proto.Cloud;
 import org.apache.doris.cloud.proto.Cloud.ClusterPB;
 import org.apache.doris.cloud.proto.Cloud.InstanceInfoPB;
+import org.apache.doris.cloud.proto.Cloud.ObjectStoreInfoPB;
 import org.apache.doris.cloud.qe.ComputeGroupException;
 import org.apache.doris.cloud.rpc.MetaServiceProxy;
 import org.apache.doris.common.AnalysisException;
@@ -1525,6 +1526,7 @@ public class CloudSystemInfoService extends 
SystemInfoService {
         try {
             Cloud.GetInstanceRequest request = builder.build();
             response = MetaServiceProxy.getInstance().getInstance(request);
+            response = hideAkSkForStorageVault(response.toBuilder());
             LOG.info("get instance info, request: {}, response: {}", request, 
response);
             if (response.getStatus().getCode() != Cloud.MetaServiceCode.OK) {
                 LOG.warn("Failed to get instance info, response: {}", 
response);
@@ -1537,6 +1539,61 @@ public class CloudSystemInfoService extends 
SystemInfoService {
         }
     }
 
+    private String hideKey(String key) {
+        if (key == null || key.isEmpty()) {
+            return "";
+        }
+
+        int keyLen = key.length();
+        int reservedCount = (keyLen > 6) ? 6 : (keyLen > 2 ? keyLen - 2 : 0);
+        int xCount = keyLen - reservedCount;
+
+        int leftXCount = xCount / 2;
+        StringBuilder result = new StringBuilder();
+
+        for (int i = 0; i < leftXCount; i++) {
+            result.append('x');
+        }
+
+        int startIndex = leftXCount;
+        int endIndex = startIndex + reservedCount;
+        result.append(key.substring(startIndex, endIndex));
+
+        int rightXCount = xCount - leftXCount;
+        for (int i = 0; i < rightXCount; i++) {
+            result.append('x');
+        }
+        return result.toString();
+    }
+
+    public Cloud.GetInstanceResponse 
hideAkSkForStorageVault(Cloud.GetInstanceResponse.Builder resp) {
+        if (resp == null) {
+            return null;
+        }
+
+        if (resp.getInstance().getObjInfoCount() == 0) {
+            return resp.build();
+        }
+
+        for (int i = 0; i < resp.getInstance().getObjInfoCount(); i++) {
+            ObjectStoreInfoPB objInfo = resp.getInstance().getObjInfo(i);
+            if (objInfo == null) {
+                continue;
+            }
+            if (objInfo.hasAk()) {
+                String ak = objInfo.getAk();
+                String hiddenAk = hideKey(ak);
+                resp.getInstanceBuilder().getObjInfoBuilder(i).setAk(hiddenAk);
+            }
+            if (objInfo.hasSk()) {
+                String sk = objInfo.getSk();
+                String hiddenSk = hideKey(sk);
+                resp.getInstanceBuilder().getObjInfoBuilder(i).setSk(hiddenSk);
+            }
+        }
+        return resp.build();
+    }
+
     public void renameComputeGroup(String originalName, String newGroupName) 
throws UserException {
         String cloudInstanceId = ((CloudEnv) 
Env.getCurrentEnv()).getCloudInstanceId();
         if (Strings.isNullOrEmpty(cloudInstanceId)) {


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

Reply via email to