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

yongzao pushed a commit to branch security-patch
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/security-patch by this push:
     new 3ae8a586ad6 Fix rename user bugs
3ae8a586ad6 is described below

commit 3ae8a586ad653b86b0fe8e88c129d1c932a0749f
Author: Yongzao <[email protected]>
AuthorDate: Wed Oct 1 15:52:36 2025 +0800

    Fix rename user bugs
---
 .../commit/IoTDBRegionReconstructForIoTV1IT.java   |  2 +-
 .../apache/iotdb/db/it/auth/IoTDBUserRenameIT.java | 31 ++++++++++++++++---
 .../scalar/IoTDBBitwiseFunctionTableIT.java        | 36 +++++++++++-----------
 .../iotdb/session/it/IoTDBSessionCompressedIT.java | 10 +++---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  4 +--
 .../receiver/protocol/IoTDBConfigNodeReceiver.java |  2 +-
 .../pipe/consensuspipe/ConsensusPipeManager.java   |  3 +-
 .../org/apache/iotdb/db/auth/AuthorityChecker.java |  3 +-
 .../config/executor/ClusterConfigTaskExecutor.java |  2 +-
 .../relational/security/AccessControlImpl.java     | 18 ++++++++---
 .../security/TreeAccessCheckVisitor.java           | 12 +++++++-
 .../plan/relational/sql/parser/AstBuilder.java     |  6 ++--
 .../auth/authorizer/LocalFileAuthorizerTest.java   |  2 +-
 .../auth/authorizer/LocalFileAuthorizer.java       |  2 +-
 .../iotdb/commons/auth/user/BasicUserManager.java  | 25 +++++++++------
 .../apache/iotdb/commons/conf/CommonConfig.java    |  2 +-
 .../apache/iotdb/commons/conf/IoTDBConstant.java   |  2 ++
 .../db/relational/grammar/sql/RelationalSql.g4     |  4 +--
 .../src/main/thrift/datanode.thrift                |  1 +
 19 files changed, 109 insertions(+), 58 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionReconstructForIoTV1IT.java
 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionReconstructForIoTV1IT.java
