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

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


The following commit(s) were added to refs/heads/branch-4.0 by this push:
     new 1741153ddab branch-4.0: [chore](tde) Pick rotate open source code 
#56838 (#57031)
1741153ddab is described below

commit 1741153ddabc6f3ce09dee07c0221b065849e6cd
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Oct 16 19:00:55 2025 +0800

    branch-4.0: [chore](tde) Pick rotate open source code #56838 (#57031)
    
    Cherry-picked from #56838
    
    Co-authored-by: Siyang Tang <[email protected]>
---
 be/src/http/action/check_encryption_action.cpp     | 80 ++++++++++++++++++++--
 .../org/apache/doris/encryption/EncryptionKey.java | 17 +++++
 .../apache/doris/encryption/KeyManagerStore.java   | 11 ++-
 .../org/apache/doris/encryption/RootKeyInfo.java   |  2 +-
 4 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/be/src/http/action/check_encryption_action.cpp 
b/be/src/http/action/check_encryption_action.cpp
index b122464a539..dbf94cb92dd 100644
--- a/be/src/http/action/check_encryption_action.cpp
+++ b/be/src/http/action/check_encryption_action.cpp
@@ -18,7 +18,11 @@
 #include "http/action/check_encryption_action.h"
 
 #include <gen_cpp/olap_file.pb.h>
+#include <glog/logging.h>
+#include <google/protobuf/util/json_util.h>
+#include <json2pb/pb_to_json.h>
 
+#include <cstdint>
 #include <exception>
 #include <memory>
 #include <shared_mutex>
@@ -27,6 +31,7 @@
 
 #include "cloud/cloud_tablet.h"
 #include "cloud/config.h"
+#include "common/status.h"
 #include "http/http_channel.h"
 #include "http/http_headers.h"
 #include "http/http_status.h"
