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 20c1b0a7a98 [feature](tde) Support rotating root key command (#55901)
20c1b0a7a98 is described below
commit 20c1b0a7a98eb5ede2bf420ebc607c90e4518bd6
Author: Siyang Tang <[email protected]>
AuthorDate: Fri Sep 12 10:45:47 2025 +0800
[feature](tde) Support rotating root key command (#55901)
---
.../antlr4/org/apache/doris/nereids/DorisLexer.g4 | 2 +
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 7 +++
.../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 | 69 ++++++++++++++++++++++
.../doris/nereids/parser/NereidsParserTest.java | 17 ++++++
8 files changed, 146 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 3ac6f9c4460..06c6ac6a082 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
@@ -466,6 +466,7 @@ ROLES: 'ROLES';
ROLLBACK: 'ROLLBACK';
ROLLUP: 'ROLLUP';
ROOT: 'ROOT';
+ROTATE: 'ROTATE';
ROUTINE: 'ROUTINE';
ROW: 'ROW';
ROWS: 'ROWS';
@@ -520,6 +521,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 1c2c5e52e98..3b81a902670 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
@@ -59,6 +59,7 @@ statementBase
| supportedDropStatement #supportedDropStatementAlias
| supportedShowStatement #supportedShowStatementAlias
| supportedKillStatement #supportedKillStatementAlias
+ | supportedAdminStatement #supportedAdminStatementAlias
| unsupportedStatement #unsupported
;
@@ -502,6 +503,10 @@ unsupportedAdminStatement
| ADMIN SET TABLE name=multipartIdentifier STATUS
properties=propertyClause? #adminSetTableStatus
;
+supportedAdminStatement
+ : ADMIN ROTATE TDE ROOT KEY properties=propertyClause?
#adminRotateTdeRootKey
+ ;
+
baseTableRef
: multipartIdentifier optScanParams? tableSnapshot? specifiedPartition?
tabletList? tableAlias sample? relationHint?
@@ -2074,6 +2079,7 @@ nonReserved
| ROLLBACK
| ROLLUP
| ROOT
+ | ROTATE
| ROUTINE
| S3
| SAMPLE
@@ -2109,6 +2115,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 1f3ff990004..867dc525683 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
@@ -46,6 +46,7 @@ import org.apache.doris.mtmv.MTMVRefreshSchedule;
import org.apache.doris.mtmv.MTMVRefreshTriggerInfo;
import org.apache.doris.nereids.DorisParser;
import org.apache.doris.nereids.DorisParser.AddConstraintContext;
+import org.apache.doris.nereids.DorisParser.AdminRotateTdeRootKeyContext;
import org.apache.doris.nereids.DorisParser.AdminSetEncryptionRootKeyContext;
import org.apache.doris.nereids.DorisParser.AggClauseContext;
import org.apache.doris.nereids.DorisParser.AggStateDataTypeContext;
@@ -342,6 +343,7 @@ import
org.apache.doris.nereids.trees.plans.algebra.Aggregate;
import org.apache.doris.nereids.trees.plans.algebra.InlineTable;
import org.apache.doris.nereids.trees.plans.algebra.SetOperation.Qualifier;
import org.apache.doris.nereids.trees.plans.commands.AddConstraintCommand;
+import
org.apache.doris.nereids.trees.plans.commands.AdminRotateTdeRootKeyCommand;
import
org.apache.doris.nereids.trees.plans.commands.AdminSetEncryptionRootKeyCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterMTMVCommand;
import org.apache.doris.nereids.trees.plans.commands.AlterStorageVaultCommand;
@@ -968,6 +970,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 1aee0ddbdae..0f2384fe141 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
@@ -179,6 +179,7 @@ public enum PlanType {
KILL_QUERY_COMMAND,
KILL_CONNECTION_COMMAND,
ADMIN_SET_ENCRYPTION_ROOT_KEY_COMMAND,
+ ADMIN_ROTATE_TDE_ROOT_KEY,
KILL_ANALYZE_JOB_COMMAND,
DROP_ANALYZE_JOB_COMMAND,
CREATE_INDEX_ANALYZER_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..2d2dbbe3996
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AdminRotateTdeRootKeyCommand.java
@@ -0,0 +1,69 @@
+// 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;
+import java.util.Objects;
+
+/**
+ * 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);
+ Objects.requireNonNull(properties, "properties are required");
+ 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.visitCommand(this, 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 6d1979092bb..18bce009623 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
@@ -873,4 +873,21 @@ public class NereidsParserTest extends ParserTestBase {
LogicalPlan logicalPlan = parser.parseSingle(sql);
Assertions.assertInstanceOf(UnsupportedCommand.class, logicalPlan);
}
+
+ @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]