index 777b1d2d652..42dee93d331 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionReconstructForIoTV1IT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/commit/IoTDBRegionReconstructForIoTV1IT.java
@@ -151,7 +151,7 @@ public class IoTDBRegionReconstructForIoTV1IT extends 
IoTDBRegionOperationReliab
                 EnvFactory.getEnv()
                     .getConnection(
                         
EnvFactory.getEnv().dataNodeIdToWrapper(dataNodeToBeReconstructed).get(),
-                        
CommonDescriptor.getInstance().getConfig().getAdminName(),
+                        
CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
                         
CommonDescriptor.getInstance().getConfig().getAdminPassword(),
                         BaseEnv.TREE_SQL_DIALECT);
             Statement flushStatement = flushConn.createStatement()) {
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBUserRenameIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBUserRenameIT.java
index b17f7786723..b9c474e2e58 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBUserRenameIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBUserRenameIT.java
@@ -68,6 +68,11 @@ public class IoTDBUserRenameIT {
         Statement adminStmt = adminCon.createStatement()) {
       adminStmt.execute("CREATE USER user1 'IoTDB@2021abc'");
       adminStmt.execute("CREATE USER user2 'IoTDB@2023abc'");
+      if (BaseEnv.TABLE_SQL_DIALECT.equals(dialect)) {
+        adminStmt.execute("GRANT SECURITY TO USER user2");
+      } else {
+        adminStmt.execute("GRANT SECURITY ON root.** TO USER user2");
+      }
       try (Connection userCon =
               EnvFactory.getEnv().getConnection("user1", "IoTDB@2021abc", 
dialect);
           Statement userStmt = userCon.createStatement()) {
@@ -77,20 +82,36 @@ public class IoTDBUserRenameIT {
         // A normal user can only rename himself
         userStmt.execute("ALTER USER user1 RENAME TO user3");
       }
+      try (Connection userCon =
+              EnvFactory.getEnv().getConnection("user2", "IoTDB@2023abc", 
dialect);
+          Statement userStmt = userCon.createStatement()) {
+        // User with SECURITY privilege can rename other users
+        userStmt.execute("ALTER USER user3 RENAME TO user1");
+        // Nobody can rename superuser
+        Assert.assertThrows(
+            SQLException.class, () -> userStmt.execute("ALTER USER root RENAME 
TO admin"));
+      }
       // Cannot rename an unexisting user
       Assert.assertThrows(
           SQLException.class, () -> adminStmt.execute("ALTER USER user4 RENAME 
TO user5"));
       // Cannot rename to an already existed user
       Assert.assertThrows(
-          SQLException.class, () -> adminStmt.execute("ALTER USER user2 RENAME 
TO user3"));
-      // The superuser can rename anyone
-      adminStmt.execute("ALTER USER user3 RENAME TO user4");
+          SQLException.class, () -> adminStmt.execute("ALTER USER user2 RENAME 
TO user1"));
+      // Cannot rename to an illegal name
+      Assert.assertThrows(
+          SQLException.class, () -> adminStmt.execute("ALTER USER user2 RENAME 
TO p00"));
+      // Only the superuser can rename him/herself
       adminStmt.execute("ALTER USER root RENAME TO admin");
     }
-    // Ensure every rename works
     try (Connection adminCon = EnvFactory.getEnv().getConnection("admin", 
"root", dialect);
         Statement adminStmt = adminCon.createStatement()) {
-      final String ans = "0,admin,\n" + "10000,user4,\n" + "10001,user2,\n";
+      // We can rename other user to root
+      adminStmt.execute("ALTER USER user1 RENAME TO root");
+      adminStmt.execute("ALTER USER root RENAME TO user4");
+      // We can create another root
+      adminStmt.execute("CREATE USER root 'IoTDB@2025abc'");
+      // Ensure everything works
+      final String ans = "0,admin,\n" + "10000,user4,\n" + "10001,user2,\n" + 
"10002,root,\n";
       ResultSet resultSet = adminStmt.executeQuery("LIST USER");
       validateResultSet(resultSet, ans);
     }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBBitwiseFunctionTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBBitwiseFunctionTableIT.java
index 904aa8a0e1e..6a8b83769cd 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBBitwiseFunctionTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBBitwiseFunctionTableIT.java
@@ -148,7 +148,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time,s2,s3,bit_count(9,64),bit_count(s2,64),bit_count(s2,s3) 
from bit_count_error_table",
         "Argument exception, the scalar function num must be representable 
with the bits specified. 9 cannot be represented with 2 bits.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -159,7 +159,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time,s2,s3,bit_count(9,1),bit_count(s2,1),bit_count(s2,s3) 
from bit_count_error_table",
         "Argument exception, the scalar function bit_count bits must be 
between 2 and 64.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -170,7 +170,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bit_count(s4) from bit_count_error_table",
         "701: Scalar function bit_count only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -178,7 +178,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bit_count(s1,s4) from bit_count_error_table",
         "701: Scalar function bit_count only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -204,7 +204,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_and(s4) from bitwise_and_table",
         "701: Scalar function bitwise_and only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -212,7 +212,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_and(s1,s4) from bitwise_and_table",
         "701: Scalar function bitwise_and only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -240,7 +240,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_not(s4) from bitwise_not_table",
         "701: Scalar function bitwise_not only accepts one argument and it 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -248,7 +248,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_not(s1,s4) from bitwise_not_table",
         "701: Scalar function bitwise_not only accepts one argument and it 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -274,7 +274,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_or(s4) from bitwise_or_table",
         "701: Scalar function bitwise_or only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -282,7 +282,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_or(s1,s4) from bitwise_or_table",
         "701: Scalar function bitwise_or only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -308,7 +308,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_xor(s4) from bitwise_xor_table",
         "701: Scalar function bitwise_xor only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -316,7 +316,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_xor(s1,s4) from bitwise_xor_table",
         "701: Scalar function bitwise_xor only accepts two arguments and they 
must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -347,7 +347,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_left_shift(s4) from bitwise_left_shift_table",
         "701: Scalar function bitwise_left_shift only accepts two arguments 
and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -355,7 +355,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_left_shift(s1,s4) from bitwise_left_shift_table",
         "701: Scalar function bitwise_left_shift only accepts two arguments 
and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -388,7 +388,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_right_shift(s4) from bitwise_right_shift_table",
         "701: Scalar function bitwise_right_shift only accepts two arguments 
and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -396,7 +396,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_right_shift(s1,s4) from 
bitwise_right_shift_table",
         "701: Scalar function bitwise_right_shift only accepts two arguments 
and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
@@ -423,7 +423,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_right_shift_arithmetic(s4) from 
bitwise_right_shift_arithmetic_table",
         "701: Scalar function bitwise_right_shift_arithmetic only accepts two 
arguments and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
 
@@ -431,7 +431,7 @@ public class IoTDBBitwiseFunctionTableIT {
         EnvFactory.getEnv(),
         "select time, bitwise_right_shift_arithmetic(s1,s4) from 
bitwise_right_shift_arithmetic_table",
         "701: Scalar function bitwise_right_shift_arithmetic only accepts two 
arguments and they must be Int32 or Int64 data type.",
-        CommonDescriptor.getInstance().getConfig().getAdminName(),
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
         CommonDescriptor.getInstance().getConfig().getAdminPassword(),
         DATABASE_NAME);
   }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionCompressedIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionCompressedIT.java
index c82bdfcdd07..f8cc5a77251 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionCompressedIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionCompressedIT.java
@@ -63,7 +63,7 @@ public class IoTDBSessionCompressedIT {
     ITableSession session1 =
         new TableSessionBuilder()
             .nodeUrls(nodeUrls)
-            
.username(CommonDescriptor.getInstance().getConfig().getAdminName())
+            
.username(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             
.password(CommonDescriptor.getInstance().getConfig().getAdminPassword())
             .enableCompression(true)
             .enableRedirection(true)
@@ -83,7 +83,7 @@ public class IoTDBSessionCompressedIT {
     ITableSession session2 =
         new TableSessionBuilder()
             .nodeUrls(nodeUrls)
-            
.username(CommonDescriptor.getInstance().getConfig().getAdminName())
+            
.username(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             
.password(CommonDescriptor.getInstance().getConfig().getAdminPassword())
             .enableCompression(true)
             .enableRedirection(true)
@@ -103,7 +103,7 @@ public class IoTDBSessionCompressedIT {
     ITableSession session3 =
         new TableSessionBuilder()
             .nodeUrls(nodeUrls)
-            
.username(CommonDescriptor.getInstance().getConfig().getAdminName())
+            
.username(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             
.password(CommonDescriptor.getInstance().getConfig().getAdminPassword())
             .enableCompression(true)
             .enableRedirection(true)
@@ -123,7 +123,7 @@ public class IoTDBSessionCompressedIT {
     ITableSession session4 =
         new TableSessionBuilder()
             .nodeUrls(nodeUrls)
-            
.username(CommonDescriptor.getInstance().getConfig().getAdminName())
+            
.username(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             
.password(CommonDescriptor.getInstance().getConfig().getAdminPassword())
             .enableCompression(true)
             .enableRedirection(true)
@@ -143,7 +143,7 @@ public class IoTDBSessionCompressedIT {
     ITableSession session5 =
         new TableSessionBuilder()
             .nodeUrls(nodeUrls)
-            
.username(CommonDescriptor.getInstance().getConfig().getAdminName())
+            
.username(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             
.password(CommonDescriptor.getInstance().getConfig().getAdminPassword())
             .enableCompression(false)
             .enableRedirection(true)
diff --git 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 14a82e77872..1972c49d5c9 100644
--- 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -1046,7 +1046,7 @@ deleteStatement
 
 // Create User
 createUser
-    : CREATE USER userName=identifier password=STRING_LITERAL
+    : CREATE USER userName=usernameWithRoot password=STRING_LITERAL
     ;
 
 // Create Role
@@ -1061,7 +1061,7 @@ alterUser
 
 // Rename user
 renameUser
-    : ALTER USER username=usernameWithRoot RENAME TO newUsername=identifier
+    : ALTER USER username=usernameWithRoot RENAME TO 
newUsername=usernameWithRoot
     ;
 
 // ---- Alter User Account Unlock
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
index 537983124b6..0e49b869e92 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/receiver/protocol/IoTDBConfigNodeReceiver.java
@@ -325,7 +325,7 @@ public class IoTDBConfigNodeReceiver extends 
IoTDBFileReceiver {
       case CreateSchemaTemplate:
       case CommitSetSchemaTemplate:
       case PipeUnsetTemplate:
-        return 
CommonDescriptor.getInstance().getConfig().getAdminName().equals(username)
+        return 
CommonDescriptor.getInstance().getConfig().getDefaultAdminName().equals(username)
             ? StatusUtils.OK
             : new TSStatus(TSStatusCode.NO_PERMISSION.getStatusCode())
                 .setMessage("Only the admin user can perform this operation");
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/pipe/consensuspipe/ConsensusPipeManager.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/pipe/consensuspipe/ConsensusPipeManager.java
index b460e69809d..525ee6b40a2 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/pipe/consensuspipe/ConsensusPipeManager.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/pipe/consensuspipe/ConsensusPipeManager.java
@@ -114,7 +114,8 @@ public class ConsensusPipeManager {
             .put(EXTRACTOR_CAPTURE_TABLE_KEY, String.valueOf(true))
             .put(EXTRACTOR_CAPTURE_TREE_KEY, String.valueOf(true))
             .put(
-                EXTRACTOR_IOTDB_USER_KEY, 
CommonDescriptor.getInstance().getConfig().getAdminName())
+                EXTRACTOR_IOTDB_USER_KEY,
+                
CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
             .build(),
         ImmutableMap.<String, String>builder()
             .put(PROCESSOR_KEY, config.getProcessorPluginName())
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index bbd9ada2b9e..495c317c1ed 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -77,7 +77,8 @@ import static 
org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.LIST_U
 public class AuthorityChecker {
 
   public static int SUPER_USER_ID = 0;
-  public static String SUPER_USER = 
CommonDescriptor.getInstance().getConfig().getAdminName();
+  public static String SUPER_USER =
+      CommonDescriptor.getInstance().getConfig().getDefaultAdminName();
   public static String SUPER_USER_ID_IN_STR = "0";
 
   public static final TSStatus SUCCEED = new 
TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index ad09bc6b351..35eee66c090 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -2678,7 +2678,7 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
               "fakePipeName",
               // TODO: currently use root to create topic
               temporaryTopicMeta.generateExtractorAttributes(
-                  CommonDescriptor.getInstance().getConfig().getAdminName()),
+                  
CommonDescriptor.getInstance().getConfig().getDefaultAdminName()),
               temporaryTopicMeta.generateProcessorAttributes(),
               
temporaryTopicMeta.generateConnectorAttributes("fakeConsumerGroupId"));
     } catch (final Exception e) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
index ad5e748e781..d7a35f39913 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
@@ -264,10 +264,20 @@ public class AccessControlImpl implements AccessControl {
       case RENAME_USER:
       case UPDATE_USER:
         auditEntity.setAuditLogOperation(AuditLogOperation.DDL);
-        // users can change the username and password of themselves
-        // the superuser can affect anyone
-        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()
-            || statement.getUserName().equals(userName)) {
+        if (statement.getUserName().equals(userName)) {
+          // users can change the username and password of themselves
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
+          return;
+        }
+        if (AuthorityChecker.SUPER_USER_ID
+            == 
AuthorityChecker.getUserId(statement.getUserName()).orElse(-1L)) {
+          // Only the superuser can alter him/herself
+          ITableAuthCheckerImpl.recordAuditLog(
+              auditEntity.setResult(false), statement::getUserName);
+          throw new AccessDeniedException("Only the superuser can alter 
him/herself.");
+        }
+        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
+          // the superuser can alter anyone
           ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
           return;
         }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
index 5f2dc126fb4..cd6cbe31336 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
@@ -519,11 +519,21 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
       case UPDATE_USER:
       case RENAME_USER:
         context.setAuditLogOperation(AuditLogOperation.DDL);
-        // users can change the username and password of themselves
         if (statement.getUserName().equals(context.getUsername())) {
+          // users can change the username and password of themselves
           recordObjectAuthenticationAuditLog(context.setResult(true), 
context::getUsername);
           return RpcUtils.SUCCESS_STATUS;
         }
+        if (AuthorityChecker.SUPER_USER_ID
+            == 
AuthorityChecker.getUserId(statement.getUserName()).orElse(-1L)) {
+          // Only the superuser can alter him/herself
+          recordObjectAuthenticationAuditLog(context.setResult(false), 
context::getUsername);
+          return AuthorityChecker.getTSStatus(
+              false,
+              "Has no permission to execute "
+                  + authorType
+                  + ", because only the superuser can alter him/herself.");
+        }
         context.setPrivilegeType(PrivilegeType.SECURITY);
         return checkGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.DDL),
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 1d2993057ce..5e7e5d99c16 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -1707,7 +1707,7 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
   @Override
   public Node 
visitCreateUserStatement(RelationalSqlParser.CreateUserStatementContext ctx) {
     RelationalAuthorStatement stmt = new 
RelationalAuthorStatement(AuthorRType.CREATE_USER);
-    stmt.setUserName(((Identifier) visit(ctx.userName)).getValue());
+    stmt.setUserName(parseIdentifier(ctx.userName.getText()));
     String password = ((StringLiteral) visit(ctx.password)).getValue();
     stmt.setPassword(password);
     return stmt;
@@ -1763,8 +1763,8 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
   @Override
   public Node 
visitRenameUserStatement(RelationalSqlParser.RenameUserStatementContext ctx) {
     RelationalAuthorStatement stmt = new 
RelationalAuthorStatement(AuthorRType.RENAME_USER);
-    stmt.setUserName(((Identifier) visit(ctx.username)).getValue());
-    stmt.setNewUsername(((Identifier) visit(ctx.newUsername)).getValue());
+    stmt.setUserName(parseIdentifier(ctx.username.getText()));
+    stmt.setNewUsername(parseIdentifier(ctx.newUsername.getText()));
     return stmt;
   }
 
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
index 96a40d0c90d..67c5de50c07 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizerTest.java
@@ -250,7 +250,7 @@ public class LocalFileAuthorizerTest {
     IAuthorizer authorizer = BasicAuthorizer.getInstance();
     List<String> userList = authorizer.listAllUsers();
     assertEquals(1, userList.size());
-    assertEquals(CommonDescriptor.getInstance().getConfig().getAdminName(), 
userList.get(0));
+    
assertEquals(CommonDescriptor.getInstance().getConfig().getDefaultAdminName(), 
userList.get(0));
 
     int userCnt = 10;
     for (int i = 0; i < userCnt; i++) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/LocalFileAuthorizer.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/LocalFileAuthorizer.java
index 117871f6e33..1e82f81fe18 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/LocalFileAuthorizer.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/authorizer/LocalFileAuthorizer.java
@@ -36,6 +36,6 @@ public class LocalFileAuthorizer extends BasicAuthorizer {
 
   @Override
   public boolean isAdmin(String username) {
-    return config.getAdminName().equals(username);
+    return config.getDefaultAdminName().equals(username);
   }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
index f781df9e114..9ee82c045ab 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
@@ -40,6 +40,7 @@ import java.io.IOException;
 import java.util.Map;
 
 import static org.apache.iotdb.commons.auth.entity.User.INTERNAL_USER_END_ID;
+import static org.apache.iotdb.commons.conf.IoTDBConstant.SUPER_USER_ID;
 
 /** This class stores information of each user. */
 public abstract class BasicUserManager extends BasicRoleManager {
@@ -76,16 +77,16 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
    * @throws AuthException if an exception is raised when interacting with the 
lower storage.
    */
   private void initAdmin() throws AuthException {
-    User admin = 
this.getEntity(CommonDescriptor.getInstance().getConfig().getAdminName());
+    User admin = this.getEntity(SUPER_USER_ID);
 
     if (admin == null) {
       createUser(
-          CommonDescriptor.getInstance().getConfig().getAdminName(),
+          CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
           CommonDescriptor.getInstance().getConfig().getAdminPassword(),
           true,
           true);
+      admin = this.getEntity(SUPER_USER_ID);
     }
-    admin = 
this.getEntity(CommonDescriptor.getInstance().getConfig().getAdminName());
     try {
       PartialPath rootPath = new PartialPath(IoTDBConstant.PATH_ROOT + ".**");
       PathPrivilege pathPri = new PathPrivilege(rootPath);
@@ -106,11 +107,12 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
     } catch (IllegalPathException e) {
       LOGGER.warn(
           "Got a wrong path for {} to init",
-          CommonDescriptor.getInstance().getConfig().getAdminName(),
+          CommonDescriptor.getInstance().getConfig().getDefaultAdminName(),
           e);
     }
     LOGGER.info(
-        "Internal user {} initialized", 
CommonDescriptor.getInstance().getConfig().getAdminName());
+        "Internal user {} initialized",
+        CommonDescriptor.getInstance().getConfig().getDefaultAdminName());
   }
 
   private void initUserId() {
@@ -152,8 +154,9 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
     lock.writeLock(username);
     try {
       long userid;
-      if 
(username.equals(CommonDescriptor.getInstance().getConfig().getAdminName())) {
-        userid = 0;
+      if 
(username.equals(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())
+          && this.getEntity(SUPER_USER_ID) == null) {
+        userid = SUPER_USER_ID;
       } else {
         userid = ++nextUserId;
       }
@@ -191,7 +194,7 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
 
   private void validCheck(String username, String password, boolean 
enableEncrypt)
       throws AuthException {
-    if 
(!CommonDescriptor.getInstance().getConfig().getAdminName().equals(username)) {
+    if 
(!CommonDescriptor.getInstance().getConfig().getDefaultAdminName().equals(username))
 {
       if (username.equals(password)
           && 
CommonDescriptor.getInstance().getConfig().isEnforceStrongPassword()) {
         throw new AuthException(
@@ -230,6 +233,7 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
   }
 
   public void renameUser(String username, String newUsername) throws 
AuthException {
+    AuthUtils.validateName(newUsername);
     User user = this.getEntity(username);
     if (user == null) {
       throw new AuthException(
@@ -295,8 +299,9 @@ public abstract class BasicUserManager extends 
BasicRoleManager {
       try {
         User user = (User) accessor.loadEntity(userId);
         if (user.getUserId() == -1) {
-          if 
(user.getName().equals(CommonDescriptor.getInstance().getConfig().getAdminName()))
 {
-            user.setUserId(0);
+          if (user.getName()
+              
.equals(CommonDescriptor.getInstance().getConfig().getDefaultAdminName())) {
+            user.setUserId(SUPER_USER_ID);
           } else {
             user.setUserId(++nextUserId);
           }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
index 2c6912bac38..c735e8d1a1d 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
@@ -537,7 +537,7 @@ public class CommonConfig {
     this.authorizerProvider = authorizerProvider;
   }
 
-  public String getAdminName() {
+  public String getDefaultAdminName() {
     return adminName;
   }
 
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
index 5c07cbfeae1..4a54d774c94 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
@@ -372,4 +372,6 @@ public class IoTDBConstant {
   // Class Name
   public static final String STRING_2D_ARRAY_CLASS_NAME = 
String[][].class.getName();
   public static final String STRING_ARRAY_CLASS_NAME = 
String[].class.getName();
+
+  public static final int SUPER_USER_ID = 0;
 }
diff --git 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index 087d3d8f639..984cf9127a4 100644
--- 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++ 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -691,7 +691,7 @@ showConfigurationStatement
 // ------------------------------------------- Authority Statement 
-----------------------------------------------------
 
 createUserStatement
-    : CREATE USER userName=identifier password=string
+    : CREATE USER userName=usernameWithRoot password=string
     ;
 
 createRoleStatement
@@ -724,7 +724,7 @@ usernameWithRootWithOptionalHost
     ;
 
 renameUserStatement
-    : ALTER USER username=identifier RENAME TO newUsername=identifier
+    : ALTER USER username=usernameWithRoot RENAME TO 
newUsername=usernameWithRoot
     ;
 
 grantUserRoleStatement
diff --git a/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift 
b/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
index 1086b5b8acd..ce2cbd0f15c 100644
--- a/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
+++ b/iotdb-protocol/thrift-datanode/src/main/thrift/datanode.thrift
@@ -267,6 +267,7 @@ struct TDropPipePluginInstanceReq {
 struct TInvalidatePermissionCacheReq {
   1: required string username
   2: required string roleName
+  3: optional bool needDisconnect
 }
 
 struct TDataNodeHeartbeatReq {


Reply via email to