@@ -40,6 +45,7 @@
 namespace doris {
 
 const std::string TABLET_ID = "tablet_id";
+const std::string GET_FOOTER = "get_footer";
 
 CheckEncryptionAction::CheckEncryptionAction(ExecEnv* exec_env, 
TPrivilegeHier::type hier,
                                              TPrivilegeType::type type)
@@ -95,7 +101,7 @@ Result<bool> is_tablet_encrypted(const BaseTabletSPtr& 
tablet) {
                 return;
             }
             std::vector<uint8_t> magic_code_buf;
-            magic_code_buf.reserve(sizeof(uint64_t));
+            magic_code_buf.resize(sizeof(uint64_t));
             Slice magic_code(magic_code_buf.data(), sizeof(uint64_t));
             size_t bytes_read;
             st = reader->read_at(reader->size() - sizeof(uint64_t), 
magic_code, &bytes_read);
@@ -117,6 +123,50 @@ Result<bool> is_tablet_encrypted(const BaseTabletSPtr& 
tablet) {
     return st;
 }
 
+Result<std::string> get_last_encrypt_footer(const BaseTabletSPtr& tablet) {
+    std::shared_lock l(tablet->get_header_lock());
+    auto rs = tablet->get_rowset_with_max_version();
+    if (rs->num_segments() == 0) {
+        return "{}";
+    }
+    auto maybe_seg_path = rs->segment_path(0);
+    if (!maybe_seg_path) {
+        return ResultError(maybe_seg_path.error());
+    }
+    auto rs_meta = rs->rowset_meta();
+    if (config::is_cloud_mode() && rs_meta->start_version() == 0 && 
rs_meta->end_version() == 1) {
+        return "{}";
+    }
+    auto fs = rs_meta->physical_fs();
+    io::FileReaderSPtr reader;
+    RETURN_IF_ERROR_RESULT(fs->open_file(maybe_seg_path.value(), &reader));
+
+    std::vector<uint8_t> pb_len_buf;
+    pb_len_buf.reserve(sizeof(uint64_t));
+    Slice pb_len_slice(pb_len_buf.data(), sizeof(uint64_t));
+    size_t bytes_read;
+    RETURN_IF_ERROR_RESULT(
+            reader->read_at(reader->size() - 256 + sizeof(uint8_t), 
pb_len_slice, &bytes_read));
+    auto info_pb_size = decode_fixed64_le(pb_len_buf.data());
+
+    std::vector<uint8_t> info_pb_buf;
+    info_pb_buf.resize(info_pb_size);
+    Slice pb_slice(info_pb_buf.data(), info_pb_size);
+    RETURN_IF_ERROR_RESULT(reader->read_at(
+            reader->size() - 256 + sizeof(uint8_t) + sizeof(uint64_t), 
pb_slice, &bytes_read));
+
+    FileEncryptionInfoPB info_pb;
+    if (!info_pb.ParseFromArray(info_pb_buf.data(), 
static_cast<int>(info_pb_buf.size()))) {
+        return ResultError(Status::Corruption("parse encryption info failed"));
+    }
+    std::string json;
+    google::protobuf::util::JsonPrintOptions opts;
+    opts.add_whitespace = false;
+    opts.preserve_proto_field_names = true;
+    auto st = google::protobuf::util::MessageToJsonString(info_pb, &json, 
opts);
+    return json;
+}
+
 Status sync_meta(const CloudTabletSPtr& tablet) {
     RETURN_IF_ERROR(tablet->sync_meta());
     RETURN_IF_ERROR(tablet->sync_rowsets());
@@ -143,6 +193,15 @@ void CheckEncryptionAction::handle(HttpRequest* req) {
         return;
     }
 
+    bool is_get_footer = false;
+    if (auto get_footer_flag = req->param(GET_FOOTER); get_footer_flag == 
"true") {
+        is_get_footer = true;
+    } else if (get_footer_flag != "false") {
+        HttpChannel::send_reply(req, HttpStatus::BAD_REQUEST,
+                                "param `get_footer` must be a boolean type");
+        return;
+    }
+
     auto maybe_tablet = ExecEnv::get_tablet(tablet_id);
     if (!maybe_tablet) {
         HttpChannel::send_reply(req, HttpStatus::BAD_REQUEST, 
maybe_tablet.error().to_string());
@@ -162,9 +221,22 @@ void CheckEncryptionAction::handle(HttpRequest* req) {
 
     auto maybe_is_encrypted = is_tablet_encrypted(tablet);
     if (maybe_is_encrypted.has_value()) {
-        HttpChannel::send_reply(
-                req, HttpStatus::OK,
-                maybe_is_encrypted.value() ? "all encrypted" : "some are not 
encrypted");
+        req->add_output_header(HttpHeaders::CONTENT_TYPE, 
HttpHeaders::JSON_TYPE.data());
+        std::string result = R"({"status":)";
+        result += maybe_is_encrypted.value() ? R"("all encrypted")" : R"("some 
are not encrypted")";
+        if (is_get_footer) {
+            auto maybe_footer = get_last_encrypt_footer(tablet);
+            if (!maybe_footer) {
+                HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR,
+                                        maybe_footer.error().to_json());
+                return;
+            }
+            result += R"(,"footer":)";
+            result += maybe_footer.value();
+        }
+        result += "}";
+
+        HttpChannel::send_reply(req, HttpStatus::OK, result);
         return;
     }
     HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/encryption/EncryptionKey.java 
b/fe/fe-core/src/main/java/org/apache/doris/encryption/EncryptionKey.java
index d07c864d0da..8322d6a0ff9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/encryption/EncryptionKey.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/encryption/EncryptionKey.java
@@ -46,6 +46,23 @@ public class EncryptionKey {
         MASTER_KEY, DATA_KEY;
     }
 
+    public EncryptionKey() {}
+
+    public EncryptionKey(EncryptionKey encryptionKey) {
+        this.id = encryptionKey.id;
+        this.version = encryptionKey.version;
+        this.parentId = encryptionKey.parentId;
+        this.parentVersion = encryptionKey.parentVersion;
+        this.type = encryptionKey.type;
+        this.algorithm = encryptionKey.algorithm;
+        this.ciphertext = encryptionKey.ciphertext;
+        this.plaintext = encryptionKey.plaintext;
+        this.iv = encryptionKey.iv;
+        this.crc = encryptionKey.crc;
+        this.ctime = encryptionKey.ctime;
+        this.mtime = encryptionKey.mtime;
+    }
+
     @SerializedName(value = "id")
     public String id;
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerStore.java 
b/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerStore.java
index 1e3a96c82a3..30744dfa591 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerStore.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerStore.java
@@ -39,7 +39,7 @@ public class KeyManagerStore implements Writable {
     private RootKeyInfo rootKeyInfo;
 
     @SerializedName(value = "masterKeys")
-    private final List<EncryptionKey> masterKeys = new ArrayList<>();
+    private List<EncryptionKey> masterKeys = new ArrayList<>();
 
     private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
 
@@ -77,6 +77,15 @@ public class KeyManagerStore implements Writable {
         }
     }
 
+    public void setMasterKeys(List<EncryptionKey> masterKeys) {
+        writeLock();
+        try {
+            this.masterKeys = masterKeys;
+        } finally {
+            writeUnlock();
+        }
+    }
+
     public void setRootKeyInfo(RootKeyInfo info) {
         writeLock();
         try {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/encryption/RootKeyInfo.java 
b/fe/fe-core/src/main/java/org/apache/doris/encryption/RootKeyInfo.java
index f056a5a95fe..e2aa248ce2e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/encryption/RootKeyInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/encryption/RootKeyInfo.java
@@ -34,7 +34,7 @@ public class RootKeyInfo {
             if (AWS_KMS.name.equalsIgnoreCase(name)) {
                 return AWS_KMS;
             }
-            throw new IllegalArgumentException("invalid name" + name);
+            throw new IllegalArgumentException("invalid name: " + name);
         }
 
         RootKeyType(String name) {


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

Reply via email to