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 a7bfa14db6b branch-4.0: [feature](tde) Support rotating root key 
command (#55901) #56342 (#56770)
a7bfa14db6b is described below

commit a7bfa14db6b449bd75fd59a7c8327fdcebda06a3
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Oct 11 16:00:01 2025 +0800

    branch-4.0: [feature](tde) Support rotating root key command (#55901) 
#56342 (#56770)
    
    Cherry-picked from #56342
    
    Co-authored-by: Siyang Tang <[email protected]>
---
 .../antlr4/org/apache/doris/nereids/DorisLexer.g4  |  2 +
 .../antlr4/org/apache/doris/nereids/DorisParser.g4 |  3 +
 .../doris/encryption/KeyManagerInterface.java      |  8 +++
 .../org/apache/doris/encryption/RootKeyInfo.java   | 35 ++++++++++-
 .../doris/nereids/parser/LogicalPlanBuilder.java   |  8 +++
 .../apache/doris/nereids/trees/plans/PlanType.java |  1 +
 .../commands/AdminRotateTdeRootKeyCommand.java     | 67 ++++++++++++++++++++++
 .../trees/plans/visitor/CommandVisitor.java        |  5 ++
 .../doris/nereids/parser/NereidsParserTest.java    | 16 ++++++
 9 files changed, 144 insertions(+), 1 deletion(-)

diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
index 360a498f611..0e1dc32b32e 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4
@@ -468,6 +468,7 @@ ROLES: 'ROLES';
 ROLLBACK: 'ROLLBACK';
 ROLLUP: 'ROLLUP';
 ROOT: 'ROOT';
+ROTATE: 'ROTATE';
 ROUTINE: 'ROUTINE';
 ROW: 'ROW';
 ROWS: 'ROWS';
@@ -525,6 +526,7 @@ TABLETS: 'TABLETS';
 TAG: 'TAG';
 TASK: 'TASK';
 TASKS: 'TASKS';
+TDE: 'TDE';
 TEMPORARY: 'TEMPORARY';
 TERMINATED: 'TERMINATED';
 TEXT: 'TEXT';
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 25075996fba..11bf78caa2b 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -608,6 +608,7 @@ supportedAdminStatement
     | ADMIN SET AUTO CLUSTER SNAPSHOT propertyClause?                          
     #adminSetAutoClusterSnapshot
     | ADMIN DROP CLUSTER SNAPSHOT WHERE (key=identifier) EQ 
(value=STRING_LITERAL)  #adminDropClusterSnapshot
     | ADMIN SET CLUSTER SNAPSHOT FEATURE (ON | OFF)                            
     #adminSetClusterSnapshotFeatureSwitch
+    | ADMIN ROTATE TDE ROOT KEY properties=propertyClause?                     
     #adminRotateTdeRootKey
     ;
 
 supportedRecoverStatement
@@ -2141,6 +2142,7 @@ nonReserved
     | ROLLBACK
     | ROLLUP
     | ROOT
+    | ROTATE
     | ROUTINE
     | S3
     | SAMPLE
@@ -2179,6 +2181,7 @@ nonReserved
     | TAG
     | TASK
     | TASKS
+    | TDE
     | TEMPORARY
     | TEXT
     | THAN
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerInterface.java 
b/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerInterface.java
index ea0e71e458e..a4c97b53e92 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerInterface.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/encryption/KeyManagerInterface.java
@@ -20,6 +20,7 @@ package org.apache.doris.encryption;
 import org.apache.doris.persist.KeyOperationInfo;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * Interface for managing cryptographic keys, including root key setup,
@@ -64,4 +65,11 @@ public interface KeyManagerInterface {
      *         (may include versioning or metadata as part of each key object)
      */
     public List<EncryptionKey> getAllMasterKeys();
+
+    /**
+     * Rotate root key
+     *
+     * @param properties rotate info
+     */
+    void rotateRootKey(Map<String, String> properties) throws Exception;
 }
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 a379a125707..f056a5a95fe 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
@@ -19,9 +19,42 @@ package org.apache.doris.encryption;
 
 import com.google.gson.annotations.SerializedName;
 
+import java.util.Objects;
+
 public class RootKeyInfo {
     public enum RootKeyType {
-        LOCAL, AWS_KMS;
+        LOCAL("local"),
+        AWS_KMS("aws_kms");
+
+        public static RootKeyType tryFrom(String name) {
+            Objects.requireNonNull(name);
+            if (LOCAL.name.equalsIgnoreCase(name)) {
+                return LOCAL;
+            }
+            if (AWS_KMS.name.equalsIgnoreCase(name)) {
+                return AWS_KMS;
+            }
+            throw new IllegalArgumentException("invalid name" + name);
+        }
+
+        RootKeyType(String name) {
+            this.name = name;
+        }
+
+        String name;
+    }
+
+    public RootKeyInfo() {}
+
+    public RootKeyInfo(RootKeyInfo info) {
+        this.type = info.type;
+        this.algorithm = info.algorithm;
+        this.region = info.region;
+        this.endpoint = info.endpoint;
+        this.cmkId = info.cmkId;
+        this.ak = info.ak;
+        this.sk = info.sk;
+        this.password = info.password;
     }
 
     @SerializedName(value = "type")
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index 828285c66df..2cb725dc55e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -86,6 +86,7 @@ import 
org.apache.doris.nereids.DorisParser.AdminCheckTabletsContext;
 import org.apache.doris.nereids.DorisParser.AdminCompactTableContext;
 import org.apache.doris.nereids.DorisParser.AdminDiagnoseTabletContext;
 import org.apache.doris.nereids.DorisParser.AdminRebalanceDiskContext;
+import org.apache.doris.nereids.DorisParser.AdminRotateTdeRootKeyContext;
 import org.apache.doris.nereids.DorisParser.AdminSetEncryptionRootKeyContext;
 import org.apache.doris.nereids.DorisParser.AdminSetTableStatusContext;
 import 
org.apache.doris.nereids.DorisParser.AdminShowReplicaDistributionContext;
@@ -602,6 +603,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.AdminCreateClusterSnapshotC
 import 
org.apache.doris.nereids.trees.plans.commands.AdminDropClusterSnapshotCommand;
 import org.apache.doris.nereids.trees.plans.commands.AdminRebalanceDiskCommand;
 import org.apache.doris.nereids.trees.plans.commands.AdminRepairTableCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.AdminRotateTdeRootKeyCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetAutoClusterSnapshotCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetClusterSnapshotFeatureSwitchCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetEncryptionRootKeyCommand;
@@ -1746,6 +1748,12 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         return new AdminSetEncryptionRootKeyCommand(properties);
     }
 
+    @Override
+    public LogicalPlan visitAdminRotateTdeRootKey(AdminRotateTdeRootKeyContext 
ctx) {
+        Map<String, String> properties = 
visitPropertyClause(ctx.propertyClause());
+        return new AdminRotateTdeRootKeyCommand(properties);
+    }
+
     @Override
     public LogicalPlan visitShowConstraint(ShowConstraintContext ctx) {
         List<String> parts = visitMultipartIdentifier(ctx.table);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
index dfb15ca2328..ab9743e64ae 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java
@@ -398,6 +398,7 @@ public enum PlanType {
     ADMIN_SET_AUTO_CLUSTER_SNAPSHOT_COMMAND,
     ADMIN_SET_CLUSTER_SNAPSHOT_FEATURE_SWITCH_COMMAND,
     ADMIN_DROP_CLUSTER_SNAPSHOT_COMMAND,
+    ADMIN_ROTATE_TDE_ROOT_KEY,
     SHOW_CREATE_ROUTINE_LOAD_COMMAND,
     PAUSE_ROUTINE_LOAD_COMMAND,
     PAUSE_ALL_ROUTINE_COMMAND,
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRotateTdeRootKeyCommand.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRotateTdeRootKeyCommand.java
new file mode 100644
index 00000000000..4952c6c586a
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRotateTdeRootKeyCommand.java
@@ -0,0 +1,67 @@
+// 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.doris.nereids.trees.plans.commands;
+
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.encryption.KeyManagerInterface;
+import org.apache.doris.nereids.trees.plans.PlanType;
+import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.qe.StmtExecutor;
+
+import java.util.Map;
+
+/**
+ * Rotate TDE root key command
+ */
+public class AdminRotateTdeRootKeyCommand extends Command implements 
ForwardWithSync {
+
+    public static final String DORIS_TDE_KEY_PROVIDER = 
"doris_tde_key_provider";
+
+    public static final String DORIS_TDE_KEY_PASSWORD = 
"doris_tde_key_password";
+
+    public static final String DORIS_TDE_KEY_ORIGINAL_PASSWORD = 
"doris_tde_key_original_password";
+
+    public static final String DORIS_TDE_KEY_ID = "doris_tde_key_id";
+
+    public static final String DORIS_TDE_KEY_ENDPOINT = 
"doris_tde_key_endpoint";
+
+    public static final String DORIS_TDE_KEY_REGION = "doris_tde_key_region";
+
+    private final Map<String, String> properties;
+
+    public AdminRotateTdeRootKeyCommand(Map<String, String> properties) {
+        super(PlanType.ADMIN_ROTATE_TDE_ROOT_KEY);
+        this.properties = properties;
+    }
+
+    @Override
+    public void run(ConnectContext ctx, StmtExecutor executor) throws 
Exception {
+        KeyManagerInterface keyManager = ctx.getEnv().getKeyManager();
+        if (keyManager != null) {
+            keyManager.rotateRootKey(properties);
+        } else {
+            throw new AnalysisException("TDE is disabled, cannot rotate root 
key");
+        }
+    }
+
+    @Override
+    public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
+        return visitor.visitAdminRotateTdeRootKeyCommand(this, context);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
index 0a2d76e8e62..8c78e8583f8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java
@@ -28,6 +28,7 @@ import 
org.apache.doris.nereids.trees.plans.commands.AdminCreateClusterSnapshotC
 import 
org.apache.doris.nereids.trees.plans.commands.AdminDropClusterSnapshotCommand;
 import org.apache.doris.nereids.trees.plans.commands.AdminRebalanceDiskCommand;
 import org.apache.doris.nereids.trees.plans.commands.AdminRepairTableCommand;
+import 
org.apache.doris.nereids.trees.plans.commands.AdminRotateTdeRootKeyCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetAutoClusterSnapshotCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetClusterSnapshotFeatureSwitchCommand;
 import 
org.apache.doris.nereids.trees.plans.commands.AdminSetFrontendConfigCommand;
@@ -1457,6 +1458,10 @@ public interface CommandVisitor<R, C> {
         return visitCommand(dropMaterializedViewCommand, context);
     }
 
+    default R visitAdminRotateTdeRootKeyCommand(AdminRotateTdeRootKeyCommand 
rotateTdeRootKeyCommand, C context) {
+        return visitCommand(rotateTdeRootKeyCommand, context);
+    }
+
     default R visitEmptyCommand(EmptyCommand emptyCommand, C context) {
         return visitCommand(emptyCommand, context);
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
index fdcda7f1b74..0d173aed5ce 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java
@@ -1284,4 +1284,20 @@ public class NereidsParserTest extends ParserTestBase {
         }
     }
 
+    @Test
+    public void testAdminRotateTdeRootKey() {
+        NereidsParser nereidsParser = new NereidsParser();
+        String sql = "admin rotate tde root key";
+        nereidsParser.parseSingle(sql);
+
+        sql = "admin rotate tde root key properties(\"k\" = \"v\")";
+        nereidsParser.parseSingle(sql);
+
+        sql = "admin rotate tde root key properties(\"k0\" = \"v0\", \"k1\" = 
\"v1\")";
+        nereidsParser.parseSingle(sql);
+
+        parsePlan("admin rotate tde root key properties()")
+                .assertThrowsExactly(ParseException.class)
+                .assertMessageContains("mismatched input ')' expecting");
+    }
 }


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

Reply via email to