You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2023/02/10 04:30:56 UTC

[doris] branch master updated: [feature](auth)Implementing privilege management with rbac model (#16091)

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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 8758cd412f [feature](auth)Implementing privilege management with rbac model (#16091)
8758cd412f is described below

commit 8758cd412f3edb8341227a7222f95bc700bd999f
Author: zhangdong <49...@qq.com>
AuthorDate: Fri Feb 10 12:30:49 2023 +0800

    [feature](auth)Implementing privilege management with rbac model (#16091)
    
    change implement of auth to rbac
    
    each user has one default role which can not be drop;
    
    if you grant priv to user,it will grant to default role ,
    
    In the current pr, the user can still only have one role other than the default role, but in the future, the user and role will be many-to-many
    
    rename PaloRole,PaloAuth,PaloPrivilege to Role,Auth,Privilege
---
 .../org/apache/doris/common/FeMetaVersion.java     |    4 +-
 .../apache/doris/analysis/AlterDatabaseRename.java |    4 +-
 .../org/apache/doris/analysis/AlterUserStmt.java   |    2 +-
 .../org/apache/doris/analysis/AnalyzeStmt.java     |    4 +-
 .../org/apache/doris/analysis/CreateUserStmt.java  |    6 +-
 .../apache/doris/analysis/DropTableStatsStmt.java  |    4 +-
 .../java/org/apache/doris/analysis/GrantStmt.java  |   24 +-
 .../org/apache/doris/analysis/RecoverDbStmt.java   |    4 +-
 .../doris/analysis/RecoverPartitionStmt.java       |    4 +-
 .../apache/doris/analysis/RecoverTableStmt.java    |    4 +-
 .../org/apache/doris/analysis/ResourcePattern.java |    2 +-
 .../java/org/apache/doris/analysis/RevokeStmt.java |    6 +-
 .../org/apache/doris/analysis/SetLdapPassVar.java  |    6 +-
 .../java/org/apache/doris/analysis/SetPassVar.java |    6 +-
 .../apache/doris/analysis/SetUserPropertyStmt.java |    4 +-
 .../org/apache/doris/analysis/ShowAnalyzeStmt.java |    4 +-
 .../org/apache/doris/analysis/ShowClusterStmt.java |    4 +-
 .../apache/doris/analysis/ShowCreateDbStmt.java    |   10 +-
 .../org/apache/doris/analysis/TablePattern.java    |    2 +-
 .../org/apache/doris/analysis/UserIdentity.java    |   14 +-
 .../org/apache/doris/catalog/AccessPrivilege.java  |   28 +-
 .../org/apache/doris/catalog/DomainResolver.java   |    6 +-
 .../main/java/org/apache/doris/catalog/Env.java    |   10 +-
 .../org/apache/doris/cluster/ClusterNamespace.java |    6 +-
 .../java/org/apache/doris/common/FeNameFormat.java |    8 +-
 .../org/apache/doris/common/proc/AuthProcDir.java  |    6 +-
 .../doris/common/proc/UserPropertyProcNode.java    |    6 +-
 .../apache/doris/datasource/InternalCatalog.java   |    4 +-
 .../doris/httpv2/controller/BaseController.java    |   10 +-
 .../httpv2/rest/manager/QueryProfileAction.java    |    6 +-
 .../java/org/apache/doris/ldap/LdapManager.java    |   20 +-
 .../org/apache/doris/ldap/LdapPrivsChecker.java    |   79 +-
 .../java/org/apache/doris/ldap/LdapUserInfo.java   |   10 +-
 .../java/org/apache/doris/load/loadv2/LoadJob.java |    6 +-
 .../java/org/apache/doris/mysql/MysqlProto.java    |    4 +-
 .../org/apache/doris/mysql/privilege/Auth.java     | 1644 ++++++++++++++++
 .../doris/mysql/privilege/CatalogPrivEntry.java    |   56 +-
 .../doris/mysql/privilege/CatalogPrivTable.java    |   29 +-
 .../apache/doris/mysql/privilege/DbPrivEntry.java  |   52 +-
 .../apache/doris/mysql/privilege/DbPrivTable.java  |   32 +-
 .../doris/mysql/privilege/GlobalPrivEntry.java     |  114 +-
 .../doris/mysql/privilege/GlobalPrivTable.java     |   44 +
 .../org/apache/doris/mysql/privilege/PaloAuth.java | 1993 --------------------
 .../org/apache/doris/mysql/privilege/PaloRole.java |  194 --
 .../org/apache/doris/mysql/privilege/Password.java |   58 +
 .../apache/doris/mysql/privilege/PrivBitSet.java   |   38 +-
 .../apache/doris/mysql/privilege/PrivEntry.java    |  180 +-
 .../doris/mysql/privilege/PrivPredicate.java       |   64 +-
 .../apache/doris/mysql/privilege/PrivTable.java    |  134 +-
 .../{PaloPrivilege.java => Privilege.java}         |   14 +-
 .../doris/mysql/privilege/ResourcePrivEntry.java   |   54 +-
 .../doris/mysql/privilege/ResourcePrivTable.java   |   24 +-
 .../org/apache/doris/mysql/privilege/Role.java     |  605 ++++++
 .../apache/doris/mysql/privilege/RoleManager.java  |  191 +-
 .../doris/mysql/privilege/TablePrivEntry.java      |   60 +-
 .../doris/mysql/privilege/TablePrivTable.java      |   42 +-
 .../org/apache/doris/mysql/privilege/User.java     |  163 ++
 .../apache/doris/mysql/privilege/UserManager.java  |  302 +++
 .../doris/mysql/privilege/UserPrivTable.java       |  166 +-
 .../apache/doris/mysql/privilege/UserProperty.java |   35 +-
 .../doris/mysql/privilege/UserPropertyMgr.java     |   59 -
 .../doris/mysql/privilege/UserRoleManager.java     |  134 ++
 .../apache/doris/mysql/privilege/WhiteList.java    |  103 +-
 .../org/apache/doris/analysis/AccessTestUtil.java  |   14 +-
 .../analysis/AdminCancelRebalanceDiskStmtTest.java |    4 +-
 .../doris/analysis/AdminRebalanceDiskStmtTest.java |    4 +-
 .../doris/analysis/AlterCatalogNameStmtTest.java   |    4 +-
 .../doris/analysis/AlterCatalogPropsStmtTest.java  |    4 +-
 .../doris/analysis/AlterClusterStmtTest.java       |    4 +-
 .../doris/analysis/AlterDatabaseQuotaStmtTest.java |    4 +-
 .../doris/analysis/AlterRoutineLoadStmtTest.java   |    4 +-
 .../doris/analysis/AlterSqlBlockRuleStmtTest.java  |    4 +-
 .../apache/doris/analysis/AlterTableStmtTest.java  |    4 +-
 .../doris/analysis/CreateCatalogStmtTest.java      |    4 +-
 .../doris/analysis/CreateClusterStmtTest.java      |    4 +-
 .../doris/analysis/CreateDataSyncJobStmtTest.java  |    4 +-
 .../apache/doris/analysis/CreateDbStmtTest.java    |    4 +-
 .../doris/analysis/CreateResourceStmtTest.java     |    6 +-
 .../doris/analysis/CreateSqlBlockRuleStmtTest.java |    4 +-
 .../apache/doris/analysis/CreateTableStmtTest.java |    4 +-
 .../apache/doris/analysis/CreateUserStmtTest.java  |    6 +-
 .../apache/doris/analysis/DataDescriptionTest.java |    4 +-
 .../org/apache/doris/analysis/DeleteStmtTest.java  |    4 +-
 .../apache/doris/analysis/DropCatalogStmtTest.java |    4 +-
 .../apache/doris/analysis/DropClusterStmtTest.java |    4 +-
 .../org/apache/doris/analysis/DropDbStmtTest.java  |    4 +-
 .../analysis/DropMaterializedViewStmtTest.java     |    4 +-
 .../apache/doris/analysis/DropTableStmtTest.java   |    4 +-
 .../apache/doris/analysis/DropUserStmtTest.java    |    4 +-
 .../org/apache/doris/analysis/GrantStmtTest.java   |   10 +-
 .../doris/analysis/InstallPluginStmtTest.java      |    4 +-
 .../org/apache/doris/analysis/LinkDbStmtTest.java  |    4 +-
 .../org/apache/doris/analysis/LoadStmtTest.java    |    6 +-
 .../apache/doris/analysis/MigrateDbStmtTest.java   |    4 +-
 .../doris/analysis/SetOperationStmtTest.java       |    4 +-
 .../org/apache/doris/analysis/SetPassVarTest.java  |    4 +-
 .../org/apache/doris/analysis/SetStmtTest.java     |    4 +-
 .../doris/analysis/SetUserPropertyStmtTest.java    |    4 +-
 .../java/org/apache/doris/analysis/SetVarTest.java |    4 +-
 .../doris/analysis/ShowCreateDbStmtTest.java       |    4 +-
 .../apache/doris/analysis/ShowDataStmtTest.java    |   10 +-
 .../apache/doris/analysis/ShowDbIdStmtTest.java    |    4 +-
 .../doris/analysis/ShowEncryptKeysStmtTest.java    |    4 +-
 .../doris/analysis/ShowFunctionsStmtTest.java      |    4 +-
 .../apache/doris/analysis/ShowIndexStmtTest.java   |    4 +-
 .../doris/analysis/ShowPartitionIdStmtTest.java    |    4 +-
 .../doris/analysis/ShowTableCreationStmtTest.java  |    4 +-
 .../apache/doris/analysis/ShowTableIdStmtTest.java |    4 +-
 .../apache/doris/analysis/ShowTableStmtTest.java   |    4 +-
 .../doris/analysis/ShowUserPropertyStmtTest.java   |    4 +-
 .../org/apache/doris/analysis/UseStmtTest.java     |    4 +-
 .../org/apache/doris/backup/CatalogMocker.java     |   12 +-
 .../doris/catalog/OdbcCatalogResourceTest.java     |    4 +-
 .../org/apache/doris/catalog/ResourceMgrTest.java  |    6 +-
 .../org/apache/doris/catalog/S3ResourceTest.java   |    6 +-
 .../apache/doris/catalog/SparkResourceTest.java    |    8 +-
 .../apache/doris/datasource/CatalogMgrTest.java    |    7 +-
 .../org/apache/doris/http/DorisHttpTestCase.java   |    4 +-
 .../apache/doris/ldap/LdapAuthenticateTest.java    |   14 +-
 .../java/org/apache/doris/ldap/LdapClientTest.java |    4 +-
 .../apache/doris/ldap/LdapPrivsCheckerTest.java    |   42 +-
 .../org/apache/doris/load/DeleteHandlerTest.java   |    4 +-
 .../apache/doris/load/loadv2/ExportMgrTest.java    |    4 +-
 .../load/routineload/RoutineLoadManagerTest.java   |   16 +-
 .../org/apache/doris/mysql/MysqlProtoTest.java     |    4 +-
 .../org/apache/doris/mysql/privilege/AuthTest.java |   52 +-
 .../apache/doris/mysql/privilege/MockedAuth.java   |    2 +-
 .../doris/mysql/privilege/PrivEntryTest.java       |   62 +-
 .../doris/mysql/privilege/SetPasswordTest.java     |    4 +-
 .../org/apache/doris/persist/PrivInfoTest.java     |    8 +-
 .../apache/doris/planner/ResourceTagQueryTest.java |   12 +-
 .../org/apache/doris/qe/ConnectContextTest.java    |    6 +-
 .../org/apache/doris/qe/PartitionCacheTest.java    |    4 +-
 .../java/org/apache/doris/qe/SetExecutorTest.java  |    4 +-
 .../java/org/apache/doris/qe/ShowExecutorTest.java |    4 +-
 .../data/account_p0/test_alter_user.out            |    6 +-
 136 files changed, 3758 insertions(+), 3672 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java b/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
index 2ef346a4f3..c0a214b166 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
@@ -50,8 +50,10 @@ public final class FeMetaVersion {
     public static final int VERSION_114 = 114;
     // change replica meta to json
     public static final int VERSION_115 = 115;
+    // change Auto to rbac
+    public static final int VERSION_116 = 116;
     // note: when increment meta version, should assign the latest version to VERSION_CURRENT
-    public static final int VERSION_CURRENT = VERSION_115;
+    public static final int VERSION_CURRENT = VERSION_116;
 
     // all logs meta version should >= the minimum version, so that we could remove many if clause, for example
     // if (FE_METAVERSION < VERSION_94) ...
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterDatabaseRename.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterDatabaseRename.java
index ed8774d46c..4410cc88a6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterDatabaseRename.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterDatabaseRename.java
@@ -25,9 +25,9 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -57,7 +57,7 @@ public class AlterDatabaseRename extends DdlStmt {
         }
 
         if (!Env.getCurrentEnv().getAuth().checkDbPriv(ConnectContext.get(), dbName,
-                PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV, PaloPrivilege.ALTER_PRIV), Operator.OR))) {
+                PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV, Privilege.ALTER_PRIV), Operator.OR))) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
                     analyzer.getQualifiedUser(), dbName);
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
index 062db75402..38eabae4a1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterUserStmt.java
@@ -23,7 +23,7 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
 import org.apache.doris.mysql.privilege.PasswordPolicy.FailedLoginPolicy;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyzeStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyzeStmt.java
index d80dda6d43..da16f87488 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyzeStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyzeStmt.java
@@ -33,7 +33,7 @@ import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.PrintableMap;
 import org.apache.doris.common.util.Util;
 import org.apache.doris.datasource.CatalogIf;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -155,7 +155,7 @@ public class AnalyzeStmt extends DdlStmt {
     }
 
     private void checkAnalyzePriv(String dbName, String tblName) throws AnalysisException {
-        PaloAuth auth = Env.getCurrentEnv().getAuth();
+        Auth auth = Env.getCurrentEnv().getAuth();
         if (!auth.checkTblPriv(ConnectContext.get(), dbName, tblName, PrivPredicate.SELECT)) {
             ErrorReport.reportAnalysisException(
                     ErrorCode.ERR_TABLEACCESS_DENIED_ERROR,
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateUserStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateUserStmt.java
index abd7bc463f..a7bcdb8140 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateUserStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateUserStmt.java
@@ -23,9 +23,9 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
-import org.apache.doris.mysql.privilege.PaloRole;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Role;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -121,7 +121,7 @@ public class CreateUserStmt extends DdlStmt {
         if (role != null) {
             if (role.equalsIgnoreCase("SUPERUSER")) {
                 // for forward compatibility
-                role = PaloRole.ADMIN_ROLE;
+                role = Role.ADMIN_ROLE;
             }
             FeNameFormat.checkRoleName(role, true /* can be admin */, "Can not granted user to role");
             role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropTableStatsStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropTableStatsStmt.java
index 73fa1682cf..6d01568ef1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropTableStatsStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropTableStatsStmt.java
@@ -25,7 +25,7 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.Util;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -105,7 +105,7 @@ public class DropTableStatsStmt extends DdlStmt {
     }
 
     private void checkAnalyzePriv(String dbName, String tblName) throws AnalysisException {
-        PaloAuth auth = Env.getCurrentEnv().getAuth();
+        Auth auth = Env.getCurrentEnv().getAuth();
         if (!auth.checkTblPriv(ConnectContext.get(), dbName, tblName, PrivPredicate.DROP)) {
             ErrorReport.reportAnalysisException(
                     ErrorCode.ERR_TABLEACCESS_DENIED_ERROR,
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java
index d44f0f51d8..3875e32bb1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/GrantStmt.java
@@ -25,10 +25,10 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Joiner;
@@ -44,7 +44,7 @@ public class GrantStmt extends DdlStmt {
     private String role;
     private TablePattern tblPattern;
     private ResourcePattern resourcePattern;
-    private List<PaloPrivilege> privileges;
+    private List<Privilege> privileges;
 
     public GrantStmt(UserIdentity userIdent, String role, TablePattern tblPattern, List<AccessPrivilege> privileges) {
         this.userIdent = userIdent;
@@ -91,7 +91,7 @@ public class GrantStmt extends DdlStmt {
         return role;
     }
 
-    public List<PaloPrivilege> getPrivileges() {
+    public List<Privilege> getPrivileges() {
         return privileges;
     }
 
@@ -138,16 +138,16 @@ public class GrantStmt extends DdlStmt {
      * @param tblPattern
      * @throws AnalysisException
      */
-    public static void checkTablePrivileges(List<PaloPrivilege> privileges, String role, TablePattern tblPattern)
+    public static void checkTablePrivileges(List<Privilege> privileges, String role, TablePattern tblPattern)
             throws AnalysisException {
         // Rule 1
-        if (tblPattern.getPrivLevel() != PrivLevel.GLOBAL && (privileges.contains(PaloPrivilege.ADMIN_PRIV)
-                || privileges.contains(PaloPrivilege.NODE_PRIV))) {
+        if (tblPattern.getPrivLevel() != PrivLevel.GLOBAL && (privileges.contains(Privilege.ADMIN_PRIV)
+                || privileges.contains(Privilege.NODE_PRIV))) {
             throw new AnalysisException("ADMIN_PRIV and NODE_PRIV can only be granted/revoke on/from *.*.*");
         }
 
         // Rule 2
-        if (privileges.contains(PaloPrivilege.NODE_PRIV) && !Env.getCurrentEnv().getAuth()
+        if (privileges.contains(Privilege.NODE_PRIV) && !Env.getCurrentEnv().getAuth()
                 .checkGlobalPriv(ConnectContext.get(), PrivPredicate.OPERATOR)) {
             throw new AnalysisException("Only user with NODE_PRIV can grant/revoke NODE_PRIV to other user");
         }
@@ -184,20 +184,20 @@ public class GrantStmt extends DdlStmt {
         }
 
         // Rule 6
-        if (privileges.contains(PaloPrivilege.USAGE_PRIV)) {
+        if (privileges.contains(Privilege.USAGE_PRIV)) {
             throw new AnalysisException("Can not grant/revoke USAGE_PRIV to/from database or table");
         }
     }
 
-    public static void checkResourcePrivileges(List<PaloPrivilege> privileges, String role,
+    public static void checkResourcePrivileges(List<Privilege> privileges, String role,
             ResourcePattern resourcePattern) throws AnalysisException {
         // Rule 1
-        if (privileges.contains(PaloPrivilege.NODE_PRIV)) {
+        if (privileges.contains(Privilege.NODE_PRIV)) {
             throw new AnalysisException("Can not grant/revoke NODE_PRIV to/from any other users or roles");
         }
 
         // Rule 2
-        if (resourcePattern.getPrivLevel() != PrivLevel.GLOBAL && privileges.contains(PaloPrivilege.ADMIN_PRIV)) {
+        if (resourcePattern.getPrivLevel() != PrivLevel.GLOBAL && privileges.contains(Privilege.ADMIN_PRIV)) {
             throw new AnalysisException("ADMIN_PRIV privilege can only be granted/revoked on/from resource *");
         }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverDbStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverDbStmt.java
index cbceaa08ce..71502b1cd8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverDbStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverDbStmt.java
@@ -24,9 +24,9 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -70,7 +70,7 @@ public class RecoverDbStmt extends DdlStmt {
 
         if (!Env.getCurrentEnv().getAuth().checkDbPriv(ConnectContext.get(), dbName,
                 PrivPredicate.of(PrivBitSet.of(
-                        PaloPrivilege.ALTER_PRIV, PaloPrivilege.CREATE_PRIV, PaloPrivilege.ADMIN_PRIV), Operator.OR))) {
+                        Privilege.ALTER_PRIV, Privilege.CREATE_PRIV, Privilege.ADMIN_PRIV), Operator.OR))) {
             ErrorReport.reportAnalysisException(
                     ErrorCode.ERR_DBACCESS_DENIED_ERROR, analyzer.getQualifiedUser(), dbName);
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverPartitionStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverPartitionStmt.java
index 8924887be8..1dd94cb1b1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverPartitionStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverPartitionStmt.java
@@ -24,9 +24,9 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.Util;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -73,7 +73,7 @@ public class RecoverPartitionStmt extends DdlStmt {
         Util.prohibitExternalCatalog(dbTblName.getCtl(), this.getClass().getSimpleName());
         if (!Env.getCurrentEnv().getAuth().checkTblPriv(ConnectContext.get(), dbTblName.getDb(),
                 dbTblName.getTbl(), PrivPredicate.of(PrivBitSet.of(
-                        PaloPrivilege.ALTER_PRIV, PaloPrivilege.CREATE_PRIV, PaloPrivilege.ADMIN_PRIV), Operator.OR))) {
+                        Privilege.ALTER_PRIV, Privilege.CREATE_PRIV, Privilege.ADMIN_PRIV), Operator.OR))) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "RECOVERY",
                     ConnectContext.get().getQualifiedUser(),
                     ConnectContext.get().getRemoteIP(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverTableStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverTableStmt.java
index b0897bf3b4..b6a0ff214c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverTableStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/RecoverTableStmt.java
@@ -24,9 +24,9 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.Util;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -68,7 +68,7 @@ public class RecoverTableStmt extends DdlStmt {
 
         if (!Env.getCurrentEnv().getAuth().checkTblPriv(
                 ConnectContext.get(), dbTblName.getDb(), dbTblName.getTbl(), PrivPredicate.of(
-                        PrivBitSet.of(PaloPrivilege.ALTER_PRIV, PaloPrivilege.CREATE_PRIV, PaloPrivilege.ADMIN_PRIV),
+                        PrivBitSet.of(Privilege.ALTER_PRIV, Privilege.CREATE_PRIV, Privilege.ADMIN_PRIV),
                         Operator.OR))) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "RECOVERY",
                                                 ConnectContext.get().getQualifiedUser(),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ResourcePattern.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ResourcePattern.java
index 19771f68b5..2e9b203c17 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ResourcePattern.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ResourcePattern.java
@@ -21,7 +21,7 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
 import org.apache.doris.persist.gson.GsonUtils;
 
 import com.google.common.base.Strings;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/RevokeStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/RevokeStmt.java
index 0c576cdbc0..4054741ef6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/RevokeStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/RevokeStmt.java
@@ -21,8 +21,8 @@ import org.apache.doris.catalog.AccessPrivilege;
 import org.apache.doris.cluster.ClusterNamespace;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.FeNameFormat;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
+import org.apache.doris.mysql.privilege.Privilege;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
@@ -39,7 +39,7 @@ public class RevokeStmt extends DdlStmt {
     private String role;
     private TablePattern tblPattern;
     private ResourcePattern resourcePattern;
-    private List<PaloPrivilege> privileges;
+    private List<Privilege> privileges;
 
     public RevokeStmt(UserIdentity userIdent, String role, TablePattern tblPattern, List<AccessPrivilege> privileges) {
         this.userIdent = userIdent;
@@ -82,7 +82,7 @@ public class RevokeStmt extends DdlStmt {
         return role;
     }
 
-    public List<PaloPrivilege> getPrivileges() {
+    public List<Privilege> getPrivileges() {
         return privileges;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetLdapPassVar.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetLdapPassVar.java
index cb42a1de95..0250deeddc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetLdapPassVar.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetLdapPassVar.java
@@ -20,7 +20,7 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -42,8 +42,8 @@ public class SetLdapPassVar extends SetVar {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_CLUSTER_NO_SELECT_CLUSTER);
         }
 
-        if (!ConnectContext.get().getCurrentUserIdentity().getQualifiedUser().equals(PaloAuth.ROOT_USER)
-                && !ConnectContext.get().getCurrentUserIdentity().getQualifiedUser().equals(PaloAuth.ADMIN_USER)) {
+        if (!ConnectContext.get().getCurrentUserIdentity().getQualifiedUser().equals(Auth.ROOT_USER)
+                && !ConnectContext.get().getCurrentUserIdentity().getQualifiedUser().equals(Auth.ADMIN_USER)) {
             throw new AnalysisException("Only root and admin user can set ldap admin password.");
         }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetPassVar.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetPassVar.java
index 2fd9636b5b..ba8fa6a53b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetPassVar.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetPassVar.java
@@ -22,7 +22,7 @@ import org.apache.doris.cluster.ClusterNamespace;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -77,8 +77,8 @@ public class SetPassVar extends SetVar {
         }
 
         // 2. No user can set password for root expect for root user itself
-        if (userIdent.getQualifiedUser().equals(PaloAuth.ROOT_USER)
-                && !ClusterNamespace.getNameFromFullName(ctx.getQualifiedUser()).equals(PaloAuth.ROOT_USER)) {
+        if (userIdent.getQualifiedUser().equals(Auth.ROOT_USER)
+                && !ClusterNamespace.getNameFromFullName(ctx.getQualifiedUser()).equals(Auth.ROOT_USER)) {
             throw new AnalysisException("Can not set password for root user, except root itself");
         }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserPropertyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserPropertyStmt.java
index fb1d4fec3b..394c8af37b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserPropertyStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserPropertyStmt.java
@@ -21,7 +21,7 @@ import org.apache.doris.cluster.ClusterNamespace;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.base.Strings;
@@ -61,7 +61,7 @@ public class SetUserPropertyStmt extends DdlStmt {
             user = ConnectContext.get().getQualifiedUser();
         } else {
             // If param 'user' is set, check if it need to be full-qualified
-            if (!user.equals(PaloAuth.ROOT_USER) && !user.equals(PaloAuth.ADMIN_USER)) {
+            if (!user.equals(Auth.ROOT_USER) && !user.equals(Auth.ADMIN_USER)) {
                 user = ClusterNamespace.getFullName(getClusterName(), user);
             }
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAnalyzeStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAnalyzeStmt.java
index a21bb340bf..1df740ef09 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAnalyzeStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowAnalyzeStmt.java
@@ -25,7 +25,7 @@ import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.OrderByPair;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.ShowResultSetMetaData;
@@ -233,7 +233,7 @@ public class ShowAnalyzeStmt extends ShowStmt {
     }
 
     private void checkShowAnalyzePriv(String dbName, String tblName) throws AnalysisException {
-        PaloAuth auth = Env.getCurrentEnv().getAuth();
+        Auth auth = Env.getCurrentEnv().getAuth();
         if (!auth.checkTblPriv(ConnectContext.get(), dbName, tblName, PrivPredicate.SHOW)) {
             ErrorReport.reportAnalysisException(
                     ErrorCode.ERR_TABLEACCESS_DENIED_ERROR,
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowClusterStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowClusterStmt.java
index 4b1d8aeea8..2695850add 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowClusterStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowClusterStmt.java
@@ -24,9 +24,9 @@ import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.ShowResultSetMetaData;
 
@@ -59,7 +59,7 @@ public class ShowClusterStmt extends ShowStmt {
     @Override
     public void analyze(Analyzer analyzer) throws AnalysisException {
         if (!Env.getCurrentEnv().getAuth().checkGlobalPriv(ConnectContext.get(),
-                PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV, PaloPrivilege.NODE_PRIV), Operator.OR))) {
+                PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV, Privilege.NODE_PRIV), Operator.OR))) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
         }
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateDbStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateDbStmt.java
index 63ee820694..8506e7255a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateDbStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateDbStmt.java
@@ -26,9 +26,9 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.ShowResultSetMetaData;
 
@@ -63,10 +63,10 @@ public class ShowCreateDbStmt extends ShowStmt {
         db = ClusterNamespace.getFullName(getClusterName(), db);
 
         if (!Env.getCurrentEnv().getAuth().checkDbPriv(ConnectContext.get(), db,
-                PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                                PaloPrivilege.ALTER_PRIV,
-                                PaloPrivilege.CREATE_PRIV,
-                                PaloPrivilege.DROP_PRIV),
+                PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+                                Privilege.ALTER_PRIV,
+                                Privilege.CREATE_PRIV,
+                                Privilege.DROP_PRIV),
                         Operator.OR))) {
             ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
                                                 ConnectContext.get().getQualifiedUser(), db);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TablePattern.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TablePattern.java
index 09ee4407ab..96f6822d5a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TablePattern.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TablePattern.java
@@ -25,7 +25,7 @@ import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
 import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/UserIdentity.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/UserIdentity.java
index 88b116cef1..b4822c197e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/UserIdentity.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/UserIdentity.java
@@ -26,7 +26,7 @@ import org.apache.doris.common.FeNameFormat;
 import org.apache.doris.common.PatternMatcherWrapper;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.thrift.TUserIdentity;
@@ -66,11 +66,11 @@ public class UserIdentity implements Writable, GsonPostProcessable {
     public static final UserIdentity UNKNOWN;
 
     static {
-        ROOT = new UserIdentity(PaloAuth.ROOT_USER, "%");
+        ROOT = new UserIdentity(Auth.ROOT_USER, "%");
         ROOT.setIsAnalyzed();
-        ADMIN = new UserIdentity(PaloAuth.ADMIN_USER, "%");
+        ADMIN = new UserIdentity(Auth.ADMIN_USER, "%");
         ADMIN.setIsAnalyzed();
-        UNKNOWN = new UserIdentity(PaloAuth.UNKNOWN_USER, "%");
+        UNKNOWN = new UserIdentity(Auth.UNKNOWN_USER, "%");
         UNKNOWN.setIsAnalyzed();
     }
 
@@ -134,7 +134,7 @@ public class UserIdentity implements Writable, GsonPostProcessable {
         }
 
         FeNameFormat.checkUserName(user);
-        if (!user.equals(PaloAuth.ROOT_USER) && !user.equals(PaloAuth.ADMIN_USER)) {
+        if (!user.equals(Auth.ROOT_USER) && !user.equals(Auth.ADMIN_USER)) {
             user = ClusterNamespace.getFullName(clusterName, user);
         }
 
@@ -183,11 +183,11 @@ public class UserIdentity implements Writable, GsonPostProcessable {
     }
 
     public boolean isRootUser() {
-        return user.equals(PaloAuth.ROOT_USER);
+        return user.equals(Auth.ROOT_USER);
     }
 
     public boolean isAdminUser() {
-        return user.equals(PaloAuth.ADMIN_USER);
+        return user.equals(Auth.ADMIN_USER);
     }
 
     public TUserIdentity toThrift() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/AccessPrivilege.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/AccessPrivilege.java
index 64a8c70dfa..246805f08a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AccessPrivilege.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AccessPrivilege.java
@@ -17,8 +17,8 @@
 
 package org.apache.doris.catalog;
 
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
+import org.apache.doris.mysql.privilege.Privilege;
 
 import com.google.common.base.Preconditions;
 
@@ -52,30 +52,30 @@ public enum AccessPrivilege {
         Preconditions.checkState(flag > 0 && flag < 13);
         switch (flag) {
             case 1:
-                return PrivBitSet.of(PaloPrivilege.SELECT_PRIV);
+                return PrivBitSet.of(Privilege.SELECT_PRIV);
             case 2:
             case 3:
-                return PrivBitSet.of(PaloPrivilege.SELECT_PRIV, PaloPrivilege.LOAD_PRIV,
-                        PaloPrivilege.ALTER_PRIV, PaloPrivilege.CREATE_PRIV,
-                        PaloPrivilege.DROP_PRIV);
+                return PrivBitSet.of(Privilege.SELECT_PRIV, Privilege.LOAD_PRIV,
+                        Privilege.ALTER_PRIV, Privilege.CREATE_PRIV,
+                        Privilege.DROP_PRIV);
             case 4:
-                return PrivBitSet.of(PaloPrivilege.NODE_PRIV);
+                return PrivBitSet.of(Privilege.NODE_PRIV);
             case 5:
-                return PrivBitSet.of(PaloPrivilege.GRANT_PRIV);
+                return PrivBitSet.of(Privilege.GRANT_PRIV);
             case 6:
-                return PrivBitSet.of(PaloPrivilege.SELECT_PRIV);
+                return PrivBitSet.of(Privilege.SELECT_PRIV);
             case 7:
-                return PrivBitSet.of(PaloPrivilege.LOAD_PRIV);
+                return PrivBitSet.of(Privilege.LOAD_PRIV);
             case 8:
-                return PrivBitSet.of(PaloPrivilege.ALTER_PRIV);
+                return PrivBitSet.of(Privilege.ALTER_PRIV);
             case 9:
-                return PrivBitSet.of(PaloPrivilege.CREATE_PRIV);
+                return PrivBitSet.of(Privilege.CREATE_PRIV);
             case 10:
-                return PrivBitSet.of(PaloPrivilege.DROP_PRIV);
+                return PrivBitSet.of(Privilege.DROP_PRIV);
             case 11:
-                return PrivBitSet.of(PaloPrivilege.ADMIN_PRIV);
+                return PrivBitSet.of(Privilege.ADMIN_PRIV);
             case 12:
-                return PrivBitSet.of(PaloPrivilege.USAGE_PRIV);
+                return PrivBitSet.of(Privilege.USAGE_PRIV);
             default:
                 return null;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/DomainResolver.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/DomainResolver.java
index 67b5336862..7fd3f0890a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/DomainResolver.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/DomainResolver.java
@@ -18,7 +18,7 @@
 package org.apache.doris.catalog;
 
 import org.apache.doris.common.util.MasterDaemon;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.Maps;
@@ -44,9 +44,9 @@ public class DomainResolver extends MasterDaemon {
     // this is only available in BAIDU, for resolving BNS
     private static final String BNS_RESOLVER_TOOLS_PATH = "/usr/bin/get_instance_by_service";
 
-    private PaloAuth auth;
+    private Auth auth;
 
-    public DomainResolver(PaloAuth auth) {
+    public DomainResolver(Auth auth) {
         super("domain resolver", 10 * 1000);
         this.auth = auth;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index 15d38f61c6..ad98182dfb 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -166,7 +166,7 @@ import org.apache.doris.master.PartitionInMemoryInfoCollector;
 import org.apache.doris.meta.MetaContext;
 import org.apache.doris.metric.MetricRepo;
 import org.apache.doris.mtmv.MTMVJobManager;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.persist.BackendIdsUpdateInfo;
 import org.apache.doris.persist.BackendReplicasInfo;
@@ -393,7 +393,7 @@ public class Env {
 
     private TabletStatMgr tabletStatMgr;
 
-    private PaloAuth auth;
+    private Auth auth;
 
     private DomainResolver domainResolver;
 
@@ -593,7 +593,7 @@ public class Env {
 
         this.tabletStatMgr = new TabletStatMgr();
 
-        this.auth = new PaloAuth();
+        this.auth = new Auth();
         this.domainResolver = new DomainResolver(auth);
 
         this.metaContext = new MetaContext();
@@ -690,7 +690,7 @@ public class Env {
         return pluginMgr;
     }
 
-    public PaloAuth getAuth() {
+    public Auth getAuth() {
         return auth;
     }
 
@@ -1807,7 +1807,7 @@ public class Env {
     }
 
     public long loadPaloAuth(DataInputStream dis, long checksum) throws IOException {
-        // CAN NOT use PaloAuth.read(), cause this auth instance is already passed to DomainResolver
+        // CAN NOT use Auth.read(), cause this auth instance is already passed to DomainResolver
         auth.readFields(dis);
         LOG.info("finished replay paloAuth from image");
         return checksum;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/cluster/ClusterNamespace.java b/fe/fe-core/src/main/java/org/apache/doris/cluster/ClusterNamespace.java
index bc1580c943..5b264e0d37 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/cluster/ClusterNamespace.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/cluster/ClusterNamespace.java
@@ -17,7 +17,7 @@
 
 package org.apache.doris.cluster;
 
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 
 import com.google.common.base.Strings;
 
@@ -63,8 +63,8 @@ public class ClusterNamespace {
         if (Strings.isNullOrEmpty(cluster) || Strings.isNullOrEmpty(name)) {
             return null;
         }
-        if (name.contains(CLUSTER_DELIMITER) || name.equalsIgnoreCase(PaloAuth.ROOT_USER)
-                || name.equalsIgnoreCase(PaloAuth.ADMIN_USER)) {
+        if (name.contains(CLUSTER_DELIMITER) || name.equalsIgnoreCase(Auth.ROOT_USER)
+                || name.equalsIgnoreCase(Auth.ADMIN_USER)) {
             return name;
         }
         final StringBuilder sb = new StringBuilder(cluster);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
index f899674440..b806cfe271 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
@@ -20,7 +20,7 @@ package org.apache.doris.common;
 import org.apache.doris.alter.SchemaChangeHandler;
 import org.apache.doris.analysis.CreateMaterializedViewStmt;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.mysql.privilege.PaloRole;
+import org.apache.doris.mysql.privilege.Role;
 
 import com.google.common.base.Strings;
 
@@ -105,10 +105,10 @@ public class FeNameFormat {
 
         boolean res = false;
         if (CaseSensibility.ROLE.getCaseSensibility()) {
-            res = role.equals(PaloRole.OPERATOR_ROLE) || (!canBeAdmin && role.equals(PaloRole.ADMIN_ROLE));
+            res = role.equals(Role.OPERATOR_ROLE) || (!canBeAdmin && role.equals(Role.ADMIN_ROLE));
         } else {
-            res = role.equalsIgnoreCase(PaloRole.OPERATOR_ROLE)
-                    || (!canBeAdmin && role.equalsIgnoreCase(PaloRole.ADMIN_ROLE));
+            res = role.equalsIgnoreCase(Role.OPERATOR_ROLE)
+                    || (!canBeAdmin && role.equalsIgnoreCase(Role.ADMIN_ROLE));
         }
 
         if (res) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/AuthProcDir.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/AuthProcDir.java
index 2699fbd62c..5b4e78408c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/AuthProcDir.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/AuthProcDir.java
@@ -20,7 +20,7 @@ package org.apache.doris.common.proc;
 import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.common.AnalysisException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
@@ -34,9 +34,9 @@ public class AuthProcDir implements ProcDirInterface {
             .add("UserIdentity").add("Password").add("GlobalPrivs").add("CatalogPrivs")
             .add("DatabasePrivs").add("TablePrivs").add("ResourcePrivs").build();
 
-    private PaloAuth auth;
+    private Auth auth;
 
-    public AuthProcDir(PaloAuth auth) {
+    public AuthProcDir(Auth auth) {
         this.auth = auth;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java
index ebf35f3c75..6a8c9eaec3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/UserPropertyProcNode.java
@@ -19,7 +19,7 @@ package org.apache.doris.common.proc;
 
 import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.common.AnalysisException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 
 import com.google.common.collect.ImmutableList;
 
@@ -31,10 +31,10 @@ public class UserPropertyProcNode implements ProcNodeInterface {
             .add("Key").add("Value")
             .build();
 
-    private PaloAuth auth;
+    private Auth auth;
     private UserIdentity userIdent;
 
-    public UserPropertyProcNode(PaloAuth auth, UserIdentity userIdent) {
+    public UserPropertyProcNode(Auth auth, UserIdentity userIdent) {
         this.auth = auth;
         this.userIdent = userIdent;
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
index 4f4d027422..eeceedf788 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
@@ -146,7 +146,7 @@ import org.apache.doris.external.iceberg.IcebergCatalogMgr;
 import org.apache.doris.external.iceberg.IcebergTableCreationRecordMgr;
 import org.apache.doris.mtmv.MTMVJobFactory;
 import org.apache.doris.mtmv.metadata.MTMVJob;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.persist.BackendIdsUpdateInfo;
 import org.apache.doris.persist.ClusterInfo;
 import org.apache.doris.persist.ColocatePersistInfo;
@@ -2791,7 +2791,7 @@ public class InternalCatalog implements CatalogIf<Database> {
         }
 
         // create super user for this cluster
-        UserIdentity adminUser = new UserIdentity(PaloAuth.ADMIN_USER, "%");
+        UserIdentity adminUser = new UserIdentity(Auth.ADMIN_USER, "%");
         try {
             adminUser.analyze(stmt.getClusterName());
         } catch (AnalysisException e) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
index a6958cc944..0e19798056 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
@@ -26,9 +26,9 @@ import org.apache.doris.common.Config;
 import org.apache.doris.httpv2.HttpAuthManager;
 import org.apache.doris.httpv2.HttpAuthManager.SessionValue;
 import org.apache.doris.httpv2.exception.UnauthorizedException;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.service.FrontendOptions;
 import org.apache.doris.system.SystemInfoService;
@@ -71,8 +71,8 @@ public class BaseController {
             UserIdentity currentUser = checkPassword(authInfo);
 
             if (checkAuth) {
-                checkGlobalAuth(currentUser, PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                        PaloPrivilege.NODE_PRIV), CompoundPredicate.Operator.OR));
+                checkGlobalAuth(currentUser, PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+                        Privilege.NODE_PRIV), CompoundPredicate.Operator.OR));
             }
 
             SessionValue value = new SessionValue();
@@ -125,8 +125,8 @@ public class BaseController {
         }
 
         if (checkAuth && !Env.getCurrentEnv().getAuth().checkGlobalPriv(sessionValue.currentUser,
-                PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                        PaloPrivilege.NODE_PRIV), CompoundPredicate.Operator.OR))) {
+                PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+                        Privilege.NODE_PRIV), CompoundPredicate.Operator.OR))) {
             // need to check auth and check auth failed
             return null;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
index f4cbcf76f9..862b56fe21 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/manager/QueryProfileAction.java
@@ -29,7 +29,7 @@ import org.apache.doris.common.profile.ProfileTreePrinter;
 import org.apache.doris.common.util.ProfileManager;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
 import org.apache.doris.httpv2.rest.RestBaseController;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.qe.ConnectContext;
@@ -234,7 +234,7 @@ public class QueryProfileAction extends RestBaseController {
         // Only admin or root user can see all profile.
         // Common user can only review the query of their own.
         String user = ConnectContext.get().getCurrentUserIdentity().getQualifiedUser();
-        if (!user.equalsIgnoreCase(PaloAuth.ADMIN_USER) && !user.equalsIgnoreCase(PaloAuth.ROOT_USER)) {
+        if (!user.equalsIgnoreCase(Auth.ADMIN_USER) && !user.equalsIgnoreCase(Auth.ROOT_USER)) {
             queryStream = queryStream.filter(q -> q.get(1).equals(user));
         }
         if (!Strings.isNullOrEmpty(queryId)) {
@@ -471,7 +471,7 @@ public class QueryProfileAction extends RestBaseController {
 
     private void checkAuthByUserAndQueryId(String queryId) throws AuthenticationException {
         String user = ConnectContext.get().getCurrentUserIdentity().getQualifiedUser();
-        if (!user.equalsIgnoreCase(PaloAuth.ADMIN_USER) && !user.equalsIgnoreCase(PaloAuth.ROOT_USER)) {
+        if (!user.equalsIgnoreCase(Auth.ADMIN_USER) && !user.equalsIgnoreCase(Auth.ROOT_USER)) {
             ProfileManager.getInstance().checkAuthByUserAndQueryId(user, queryId);
         }
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapManager.java b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapManager.java
index dafe5a5ce6..76053a6854 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapManager.java
@@ -20,9 +20,10 @@ package org.apache.doris.ldap;
 import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.cluster.ClusterNamespace;
+import org.apache.doris.common.DdlException;
 import org.apache.doris.common.LdapConfig;
-import org.apache.doris.mysql.privilege.PaloAuth;
-import org.apache.doris.mysql.privilege.PaloRole;
+import org.apache.doris.mysql.privilege.Auth;
+import org.apache.doris.mysql.privilege.Role;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -76,7 +77,12 @@ public class LdapManager {
         if (ldapUserInfo != null && !ldapUserInfo.checkTimeout()) {
             return ldapUserInfo;
         }
-        return getUserInfoAndUpdateCache(fullName);
+        try {
+            return getUserInfoAndUpdateCache(fullName);
+        } catch (DdlException e) {
+            LOG.warn("getUserInfo for {} failed", fullName, e);
+            return null;
+        }
     }
 
     public boolean doesUserExist(String fullName) {
@@ -117,10 +123,10 @@ public class LdapManager {
 
     private boolean checkParam(String fullName) {
         return LdapConfig.ldap_authentication_enabled && !Strings.isNullOrEmpty(fullName) && !fullName.equalsIgnoreCase(
-                PaloAuth.ROOT_USER) && !fullName.equalsIgnoreCase(PaloAuth.ADMIN_USER);
+                Auth.ROOT_USER) && !fullName.equalsIgnoreCase(Auth.ADMIN_USER);
     }
 
-    private LdapUserInfo getUserInfoAndUpdateCache(String fulName) {
+    private LdapUserInfo getUserInfoAndUpdateCache(String fulName) throws DdlException {
         String cluster = ClusterNamespace.getClusterNameFromFullName(fulName);
         String userName = ClusterNamespace.getNameFromFullName(fulName);
         if (Strings.isNullOrEmpty(userName)) {
@@ -194,7 +200,7 @@ public class LdapManager {
      * Step2: get roles by ldap groups;
      * Step3: merge the roles;
      */
-    private PaloRole getLdapGroupsPrivs(String userName, String clusterName) {
+    private Role getLdapGroupsPrivs(String userName, String clusterName) throws DdlException {
         //get user ldap group. the ldap group name should be the same as the doris role name
         List<String> ldapGroups = ldapClient.getGroups(userName);
         List<String> rolesNames = Lists.newArrayList();
@@ -206,7 +212,7 @@ public class LdapManager {
         }
         LOG.debug("get user:{} ldap groups:{} and doris roles:{}", userName, ldapGroups, rolesNames);
 
-        PaloRole ldapGroupsPrivs = new PaloRole(LDAP_GROUPS_PRIVS_NAME);
+        Role ldapGroupsPrivs = new Role(LDAP_GROUPS_PRIVS_NAME);
         LdapPrivsChecker.grantDefaultPrivToTempUser(ldapGroupsPrivs, clusterName);
         if (!rolesNames.isEmpty()) {
             Env.getCurrentEnv().getAuth().mergeRolesNoCheckName(rolesNames, ldapGroupsPrivs);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapPrivsChecker.java b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapPrivsChecker.java
index 2f44bf81f5..f8da4dd7a1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapPrivsChecker.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapPrivsChecker.java
@@ -23,12 +23,13 @@ import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.InfoSchemaDb;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.DdlException;
 import org.apache.doris.common.LdapConfig;
-import org.apache.doris.mysql.privilege.PaloAuth;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
-import org.apache.doris.mysql.privilege.PaloRole;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivBitSet;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
+import org.apache.doris.mysql.privilege.Role;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
@@ -44,94 +45,94 @@ public class LdapPrivsChecker {
     private static final Logger LOG = LogManager.getLogger(LdapPrivsChecker.class);
 
     public static boolean hasGlobalPrivFromLdap(UserIdentity currentUser, PrivPredicate wanted) {
-        return hasTblPatternPrivs(currentUser, wanted, null, null, PaloAuth.PrivLevel.GLOBAL)
-                || hasResourcePatternPrivs(currentUser, wanted, null, PaloAuth.PrivLevel.GLOBAL);
+        return hasTblPatternPrivs(currentUser, wanted, null, null, Auth.PrivLevel.GLOBAL)
+                || hasResourcePatternPrivs(currentUser, wanted, null, Auth.PrivLevel.GLOBAL);
     }
 
     public static boolean hasDbPrivFromLdap(UserIdentity currentUser, String db, PrivPredicate wanted) {
-        return hasTblPatternPrivs(currentUser, wanted, db, null, PaloAuth.PrivLevel.DATABASE);
+        return hasTblPatternPrivs(currentUser, wanted, db, null, Auth.PrivLevel.DATABASE);
     }
 
     // Any database has wanted priv return true.
     public static boolean hasDbPrivFromLdap(UserIdentity currentUser, PrivPredicate wanted) {
-        return hasPrivs(currentUser, wanted, PaloAuth.PrivLevel.DATABASE);
+        return hasPrivs(currentUser, wanted, Auth.PrivLevel.DATABASE);
     }
 
     public static boolean hasTblPrivFromLdap(UserIdentity currentUser, String db, String tbl, PrivPredicate wanted) {
-        return hasTblPatternPrivs(currentUser, wanted, db, tbl, PaloAuth.PrivLevel.TABLE);
+        return hasTblPatternPrivs(currentUser, wanted, db, tbl, Auth.PrivLevel.TABLE);
     }
 
     // Any table has wanted priv return true.
     public static boolean hasTblPrivFromLdap(UserIdentity currentUser, PrivPredicate wanted) {
-        return hasPrivs(currentUser, wanted, PaloAuth.PrivLevel.TABLE);
+        return hasPrivs(currentUser, wanted, Auth.PrivLevel.TABLE);
     }
 
     public static boolean hasResourcePrivFromLdap(UserIdentity currentUser, String resourceName, PrivPredicate wanted) {
-        return hasResourcePatternPrivs(currentUser, wanted, resourceName, PaloAuth.PrivLevel.RESOURCE);
+        return hasResourcePatternPrivs(currentUser, wanted, resourceName, Auth.PrivLevel.RESOURCE);
     }
 
     private static boolean hasTblPatternPrivs(UserIdentity currentUser, PrivPredicate wanted, String db, String tbl,
-            PaloAuth.PrivLevel level) {
+            Auth.PrivLevel level) {
         PrivBitSet savedPrivs = PrivBitSet.of();
         getCurrentUserTblPrivs(currentUser, db, tbl, savedPrivs, level);
-        return PaloPrivilege.satisfy(savedPrivs, wanted);
+        return Privilege.satisfy(savedPrivs, wanted);
     }
 
     private static boolean hasResourcePatternPrivs(UserIdentity currentUser, PrivPredicate wanted, String resourceName,
-            PaloAuth.PrivLevel level) {
+            Auth.PrivLevel level) {
         PrivBitSet savedPrivs = PrivBitSet.of();
         getCurrentUserResourcePrivs(currentUser, resourceName, savedPrivs, level);
-        return PaloPrivilege.satisfy(savedPrivs, wanted);
+        return Privilege.satisfy(savedPrivs, wanted);
     }
 
     public static PrivBitSet getGlobalPrivFromLdap(UserIdentity currentUser) {
         PrivBitSet savedPrivs = PrivBitSet.of();
-        getCurrentUserTblPrivs(currentUser, null, null, savedPrivs, PaloAuth.PrivLevel.GLOBAL);
-        getCurrentUserResourcePrivs(currentUser, null, savedPrivs, PaloAuth.PrivLevel.GLOBAL);
+        getCurrentUserTblPrivs(currentUser, null, null, savedPrivs, Auth.PrivLevel.GLOBAL);
+        getCurrentUserResourcePrivs(currentUser, null, savedPrivs, Auth.PrivLevel.GLOBAL);
         return savedPrivs;
     }
 
     public static PrivBitSet getDbPrivFromLdap(UserIdentity currentUser, String db) {
         PrivBitSet savedPrivs = PrivBitSet.of();
-        getCurrentUserTblPrivs(currentUser, db, null, savedPrivs, PaloAuth.PrivLevel.DATABASE);
+        getCurrentUserTblPrivs(currentUser, db, null, savedPrivs, Auth.PrivLevel.DATABASE);
         return savedPrivs;
     }
 
     public static PrivBitSet getTblPrivFromLdap(UserIdentity currentUser, String db, String tbl) {
         PrivBitSet savedPrivs = PrivBitSet.of();
-        getCurrentUserTblPrivs(currentUser, db, tbl, savedPrivs, PaloAuth.PrivLevel.TABLE);
+        getCurrentUserTblPrivs(currentUser, db, tbl, savedPrivs, Auth.PrivLevel.TABLE);
         return savedPrivs;
     }
 
     public static PrivBitSet getResourcePrivFromLdap(UserIdentity currentUser, String resourceName) {
         PrivBitSet savedPrivs = PrivBitSet.of();
-        getCurrentUserResourcePrivs(currentUser, resourceName, savedPrivs, PaloAuth.PrivLevel.RESOURCE);
+        getCurrentUserResourcePrivs(currentUser, resourceName, savedPrivs, Auth.PrivLevel.RESOURCE);
         return savedPrivs;
     }
 
     private static void getCurrentUserTblPrivs(UserIdentity currentUser, String db, String tbl, PrivBitSet savedPrivs,
-            PaloAuth.PrivLevel level) {
+            Auth.PrivLevel level) {
         if (!hasLdapPrivs(currentUser)) {
             return;
         }
-        PaloRole currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
+        Role currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
         for (Map.Entry<TablePattern, PrivBitSet> entry : currentUserLdapPrivs.getTblPatternToPrivs().entrySet()) {
             switch (entry.getKey().getPrivLevel()) {
                 case GLOBAL:
-                    if (level.equals(PaloAuth.PrivLevel.GLOBAL)) {
+                    if (level.equals(Auth.PrivLevel.GLOBAL)) {
                         savedPrivs.or(entry.getValue());
                         return;
                     }
                     break;
                 case DATABASE:
-                    if (level.equals(PaloAuth.PrivLevel.DATABASE) && db != null
+                    if (level.equals(Auth.PrivLevel.DATABASE) && db != null
                             && entry.getKey().getQualifiedDb().equals(db)) {
                         savedPrivs.or(entry.getValue());
                         return;
                     }
                     break;
                 case TABLE:
-                    if (level.equals(PaloAuth.PrivLevel.TABLE) && db != null && tbl != null
+                    if (level.equals(Auth.PrivLevel.TABLE) && db != null && tbl != null
                             && entry.getKey().getQualifiedDb().equals(db) && entry.getKey().getTbl().equals(tbl)) {
                         savedPrivs.or(entry.getValue());
                         return;
@@ -144,22 +145,22 @@ public class LdapPrivsChecker {
     }
 
     private static void getCurrentUserResourcePrivs(UserIdentity currentUser,
-            String resourceName, PrivBitSet savedPrivs, PaloAuth.PrivLevel level) {
+            String resourceName, PrivBitSet savedPrivs, Auth.PrivLevel level) {
         if (!hasLdapPrivs(currentUser)) {
             return;
         }
-        PaloRole currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
+        Role currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
         for (Map.Entry<ResourcePattern, PrivBitSet> entry
                 : currentUserLdapPrivs.getResourcePatternToPrivs().entrySet()) {
             switch (entry.getKey().getPrivLevel()) {
                 case GLOBAL:
-                    if (level.equals(PaloAuth.PrivLevel.GLOBAL)) {
+                    if (level.equals(Auth.PrivLevel.GLOBAL)) {
                         savedPrivs.or(entry.getValue());
                         return;
                     }
                     break;
                 case RESOURCE:
-                    if (level.equals(PaloAuth.PrivLevel.RESOURCE) && resourceName != null
+                    if (level.equals(Auth.PrivLevel.RESOURCE) && resourceName != null
                             && entry.getKey().getResourceName().equals(resourceName)) {
                         savedPrivs.or(entry.getValue());
                         return;
@@ -171,13 +172,13 @@ public class LdapPrivsChecker {
         }
     }
 
-    private static boolean hasPrivs(UserIdentity currentUser, PrivPredicate wanted, PaloAuth.PrivLevel level) {
+    private static boolean hasPrivs(UserIdentity currentUser, PrivPredicate wanted, Auth.PrivLevel level) {
         if (!hasLdapPrivs(currentUser)) {
             return false;
         }
-        PaloRole currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
+        Role currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
         for (Map.Entry<TablePattern, PrivBitSet> entry : currentUserLdapPrivs.getTblPatternToPrivs().entrySet()) {
-            if (entry.getKey().getPrivLevel().equals(level) && PaloPrivilege.satisfy(entry.getValue(), wanted)) {
+            if (entry.getKey().getPrivLevel().equals(level) && Privilege.satisfy(entry.getValue(), wanted)) {
                 return true;
             }
         }
@@ -189,9 +190,9 @@ public class LdapPrivsChecker {
         if (!hasLdapPrivs(currentUser)) {
             return false;
         }
-        PaloRole currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
+        Role currentUserLdapPrivs = getUserLdapPrivs(currentUser.getQualifiedUser());
         for (Map.Entry<TablePattern, PrivBitSet> entry : currentUserLdapPrivs.getTblPatternToPrivs().entrySet()) {
-            if (entry.getKey().getPrivLevel().equals(PaloAuth.PrivLevel.TABLE)
+            if (entry.getKey().getPrivLevel().equals(Auth.PrivLevel.TABLE)
                     && entry.getKey().getQualifiedDb().equals(db)) {
                 return true;
             }
@@ -211,7 +212,7 @@ public class LdapPrivsChecker {
         }
         for (Map.Entry<TablePattern, PrivBitSet> entry : getUserLdapPrivs(userIdentity.getQualifiedUser())
                 .getTblPatternToPrivs().entrySet()) {
-            if (entry.getKey().getPrivLevel().equals(PaloAuth.PrivLevel.DATABASE)) {
+            if (entry.getKey().getPrivLevel().equals(Auth.PrivLevel.DATABASE)) {
                 ldapDbPrivs.put(entry.getKey(), entry.getValue());
             }
         }
@@ -225,7 +226,7 @@ public class LdapPrivsChecker {
         }
         for (Map.Entry<TablePattern, PrivBitSet> entry : getUserLdapPrivs(userIdentity.getQualifiedUser())
                 .getTblPatternToPrivs().entrySet()) {
-            if (entry.getKey().getPrivLevel().equals(PaloAuth.PrivLevel.TABLE)) {
+            if (entry.getKey().getPrivLevel().equals(Auth.PrivLevel.TABLE)) {
                 ldapTblPrivs.put(entry.getKey(), entry.getValue());
             }
         }
@@ -239,26 +240,26 @@ public class LdapPrivsChecker {
         }
         for (Map.Entry<ResourcePattern, PrivBitSet> entry : getUserLdapPrivs(userIdentity.getQualifiedUser())
                 .getResourcePatternToPrivs().entrySet()) {
-            if (entry.getKey().getPrivLevel().equals(PaloAuth.PrivLevel.RESOURCE)) {
+            if (entry.getKey().getPrivLevel().equals(Auth.PrivLevel.RESOURCE)) {
                 ldapResourcePrivs.put(entry.getKey(), entry.getValue());
             }
         }
         return ldapResourcePrivs;
     }
 
-    private static PaloRole getUserLdapPrivs(String fullName) {
+    private static Role getUserLdapPrivs(String fullName) {
         return Env.getCurrentEnv().getAuth().getLdapManager().getUserInfo(fullName).getPaloRole();
     }
 
     // Temporary user has information_schema 'Select_priv' priv by default.
-    public static void grantDefaultPrivToTempUser(PaloRole role, String clusterName) {
+    public static void grantDefaultPrivToTempUser(Role role, String clusterName) throws DdlException {
         TablePattern tblPattern = new TablePattern(InfoSchemaDb.DATABASE_NAME, "*");
         try {
             tblPattern.analyze(clusterName);
         } catch (AnalysisException e) {
             LOG.warn("should not happen.", e);
         }
-        PaloRole newRole = new PaloRole(role.getRoleName(), tblPattern, PrivBitSet.of(PaloPrivilege.SELECT_PRIV));
+        Role newRole = new Role(role.getRoleName(), tblPattern, PrivBitSet.of(Privilege.SELECT_PRIV));
         role.merge(newRole);
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapUserInfo.java b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapUserInfo.java
index 8fa046845b..50c3d9ef53 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapUserInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/ldap/LdapUserInfo.java
@@ -18,7 +18,7 @@
 package org.apache.doris.ldap;
 
 import org.apache.doris.common.LdapConfig;
-import org.apache.doris.mysql.privilege.PaloRole;
+import org.apache.doris.mysql.privilege.Role;
 
 import java.util.Objects;
 
@@ -26,7 +26,7 @@ import java.util.Objects;
  * Used to cache LDAP information of user, such as password and privileges.
  */
 public class LdapUserInfo {
-    public LdapUserInfo(String userName, boolean isSetPasswd, String passwd, PaloRole role) {
+    public LdapUserInfo(String userName, boolean isSetPasswd, String passwd, Role role) {
         this.userName = userName;
         this.isSetPasswd = isSetPasswd;
         this.passwd = passwd;
@@ -34,7 +34,7 @@ public class LdapUserInfo {
         this.lastTimeStamp = System.currentTimeMillis();
     }
 
-    private LdapUserInfo(String userName, boolean isSetPasswd, String passwd, PaloRole role, long lastTimeStamp) {
+    private LdapUserInfo(String userName, boolean isSetPasswd, String passwd, Role role, long lastTimeStamp) {
         this.userName = userName;
         this.isSetPasswd = isSetPasswd;
         this.passwd = passwd;
@@ -48,7 +48,7 @@ public class LdapUserInfo {
 
     private final String passwd;
 
-    private final PaloRole role;
+    private final Role role;
 
     private final long lastTimeStamp;
 
@@ -65,7 +65,7 @@ public class LdapUserInfo {
         return passwd;
     }
 
-    public PaloRole getPaloRole() {
+    public Role getPaloRole() {
         return role;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/LoadJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/LoadJob.java
index 198d388ef7..9374925e7b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/LoadJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/LoadJob.java
@@ -44,8 +44,8 @@ import org.apache.doris.load.EtlStatus;
 import org.apache.doris.load.FailMsg;
 import org.apache.doris.load.FailMsg.CancelType;
 import org.apache.doris.load.Load;
-import org.apache.doris.mysql.privilege.PaloPrivilege;
 import org.apache.doris.mysql.privilege.PrivPredicate;
+import org.apache.doris.mysql.privilege.Privilege;
 import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.qe.Coordinator;
@@ -583,7 +583,7 @@ public abstract class LoadJob extends AbstractTxnStateChangeCallback implements
         if (!Env.getCurrentEnv().getAuth().checkPrivByAuthInfo(ConnectContext.get(), authorizationInfo,
                 PrivPredicate.LOAD)) {
             ErrorReport.reportDdlException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR,
-                    PaloPrivilege.LOAD_PRIV);
+                    Privilege.LOAD_PRIV);
         }
     }
 
@@ -604,7 +604,7 @@ public abstract class LoadJob extends AbstractTxnStateChangeCallback implements
                 if (!Env.getCurrentEnv().getAuth().checkDbPriv(ConnectContext.get(), db.getFullName(),
                         PrivPredicate.LOAD)) {
                     ErrorReport.reportDdlException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR,
-                            PaloPrivilege.LOAD_PRIV);
+                            Privilege.LOAD_PRIV);
                 }
             } else {
                 for (String tblName : tableNames) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlProto.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlProto.java
index 9dd346ce6e..fc48fcd553 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlProto.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlProto.java
@@ -28,7 +28,7 @@ import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.LdapConfig;
 import org.apache.doris.datasource.CatalogIf;
 import org.apache.doris.ldap.LdapAuthenticate;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.UserResource;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.system.SystemInfoService;
@@ -134,7 +134,7 @@ public class MysqlProto {
 
     private static boolean useLdapAuthenticate(String qualifiedUser) {
         // The root and admin are used to set the ldap admin password and cannot use ldap authentication.
-        if (qualifiedUser.equals(PaloAuth.ROOT_USER) || qualifiedUser.equals(PaloAuth.ADMIN_USER)) {
+        if (qualifiedUser.equals(Auth.ROOT_USER) || qualifiedUser.equals(Auth.ADMIN_USER)) {
             return false;
         }
         // If LDAP authentication is enabled and the user exists in LDAP, use LDAP authentication,
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
new file mode 100644
index 0000000000..b66331f041
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
@@ -0,0 +1,1644 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.analysis.AlterUserStmt;
+import org.apache.doris.analysis.AlterUserStmt.OpType;
+import org.apache.doris.analysis.CreateRoleStmt;
+import org.apache.doris.analysis.CreateUserStmt;
+import org.apache.doris.analysis.DropRoleStmt;
+import org.apache.doris.analysis.DropUserStmt;
+import org.apache.doris.analysis.GrantStmt;
+import org.apache.doris.analysis.PasswordOptions;
+import org.apache.doris.analysis.ResourcePattern;
+import org.apache.doris.analysis.RevokeStmt;
+import org.apache.doris.analysis.SetLdapPassVar;
+import org.apache.doris.analysis.SetPassVar;
+import org.apache.doris.analysis.SetUserPropertyStmt;
+import org.apache.doris.analysis.TableName;
+import org.apache.doris.analysis.TablePattern;
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.catalog.AuthorizationInfo;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.cluster.ClusterNamespace;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.AuthenticationException;
+import org.apache.doris.common.DdlException;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
+import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.LdapConfig;
+import org.apache.doris.common.Pair;
+import org.apache.doris.common.PatternMatcherException;
+import org.apache.doris.common.UserException;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.ldap.LdapManager;
+import org.apache.doris.ldap.LdapPrivsChecker;
+import org.apache.doris.load.DppConfig;
+import org.apache.doris.persist.AlterUserOperationLog;
+import org.apache.doris.persist.LdapInfo;
+import org.apache.doris.persist.PrivInfo;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.resource.Tag;
+import org.apache.doris.system.SystemInfoService;
+import org.apache.doris.thrift.TFetchResourceResult;
+import org.apache.doris.thrift.TPrivilegeStatus;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.Collectors;
+
+public class Auth implements Writable {
+    private static final Logger LOG = LogManager.getLogger(Auth.class);
+
+    // root user's role is operator.
+    // each Palo system has only one root user.
+    public static final String ROOT_USER = "root";
+    public static final String ADMIN_USER = "admin";
+    // unknown user does not have any privilege, this is just to be compatible with old version.
+    public static final String UNKNOWN_USER = "unknown";
+    public static final String DEFAULT_CATALOG = InternalCatalog.INTERNAL_CATALOG_NAME;
+
+    //There is no concurrency control logic inside roleManager,userManager,userRoleManage and rpropertyMgr,
+    // and it is completely managed by Auth.
+    // Therefore, their methods cannot be directly called outside, and should be called indirectly through Auth.
+    private RoleManager roleManager = new RoleManager();
+    private UserManager userManager = new UserManager();
+    private UserRoleManager userRoleManager = new UserRoleManager();
+    private UserPropertyMgr propertyMgr = new UserPropertyMgr();
+
+
+    private LdapInfo ldapInfo = new LdapInfo();
+
+    private LdapManager ldapManager = new LdapManager();
+
+    private PasswordPolicyManager passwdPolicyManager = new PasswordPolicyManager();
+
+    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+    private void readLock() {
+        lock.readLock().lock();
+    }
+
+    private void readUnlock() {
+        lock.readLock().unlock();
+    }
+
+    private void writeLock() {
+        lock.writeLock().lock();
+    }
+
+    private void writeUnlock() {
+        lock.writeLock().unlock();
+    }
+
+    public enum PrivLevel {
+        GLOBAL, CATALOG, DATABASE, TABLE, RESOURCE
+    }
+
+    public Auth() {
+        initUser();
+    }
+
+    public LdapInfo getLdapInfo() {
+        return ldapInfo;
+    }
+
+    public void setLdapInfo(LdapInfo ldapInfo) {
+        this.ldapInfo = ldapInfo;
+    }
+
+    public LdapManager getLdapManager() {
+        return ldapManager;
+    }
+
+    public PasswordPolicyManager getPasswdPolicyManager() {
+        return passwdPolicyManager;
+    }
+
+    public boolean doesRoleExist(String qualifiedRole) {
+        return roleManager.getRole(qualifiedRole) != null;
+    }
+
+    public void mergeRolesNoCheckName(List<String> roles, Role savedRole) throws DdlException {
+        readLock();
+        try {
+            for (String roleName : roles) {
+                if (doesRoleExist(roleName)) {
+                    Role role = roleManager.getRole(roleName);
+                    savedRole.mergeNotCheck(role);
+                }
+            }
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * check password, if matched, save the userIdentity in matched entry.
+     * the following auth checking should use userIdentity saved in currentUser.
+     */
+    public void checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString,
+            List<UserIdentity> currentUser) throws AuthenticationException {
+        if ((remoteUser.equals(ROOT_USER) || remoteUser.equals(ADMIN_USER)) && remoteHost.equals("127.0.0.1")) {
+            // root and admin user is allowed to login from 127.0.0.1, in case user forget password.
+            if (remoteUser.equals(ROOT_USER)) {
+                currentUser.add(UserIdentity.ROOT);
+            } else {
+                currentUser.add(UserIdentity.ADMIN);
+            }
+            return;
+        }
+        readLock();
+        try {
+            userManager.checkPassword(remoteUser, remoteHost, remotePasswd, randomString, currentUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // For unit test only, wrapper of "void checkPlainPassword"
+    public boolean checkPlainPasswordForTest(String remoteUser, String remoteHost, String remotePasswd,
+            List<UserIdentity> currentUser) {
+        try {
+            checkPlainPassword(remoteUser, remoteHost, remotePasswd, currentUser);
+            return true;
+        } catch (AuthenticationException e) {
+            return false;
+        }
+    }
+
+    public void checkPlainPassword(String remoteUser, String remoteHost, String remotePasswd,
+            List<UserIdentity> currentUser) throws AuthenticationException {
+        // Check the LDAP password when the user exists in the LDAP service.
+        if (ldapManager.doesUserExist(remoteUser)) {
+            if (!ldapManager.checkUserPasswd(remoteUser, remotePasswd, remoteHost, currentUser)) {
+                throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
+                        Strings.isNullOrEmpty(remotePasswd) ? "NO" : "YES");
+            }
+            return;
+        }
+        readLock();
+        try {
+            userManager.checkPlainPassword(remoteUser, remoteHost, remotePasswd, currentUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public boolean checkGlobalPriv(ConnectContext ctx, PrivPredicate wanted) {
+        return checkGlobalPriv(ctx.getCurrentUserIdentity(), wanted);
+    }
+
+    public boolean checkGlobalPriv(UserIdentity currentUser, PrivPredicate wanted) {
+        if (isLdapAuthEnabled() && LdapPrivsChecker.hasGlobalPrivFromLdap(currentUser, wanted)) {
+            return true;
+        }
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(currentUser);
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkGlobalPriv(wanted)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+
+    }
+
+    public boolean checkCtlPriv(ConnectContext ctx, String ctl, PrivPredicate wanted) {
+        return checkCtlPriv(ctx.getCurrentUserIdentity(), ctl, wanted);
+    }
+
+    public boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) {
+        if (wanted.getPrivs().containsNodePriv()) {
+            LOG.debug("should not check NODE priv in catalog level. user: {}, catalog: {}",
+                    currentUser, ctl);
+            return false;
+        }
+        //ldap(before change to rbac)
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(currentUser);
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkCtlPriv(ctl, wanted)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+
+    }
+
+    public boolean checkDbPriv(ConnectContext ctx, String qualifiedDb, PrivPredicate wanted) {
+        return checkDbPriv(ctx.getCurrentUserIdentity(), qualifiedDb, wanted);
+    }
+
+    public boolean checkDbPriv(UserIdentity currentUser, String db, PrivPredicate wanted) {
+        return checkDbPriv(currentUser, DEFAULT_CATALOG, db, wanted);
+    }
+
+    public boolean checkDbPriv(ConnectContext ctx, String ctl, String db, PrivPredicate wanted) {
+        return checkDbPriv(ctx.getCurrentUserIdentity(), ctl, db, wanted);
+    }
+
+    /*
+     * Check if 'user'@'host' on 'db' has 'wanted' priv.
+     * If the given db is null, which means it will no check if database name is matched.
+     */
+    public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
+        if (isLdapAuthEnabled() && (LdapPrivsChecker.hasDbPrivFromLdap(currentUser, wanted) || LdapPrivsChecker
+                .hasPrivsOfDb(currentUser, db))) {
+            return true;
+        }
+        if (wanted.getPrivs().containsNodePriv()) {
+            LOG.debug("should not check NODE priv in Database level. user: {}, db: {}",
+                    currentUser, db);
+            return false;
+        }
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(currentUser);
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkDbPriv(ctl, db, wanted)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+
+    }
+
+    public boolean checkTblPriv(ConnectContext ctx, String qualifiedCtl,
+            String qualifiedDb, String tbl, PrivPredicate wanted) {
+        return checkTblPriv(ctx.getCurrentUserIdentity(), qualifiedCtl, qualifiedDb, tbl, wanted);
+    }
+
+    public boolean checkTblPriv(ConnectContext ctx, String qualifiedDb, String tbl, PrivPredicate wanted) {
+        return checkTblPriv(ctx, DEFAULT_CATALOG, qualifiedDb, tbl, wanted);
+    }
+
+    public boolean checkTblPriv(ConnectContext ctx, TableName tableName, PrivPredicate wanted) {
+        Preconditions.checkState(tableName.isFullyQualified());
+        return checkTblPriv(ctx, tableName.getCtl(), tableName.getDb(), tableName.getTbl(), wanted);
+    }
+
+    public boolean checkTblPriv(UserIdentity currentUser, String db, String tbl, PrivPredicate wanted) {
+        return checkTblPriv(currentUser, DEFAULT_CATALOG, db, tbl, wanted);
+    }
+
+    public boolean checkTblPriv(UserIdentity currentUser, String ctl, String db, String tbl, PrivPredicate wanted) {
+        if (isLdapAuthEnabled() && LdapPrivsChecker.hasTblPrivFromLdap(currentUser, db, tbl, wanted)) {
+            return true;
+        }
+        if (wanted.getPrivs().containsNodePriv()) {
+            LOG.debug("should check NODE priv in GLOBAL level. user: {}, db: {}, tbl: {}", currentUser, db, tbl);
+            return false;
+        }
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(currentUser);
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkTblPriv(ctl, db, tbl, wanted)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public boolean checkResourcePriv(ConnectContext ctx, String resourceName, PrivPredicate wanted) {
+        return checkResourcePriv(ctx.getCurrentUserIdentity(), resourceName, wanted);
+    }
+
+    public boolean checkResourcePriv(UserIdentity currentUser, String resourceName, PrivPredicate wanted) {
+        if (isLdapAuthEnabled() && LdapPrivsChecker.hasResourcePrivFromLdap(currentUser, resourceName, wanted)) {
+            return true;
+        }
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(currentUser);
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkResourcePriv(resourceName, wanted)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public boolean checkPrivByAuthInfo(ConnectContext ctx, AuthorizationInfo authInfo, PrivPredicate wanted) {
+        if (authInfo == null) {
+            return false;
+        }
+        if (authInfo.getDbName() == null) {
+            return false;
+        }
+        if (authInfo.getTableNameList() == null || authInfo.getTableNameList().isEmpty()) {
+            return checkDbPriv(ctx, authInfo.getDbName(), wanted);
+        }
+        for (String tblName : authInfo.getTableNameList()) {
+            if (!checkTblPriv(ConnectContext.get(), authInfo.getDbName(), tblName, wanted)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * Check if current user has certain privilege.
+     * This method will check the given privilege levels
+     */
+    public boolean checkHasPriv(ConnectContext ctx, PrivPredicate priv, PrivLevel... levels) {
+        if (isLdapAuthEnabled() && checkHasPrivLdap(ctx.getCurrentUserIdentity(), priv, levels)) {
+            return true;
+        }
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(ctx.getCurrentUserIdentity());
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkHasPriv(priv, levels)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+
+    }
+
+    public boolean checkHasPrivLdap(UserIdentity currentUser, PrivPredicate priv, PrivLevel... levels) {
+        for (PrivLevel privLevel : levels) {
+            switch (privLevel) {
+                case GLOBAL:
+                    if (LdapPrivsChecker.hasGlobalPrivFromLdap(currentUser, priv)) {
+                        return true;
+                    }
+                    break;
+                case DATABASE:
+                    if (LdapPrivsChecker.hasDbPrivFromLdap(currentUser, priv)) {
+                        return true;
+                    }
+                    break;
+                case TABLE:
+                    if (LdapPrivsChecker.hasTblPrivFromLdap(currentUser, priv)) {
+                        return true;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+        return false;
+
+    }
+
+    // Check if LDAP authentication is enabled.
+    private boolean isLdapAuthEnabled() {
+        return LdapConfig.ldap_authentication_enabled;
+    }
+
+    // create user
+    public void createUser(CreateUserStmt stmt) throws DdlException {
+        createUserInternal(stmt.getUserIdent(), stmt.getQualifiedRole(),
+                stmt.getPassword(), stmt.isIfNotExist(), stmt.getPasswordOptions(), false);
+    }
+
+    public void replayCreateUser(PrivInfo privInfo) {
+        try {
+            createUserInternal(privInfo.getUserIdent(), privInfo.getRole(), privInfo.getPasswd(), false,
+                    privInfo.getPasswordOptions(), true);
+        } catch (DdlException e) {
+            LOG.error("should not happen", e);
+        }
+    }
+
+    private void createUserInternal(UserIdentity userIdent, String roleName, byte[] password,
+            boolean ignoreIfExists, PasswordOptions passwordOptions, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            // check if role exist
+            Role role = null;
+            if (roleName != null) {
+                role = roleManager.getRole(roleName);
+                if (role == null) {
+                    throw new DdlException("Role: " + roleName + " does not exist");
+                }
+            }
+
+            // check if user already exist
+            if (doesUserExist(userIdent)) {
+                if (ignoreIfExists) {
+                    LOG.info("user exists, ignored to create user: {}, is replay: {}", userIdent, isReplay);
+                    return;
+                }
+                throw new DdlException("User " + userIdent + " already exist");
+            }
+
+            // create user
+            try {
+                //we should not throw AnalysisException at here,so transfer it
+                userManager.createUser(userIdent, password, null, false);
+            } catch (PatternMatcherException e) {
+                throw new DdlException("create user failed,", e);
+            }
+            if (password != null) {
+                // save password to password history
+                passwdPolicyManager.updatePassword(userIdent, password);
+            }
+            //4.create defaultRole
+            Role defaultRole = roleManager.createDefaultRole(userIdent);
+            // 5.create user role
+            userRoleManager.addUserRole(userIdent, defaultRole.getRoleName());
+            if (role != null) {
+                userRoleManager.addUserRole(userIdent, roleName);
+            }
+            // other user properties
+            propertyMgr.addUserResource(userIdent.getQualifiedUser(), false);
+
+            // 5. update password policy
+            passwdPolicyManager.updatePolicy(userIdent, password, passwordOptions);
+
+            if (!isReplay) {
+                PrivInfo privInfo = new PrivInfo(userIdent, null, password, roleName, passwordOptions);
+                Env.getCurrentEnv().getEditLog().logCreateUser(privInfo);
+            }
+            LOG.info("finished to create user: {}, is replay: {}", userIdent, isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // drop user
+    public void dropUser(DropUserStmt stmt) throws DdlException {
+        dropUserInternal(stmt.getUserIdentity(), stmt.isSetIfExists(), false);
+    }
+
+    public void replayDropUser(UserIdentity userIdent) throws DdlException {
+        dropUserInternal(userIdent, false, true);
+    }
+
+    private void dropUserInternal(UserIdentity userIdent, boolean ignoreIfNonExists, boolean isReplay)
+            throws DdlException {
+        writeLock();
+        try {
+            // check if user exists
+            if (!doesUserExist(userIdent)) {
+                if (ignoreIfNonExists) {
+                    LOG.info("user non exists, ignored to drop user: {}, is replay: {}",
+                            userIdent.getQualifiedUser(), isReplay);
+                    return;
+                }
+                throw new DdlException(String.format("User `%s`@`%s` does not exist.",
+                        userIdent.getQualifiedUser(), userIdent.getHost()));
+            }
+
+            // drop default role
+            roleManager.removeDefaultRole(userIdent);
+            //drop user role
+            userRoleManager.dropUser(userIdent);
+            passwdPolicyManager.dropUser(userIdent);
+            userManager.removeUser(userIdent);
+            if (CollectionUtils.isEmpty(userManager.getUserByName(userIdent.getQualifiedUser()))) {
+                propertyMgr.dropUser(userIdent);
+            }
+
+            if (!isReplay) {
+                Env.getCurrentEnv().getEditLog().logNewDropUser(userIdent);
+            }
+            LOG.info("finished to drop user: {}, is replay: {}", userIdent.getQualifiedUser(), isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // grant
+    public void grant(GrantStmt stmt) throws DdlException {
+        PrivBitSet privs = PrivBitSet.of(stmt.getPrivileges());
+        if (stmt.getTblPattern() != null) {
+            grantInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getTblPattern(), privs,
+                    true /* err on non exist */, false /* not replay */);
+        } else {
+            grantInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getResourcePattern(), privs,
+                    true /* err on non exist */, false /* not replay */);
+        }
+    }
+
+    public void replayGrant(PrivInfo privInfo) {
+        try {
+            if (privInfo.getTblPattern() != null) {
+                grantInternal(privInfo.getUserIdent(), privInfo.getRole(),
+                        privInfo.getTblPattern(), privInfo.getPrivs(),
+                        true /* err on non exist */, true /* is replay */);
+            } else {
+                grantInternal(privInfo.getUserIdent(), privInfo.getRole(),
+                        privInfo.getResourcePattern(), privInfo.getPrivs(),
+                        true /* err on non exist */, true /* is replay */);
+            }
+        } catch (DdlException e) {
+            LOG.error("should not happen", e);
+        }
+    }
+
+    // grant for TablePattern
+    //if no role,role is default role of userIdent
+    private void grantInternal(UserIdentity userIdent, String role, TablePattern tblPattern,
+            PrivBitSet privs, boolean errOnNonExist, boolean isReplay)
+            throws DdlException {
+        writeLock();
+        try {
+            if (role == null) {
+                if (!doesUserExist(userIdent)) {
+                    throw new DdlException("user " + userIdent + " does not exist");
+                }
+                role = roleManager.getUserDefaultRoleName(userIdent);
+            }
+            Role newRole = new Role(role, tblPattern, privs);
+            roleManager.addOrMergeRole(newRole, false /* err on exist */);
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(userIdent, tblPattern, privs, null, role);
+                Env.getCurrentEnv().getEditLog().logGrantPriv(info);
+            }
+            LOG.info("finished to grant privilege. is replay: {}", isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // grant for ResourcePattern
+    private void grantInternal(UserIdentity userIdent, String role, ResourcePattern resourcePattern, PrivBitSet privs,
+            boolean errOnNonExist, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            if (role == null) {
+                role = roleManager.getUserDefaultRoleName(userIdent);
+            }
+
+            // grant privs to role, role must exist
+            Role newRole = new Role(role, resourcePattern, privs);
+            roleManager.addOrMergeRole(newRole, false /* err on exist */);
+
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(userIdent, resourcePattern, privs, null, role);
+                Env.getCurrentEnv().getEditLog().logGrantPriv(info);
+            }
+            LOG.info("finished to grant resource privilege. is replay: {}", isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+
+    // return true if user ident exist
+    private boolean doesUserExist(UserIdentity userIdent) {
+        return userManager.userIdentityExist(userIdent, false);
+    }
+
+    // Check whether the user exists. If the user exists, return UserIdentity, otherwise return null.
+    public UserIdentity getCurrentUserIdentity(UserIdentity userIdent) {
+        readLock();
+        try {
+            if (doesUserExist(userIdent)) {
+                return userIdent;
+            }
+            return null;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // revoke
+    public void revoke(RevokeStmt stmt) throws DdlException {
+        PrivBitSet privs = PrivBitSet.of(stmt.getPrivileges());
+        if (stmt.getTblPattern() != null) {
+            revokeInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getTblPattern(), privs,
+                    true /* err on non exist */, false /* is replay */);
+        } else {
+            revokeInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getResourcePattern(), privs,
+                    true /* err on non exist */, false /* is replay */);
+        }
+    }
+
+    public void replayRevoke(PrivInfo info) {
+        try {
+            if (info.getTblPattern() != null) {
+                revokeInternal(info.getUserIdent(), info.getRole(), info.getTblPattern(), info.getPrivs(),
+                        true /* err on non exist */, true /* is replay */);
+            } else {
+                revokeInternal(info.getUserIdent(), info.getRole(), info.getResourcePattern(), info.getPrivs(),
+                        true /* err on non exist */, true /* is replay */);
+            }
+        } catch (DdlException e) {
+            LOG.error("should not happened", e);
+        }
+    }
+
+    private void revokeInternal(UserIdentity userIdent, String role, TablePattern tblPattern,
+            PrivBitSet privs, boolean errOnNonExist, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            if (role == null) {
+                role = roleManager.getUserDefaultRoleName(userIdent);
+            }
+            // revoke privs from role
+            roleManager.revokePrivs(role, tblPattern, privs, errOnNonExist);
+
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(userIdent, tblPattern, privs, null, role);
+                Env.getCurrentEnv().getEditLog().logRevokePriv(info);
+            }
+            LOG.info("finished to revoke privilege. is replay: {}", isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    private void revokeInternal(UserIdentity userIdent, String role, ResourcePattern resourcePattern,
+            PrivBitSet privs, boolean errOnNonExist, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            if (role == null) {
+                role = roleManager.getUserDefaultRoleName(userIdent);
+            }
+
+            // revoke privs from role
+            roleManager.revokePrivs(role, resourcePattern, privs, errOnNonExist);
+
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(userIdent, resourcePattern, privs, null, role);
+                Env.getCurrentEnv().getEditLog().logRevokePriv(info);
+            }
+            LOG.info("finished to revoke privilege. is replay: {}", isReplay);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // set password
+    public void setPassword(SetPassVar stmt) throws DdlException {
+        setPasswordInternal(stmt.getUserIdent(), stmt.getPassword(), null, true /* err on non exist */,
+                false /* set by resolver */, false);
+    }
+
+    public void replaySetPassword(PrivInfo info) {
+        try {
+            setPasswordInternal(info.getUserIdent(), info.getPasswd(), null, true /* err on non exist */,
+                    false /* set by resolver */, true);
+        } catch (DdlException e) {
+            LOG.error("should not happened", e);
+        }
+    }
+
+    public void setPasswordInternal(UserIdentity userIdent, byte[] password, UserIdentity domainUserIdent,
+            boolean errOnNonExist, boolean setByResolver, boolean isReplay) throws DdlException {
+        Preconditions.checkArgument(!setByResolver || domainUserIdent != null, setByResolver + ", " + domainUserIdent);
+        writeLock();
+        try {
+            if (!isReplay) {
+                if (!passwdPolicyManager.checkPasswordHistory(userIdent, password)) {
+                    ErrorReport.reportDdlException(ErrorCode.ERR_CREDENTIALS_CONTRADICT_TO_HISTORY,
+                            userIdent.getQualifiedUser(), userIdent.getHost());
+                }
+            }
+            userManager.setPassword(userIdent, password, errOnNonExist);
+            if (password != null) {
+                // save password to password history
+                passwdPolicyManager.updatePassword(userIdent, password);
+            }
+
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(userIdent, null, password, null, null);
+                Env.getCurrentEnv().getEditLog().logSetPassword(info);
+            }
+        } finally {
+            writeUnlock();
+        }
+        LOG.info("finished to set password for {}. is replay: {}", userIdent, isReplay);
+    }
+
+    // set ldap admin password.
+    public void setLdapPassword(SetLdapPassVar stmt) {
+        ldapInfo = new LdapInfo(stmt.getLdapPassword());
+        Env.getCurrentEnv().getEditLog().logSetLdapPassword(ldapInfo);
+        LOG.info("finished to set ldap password.");
+    }
+
+    public void replaySetLdapPassword(LdapInfo info) {
+        ldapInfo = info;
+        LOG.debug("finish replaying ldap admin password.");
+    }
+
+    // create role
+    public void createRole(CreateRoleStmt stmt) throws DdlException {
+        createRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfNotExists(), false);
+    }
+
+    public void replayCreateRole(PrivInfo info) {
+        try {
+            createRoleInternal(info.getRole(), false, true);
+        } catch (DdlException e) {
+            LOG.error("should not happened", e);
+        }
+    }
+
+    private void createRoleInternal(String role, boolean ignoreIfExists, boolean isReplay) throws DdlException {
+        Role emptyPrivsRole = new Role(role);
+        writeLock();
+        try {
+            if (role.startsWith(RoleManager.DEFAULT_ROLE_PREFIX)) {
+                throw new DdlException("Can not create role starts with " + RoleManager.DEFAULT_ROLE_PREFIX);
+            }
+            if (ignoreIfExists && roleManager.getRole(role) != null) {
+                LOG.info("role exists, ignored to create role: {}, is replay: {}", role, isReplay);
+                return;
+            }
+
+            roleManager.addOrMergeRole(emptyPrivsRole, true /* err on exist */);
+
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(null, null, null, role, null);
+                Env.getCurrentEnv().getEditLog().logCreateRole(info);
+            }
+        } finally {
+            writeUnlock();
+        }
+        LOG.info("finished to create role: {}, is replay: {}", role, isReplay);
+    }
+
+    // drop role
+    public void dropRole(DropRoleStmt stmt) throws DdlException {
+        dropRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfExists(), false);
+    }
+
+    public void replayDropRole(PrivInfo info) {
+        try {
+            dropRoleInternal(info.getRole(), false, true);
+        } catch (DdlException e) {
+            LOG.error("should not happened", e);
+        }
+    }
+
+    private void dropRoleInternal(String role, boolean ignoreIfNonExists, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            if (role.startsWith(RoleManager.DEFAULT_ROLE_PREFIX)) {
+                throw new DdlException("Can not drop role starts with " + RoleManager.DEFAULT_ROLE_PREFIX);
+            }
+            if (ignoreIfNonExists && roleManager.getRole(role) == null) {
+                LOG.info("role non exists, ignored to drop role: {}, is replay: {}", role, isReplay);
+                return;
+            }
+
+            roleManager.dropRole(role, true /* err on non exist */);
+            userRoleManager.dropRole(role);
+            if (!isReplay) {
+                PrivInfo info = new PrivInfo(null, null, null, role, null);
+                Env.getCurrentEnv().getEditLog().logDropRole(info);
+            }
+        } finally {
+            writeUnlock();
+        }
+        LOG.info("finished to drop role: {}, is replay: {}", role, isReplay);
+    }
+
+    public Set<UserIdentity> getRoleUsers(String roleName) {
+        readLock();
+        try {
+            return userRoleManager.getUsersByRole(roleName);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // update user property
+    public void updateUserProperty(SetUserPropertyStmt stmt) throws UserException {
+        List<Pair<String, String>> properties = stmt.getPropertyPairList();
+        updateUserPropertyInternal(stmt.getUser(), properties, false /* is replay */);
+    }
+
+    public void replayUpdateUserProperty(UserPropertyInfo propInfo) throws UserException {
+        updateUserPropertyInternal(propInfo.getUser(), propInfo.getProperties(), true /* is replay */);
+    }
+
+    public void updateUserPropertyInternal(String user, List<Pair<String, String>> properties, boolean isReplay)
+            throws UserException {
+        writeLock();
+        try {
+            propertyMgr.updateUserProperty(user, properties);
+            if (!isReplay) {
+                UserPropertyInfo propertyInfo = new UserPropertyInfo(user, properties);
+                Env.getCurrentEnv().getEditLog().logUpdateUserProperty(propertyInfo);
+            }
+            LOG.info("finished to set properties for user: {}", user);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    public long getMaxConn(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getMaxConn(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public long getQueryTimeout(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getQueryTimeout(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public long getMaxQueryInstances(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getMaxQueryInstances(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public String[] getSqlBlockRules(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getSqlBlockRules(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public int getCpuResourceLimit(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getCpuResourceLimit(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public Set<Tag> getResourceTags(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getResourceTags(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public long getExecMemLimit(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.getExecMemLimit(qualifiedUser);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public void getAllDomains(Set<String> allDomains) {
+        readLock();
+        try {
+            userManager.getAllDomains(allDomains);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // refresh all user set by domain resolver.
+    public void refreshUserPrivEntriesByResovledIPs(Map<String, Set<String>> resolvedIPsMap) {
+        writeLock();
+        try {
+            // 1. delete all user
+            userManager.clearEntriesSetByResolver();
+            // 2. add new user
+            userManager.addUserPrivEntriesByResolvedIPs(resolvedIPsMap);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // return the auth info of specified user, or infos of all users, if user is not specified.
+    // the returned columns are defined in AuthProcDir
+    // the specified user identity should be the identity created by CREATE USER, same as result of
+    // SELECT CURRENT_USER();
+    public List<List<String>> getAuthInfo(UserIdentity specifiedUserIdent) {
+        List<List<String>> userAuthInfos = Lists.newArrayList();
+        readLock();
+        try {
+            if (specifiedUserIdent == null) {
+                // get all users' auth info
+                Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+                for (List<User> users : nameToUsers.values()) {
+                    for (User user : users) {
+                        if (!user.isSetByDomainResolver()) {
+                            getUserAuthInfo(userAuthInfos, user.getUserIdentity());
+                        }
+                    }
+                }
+            } else {
+                getUserAuthInfo(userAuthInfos, specifiedUserIdent);
+            }
+        } finally {
+            readUnlock();
+        }
+        return userAuthInfos;
+    }
+
+    private void getUserAuthInfo(List<List<String>> userAuthInfos, UserIdentity userIdent) {
+        // AuthProcDir.TITLE_NAMES
+        List<String> userAuthInfo = Lists.newArrayList();
+        User user = userManager.getUserByUserIdentity(userIdent);
+        // ================= UserIdentity =======================
+        userAuthInfo.add(userIdent.toString());
+        // ============== Password ==============
+        userAuthInfo.add(user.hasPassword() ? "Yes" : "No");
+        // ==============GlobalPrivs==============
+        PrivBitSet ldapGlobalPrivs = LdapPrivsChecker.getGlobalPrivFromLdap(userIdent);
+        PrivBitSet globalPrivs = ldapGlobalPrivs.copy();
+        List<PrivEntry> globalEntries = getUserGlobalPrivTable(userIdent).entries;
+        if (!CollectionUtils.isEmpty(globalEntries)) {
+            globalPrivs.or(globalEntries.get(0).privSet);
+        }
+        userAuthInfo.add(globalPrivs.isEmpty() ? FeConstants.null_string : globalPrivs.toString());
+        // ============== CatalogPrivs ========================
+        String ctlPrivs = getUserCtlPrivTable(userIdent).entries.stream()
+                .map(entry -> String.format("%s: %s",
+                        ((CatalogPrivEntry) entry).getOrigCtl(), entry.privSet, user.isSetByDomainResolver()))
+                .collect(Collectors.joining("; "));
+        if (Strings.isNullOrEmpty(ctlPrivs)) {
+            ctlPrivs = FeConstants.null_string;
+        }
+        userAuthInfo.add(ctlPrivs);
+        // ============== DatabasePrivs ==============
+        List<String> dbPrivs = Lists.newArrayList();
+        Set<String> addedDbs = Sets.newHashSet();
+        for (PrivEntry entry : getUserDbPrivTable(userIdent).entries) {
+            DbPrivEntry dEntry = (DbPrivEntry) entry;
+            /**
+             * Doris and Ldap may have different privs on one database.
+             * Merge these privs and add.
+             */
+            PrivBitSet savedPrivs = dEntry.getPrivSet().copy();
+            savedPrivs.or(LdapPrivsChecker.getDbPrivFromLdap(userIdent, dEntry.getOrigDb()));
+            addedDbs.add(dEntry.getOrigDb());
+            dbPrivs.add(String.format("%s.%s: %s", dEntry.getOrigCtl(), dEntry.getOrigDb(),
+                    savedPrivs));
+        }
+        // Add privs from ldap groups that have not been added in Doris.
+        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
+            Map<TablePattern, PrivBitSet> ldapDbPrivs = LdapPrivsChecker.getLdapAllDbPrivs(userIdent);
+            for (Entry<TablePattern, PrivBitSet> entry : ldapDbPrivs.entrySet()) {
+                if (!addedDbs.contains(entry.getKey().getQualifiedDb())) {
+                    dbPrivs.add(String.format("%s.%s: %s", entry.getKey().getQualifiedCtl(),
+                            entry.getKey().getQualifiedDb(), entry.getValue()));
+                }
+            }
+        }
+
+        if (dbPrivs.isEmpty()) {
+            userAuthInfo.add(FeConstants.null_string);
+        } else {
+            userAuthInfo.add(Joiner.on("; ").join(dbPrivs));
+        }
+
+        // tbl
+        List<String> tblPrivs = Lists.newArrayList();
+        Set<String> addedtbls = Sets.newHashSet();
+        for (PrivEntry entry : getUserTblPrivTable(userIdent).entries) {
+            TablePrivEntry tEntry = (TablePrivEntry) entry;
+            /**
+             * Doris and Ldap may have different privs on one table.
+             * Merge these privs and add.
+             */
+            PrivBitSet savedPrivs = tEntry.getPrivSet().copy();
+            savedPrivs.or(LdapPrivsChecker.getTblPrivFromLdap(userIdent, tEntry.getOrigDb(), tEntry.getOrigTbl()));
+            addedtbls.add(tEntry.getOrigDb().concat(".").concat(tEntry.getOrigTbl()));
+            tblPrivs.add(String.format("%s.%s.%s: %s", tEntry.getOrigCtl(), tEntry.getOrigDb(),
+                    tEntry.getOrigTbl(), savedPrivs));
+        }
+        // Add privs from ldap groups that have not been added in Doris.
+        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
+            Map<TablePattern, PrivBitSet> ldapTblPrivs = LdapPrivsChecker.getLdapAllTblPrivs(userIdent);
+            for (Entry<TablePattern, PrivBitSet> entry : ldapTblPrivs.entrySet()) {
+                if (!addedtbls.contains(entry.getKey().getQualifiedDb().concat(".").concat(entry.getKey().getTbl()))) {
+                    tblPrivs.add(String.format("%s: %s", entry.getKey(), entry.getValue()));
+                }
+            }
+        }
+
+        if (tblPrivs.isEmpty()) {
+            userAuthInfo.add(FeConstants.null_string);
+        } else {
+            userAuthInfo.add(Joiner.on("; ").join(tblPrivs));
+        }
+
+        // resource
+        List<String> resourcePrivs = Lists.newArrayList();
+        Set<String> addedResources = Sets.newHashSet();
+        for (PrivEntry entry : getUserResourcePrivTable(userIdent).entries) {
+            ResourcePrivEntry rEntry = (ResourcePrivEntry) entry;
+            /**
+             * Doris and Ldap may have different privs on one resource.
+             * Merge these privs and add.
+             */
+            PrivBitSet savedPrivs = rEntry.getPrivSet().copy();
+            savedPrivs.or(LdapPrivsChecker.getResourcePrivFromLdap(userIdent, rEntry.getOrigResource()));
+            addedResources.add(rEntry.getOrigResource());
+            resourcePrivs.add(rEntry.getOrigResource() + ": " + savedPrivs.toString());
+        }
+        // Add privs from ldap groups that have not been added in Doris.
+        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
+            Map<ResourcePattern, PrivBitSet> ldapResourcePrivs = LdapPrivsChecker.getLdapAllResourcePrivs(userIdent);
+            for (Entry<ResourcePattern, PrivBitSet> entry : ldapResourcePrivs.entrySet()) {
+                if (!addedResources.contains(entry.getKey().getResourceName())) {
+                    tblPrivs.add(entry.getKey().getResourceName().concat(": ").concat(entry.getValue().toString()));
+                }
+            }
+        }
+
+        if (resourcePrivs.isEmpty()) {
+            userAuthInfo.add(FeConstants.null_string);
+        } else {
+            userAuthInfo.add(Joiner.on("; ").join(resourcePrivs));
+        }
+
+        userAuthInfos.add(userAuthInfo);
+    }
+
+    private GlobalPrivTable getUserGlobalPrivTable(UserIdentity userIdentity) {
+        GlobalPrivTable table = new GlobalPrivTable();
+        Set<String> roles = userRoleManager.getRolesByUser(userIdentity);
+        for (String roleName : roles) {
+            table.merge(roleManager.getRole(roleName).getGlobalPrivTable());
+        }
+        return table;
+    }
+
+    private CatalogPrivTable getUserCtlPrivTable(UserIdentity userIdentity) {
+        CatalogPrivTable table = new CatalogPrivTable();
+        Set<String> roles = userRoleManager.getRolesByUser(userIdentity);
+        for (String roleName : roles) {
+            table.merge(roleManager.getRole(roleName).getCatalogPrivTable());
+        }
+        return table;
+    }
+
+    private DbPrivTable getUserDbPrivTable(UserIdentity userIdentity) {
+        DbPrivTable table = new DbPrivTable();
+        Set<String> roles = userRoleManager.getRolesByUser(userIdentity);
+        for (String roleName : roles) {
+            table.merge(roleManager.getRole(roleName).getDbPrivTable());
+        }
+        return table;
+    }
+
+    private TablePrivTable getUserTblPrivTable(UserIdentity userIdentity) {
+        TablePrivTable table = new TablePrivTable();
+        Set<String> roles = userRoleManager.getRolesByUser(userIdentity);
+        for (String roleName : roles) {
+            table.merge(roleManager.getRole(roleName).getTablePrivTable());
+        }
+        return table;
+    }
+
+    private ResourcePrivTable getUserResourcePrivTable(UserIdentity userIdentity) {
+        ResourcePrivTable table = new ResourcePrivTable();
+        Set<String> roles = userRoleManager.getRolesByUser(userIdentity);
+        for (String roleName : roles) {
+            table.merge(roleManager.getRole(roleName).getResourcePrivTable());
+        }
+        return table;
+    }
+
+    public List<List<String>> getUserProperties(String qualifiedUser) {
+        readLock();
+        try {
+            return propertyMgr.fetchUserProperty(qualifiedUser);
+        } catch (AnalysisException e) {
+            return Lists.newArrayList();
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public void dropUserOfCluster(String clusterName, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+            for (List<User> users : nameToUsers.values()) {
+                for (User user : users) {
+                    if (user.getUserIdentity().getQualifiedUser().startsWith(clusterName)) {
+                        dropUserInternal(user.getUserIdentity(), false, isReplay);
+                    }
+                }
+            }
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    public Pair<String, DppConfig> getLoadClusterInfo(String qualifiedUser, String cluster) throws DdlException {
+        readLock();
+        try {
+            return propertyMgr.getLoadClusterInfo(qualifiedUser, cluster);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // user can enter a cluster, if it has any privs of database or table in this cluster.
+    public boolean checkCanEnterCluster(ConnectContext ctx, String clusterName) {
+        readLock();
+        try {
+            Set<String> roles = userRoleManager.getRolesByUser(ctx.getCurrentUserIdentity());
+            for (String roleName : roles) {
+                if (roleManager.getRole(roleName).checkCanEnterCluster(clusterName)) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    private void initUser() {
+        try {
+            UserIdentity rootUser = new UserIdentity(ROOT_USER, "%");
+            rootUser.setIsAnalyzed();
+            createUserInternal(rootUser, Role.OPERATOR_ROLE, new byte[0],
+                    false /* ignore if exists */, PasswordOptions.UNSET_OPTION, true /* is replay */);
+            UserIdentity adminUser = new UserIdentity(ADMIN_USER, "%");
+            adminUser.setIsAnalyzed();
+            createUserInternal(adminUser, Role.ADMIN_ROLE, new byte[0],
+                    false /* ignore if exists */, PasswordOptions.UNSET_OPTION, true /* is replay */);
+        } catch (DdlException e) {
+            LOG.error("should not happened", e);
+        }
+    }
+
+    public TFetchResourceResult toResourceThrift() {
+        readLock();
+        try {
+            return propertyMgr.toResourceThrift();
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public List<List<String>> getRoleInfo() {
+        readLock();
+        try {
+            List<List<String>> results = Lists.newArrayList();
+            roleManager.getRoleInfo(results);
+            return results;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // Used for creating table_privileges table in information_schema.
+    public void getTablePrivStatus(List<TPrivilegeStatus> tblPrivResult, UserIdentity currentUser) {
+        readLock();
+        try {
+            Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+            for (List<User> users : nameToUsers.values()) {
+                for (User user : users) {
+                    if (!user.isSetByDomainResolver()) {
+                        TablePrivTable tablePrivTable = getUserTblPrivTable(user.getUserIdentity());
+                        if (tablePrivTable.isEmpty()) {
+                            continue;
+                        }
+                        for (PrivEntry entry : tablePrivTable.getEntries()) {
+                            TablePrivEntry tablePrivEntry = (TablePrivEntry) entry;
+                            String dbName = ClusterNamespace.getNameFromFullName(tablePrivEntry.getOrigDb());
+                            String tblName = tablePrivEntry.getOrigTbl();
+                            // Don't show privileges in information_schema
+                            if (InfoSchemaDb.DATABASE_NAME.equals(dbName)
+                                    || !checkTblPriv(currentUser, tablePrivEntry.getOrigDb(), tblName,
+                                    PrivPredicate.SHOW)) {
+                                continue;
+                            }
+
+                            String grantee = new String("\'")
+                                    .concat(ClusterNamespace
+                                            .getNameFromFullName(user.getUserIdentity().getQualifiedUser()))
+                                    .concat("\'@\'").concat(user.getUserIdentity().getHost()).concat("\'");
+                            String isGrantable = tablePrivEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
+                            for (Privilege paloPriv : tablePrivEntry.getPrivSet().toPrivilegeList()) {
+                                if (!Privilege.privInDorisToMysql.containsKey(paloPriv)) {
+                                    continue;
+                                }
+                                TPrivilegeStatus status = new TPrivilegeStatus();
+                                status.setTableName(tblName);
+                                status.setPrivilegeType(Privilege.privInDorisToMysql.get(paloPriv));
+                                status.setGrantee(grantee);
+                                status.setSchema(dbName);
+                                status.setIsGrantable(isGrantable);
+                                tblPrivResult.add(status);
+                            }
+                        }
+
+                    }
+                }
+            }
+
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // Used for creating schema_privileges table in information_schema.
+    public void getSchemaPrivStatus(List<TPrivilegeStatus> dbPrivResult, UserIdentity currentUser) {
+        readLock();
+        try {
+            Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+            for (List<User> users : nameToUsers.values()) {
+                for (User user : users) {
+                    if (!user.isSetByDomainResolver()) {
+                        DbPrivTable dbPrivTable = getUserDbPrivTable(user.getUserIdentity());
+                        if (dbPrivTable.isEmpty()) {
+                            continue;
+                        }
+                        for (PrivEntry entry : dbPrivTable.getEntries()) {
+                            DbPrivEntry dbPrivEntry = (DbPrivEntry) entry;
+                            String origDb = dbPrivEntry.getOrigDb();
+                            String dbName = ClusterNamespace.getNameFromFullName(dbPrivEntry.getOrigDb());
+                            // Don't show privileges in information_schema
+                            if (InfoSchemaDb.DATABASE_NAME.equals(dbName)
+                                    || !checkDbPriv(currentUser, origDb, PrivPredicate.SHOW)) {
+                                continue;
+                            }
+
+                            String grantee = new String("\'")
+                                    .concat(ClusterNamespace
+                                            .getNameFromFullName(user.getUserIdentity().getQualifiedUser()))
+                                    .concat("\'@\'").concat(user.getUserIdentity().getHost()).concat("\'");
+                            String isGrantable = dbPrivEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
+                            for (Privilege paloPriv : dbPrivEntry.getPrivSet().toPrivilegeList()) {
+                                if (!Privilege.privInDorisToMysql.containsKey(paloPriv)) {
+                                    continue;
+                                }
+                                TPrivilegeStatus status = new TPrivilegeStatus();
+                                status.setPrivilegeType(Privilege.privInDorisToMysql.get(paloPriv));
+                                status.setGrantee(grantee);
+                                status.setSchema(dbName);
+                                status.setIsGrantable(isGrantable);
+                                dbPrivResult.add(status);
+                            }
+                        }
+
+                    }
+                }
+            }
+
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // Used for creating user_privileges table in information_schema.
+    public void getGlobalPrivStatus(List<TPrivilegeStatus> userPrivResult, UserIdentity currentUser) {
+        readLock();
+        try {
+            if (!checkGlobalPriv(currentUser, PrivPredicate.SHOW)) {
+                return;
+            }
+            Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+            for (List<User> users : nameToUsers.values()) {
+                for (User user : users) {
+                    if (!user.isSetByDomainResolver()) {
+                        GlobalPrivTable userGlobalPrivTable = getUserGlobalPrivTable(user.getUserIdentity());
+                        if (userGlobalPrivTable.isEmpty()) {
+                            continue;
+                        }
+                        PrivEntry privEntry = userGlobalPrivTable.entries.get(0);
+                        if (privEntry.getPrivSet().isEmpty()) {
+                            continue;
+                        }
+                        String grantee = new String("\'")
+                                .concat(ClusterNamespace.getNameFromFullName(user.getUserIdentity().getQualifiedUser()))
+                                .concat("\'@\'").concat(user.getUserIdentity().getHost()).concat("\'");
+                        String isGrantable = privEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
+                        for (Privilege paloPriv : privEntry.getPrivSet().toPrivilegeList()) {
+                            if (paloPriv == Privilege.ADMIN_PRIV) {
+                                // ADMIN_PRIV includes all privileges of table and resource.
+                                for (String priv : Privilege.privInDorisToMysql.values()) {
+                                    TPrivilegeStatus status = new TPrivilegeStatus();
+                                    status.setPrivilegeType(priv);
+                                    status.setGrantee(grantee);
+                                    status.setIsGrantable("YES");
+                                    userPrivResult.add(status);
+                                }
+                                break;
+                            }
+                            if (!Privilege.privInDorisToMysql.containsKey(paloPriv)) {
+                                continue;
+                            }
+                            TPrivilegeStatus status = new TPrivilegeStatus();
+                            status.setPrivilegeType(Privilege.privInDorisToMysql.get(paloPriv));
+                            status.setGrantee(grantee);
+                            status.setIsGrantable(isGrantable);
+                            userPrivResult.add(status);
+                        }
+                    }
+                }
+            }
+        } finally {
+            readUnlock();
+        }
+    }
+
+    public List<List<String>> getPasswdPolicyInfo(UserIdentity userIdent) {
+        return passwdPolicyManager.getPolicyInfo(userIdent);
+    }
+
+    public void alterUser(AlterUserStmt stmt) throws DdlException {
+        alterUserInternal(stmt.isIfExist(), stmt.getOpType(), stmt.getUserIdent(), stmt.getPassword(), stmt.getRole(),
+                stmt.getPasswordOptions(), false);
+    }
+
+    public void replayAlterUser(AlterUserOperationLog log) {
+        try {
+            alterUserInternal(true, log.getOp(), log.getUserIdent(), log.getPassword(), log.getRole(),
+                    log.getPasswordOptions(), true);
+        } catch (DdlException e) {
+            LOG.error("should not happen", e);
+        }
+    }
+
+    private void alterUserInternal(boolean ifExists, OpType opType, UserIdentity userIdent, byte[] password,
+            String role, PasswordOptions passwordOptions, boolean isReplay) throws DdlException {
+        writeLock();
+        try {
+            if (!doesUserExist(userIdent)) {
+                if (ifExists) {
+                    return;
+                }
+                throw new DdlException("User " + userIdent + " does not exist");
+            }
+            switch (opType) {
+                case SET_PASSWORD:
+                    setPasswordInternal(userIdent, password, null, false, false, isReplay);
+                    break;
+                case SET_ROLE:
+                    setRoleToUser(userIdent, role);
+                    break;
+                case SET_PASSWORD_POLICY:
+                    passwdPolicyManager.updatePolicy(userIdent, null, passwordOptions);
+                    break;
+                case UNLOCK_ACCOUNT:
+                    passwdPolicyManager.unlockUser(userIdent);
+                    break;
+                default:
+                    throw new DdlException("Unknown alter user operation type: " + opType.name());
+            }
+            if (opType != OpType.SET_PASSWORD && !isReplay) {
+                // For SET_PASSWORD:
+                //      the edit log is wrote in "setPasswordInternal"
+                AlterUserOperationLog log = new AlterUserOperationLog(opType, userIdent, password, role,
+                        passwordOptions);
+                Env.getCurrentEnv().getEditLog().logAlterUser(log);
+            }
+        } finally {
+            writeUnlock();
+        }
+    }
+
+
+    //tmp for current user can only has one role
+    private void setRoleToUser(UserIdentity userIdent, String role) throws DdlException {
+        // 1. check if role exist
+        Role newRole = roleManager.getRole(role);
+        if (newRole == null) {
+            throw new DdlException("Role " + role + " does not exist");
+        }
+        userRoleManager.dropUser(userIdent);
+        userRoleManager.addUserRole(userIdent, role);
+        userRoleManager.addUserRole(userIdent, roleManager.getUserDefaultRoleName(userIdent));
+    }
+
+    public static Auth read(DataInput in) throws IOException {
+        Auth auth = new Auth();
+        auth.readFields(in);
+        return auth;
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        // role manager must be first, because role should be exist before any user
+        roleManager.write(out);
+        userManager.write(out);
+        userRoleManager.write(out);
+        propertyMgr.write(out);
+        ldapInfo.write(out);
+        passwdPolicyManager.write(out);
+    }
+
+    public void readFields(DataInput in) throws IOException {
+        roleManager = RoleManager.read(in);
+        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_116) {
+            userManager = UserManager.read(in);
+            userRoleManager = UserRoleManager.read(in);
+            propertyMgr = UserPropertyMgr.read(in);
+        } else {
+            // new Auth will fill userManager,roleManager,and userRoleManager,roleManager will be reset when read,
+            // so we need reset userManager and userRoleManager to avoid data inconsistency
+            userManager = new UserManager();
+            userRoleManager = new UserRoleManager();
+            UserPrivTable userPrivTable = (UserPrivTable) PrivTable.read(in);
+            CatalogPrivTable catalogPrivTable;
+            if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_111) {
+                catalogPrivTable = (CatalogPrivTable) PrivTable.read(in);
+            } else {
+                catalogPrivTable = userPrivTable.degradeToInternalCatalogPriv();
+                LOG.info("Load PaloAuth from meta version < {}, degrade UserPrivTable to CatalogPrivTable",
+                        FeMetaVersion.VERSION_111);
+            }
+            DbPrivTable dbPrivTable = (DbPrivTable) PrivTable.read(in);
+            TablePrivTable tablePrivTable = (TablePrivTable) PrivTable.read(in);
+            ResourcePrivTable resourcePrivTable = (ResourcePrivTable) PrivTable.read(in);
+            propertyMgr = UserPropertyMgr.read(in);
+            try {
+                upgradeToVersion116(userPrivTable, catalogPrivTable, dbPrivTable, tablePrivTable, resourcePrivTable);
+            } catch (Exception e) {
+                // will not generate exception
+                LOG.warn("upgrade failed,", e);
+            }
+        }
+        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_106) {
+            ldapInfo = LdapInfo.read(in);
+        }
+
+        if (userManager.getNameToUsers().isEmpty()) {
+            // init root and admin user
+            initUser();
+        }
+        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_113) {
+            passwdPolicyManager = PasswordPolicyManager.read(in);
+        } else {
+            passwdPolicyManager = new PasswordPolicyManager();
+        }
+    }
+
+    private void upgradeToVersion116(UserPrivTable userPrivTable, CatalogPrivTable catalogPrivTable,
+            DbPrivTable dbPrivTable, TablePrivTable tablePrivTable, ResourcePrivTable resourcePrivTable)
+            throws AnalysisException, DdlException, PatternMatcherException {
+        //OPERATOR and Admin role not save users,if not inituser,root will do not have admin role
+        initUser();
+        for (Entry<String, UserProperty> entry : propertyMgr.propertyMap.entrySet()) {
+            for (Entry<String, byte[]> userEntry : entry.getValue().getWhiteList().getPasswordMap().entrySet()) {
+                //create user
+                User user = userManager
+                        .createUser(UserIdentity.createAnalyzedUserIdentWithDomain(entry.getKey(), userEntry.getKey()),
+                                userEntry.getValue(), null, false);
+                //create default role
+                Role defaultRole = roleManager.createDefaultRole(user.getUserIdentity());
+                userRoleManager
+                        .addUserRole(user.getUserIdentity(), defaultRole.getRoleName());
+            }
+        }
+        List<PrivEntry> userPrivTableEntries = userPrivTable.getEntries();
+        for (PrivEntry privEntry : userPrivTableEntries) {
+            GlobalPrivEntry globalPrivEntry = (GlobalPrivEntry) privEntry;
+            //may repeat with created user from propertyMgr,but no influence
+            User user = userManager
+                    .createUser(globalPrivEntry.userIdentity, globalPrivEntry.password, globalPrivEntry.domainUserIdent,
+                            globalPrivEntry.isSetByDomainResolver);
+            //create default role
+            Role defaultRole = roleManager.createDefaultRole(user.getUserIdentity());
+            userRoleManager
+                    .addUserRole(user.getUserIdentity(), defaultRole.getRoleName());
+            if (globalPrivEntry.privSet.isEmpty()) {
+                continue;
+            }
+            //grant global auth
+            if (globalPrivEntry.privSet.containsResourcePriv()) {
+                roleManager.addOrMergeRole(new Role(roleManager.getUserDefaultRoleName(user.getUserIdentity()),
+                        ResourcePattern.ALL, PrivBitSet.of(Privilege.USAGE_PRIV)), false);
+            }
+            PrivBitSet copy = globalPrivEntry.privSet.copy();
+            copy.unset(Privilege.USAGE_PRIV.getIdx());
+            if (!copy.isEmpty()) {
+                roleManager.addOrMergeRole(new Role(roleManager.getUserDefaultRoleName(user.getUserIdentity()),
+                        TablePattern.ALL, copy), false);
+            }
+        }
+
+        Map<String, Role> roles = roleManager.getRoles();
+        for (Role role : roles.values()) {
+            Set<UserIdentity> users = role.getUsers();
+            for (UserIdentity userIdentity : users) {
+                userRoleManager.addUserRole(userIdentity, role.getRoleName());
+            }
+        }
+
+        List<PrivEntry> catalogPrivTableEntries = catalogPrivTable.getEntries();
+        for (PrivEntry privEntry : catalogPrivTableEntries) {
+            CatalogPrivEntry catalogPrivEntry = (CatalogPrivEntry) privEntry;
+            TablePattern tablePattern = new TablePattern(ClusterNamespace.getNameFromFullName(catalogPrivEntry.origCtl),
+                    "*", "*");
+            String clusterName = ClusterNamespace.getClusterNameFromFullName(catalogPrivEntry.origCtl);
+            tablePattern.analyze(clusterName == null ? SystemInfoService.DEFAULT_CLUSTER : clusterName);
+            Role newRole = new Role(roleManager.getUserDefaultRoleName(catalogPrivEntry.userIdentity),
+                    tablePattern, catalogPrivEntry.privSet);
+            roleManager.addOrMergeRole(newRole, false);
+        }
+
+        List<PrivEntry> dbPrivTableEntries = dbPrivTable.getEntries();
+        for (PrivEntry privEntry : dbPrivTableEntries) {
+            DbPrivEntry dbPrivEntry = (DbPrivEntry) privEntry;
+            TablePattern tablePattern = new TablePattern(ClusterNamespace.getNameFromFullName(dbPrivEntry.origCtl),
+                    ClusterNamespace.getNameFromFullName(dbPrivEntry.origDb), "*");
+            String clusterName = ClusterNamespace.getClusterNameFromFullName(dbPrivEntry.origCtl);
+            tablePattern.analyze(clusterName == null ? SystemInfoService.DEFAULT_CLUSTER : clusterName);
+            Role newRole = new Role(roleManager.getUserDefaultRoleName(dbPrivEntry.userIdentity),
+                    tablePattern, dbPrivEntry.privSet);
+            roleManager.addOrMergeRole(newRole, false);
+        }
+
+        List<PrivEntry> tblPrivTableEntries = tablePrivTable.getEntries();
+        for (PrivEntry privEntry : tblPrivTableEntries) {
+            TablePrivEntry tblPrivEntry = (TablePrivEntry) privEntry;
+            TablePattern tablePattern = new TablePattern(ClusterNamespace.getNameFromFullName(tblPrivEntry.origCtl),
+                    ClusterNamespace.getNameFromFullName(tblPrivEntry.origDb),
+                    ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigTbl()));
+            String clusterName = ClusterNamespace.getClusterNameFromFullName(tblPrivEntry.origCtl);
+            tablePattern.analyze(clusterName == null ? SystemInfoService.DEFAULT_CLUSTER : clusterName);
+            Role newRole = new Role(roleManager.getUserDefaultRoleName(tblPrivEntry.userIdentity),
+                    tablePattern, tblPrivEntry.privSet);
+            roleManager.addOrMergeRole(newRole, false);
+        }
+
+        List<PrivEntry> resourcePrivTableEntries = resourcePrivTable.getEntries();
+        for (PrivEntry privEntry : resourcePrivTableEntries) {
+            ResourcePrivEntry resourcePrivEntry = (ResourcePrivEntry) privEntry;
+            ResourcePattern resourcePattern = new ResourcePattern(
+                    ClusterNamespace.getNameFromFullName(resourcePrivEntry.origResource));
+            resourcePattern.analyze();
+            Role newRole = new Role(roleManager.getUserDefaultRoleName(resourcePrivEntry.userIdentity),
+                    resourcePattern, resourcePrivEntry.privSet);
+            roleManager.addOrMergeRole(newRole, false);
+        }
+
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(userManager).append("\n");
+        sb.append(userRoleManager).append("\n");
+        sb.append(roleManager).append("\n");
+        sb.append(propertyMgr).append("\n");
+        sb.append(ldapInfo).append("\n");
+        return sb.toString();
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivEntry.java
index 95ba647c89..97fde3ae5d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivEntry.java
@@ -27,7 +27,6 @@ import org.apache.doris.common.io.Text;
 import org.apache.doris.datasource.InternalCatalog;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 
 public class CatalogPrivEntry extends PrivEntry {
@@ -40,10 +39,22 @@ public class CatalogPrivEntry extends PrivEntry {
     protected CatalogPrivEntry() {
     }
 
+    protected CatalogPrivEntry(
+            PatternMatcher ctlPattern, String origCtl,
+            PrivBitSet privSet) {
+        super(privSet);
+        this.ctlPattern = ctlPattern;
+        this.origCtl = origCtl;
+        if (origCtl.equals(ANY_CTL)) {
+            isAnyCtl = true;
+        }
+    }
+
+    @Deprecated
     protected CatalogPrivEntry(PatternMatcher userPattern, String user,
-                               PatternMatcher hostPattern, String origHost,
-                               PatternMatcher ctlPattern, String origCtl,
-                               boolean isDomain, PrivBitSet privSet) {
+            PatternMatcher hostPattern, String origHost,
+            PatternMatcher ctlPattern, String origCtl,
+            boolean isDomain, PrivBitSet privSet) {
         super(hostPattern, origHost, userPattern, user, isDomain, privSet);
         this.ctlPattern = ctlPattern;
         this.origCtl = origCtl;
@@ -52,6 +63,18 @@ public class CatalogPrivEntry extends PrivEntry {
         }
     }
 
+    public static CatalogPrivEntry create(String ctl, PrivBitSet privs)
+            throws AnalysisException {
+        PatternMatcher ctlPattern = createCtlPatternMatcher(ctl);
+
+        if (privs.containsNodePriv() || privs.containsResourcePriv()) {
+            throw new AnalysisException("Catalog privilege can not contains node or resource privileges: " + privs);
+        }
+
+        return new CatalogPrivEntry(ctlPattern, ctl, privs);
+    }
+
+    @Deprecated
     public static CatalogPrivEntry create(String user, String host, String ctl, boolean isDomain, PrivBitSet privs)
             throws AnalysisException {
         PatternMatcher hostPattern = PatternMatcherWrapper.createMysqlPattern(host,
@@ -92,9 +115,7 @@ public class CatalogPrivEntry extends PrivEntry {
         }
 
         CatalogPrivEntry otherEntry = (CatalogPrivEntry) other;
-        return compareAssist(origUser, otherEntry.origUser,
-                             origHost, otherEntry.origHost,
-                             origCtl, otherEntry.origCtl);
+        return compareAssist(origCtl, otherEntry.origCtl);
     }
 
     @Override
@@ -102,30 +123,17 @@ public class CatalogPrivEntry extends PrivEntry {
         if (!(other instanceof CatalogPrivEntry)) {
             return false;
         }
-
         CatalogPrivEntry otherEntry = (CatalogPrivEntry) other;
-        return origUser.equals(otherEntry.origUser) && origHost.equals(otherEntry.origHost)
-                && origCtl.equals(otherEntry.origCtl) && isDomain == otherEntry.isDomain;
+        return origCtl.equals(otherEntry.origCtl);
     }
 
     @Override
     public String toString() {
-        return String.format("catalog privilege. user: %s, host: %s, ctl: %s, priv: %s, set by resolver: %b",
-                origUser, origHost, origCtl, privSet.toString(), isSetByDomainResolver);
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = CatalogPrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        super.write(out);
-        Text.writeString(out, origCtl);
-        isClassNameWrote = false;
+        return String.format("catalog privilege. ctl: %s, priv: %s",
+                origCtl, privSet.toString());
     }
 
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivTable.java
index a1febfbf37..15995a20ed 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/CatalogPrivTable.java
@@ -17,15 +17,9 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.io.Text;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
 /*
  * CatalogPrivTable saves all catalog level privs
  */
@@ -36,21 +30,17 @@ public class CatalogPrivTable extends PrivTable {
      * Return first priv which match the user@host on ctl.* The returned priv will be
      * saved in 'savedPrivs'.
      */
-    public void getPrivs(UserIdentity currentUser, String ctl, PrivBitSet savedPrivs) {
+    public void getPrivs(String ctl, PrivBitSet savedPrivs) {
         CatalogPrivEntry matchedEntry = null;
         for (PrivEntry entry : entries) {
-            CatalogPrivEntry dsPrivEntry = (CatalogPrivEntry) entry;
-
-            if (!dsPrivEntry.match(currentUser, true)) {
-                continue;
-            }
+            CatalogPrivEntry ctlPrivEntry = (CatalogPrivEntry) entry;
 
             // check catalog
-            if (!dsPrivEntry.isAnyCtl() && !dsPrivEntry.getCtlPattern().match(ctl)) {
+            if (!ctlPrivEntry.isAnyCtl() && !ctlPrivEntry.getCtlPattern().match(ctl)) {
                 continue;
             }
 
-            matchedEntry = dsPrivEntry;
+            matchedEntry = ctlPrivEntry;
             break;
         }
         if (matchedEntry == null) {
@@ -59,15 +49,4 @@ public class CatalogPrivTable extends PrivTable {
 
         savedPrivs.or(matchedEntry.getPrivSet());
     }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = CatalogPrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        super.write(out);
-    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
index b66792a739..a08fb70cdd 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
@@ -22,11 +22,9 @@ import org.apache.doris.cluster.ClusterNamespace;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.CaseSensibility;
 import org.apache.doris.common.PatternMatcher;
-import org.apache.doris.common.PatternMatcherWrapper;
 import org.apache.doris.common.io.Text;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 
 public class DbPrivEntry extends CatalogPrivEntry {
@@ -39,12 +37,11 @@ public class DbPrivEntry extends CatalogPrivEntry {
     protected DbPrivEntry() {
     }
 
-    protected DbPrivEntry(PatternMatcher userPattern, String user,
-                          PatternMatcher hostPattern, String origHost,
-                          PatternMatcher ctlPattern, String origCtl,
-                          PatternMatcher dbPattern, String origDb,
-                          boolean isDomain, PrivBitSet privSet) {
-        super(userPattern, user, hostPattern, origHost, ctlPattern, origCtl, isDomain, privSet);
+    protected DbPrivEntry(
+            PatternMatcher ctlPattern, String origCtl,
+            PatternMatcher dbPattern, String origDb,
+            PrivBitSet privSet) {
+        super(ctlPattern, origCtl, privSet);
         this.dbPattern = dbPattern;
         this.origDb = origDb;
         if (origDb.equals(ANY_DB)) {
@@ -53,24 +50,17 @@ public class DbPrivEntry extends CatalogPrivEntry {
     }
 
     public static DbPrivEntry create(
-            String user, String host,
-            String ctl, String db,
-            boolean isDomain, PrivBitSet privs) throws AnalysisException {
-        PatternMatcher hostPattern = PatternMatcherWrapper.createMysqlPattern(host,
-                CaseSensibility.HOST.getCaseSensibility());
-
+            String ctl, String db, PrivBitSet privs) throws AnalysisException {
         PatternMatcher ctlPattern = PatternMatcher.createFlatPattern(
                 ctl, CaseSensibility.CATALOG.getCaseSensibility(), ctl.equals(ANY_CTL));
 
         PatternMatcher dbPattern = createDbPatternMatcher(db);
 
-        PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
-
         if (privs.containsNodePriv() || privs.containsResourcePriv()) {
             throw new AnalysisException("Db privilege can not contains global or resource privileges: " + privs);
         }
 
-        return new DbPrivEntry(userPattern, user, hostPattern, host, ctlPattern, ctl, dbPattern, db, isDomain, privs);
+        return new DbPrivEntry(ctlPattern, ctl, dbPattern, db, privs);
     }
 
     private static PatternMatcher createDbPatternMatcher(String db) throws AnalysisException {
@@ -102,10 +92,9 @@ public class DbPrivEntry extends CatalogPrivEntry {
         }
 
         DbPrivEntry otherEntry = (DbPrivEntry) other;
-        return compareAssist(origUser, otherEntry.origUser,
-                             origHost, otherEntry.origHost,
-                             origCtl, otherEntry.origCtl,
-                             origDb, otherEntry.origDb);
+        return compareAssist(
+                origCtl, otherEntry.origCtl,
+                origDb, otherEntry.origDb);
     }
 
     @Override
@@ -115,29 +104,16 @@ public class DbPrivEntry extends CatalogPrivEntry {
         }
 
         DbPrivEntry otherEntry = (DbPrivEntry) other;
-        return origUser.equals(otherEntry.origUser) && origHost.equals(otherEntry.origHost)
-                && origCtl.equals(otherEntry.origCtl) && origDb.equals(otherEntry.origDb)
-                && isDomain == otherEntry.isDomain;
+        return origCtl.equals(otherEntry.origCtl) && origDb.equals(otherEntry.origDb);
     }
 
     @Override
     public String toString() {
-        return String.format("database privilege. user: %s, host: %s, ctl: %s, db: %s, priv: %s, set by resolver: %b",
-                origUser, origHost, origCtl, origDb, privSet.toString(), isSetByDomainResolver);
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = DbPrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        super.write(out);
-        Text.writeString(out, origDb);
-        isClassNameWrote = false;
+        return String.format("database privilege.ctl: %s, db: %s, priv: %s",
+                origCtl, origDb, privSet.toString());
     }
 
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java
index 961cd1cb8c..8c9daa6abe 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivTable.java
@@ -17,17 +17,10 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.io.Text;
-import org.apache.doris.qe.ConnectContext;
-
 import com.google.common.base.Preconditions;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
 /*
  * DbPrivTable saves all database level privs
  */
@@ -38,15 +31,11 @@ public class DbPrivTable extends PrivTable {
      * Return first priv which match the user@host on ctl.db.* The returned priv will be
      * saved in 'savedPrivs'.
      */
-    public void getPrivs(UserIdentity currentUser, String ctl, String db, PrivBitSet savedPrivs) {
+    public void getPrivs(String ctl, String db, PrivBitSet savedPrivs) {
         DbPrivEntry matchedEntry = null;
         for (PrivEntry entry : entries) {
             DbPrivEntry dbPrivEntry = (DbPrivEntry) entry;
 
-            if (!dbPrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
             // check catalog
             if (!dbPrivEntry.isAnyCtl() && !dbPrivEntry.getCtlPattern().match(ctl)) {
                 continue;
@@ -67,14 +56,10 @@ public class DbPrivTable extends PrivTable {
         savedPrivs.or(matchedEntry.getPrivSet());
     }
 
-    public boolean hasPrivsOfCatalog(UserIdentity currentUser, String ctl) {
+    public boolean hasPrivsOfCatalog(String ctl) {
         for (PrivEntry entry : entries) {
             DbPrivEntry dbPrivEntry = (DbPrivEntry) entry;
 
-            if (!dbPrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
             // check catalog
             Preconditions.checkState(!dbPrivEntry.isAnyCtl());
             if (dbPrivEntry.getCtlPattern().match(ctl)) {
@@ -84,7 +69,7 @@ public class DbPrivTable extends PrivTable {
         return false;
     }
 
-    public boolean hasClusterPriv(ConnectContext ctx, String clusterName) {
+    public boolean hasClusterPriv(String clusterName) {
         for (PrivEntry entry : entries) {
             DbPrivEntry dbPrivEntry = (DbPrivEntry) entry;
             if (dbPrivEntry.getOrigDb().startsWith(clusterName)) {
@@ -93,15 +78,4 @@ public class DbPrivTable extends PrivTable {
         }
         return false;
     }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = DbPrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        super.write(out);
-    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
index 163cc5a7a6..5281acb86a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
@@ -18,105 +18,39 @@
 package org.apache.doris.mysql.privilege;
 
 import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.CaseSensibility;
-import org.apache.doris.common.PatternMatcher;
-import org.apache.doris.common.PatternMatcherWrapper;
-import org.apache.doris.common.io.Text;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 
 public class GlobalPrivEntry extends PrivEntry {
     private static final Logger LOG = LogManager.getLogger(GlobalPrivEntry.class);
 
-    private byte[] password;
-    // set domainUserIdent when this a password entry and is set by domain resolver.
-    // so that when user checking password with user@'IP' and match a entry set by the resolver,
-    // it should return this domainUserIdent as "current user". And user can use this user ident to get privileges
-    // further.
-    private UserIdentity domainUserIdent;
+    @Deprecated
+    protected byte[] password;
+    @Deprecated
+    protected UserIdentity domainUserIdent;
 
     protected GlobalPrivEntry() {
     }
 
-    protected GlobalPrivEntry(PatternMatcher hostPattern, String origHost,
-            PatternMatcher userPattern, String origUser, boolean isDomain,
-            byte[] password, PrivBitSet privSet) {
-        super(hostPattern, origHost, userPattern, origUser, isDomain, privSet);
-        this.password = password;
+    protected GlobalPrivEntry(PrivBitSet privSet) {
+        super(privSet);
     }
 
-    public static GlobalPrivEntry create(String host, String user, boolean isDomain, byte[] password, PrivBitSet privs)
-            throws AnalysisException {
-        PatternMatcher hostPattern = PatternMatcherWrapper.createMysqlPattern(host,
-                CaseSensibility.HOST.getCaseSensibility());
-        PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
-        return new GlobalPrivEntry(hostPattern, host, userPattern, user, isDomain, password, privs);
+    public static GlobalPrivEntry create(PrivBitSet privs) {
+        return new GlobalPrivEntry(privs);
     }
 
-    public byte[] getPassword() {
-        return password;
-    }
-
-    public void setPassword(byte[] password) {
-        this.password = password;
-    }
-
-    public void setDomainUserIdent(UserIdentity domainUserIdent) {
-        this.domainUserIdent = domainUserIdent;
-    }
-
-    public UserIdentity getDomainUserIdent() {
-        if (isSetByDomainResolver()) {
-            return domainUserIdent;
-        } else {
-            return getUserIdent();
-        }
-    }
-
-    /*
-     * UserTable is ordered by Host, User
-     * eg:
-     * +-----------+----------+-
-     * | Host      | User     | ...
-     * +-----------+----------+-
-     * | %         | root     | ...
-     * | %         | jeffrey  | ...
-     * | localhost | root     | ...
-     * | localhost |          | ...
-     * +-----------+----------+-
-     *
-     * will be sorted like:
-     *
-     * +-----------+----------+-
-     * | Host      | User     | ...
-     * +-----------+----------+-
-     * | localhost | root     | ...
-     * | localhost |          | ...
-     * | %         | jeffrey  | ...
-     * | %         | root     | ...
-     * +-----------+----------+-
-     *
-     * https://dev.mysql.com/doc/refman/8.0/en/connection-access.html
-     */
     @Override
     public int compareTo(PrivEntry other) {
         if (!(other instanceof GlobalPrivEntry)) {
             throw new ClassCastException("cannot cast " + other.getClass().toString() + " to " + this.getClass());
         }
 
-        GlobalPrivEntry otherEntry = (GlobalPrivEntry) other;
-        int res = origHost.compareTo(otherEntry.origHost);
-        if (res != 0) {
-            return -res;
-        }
-
-        return -origUser.compareTo(otherEntry.origUser);
+        return 0;
     }
 
     @Override
@@ -124,38 +58,12 @@ public class GlobalPrivEntry extends PrivEntry {
         if (!(other instanceof GlobalPrivEntry)) {
             return false;
         }
-
-        GlobalPrivEntry otherEntry = (GlobalPrivEntry) other;
-        if (origHost.equals(otherEntry.origHost) && origUser.equals(otherEntry.origUser)
-                && isDomain == otherEntry.isDomain) {
-            return true;
-        }
-        return false;
+        return true;
     }
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("global priv. host: ").append(origHost).append(", user: ").append(origUser);
-        sb.append(", priv: ").append(privSet).append(", set by resolver: ").append(isSetByDomainResolver);
-        sb.append(", domain user ident: ").append(domainUserIdent);
-        return sb.toString();
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = GlobalPrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        LOG.info("global priv: {}", this.toString());
-        super.write(out);
-
-        out.writeInt(password.length);
-        out.write(password);
-        isClassNameWrote = false;
+        return privSet.toString();
     }
 
     public void readFields(DataInput in) throws IOException {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivTable.java
new file mode 100644
index 0000000000..7dbbeaef76
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivTable.java
@@ -0,0 +1,44 @@
+// 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.mysql.privilege;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/*
+ * GlobalPrivTable saves all global privs and also password for users
+ */
+public class GlobalPrivTable extends PrivTable {
+    private static final Logger LOG = LogManager.getLogger(GlobalPrivTable.class);
+
+    public GlobalPrivTable() {
+    }
+
+    public void getPrivs(PrivBitSet savedPrivs) {
+        if (CollectionUtils.isEmpty(entries)) {
+            return;
+        }
+        // GlobalPrivTable saves global permissions.
+        // Unlike CatalogPrivTable, it needs to save an entry for each catalog,
+        // so the length of entries can only be 1 at most.
+        Preconditions.checkArgument(entries.size() == 1);
+        savedPrivs.or(entries.get(0).getPrivSet());
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java
deleted file mode 100644
index 4729c4552a..0000000000
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloAuth.java
+++ /dev/null
@@ -1,1993 +0,0 @@
-// 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.mysql.privilege;
-
-import org.apache.doris.analysis.AlterUserStmt;
-import org.apache.doris.analysis.AlterUserStmt.OpType;
-import org.apache.doris.analysis.CreateRoleStmt;
-import org.apache.doris.analysis.CreateUserStmt;
-import org.apache.doris.analysis.DropRoleStmt;
-import org.apache.doris.analysis.DropUserStmt;
-import org.apache.doris.analysis.GrantStmt;
-import org.apache.doris.analysis.PasswordOptions;
-import org.apache.doris.analysis.ResourcePattern;
-import org.apache.doris.analysis.RevokeStmt;
-import org.apache.doris.analysis.SetLdapPassVar;
-import org.apache.doris.analysis.SetPassVar;
-import org.apache.doris.analysis.SetUserPropertyStmt;
-import org.apache.doris.analysis.TableName;
-import org.apache.doris.analysis.TablePattern;
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.catalog.AuthorizationInfo;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.catalog.InfoSchemaDb;
-import org.apache.doris.cluster.ClusterNamespace;
-import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.AuthenticationException;
-import org.apache.doris.common.DdlException;
-import org.apache.doris.common.ErrorCode;
-import org.apache.doris.common.ErrorReport;
-import org.apache.doris.common.FeConstants;
-import org.apache.doris.common.FeMetaVersion;
-import org.apache.doris.common.LdapConfig;
-import org.apache.doris.common.Pair;
-import org.apache.doris.common.UserException;
-import org.apache.doris.common.io.Writable;
-import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.ldap.LdapManager;
-import org.apache.doris.ldap.LdapPrivsChecker;
-import org.apache.doris.load.DppConfig;
-import org.apache.doris.persist.AlterUserOperationLog;
-import org.apache.doris.persist.LdapInfo;
-import org.apache.doris.persist.PrivInfo;
-import org.apache.doris.qe.ConnectContext;
-import org.apache.doris.resource.Tag;
-import org.apache.doris.thrift.TFetchResourceResult;
-import org.apache.doris.thrift.TPrivilegeStatus;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.stream.Collectors;
-
-public class PaloAuth implements Writable {
-    private static final Logger LOG = LogManager.getLogger(PaloAuth.class);
-
-    // root user's role is operator.
-    // each Palo system has only one root user.
-    public static final String ROOT_USER = "root";
-    public static final String ADMIN_USER = "admin";
-    // unknown user does not have any privilege, this is just to be compatible with old version.
-    public static final String UNKNOWN_USER = "unknown";
-    private static final String DEFAULT_CATALOG = InternalCatalog.INTERNAL_CATALOG_NAME;
-
-    private UserPrivTable userPrivTable = new UserPrivTable();
-    private CatalogPrivTable catalogPrivTable = new CatalogPrivTable();
-    private DbPrivTable dbPrivTable = new DbPrivTable();
-    private TablePrivTable tablePrivTable = new TablePrivTable();
-    private ResourcePrivTable resourcePrivTable = new ResourcePrivTable();
-
-    private RoleManager roleManager = new RoleManager();
-    private UserPropertyMgr propertyMgr = new UserPropertyMgr();
-
-    private LdapInfo ldapInfo = new LdapInfo();
-
-    private LdapManager ldapManager = new LdapManager();
-
-    private PasswordPolicyManager passwdPolicyManager = new PasswordPolicyManager();
-
-    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-
-    private void readLock() {
-        lock.readLock().lock();
-    }
-
-    private void readUnlock() {
-        lock.readLock().unlock();
-    }
-
-    private void writeLock() {
-        lock.writeLock().lock();
-    }
-
-    private void writeUnlock() {
-        lock.writeLock().unlock();
-    }
-
-    public enum PrivLevel {
-        GLOBAL, CATALOG, DATABASE, TABLE, RESOURCE
-    }
-
-    public PaloAuth() {
-        initUser();
-    }
-
-    public UserPrivTable getUserPrivTable() {
-        return userPrivTable;
-    }
-
-    public DbPrivTable getDbPrivTable() {
-        return dbPrivTable;
-    }
-
-    public TablePrivTable getTablePrivTable() {
-        return tablePrivTable;
-    }
-
-    public LdapInfo getLdapInfo() {
-        return ldapInfo;
-    }
-
-    public void setLdapInfo(LdapInfo ldapInfo) {
-        this.ldapInfo = ldapInfo;
-    }
-
-    public LdapManager getLdapManager() {
-        return ldapManager;
-    }
-
-    public PasswordPolicyManager getPasswdPolicyManager() {
-        return passwdPolicyManager;
-    }
-
-    private GlobalPrivEntry grantGlobalPrivs(UserIdentity userIdentity, boolean errOnExist, boolean errOnNonExist,
-            PrivBitSet privs) throws DdlException {
-        if (errOnExist && errOnNonExist) {
-            throw new DdlException("Can only specified errOnExist or errOnNonExist");
-        }
-        GlobalPrivEntry entry;
-        try {
-            // password set here will not overwrite the password of existing entry, no need to worry.
-            entry = GlobalPrivEntry.create(userIdentity.getHost(), userIdentity.getQualifiedUser(),
-                    userIdentity.isDomain(), new byte[0] /* no use */, privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        userPrivTable.addEntry(entry, errOnExist, errOnNonExist);
-        return entry;
-    }
-
-    private void revokeGlobalPrivs(UserIdentity userIdentity, PrivBitSet privs, boolean errOnNonExist)
-            throws DdlException {
-        GlobalPrivEntry entry;
-        try {
-            entry = GlobalPrivEntry.create(userIdentity.getHost(), userIdentity.getQualifiedUser(),
-                    userIdentity.isDomain(), new byte[0] /* no use */, privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-
-        userPrivTable.revoke(entry, errOnNonExist,
-                false /* not delete entry if priv is empty, because global priv entry has password */);
-    }
-
-    private void grantCatalogPrivs(UserIdentity userIdentity, String ctl,
-            boolean errOnExist, boolean errOnNonExist, PrivBitSet privs) throws DdlException {
-        CatalogPrivEntry entry;
-        try {
-            entry = CatalogPrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        catalogPrivTable.addEntry(entry, errOnExist, errOnNonExist);
-    }
-
-    private void revokeCatalogPrivs(UserIdentity userIdentity, String ctl,
-            PrivBitSet privs, boolean errOnNonExist) throws DdlException {
-        CatalogPrivEntry entry;
-        try {
-            entry = CatalogPrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-
-        catalogPrivTable.revoke(entry, errOnNonExist, true /* delete entry when empty */);
-    }
-
-    private void grantDbPrivs(UserIdentity userIdentity, String ctl, String db,
-            boolean errOnExist, boolean errOnNonExist, PrivBitSet privs) throws DdlException {
-        DbPrivEntry entry;
-        try {
-            entry = DbPrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, db, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        dbPrivTable.addEntry(entry, errOnExist, errOnNonExist);
-    }
-
-    private void revokeDbPrivs(UserIdentity userIdentity, String ctl, String db,
-            PrivBitSet privs, boolean errOnNonExist) throws DdlException {
-        DbPrivEntry entry;
-        try {
-            entry = DbPrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, db, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-
-        dbPrivTable.revoke(entry, errOnNonExist, true /* delete entry when empty */);
-    }
-
-    private void grantTblPrivs(UserIdentity userIdentity, String ctl, String db, String tbl,
-            boolean errOnExist, boolean errOnNonExist, PrivBitSet privs) throws DdlException {
-        TablePrivEntry entry;
-        try {
-            entry = TablePrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, db, tbl, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        tablePrivTable.addEntry(entry, errOnExist, errOnNonExist);
-    }
-
-    private void revokeTblPrivs(UserIdentity userIdentity, String ctl, String db, String tbl,
-            PrivBitSet privs, boolean errOnNonExist) throws DdlException {
-        TablePrivEntry entry;
-        try {
-            entry = TablePrivEntry.create(userIdentity.getQualifiedUser(), userIdentity.getHost(),
-                    ctl, db, tbl, userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        tablePrivTable.revoke(entry, errOnNonExist, true /* delete entry when empty */);
-    }
-
-    private void grantResourcePrivs(UserIdentity userIdentity, String resourceName, boolean errOnExist,
-                                    boolean errOnNonExist, PrivBitSet privs) throws DdlException {
-        ResourcePrivEntry entry;
-        try {
-            entry = ResourcePrivEntry.create(userIdentity.getHost(), resourceName, userIdentity.getQualifiedUser(),
-                                             userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-        resourcePrivTable.addEntry(entry, errOnExist, errOnNonExist);
-    }
-
-    private void revokeResourcePrivs(UserIdentity userIdentity, String resourceName, PrivBitSet privs,
-                                     boolean errOnNonExist) throws DdlException {
-        ResourcePrivEntry entry;
-        try {
-            entry = ResourcePrivEntry.create(userIdentity.getHost(), resourceName, userIdentity.getQualifiedUser(),
-                                             userIdentity.isDomain(), privs);
-            entry.setSetByDomainResolver(false);
-        } catch (AnalysisException e) {
-            throw new DdlException(e.getMessage());
-        }
-
-        resourcePrivTable.revoke(entry, errOnNonExist, true /* delete entry when empty */);
-    }
-
-    public boolean doesRoleExist(String qualifiedRole) {
-        return roleManager.getRole(qualifiedRole) != null;
-    }
-
-    public void mergeRolesNoCheckName(List<String> roles, PaloRole savedRole) {
-        readLock();
-        try {
-            for (String roleName : roles) {
-                if (doesRoleExist(roleName)) {
-                    PaloRole role = roleManager.getRole(roleName);
-                    savedRole.mergeNotCheck(role);
-                }
-            }
-        } finally {
-            readUnlock();
-        }
-    }
-
-    /*
-     * check password, if matched, save the userIdentity in matched entry.
-     * the following auth checking should use userIdentity saved in currentUser.
-     */
-    public void checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString,
-            List<UserIdentity> currentUser) throws AuthenticationException {
-        if ((remoteUser.equals(ROOT_USER) || remoteUser.equals(ADMIN_USER)) && remoteHost.equals("127.0.0.1")) {
-            // root and admin user is allowed to login from 127.0.0.1, in case user forget password.
-            if (remoteUser.equals(ROOT_USER)) {
-                currentUser.add(UserIdentity.ROOT);
-            } else {
-                currentUser.add(UserIdentity.ADMIN);
-            }
-            return;
-        }
-
-        readLock();
-        try {
-            userPrivTable.checkPassword(remoteUser, remoteHost, remotePasswd, randomString, currentUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // For unit test only, wrapper of "void checkPlainPassword"
-    public boolean checkPlainPasswordForTest(String remoteUser, String remoteHost, String remotePasswd,
-            List<UserIdentity> currentUser) {
-        try {
-            checkPlainPassword(remoteUser, remoteHost, remotePasswd, currentUser);
-            return true;
-        } catch (AuthenticationException e) {
-            return false;
-        }
-    }
-
-    public void checkPlainPassword(String remoteUser, String remoteHost, String remotePasswd,
-            List<UserIdentity> currentUser) throws AuthenticationException {
-        // Check the LDAP password when the user exists in the LDAP service.
-        if (ldapManager.doesUserExist(remoteUser)) {
-            if (!ldapManager.checkUserPasswd(remoteUser, remotePasswd, remoteHost, currentUser)) {
-                throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
-                        Strings.isNullOrEmpty(remotePasswd) ? "NO" : "YES");
-            }
-            return;
-        }
-        readLock();
-        try {
-            userPrivTable.checkPlainPassword(remoteUser, remoteHost, remotePasswd, currentUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public boolean checkGlobalPriv(ConnectContext ctx, PrivPredicate wanted) {
-        return checkGlobalPriv(ctx.getCurrentUserIdentity(), wanted);
-    }
-
-    public boolean checkGlobalPriv(UserIdentity currentUser, PrivPredicate wanted) {
-        PrivBitSet savedPrivs = PrivBitSet.of();
-        if (checkGlobalInternal(currentUser, wanted, savedPrivs)) {
-            return true;
-        }
-
-        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
-        return false;
-    }
-
-    public boolean checkCtlPriv(ConnectContext ctx, String ctl, PrivPredicate wanted) {
-        return checkCtlPriv(ctx.getCurrentUserIdentity(), ctl, wanted);
-    }
-
-    public boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) {
-        if (wanted.getPrivs().containsNodePriv()) {
-            LOG.debug("should not check NODE priv in catalog level. user: {}, catalog: {}",
-                    currentUser, ctl);
-            return false;
-        }
-
-        PrivBitSet savedPrivs = PrivBitSet.of();
-        if (checkGlobalInternal(currentUser, wanted, savedPrivs)
-                || checkCatalogInternal(currentUser, ctl, wanted, savedPrivs)) {
-            return true;
-        }
-
-        // if user has any privs of databases or tables in this catalog, and the wanted priv is SHOW, return true
-        if (ctl != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinCatalog(currentUser, ctl)) {
-            return true;
-        }
-
-        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
-        return false;
-    }
-
-    public boolean checkDbPriv(ConnectContext ctx, String qualifiedDb, PrivPredicate wanted) {
-        return checkDbPriv(ctx.getCurrentUserIdentity(), qualifiedDb, wanted);
-    }
-
-    public boolean checkDbPriv(UserIdentity currentUser, String db, PrivPredicate wanted) {
-        return checkDbPriv(currentUser, DEFAULT_CATALOG, db, wanted);
-    }
-
-    public boolean checkDbPriv(ConnectContext ctx, String ctl, String db, PrivPredicate wanted) {
-        return checkDbPriv(ctx.getCurrentUserIdentity(), ctl, db, wanted);
-    }
-
-    /*
-     * Check if 'user'@'host' on 'db' has 'wanted' priv.
-     * If the given db is null, which means it will no check if database name is matched.
-     */
-    public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
-        if (wanted.getPrivs().containsNodePriv()) {
-            LOG.debug("should not check NODE priv in Database level. user: {}, db: {}",
-                    currentUser, db);
-            return false;
-        }
-
-        PrivBitSet savedPrivs = PrivBitSet.of();
-        if (checkGlobalInternal(currentUser, wanted, savedPrivs)
-                || checkCatalogInternal(currentUser, ctl, wanted, savedPrivs)
-                || checkDbInternal(currentUser, ctl, db, wanted, savedPrivs)) {
-            return true;
-        }
-
-        // if user has any privs of table in this db, and the wanted priv is SHOW, return true
-        if (ctl != null && db != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinDb(currentUser, ctl, db)) {
-            return true;
-        }
-
-        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
-        return false;
-    }
-
-    /*
-     * User may not have privs on a catalog, but have privs of databases or tables in this catalog.
-     * So we have to check if user has any privs of databases or tables in this catalog.
-     * if so, the catalog should be visible to this user.
-     */
-    private boolean checkAnyPrivWithinCatalog(UserIdentity currentUser, String ctl) {
-        readLock();
-        try {
-            return dbPrivTable.hasPrivsOfCatalog(currentUser, ctl)
-                    || tablePrivTable.hasPrivsOfCatalog(currentUser, ctl);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    /*
-     * User may not have privs on a database, but have privs of tables in this database.
-     * So we have to check if user has any privs of tables in this database.
-     * if so, the database should be visible to this user.
-     */
-    private boolean checkAnyPrivWithinDb(UserIdentity currentUser, String ctl, String db) {
-        readLock();
-        try {
-            return (isLdapAuthEnabled() && LdapPrivsChecker.hasPrivsOfDb(currentUser, db))
-                    || tablePrivTable.hasPrivsOfDb(currentUser, ctl, db);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public boolean checkTblPriv(ConnectContext ctx, String qualifiedCtl,
-                                String qualifiedDb, String tbl, PrivPredicate wanted) {
-        return checkTblPriv(ctx.getCurrentUserIdentity(), qualifiedCtl, qualifiedDb, tbl, wanted);
-    }
-
-    public boolean checkTblPriv(ConnectContext ctx, String qualifiedDb, String tbl, PrivPredicate wanted) {
-        return checkTblPriv(ctx, DEFAULT_CATALOG, qualifiedDb, tbl, wanted);
-    }
-
-    public boolean checkTblPriv(ConnectContext ctx, TableName tableName, PrivPredicate wanted) {
-        Preconditions.checkState(tableName.isFullyQualified());
-        return checkTblPriv(ctx, tableName.getDb(), tableName.getTbl(), wanted);
-    }
-
-    public boolean checkTblPriv(UserIdentity currentUser, String ctl, String db, String tbl, PrivPredicate wanted) {
-        if (wanted.getPrivs().containsNodePriv()) {
-            LOG.debug("should check NODE priv in GLOBAL level. user: {}, db: {}, tbl: {}", currentUser, db, tbl);
-            return false;
-        }
-
-        PrivBitSet savedPrivs = PrivBitSet.of();
-        if (checkGlobalInternal(currentUser, wanted, savedPrivs)
-                || checkCatalogInternal(currentUser, ctl, wanted, savedPrivs)
-                || checkDbInternal(currentUser, ctl, db, wanted, savedPrivs)
-                || checkTblInternal(currentUser, ctl, db, tbl, wanted, savedPrivs)) {
-            return true;
-        }
-
-        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
-        return false;
-    }
-
-    public boolean checkTblPriv(UserIdentity currentUser, String db, String tbl, PrivPredicate wanted) {
-        return checkTblPriv(currentUser, DEFAULT_CATALOG, db, tbl, wanted);
-    }
-
-    public boolean checkResourcePriv(ConnectContext ctx, String resourceName, PrivPredicate wanted) {
-        return checkResourcePriv(ctx.getCurrentUserIdentity(), resourceName, wanted);
-    }
-
-    public boolean checkResourcePriv(UserIdentity currentUser, String resourceName, PrivPredicate wanted) {
-        PrivBitSet savedPrivs = PrivBitSet.of();
-        if (checkGlobalInternal(currentUser, wanted, savedPrivs)
-                || checkResourceInternal(currentUser, resourceName, wanted, savedPrivs)) {
-            return true;
-        }
-
-        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
-        return false;
-    }
-
-    public boolean checkPrivByAuthInfo(ConnectContext ctx, AuthorizationInfo authInfo, PrivPredicate wanted) {
-        if (authInfo == null) {
-            return false;
-        }
-        if (authInfo.getDbName() == null) {
-            return false;
-        }
-        if (authInfo.getTableNameList() == null || authInfo.getTableNameList().isEmpty()) {
-            return checkDbPriv(ctx, authInfo.getDbName(), wanted);
-        }
-        for (String tblName : authInfo.getTableNameList()) {
-            if (!Env.getCurrentEnv().getAuth()
-                    .checkTblPriv(ConnectContext.get(), authInfo.getDbName(), tblName, wanted)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /*
-     * Check if current user has certain privilege.
-     * This method will check the given privilege levels
-     */
-    public boolean checkHasPriv(ConnectContext ctx, PrivPredicate priv, PrivLevel... levels) {
-        return checkHasPrivInternal(ctx.getCurrentUserIdentity(),
-                ctx.getRemoteIP(), ctx.getQualifiedUser(), priv, levels);
-    }
-
-    private boolean checkHasPrivInternal(UserIdentity currentUser, String host, String user, PrivPredicate priv,
-                                         PrivLevel... levels) {
-        for (PrivLevel privLevel : levels) {
-            switch (privLevel) {
-                case GLOBAL:
-                    if ((isLdapAuthEnabled() && LdapPrivsChecker.hasGlobalPrivFromLdap(currentUser, priv))
-                            || userPrivTable.hasPriv(host, user, priv)) {
-                        return true;
-                    }
-                    break;
-                case DATABASE:
-                    if ((isLdapAuthEnabled() && LdapPrivsChecker.hasDbPrivFromLdap(currentUser, priv))
-                            || dbPrivTable.hasPriv(host, user, priv)) {
-                        return true;
-                    }
-                    break;
-                case TABLE:
-                    if ((isLdapAuthEnabled() && LdapPrivsChecker.hasTblPrivFromLdap(currentUser, priv))
-                            || tablePrivTable.hasPriv(host, user, priv)) {
-                        return true;
-                    }
-                    break;
-                default:
-                    break;
-            }
-        }
-        return false;
-    }
-
-    private boolean checkGlobalInternal(UserIdentity currentUser, PrivPredicate wanted, PrivBitSet savedPrivs) {
-        if (isLdapAuthEnabled() && LdapPrivsChecker.hasGlobalPrivFromLdap(currentUser, wanted)) {
-            return true;
-        }
-
-        readLock();
-        try {
-            userPrivTable.getPrivs(currentUser, savedPrivs);
-            if (PaloPrivilege.satisfy(savedPrivs, wanted)) {
-                return true;
-            }
-            return false;
-        } finally {
-            readUnlock();
-        }
-    }
-
-    private boolean checkCatalogInternal(UserIdentity currentUser, String ctl,
-                                         PrivPredicate wanted, PrivBitSet savedPrivs) {
-        // TODO(gaoxin): check privileges by ldap.
-        readLock();
-        try {
-            catalogPrivTable.getPrivs(currentUser, ctl, savedPrivs);
-            if (PaloPrivilege.satisfy(savedPrivs, wanted)) {
-                return true;
-            }
-        } finally {
-            readUnlock();
-        }
-        return false;
-    }
-
-    private boolean checkDbInternal(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted,
-                                    PrivBitSet savedPrivs) {
-        if (isLdapAuthEnabled() && LdapPrivsChecker.hasDbPrivFromLdap(currentUser, db, wanted)) {
-            return true;
-        }
-
-        readLock();
-        try {
-            dbPrivTable.getPrivs(currentUser, ctl, db, savedPrivs);
-            if (PaloPrivilege.satisfy(savedPrivs, wanted)) {
-                return true;
-            }
-        } finally {
-            readUnlock();
-        }
-        return false;
-    }
-
-    private boolean checkTblInternal(UserIdentity currentUser, String ctl, String db, String tbl,
-                                     PrivPredicate wanted, PrivBitSet savedPrivs) {
-        if (isLdapAuthEnabled() && LdapPrivsChecker.hasTblPrivFromLdap(currentUser, db, tbl, wanted)) {
-            return true;
-        }
-
-        readLock();
-        try {
-            tablePrivTable.getPrivs(currentUser, ctl, db, tbl, savedPrivs);
-            if (PaloPrivilege.satisfy(savedPrivs, wanted)) {
-                return true;
-            }
-            return false;
-        } finally {
-            readUnlock();
-        }
-    }
-
-    private boolean checkResourceInternal(UserIdentity currentUser, String resourceName,
-                                          PrivPredicate wanted, PrivBitSet savedPrivs) {
-        if (isLdapAuthEnabled() && LdapPrivsChecker.hasResourcePrivFromLdap(currentUser, resourceName, wanted)) {
-            return true;
-        }
-
-        readLock();
-        try {
-            resourcePrivTable.getPrivs(currentUser, resourceName, savedPrivs);
-            if (PaloPrivilege.satisfy(savedPrivs, wanted)) {
-                return true;
-            }
-            return false;
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // Check if LDAP authentication is enabled.
-    private boolean isLdapAuthEnabled() {
-        return LdapConfig.ldap_authentication_enabled;
-    }
-
-    // for test only
-    public void clear() {
-        userPrivTable.clear();
-        dbPrivTable.clear();
-        tablePrivTable.clear();
-        resourcePrivTable.clear();
-    }
-
-    // create user
-    public void createUser(CreateUserStmt stmt) throws DdlException {
-        createUserInternal(stmt.getUserIdent(), stmt.getQualifiedRole(),
-                stmt.getPassword(), stmt.isIfNotExist(), stmt.getPasswordOptions(), false);
-    }
-
-    public void replayCreateUser(PrivInfo privInfo) {
-        try {
-            createUserInternal(privInfo.getUserIdent(), privInfo.getRole(), privInfo.getPasswd(), false,
-                    privInfo.getPasswordOptions(), true);
-        } catch (DdlException e) {
-            LOG.error("should not happen", e);
-        }
-    }
-
-    /*
-     * Do following steps:
-     * 1. Check does specified role exist. If not, throw exception.
-     * 2. Check does user already exist. If yes && ignoreIfExists, just return. Otherwise, throw exception.
-     * 3. set password for specified user.
-     * 4. grant privs of role to user, if role is specified.
-     */
-    private void createUserInternal(UserIdentity userIdent, String roleName, byte[] password,
-            boolean ignoreIfExists, PasswordOptions passwordOptions, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            // 1. check if role exist
-            PaloRole role = null;
-            if (roleName != null) {
-                role = roleManager.getRole(roleName);
-                if (role == null) {
-                    throw new DdlException("Role: " + roleName + " does not exist");
-                }
-            }
-
-            // 2. check if user already exist
-            if (userPrivTable.doesUserExist(userIdent)) {
-                if (ignoreIfExists) {
-                    LOG.info("user exists, ignored to create user: {}, is replay: {}", userIdent, isReplay);
-                    return;
-                }
-                throw new DdlException("User " + userIdent + " already exist");
-            }
-
-            // 3. set password
-            setPasswordInternal(userIdent, password, null, false /* err on non exist */, false /* set by resolver */,
-                    true /* is replay */);
-            try {
-                // 4. grant privs of role to user
-                grantPrivsByRole(userIdent, role);
-
-                // other user properties
-                propertyMgr.addUserResource(userIdent.getQualifiedUser(), false /* not system user */);
-
-                if (!userIdent.getQualifiedUser().equals(ROOT_USER) && !userIdent.getQualifiedUser()
-                        .equals(ADMIN_USER)) {
-                    // grant read privs to database information_schema
-                    TablePattern tblPattern = new TablePattern(DEFAULT_CATALOG, InfoSchemaDb.DATABASE_NAME, "*");
-                    try {
-                        tblPattern.analyze(ClusterNamespace.getClusterNameFromFullName(userIdent.getQualifiedUser()));
-                    } catch (AnalysisException e) {
-                        LOG.warn("should not happen", e);
-                    }
-                    grantInternal(userIdent, null /* role */, tblPattern, PrivBitSet.of(PaloPrivilege.SELECT_PRIV),
-                            false /* err on non exist */, true /* is replay */);
-                }
-            } catch (Throwable t) {
-                // This is a temp protection to avoid bug such as described in
-                // https://github.com/apache/doris/issues/11235
-                // Normally, all operations in try..catch block should not fail
-                // Why add try..catch block after "setPasswordInternal"?
-                // Because after calling "setPasswordInternal()", the in-memory state has been changed,
-                // so we should make sure the following operations not throw any exception, if it throws,
-                // exit the process because there is no way to rollback in-memory state.
-                LOG.error("got unexpected exception when creating user. exit", t);
-                System.exit(-1);
-            }
-
-            // 5. update password policy
-            passwdPolicyManager.updatePolicy(userIdent, password, passwordOptions);
-
-            if (!isReplay) {
-                PrivInfo privInfo = new PrivInfo(userIdent, null, password, roleName, passwordOptions);
-                Env.getCurrentEnv().getEditLog().logCreateUser(privInfo);
-            }
-            LOG.info("finished to create user: {}, is replay: {}", userIdent, isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    private void grantPrivsByRole(UserIdentity userIdent, PaloRole role) throws DdlException {
-        if (role == null) {
-            return;
-        }
-        writeLock();
-        try {
-            for (Map.Entry<TablePattern, PrivBitSet> entry : role.getTblPatternToPrivs().entrySet()) {
-                // use PrivBitSet copy to avoid same object being changed synchronously
-                grantInternal(userIdent, null /* role */, entry.getKey(), entry.getValue().copy(),
-                        false /* err on non exist */, true /* is replay */);
-            }
-            for (Map.Entry<ResourcePattern, PrivBitSet> entry : role.getResourcePatternToPrivs().entrySet()) {
-                // use PrivBitSet copy to avoid same object being changed synchronously
-                grantInternal(userIdent, null /* role */, entry.getKey(), entry.getValue().copy(),
-                        false /* err on non exist */, true /* is replay */);
-            }
-            // add user to this role
-            role.addUser(userIdent);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    private void revokePrivsByRole(UserIdentity userIdent, PaloRole role) throws DdlException {
-        if (role == null) {
-            return;
-        }
-        writeLock();
-        try {
-            for (Map.Entry<TablePattern, PrivBitSet> entry : role.getTblPatternToPrivs().entrySet()) {
-                revokeInternal(userIdent, null, entry.getKey(), entry.getValue().copy(), false, true);
-            }
-
-            for (Map.Entry<ResourcePattern, PrivBitSet> entry : role.getResourcePatternToPrivs().entrySet()) {
-                revokeInternal(userIdent, null, entry.getKey(), entry.getValue().copy(),
-                        false, true);
-            }
-            // drop user from this role
-            role.dropUser(userIdent);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-
-    // drop user
-    public void dropUser(DropUserStmt stmt) throws DdlException {
-        dropUserInternal(stmt.getUserIdentity(), stmt.isSetIfExists(), false);
-    }
-
-    public void replayDropUser(UserIdentity userIdent) throws DdlException {
-        dropUserInternal(userIdent, false, true);
-    }
-
-    public void replayOldDropUser(String userName) throws DdlException {
-        UserIdentity userIdentity = new UserIdentity(userName, "%");
-        userIdentity.setIsAnalyzed();
-        dropUserInternal(userIdentity, false /* ignore if non exists */, true /* is replay */);
-    }
-
-    private void dropUserInternal(UserIdentity userIdent, boolean ignoreIfNonExists, boolean isReplay)
-            throws DdlException {
-        writeLock();
-        try {
-            // check if user exists
-            if (!doesUserExist(userIdent)) {
-                if (ignoreIfNonExists) {
-                    LOG.info("user non exists, ignored to drop user: {}, is replay: {}",
-                            userIdent.getQualifiedUser(), isReplay);
-                    return;
-                }
-                throw new DdlException(String.format("User `%s`@`%s` does not exist.",
-                        userIdent.getQualifiedUser(), userIdent.getHost()));
-            }
-
-            // we don't check if user exists
-            userPrivTable.dropUser(userIdent);
-            catalogPrivTable.dropUser(userIdent);
-            dbPrivTable.dropUser(userIdent);
-            tablePrivTable.dropUser(userIdent);
-            resourcePrivTable.dropUser(userIdent);
-            // drop user in roles if exist
-            roleManager.dropUser(userIdent);
-
-            if (!userPrivTable.doesUsernameExist(userIdent.getQualifiedUser())) {
-                // if user name does not exist in userPrivTable, which means all userIdent with this name
-                // has been remove, then we can drop this user from property manager
-                propertyMgr.dropUser(userIdent);
-            } else if (userIdent.isDomain()) {
-                // if there still has entry with this user name, we can not drop user from property map,
-                // but we need to remove the specified domain from this user.
-                propertyMgr.removeDomainFromUser(userIdent);
-            }
-            passwdPolicyManager.dropUser(userIdent);
-
-            if (!isReplay) {
-                Env.getCurrentEnv().getEditLog().logNewDropUser(userIdent);
-            }
-            LOG.info("finished to drop user: {}, is replay: {}", userIdent.getQualifiedUser(), isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    // grant
-    public void grant(GrantStmt stmt) throws DdlException {
-        PrivBitSet privs = PrivBitSet.of(stmt.getPrivileges());
-        if (stmt.getTblPattern() != null) {
-            grantInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getTblPattern(), privs,
-                          true /* err on non exist */, false /* not replay */);
-        } else {
-            grantInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getResourcePattern(), privs,
-                          true /* err on non exist */, false /* not replay */);
-        }
-    }
-
-    public void replayGrant(PrivInfo privInfo) {
-        try {
-            if (privInfo.getTblPattern() != null) {
-                grantInternal(privInfo.getUserIdent(), privInfo.getRole(),
-                              privInfo.getTblPattern(), privInfo.getPrivs(),
-                              true /* err on non exist */, true /* is replay */);
-            } else {
-                grantInternal(privInfo.getUserIdent(), privInfo.getRole(),
-                              privInfo.getResourcePattern(), privInfo.getPrivs(),
-                              true /* err on non exist */, true /* is replay */);
-            }
-        } catch (DdlException e) {
-            LOG.error("should not happen", e);
-        }
-    }
-
-    // grant for TablePattern
-    private void grantInternal(UserIdentity userIdent, String role, TablePattern tblPattern,
-            PrivBitSet privs, boolean errOnNonExist, boolean isReplay)
-            throws DdlException {
-        writeLock();
-        try {
-            if (role != null) {
-                // grant privs to role, role must exist
-                PaloRole newRole = new PaloRole(role, tblPattern, privs);
-                PaloRole existingRole = roleManager.addRole(newRole, false /* err on exist */);
-
-                // update users' privs of this role
-                for (UserIdentity user : existingRole.getUsers()) {
-                    for (Map.Entry<TablePattern, PrivBitSet> entry : existingRole.getTblPatternToPrivs().entrySet()) {
-                        // copy the PrivBitSet
-                        grantPrivs(user, entry.getKey(), entry.getValue().copy(), errOnNonExist);
-                    }
-                }
-            } else {
-                grantPrivs(userIdent, tblPattern, privs, errOnNonExist);
-            }
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(userIdent, tblPattern, privs, null, role);
-                Env.getCurrentEnv().getEditLog().logGrantPriv(info);
-            }
-            LOG.info("finished to grant privilege. is replay: {}", isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    // grant for ResourcePattern
-    private void grantInternal(UserIdentity userIdent, String role, ResourcePattern resourcePattern, PrivBitSet privs,
-            boolean errOnNonExist, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            if (role != null) {
-                // grant privs to role, role must exist
-                PaloRole newRole = new PaloRole(role, resourcePattern, privs);
-                PaloRole existingRole = roleManager.addRole(newRole, false /* err on exist */);
-
-                // update users' privs of this role
-                for (UserIdentity user : existingRole.getUsers()) {
-                    for (Map.Entry<ResourcePattern, PrivBitSet> entry
-                            : existingRole.getResourcePatternToPrivs().entrySet()) {
-                        // copy the PrivBitSet
-                        grantPrivs(user, entry.getKey(), entry.getValue().copy(), errOnNonExist);
-                    }
-                }
-            } else {
-                grantPrivs(userIdent, resourcePattern, privs, errOnNonExist);
-            }
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(userIdent, resourcePattern, privs, null, role);
-                Env.getCurrentEnv().getEditLog().logGrantPriv(info);
-            }
-            LOG.info("finished to grant resource privilege. is replay: {}", isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public void grantPrivs(UserIdentity userIdent, TablePattern tblPattern, PrivBitSet privs,
-            boolean errOnNonExist) throws DdlException {
-        LOG.debug("grant {} on {} to {}, err on non exist: {}", privs, tblPattern, userIdent, errOnNonExist);
-
-        writeLock();
-        try {
-            // check if user identity already exist
-            if (errOnNonExist && !doesUserExist(userIdent)) {
-                throw new DdlException("user " + userIdent + " does not exist");
-            }
-
-            // grant privs to user
-            switch (tblPattern.getPrivLevel()) {
-                case GLOBAL:
-                    grantGlobalPrivs(userIdent,
-                                     false /* err on exist */,
-                                     errOnNonExist,
-                                     privs);
-                    break;
-                case CATALOG:
-                    grantCatalogPrivs(userIdent, tblPattern.getQualifiedCtl(),
-                                      false /* err on exist */,
-                                      false /* err on non exist */,
-                                      privs);
-                    break;
-                case DATABASE:
-                    grantDbPrivs(userIdent, tblPattern.getQualifiedCtl(),
-                                 tblPattern.getQualifiedDb(),
-                                 false /* err on exist */,
-                                 false /* err on non exist */,
-                                 privs);
-                    break;
-                case TABLE:
-                    grantTblPrivs(userIdent, tblPattern.getQualifiedCtl(),
-                                  tblPattern.getQualifiedDb(),
-                                  tblPattern.getTbl(),
-                                  false /* err on exist */,
-                                  false /* err on non exist */,
-                                  privs);
-                    break;
-                default:
-                    Preconditions.checkNotNull(null, tblPattern.getPrivLevel());
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public void grantPrivs(UserIdentity userIdent, ResourcePattern resourcePattern, PrivBitSet privs,
-                           boolean errOnNonExist) throws DdlException {
-        LOG.debug("grant {} on resource {} to {}, err on non exist: {}",
-                privs, resourcePattern, userIdent, errOnNonExist);
-
-        writeLock();
-        try {
-            // check if user identity already exist
-            if (errOnNonExist && !doesUserExist(userIdent)) {
-                throw new DdlException("user " + userIdent + " does not exist");
-            }
-
-            // grant privs to user
-            switch (resourcePattern.getPrivLevel()) {
-                case GLOBAL:
-                    grantGlobalPrivs(userIdent, false, errOnNonExist, privs);
-                    break;
-                case RESOURCE:
-                    grantResourcePrivs(userIdent, resourcePattern.getResourceName(), false, false, privs);
-                    break;
-                default:
-                    Preconditions.checkNotNull(null, resourcePattern.getPrivLevel());
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    // return true if user ident exist
-    private boolean doesUserExist(UserIdentity userIdent) {
-        if (userIdent.isDomain()) {
-            return propertyMgr.doesUserExist(userIdent);
-        } else {
-            return userPrivTable.doesUserExist(userIdent);
-        }
-    }
-
-    // Check whether the user exists. If the user exists, return UserIdentity, otherwise return null.
-    public UserIdentity getCurrentUserIdentity(UserIdentity userIdent) {
-        readLock();
-        try {
-            return userPrivTable.getCurrentUserIdentity(userIdent);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // revoke
-    public void revoke(RevokeStmt stmt) throws DdlException {
-        PrivBitSet privs = PrivBitSet.of(stmt.getPrivileges());
-        if (stmt.getTblPattern() != null) {
-            revokeInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getTblPattern(), privs,
-                           true /* err on non exist */, false /* is replay */);
-        } else {
-            revokeInternal(stmt.getUserIdent(), stmt.getQualifiedRole(), stmt.getResourcePattern(), privs,
-                           true /* err on non exist */, false /* is replay */);
-        }
-    }
-
-    public void replayRevoke(PrivInfo info) {
-        try {
-            if (info.getTblPattern() != null) {
-                revokeInternal(info.getUserIdent(), info.getRole(), info.getTblPattern(), info.getPrivs(),
-                               true /* err on non exist */, true /* is replay */);
-            } else {
-                revokeInternal(info.getUserIdent(), info.getRole(), info.getResourcePattern(), info.getPrivs(),
-                               true /* err on non exist */, true /* is replay */);
-            }
-        } catch (DdlException e) {
-            LOG.error("should not happened", e);
-        }
-    }
-
-    private void revokeInternal(UserIdentity userIdent, String role, TablePattern tblPattern,
-            PrivBitSet privs, boolean errOnNonExist, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            if (role != null) {
-                // revoke privs from role
-                PaloRole existingRole = roleManager.revokePrivs(role, tblPattern, privs, errOnNonExist);
-                if (existingRole != null) {
-                    // revoke privs from users of this role
-                    for (UserIdentity user : existingRole.getUsers()) {
-                        revokePrivs(user, tblPattern, privs, false /* err on non exist */);
-                    }
-                }
-            } else {
-                revokePrivs(userIdent, tblPattern, privs, errOnNonExist);
-            }
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(userIdent, tblPattern, privs, null, role);
-                Env.getCurrentEnv().getEditLog().logRevokePriv(info);
-            }
-            LOG.info("finished to revoke privilege. is replay: {}", isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    private void revokeInternal(UserIdentity userIdent, String role, ResourcePattern resourcePattern,
-                                PrivBitSet privs, boolean errOnNonExist, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            if (role != null) {
-                // revoke privs from role
-                PaloRole existingRole = roleManager.revokePrivs(role, resourcePattern, privs, errOnNonExist);
-                if (existingRole != null) {
-                    // revoke privs from users of this role
-                    for (UserIdentity user : existingRole.getUsers()) {
-                        revokePrivs(user, resourcePattern, privs, false /* err on non exist */);
-                    }
-                }
-            } else {
-                revokePrivs(userIdent, resourcePattern, privs, errOnNonExist);
-            }
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(userIdent, resourcePattern, privs, null, role);
-                Env.getCurrentEnv().getEditLog().logRevokePriv(info);
-            }
-            LOG.info("finished to revoke privilege. is replay: {}", isReplay);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public void revokePrivs(UserIdentity userIdent, TablePattern tblPattern, PrivBitSet privs,
-            boolean errOnNonExist) throws DdlException {
-        writeLock();
-        try {
-            switch (tblPattern.getPrivLevel()) {
-                case GLOBAL:
-                    revokeGlobalPrivs(userIdent, privs, errOnNonExist);
-                    break;
-                case CATALOG:
-                    revokeCatalogPrivs(userIdent, tblPattern.getQualifiedCtl(), privs, errOnNonExist);
-                    break;
-                case DATABASE:
-                    revokeDbPrivs(userIdent, tblPattern.getQualifiedCtl(),
-                            tblPattern.getQualifiedDb(), privs, errOnNonExist);
-                    break;
-                case TABLE:
-                    revokeTblPrivs(userIdent, tblPattern.getQualifiedCtl(), tblPattern.getQualifiedDb(),
-                            tblPattern.getTbl(), privs, errOnNonExist);
-                    break;
-                default:
-                    Preconditions.checkNotNull(null, tblPattern.getPrivLevel());
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public void revokePrivs(UserIdentity userIdent, ResourcePattern resourcePattern, PrivBitSet privs,
-                            boolean errOnNonExist) throws DdlException {
-        writeLock();
-        try {
-            switch (resourcePattern.getPrivLevel()) { // CHECKSTYLE IGNORE THIS LINE: missing switch default
-                case GLOBAL:
-                    revokeGlobalPrivs(userIdent, privs, errOnNonExist);
-                    break;
-                case RESOURCE:
-                    revokeResourcePrivs(userIdent, resourcePattern.getResourceName(), privs, errOnNonExist);
-                    break;
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    // set password
-    public void setPassword(SetPassVar stmt) throws DdlException {
-        setPasswordInternal(stmt.getUserIdent(), stmt.getPassword(), null, true /* err on non exist */,
-                            false /* set by resolver */, false);
-    }
-
-    public void replaySetPassword(PrivInfo info) {
-        try {
-            setPasswordInternal(info.getUserIdent(), info.getPasswd(), null, true /* err on non exist */,
-                                false /* set by resolver */, true);
-        } catch (DdlException e) {
-            LOG.error("should not happened", e);
-        }
-    }
-
-    public void setPasswordInternal(UserIdentity userIdent, byte[] password, UserIdentity domainUserIdent,
-            boolean errOnNonExist, boolean setByResolver, boolean isReplay) throws DdlException {
-        Preconditions.checkArgument(!setByResolver || domainUserIdent != null, setByResolver + ", " + domainUserIdent);
-        writeLock();
-        try {
-            if (!isReplay) {
-                if (!passwdPolicyManager.checkPasswordHistory(userIdent, password)) {
-                    ErrorReport.reportDdlException(ErrorCode.ERR_CREDENTIALS_CONTRADICT_TO_HISTORY,
-                            userIdent.getQualifiedUser(), userIdent.getHost());
-                }
-            }
-            if (userIdent.isDomain()) {
-                // throw exception if this user already contains this domain
-                propertyMgr.setPasswordForDomain(userIdent, password,
-                        true /* err on exist */, errOnNonExist /* err on non exist */);
-            } else {
-                GlobalPrivEntry passwdEntry;
-                try {
-                    passwdEntry = GlobalPrivEntry.create(userIdent.getHost(), userIdent.getQualifiedUser(),
-                            userIdent.isDomain(), password, PrivBitSet.of());
-                    passwdEntry.setSetByDomainResolver(setByResolver);
-                    if (setByResolver) {
-                        Preconditions.checkNotNull(domainUserIdent);
-                        passwdEntry.setDomainUserIdent(domainUserIdent);
-                    }
-                } catch (AnalysisException e) {
-                    throw new DdlException(e.getMessage());
-                }
-                userPrivTable.setPassword(passwdEntry, errOnNonExist);
-            }
-            if (password != null) {
-                // save password to password history
-                passwdPolicyManager.updatePassword(userIdent, password);
-            }
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(userIdent, null, password, null, null);
-                Env.getCurrentEnv().getEditLog().logSetPassword(info);
-            }
-        } finally {
-            writeUnlock();
-        }
-        LOG.info("finished to set password for {}. is replay: {}", userIdent, isReplay);
-    }
-
-    // set ldap admin password.
-    public void setLdapPassword(SetLdapPassVar stmt) {
-        ldapInfo = new LdapInfo(stmt.getLdapPassword());
-        Env.getCurrentEnv().getEditLog().logSetLdapPassword(ldapInfo);
-        LOG.info("finished to set ldap password.");
-    }
-
-    public void replaySetLdapPassword(LdapInfo info) {
-        ldapInfo = info;
-        LOG.debug("finish replaying ldap admin password.");
-    }
-
-    // create role
-    public void createRole(CreateRoleStmt stmt) throws DdlException {
-        createRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfNotExists(), false);
-    }
-
-    public void replayCreateRole(PrivInfo info) {
-        try {
-            createRoleInternal(info.getRole(), false, true);
-        } catch (DdlException e) {
-            LOG.error("should not happened", e);
-        }
-    }
-
-    private void createRoleInternal(String role, boolean ignoreIfExists, boolean isReplay) throws DdlException {
-        PaloRole emptyPrivsRole = new PaloRole(role);
-        writeLock();
-        try {
-            if (ignoreIfExists && roleManager.getRole(role) != null) {
-                LOG.info("role exists, ignored to create role: {}, is replay: {}", role, isReplay);
-                return;
-            }
-
-            roleManager.addRole(emptyPrivsRole, true /* err on exist */);
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(null, null, null, role, null);
-                Env.getCurrentEnv().getEditLog().logCreateRole(info);
-            }
-        } finally {
-            writeUnlock();
-        }
-        LOG.info("finished to create role: {}, is replay: {}", role, isReplay);
-    }
-
-    // drop role
-    public void dropRole(DropRoleStmt stmt) throws DdlException {
-        dropRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfExists(), false);
-    }
-
-    public void replayDropRole(PrivInfo info) {
-        try {
-            dropRoleInternal(info.getRole(), false, true);
-        } catch (DdlException e) {
-            LOG.error("should not happened", e);
-        }
-    }
-
-    private void dropRoleInternal(String role, boolean ignoreIfNonExists, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            if (ignoreIfNonExists && roleManager.getRole(role) == null) {
-                LOG.info("role non exists, ignored to drop role: {}, is replay: {}", role, isReplay);
-                return;
-            }
-
-            roleManager.dropRole(role, true /* err on non exist */);
-
-            if (!isReplay) {
-                PrivInfo info = new PrivInfo(null, null, null, role, null);
-                Env.getCurrentEnv().getEditLog().logDropRole(info);
-            }
-        } finally {
-            writeUnlock();
-        }
-        LOG.info("finished to drop role: {}, is replay: {}", role, isReplay);
-    }
-
-    // update user property
-    public void updateUserProperty(SetUserPropertyStmt stmt) throws UserException {
-        List<Pair<String, String>> properties = stmt.getPropertyPairList();
-        updateUserPropertyInternal(stmt.getUser(), properties, false /* is replay */);
-    }
-
-    public void replayUpdateUserProperty(UserPropertyInfo propInfo) throws UserException {
-        updateUserPropertyInternal(propInfo.getUser(), propInfo.getProperties(), true /* is replay */);
-    }
-
-    public void updateUserPropertyInternal(String user, List<Pair<String, String>> properties, boolean isReplay)
-            throws UserException {
-        writeLock();
-        try {
-            propertyMgr.updateUserProperty(user, properties);
-            if (!isReplay) {
-                UserPropertyInfo propertyInfo = new UserPropertyInfo(user, properties);
-                Env.getCurrentEnv().getEditLog().logUpdateUserProperty(propertyInfo);
-            }
-            LOG.info("finished to set properties for user: {}", user);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public long getMaxConn(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getMaxConn(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public long getQueryTimeout(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getQueryTimeout(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public long getMaxQueryInstances(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getMaxQueryInstances(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public String[] getSqlBlockRules(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getSqlBlockRules(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public int getCpuResourceLimit(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getCpuResourceLimit(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public Set<Tag> getResourceTags(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getResourceTags(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public long getExecMemLimit(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.getExecMemLimit(qualifiedUser);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public void getAllDomains(Set<String> allDomains) {
-        readLock();
-        try {
-            propertyMgr.getAllDomains(allDomains);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // refresh all priv entries set by domain resolver.
-    // 1. delete all priv entries in user priv table which are set by domain resolver previously.
-    // 2. add priv entries by new resolving IPs
-    public void refreshUserPrivEntriesByResovledIPs(Map<String, Set<String>> resolvedIPsMap) {
-        writeLock();
-        try {
-            // 1. delete all previously set entries
-            userPrivTable.clearEntriesSetByResolver();
-            // 2. add new entries
-            propertyMgr.addUserPrivEntriesByResolvedIPs(resolvedIPsMap);
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    // return the auth info of specified user, or infos of all users, if user is not specified.
-    // the returned columns are defined in AuthProcDir
-    // the specified user identity should be the identity created by CREATE USER, same as result of
-    // SELECT CURRENT_USER();
-    public List<List<String>> getAuthInfo(UserIdentity specifiedUserIdent) {
-        List<List<String>> userAuthInfos = Lists.newArrayList();
-        readLock();
-        try {
-            if (specifiedUserIdent == null) {
-                // get all users' auth info
-                Set<UserIdentity> userIdents = getAllUserIdents(false /* include entry set by resolver */);
-                for (UserIdentity userIdent : userIdents) {
-                    getUserAuthInfo(userAuthInfos, userIdent);
-                }
-            } else {
-                getUserAuthInfo(userAuthInfos, specifiedUserIdent);
-            }
-        } finally {
-            readUnlock();
-        }
-        return userAuthInfos;
-    }
-
-    private void getUserAuthInfo(List<List<String>> userAuthInfos, UserIdentity userIdent) {
-        List<String> userAuthInfo = Lists.newArrayList();
-
-        // global
-        // ldap global privs.
-        PrivBitSet ldapGlobalPrivs = LdapPrivsChecker.getGlobalPrivFromLdap(userIdent);
-        for (PrivEntry entry : userPrivTable.entries) {
-            if (!entry.match(userIdent, true /* exact match */)) {
-                continue;
-            }
-            GlobalPrivEntry gEntry = (GlobalPrivEntry) entry;
-            userAuthInfo.add(userIdent.toString());
-            if (userIdent.isDomain()) {
-                // for domain user ident, password is saved in property manager
-                userAuthInfo.add(propertyMgr.doesUserHasPassword(userIdent) ? "No" : "Yes");
-            } else {
-                userAuthInfo.add((gEntry.getPassword() == null || gEntry.getPassword().length == 0) ? "No" : "Yes");
-            }
-            PrivBitSet savedPrivs = gEntry.getPrivSet().copy();
-            savedPrivs.or(ldapGlobalPrivs);
-            userAuthInfo.add(savedPrivs.toString() + " (" + gEntry.isSetByDomainResolver() + ")");
-            break;
-        }
-
-        if (userAuthInfo.isEmpty()) {
-            userAuthInfo.add(userIdent.toString());
-            if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
-                userAuthInfo.add("No");
-                userAuthInfo.add(ldapGlobalPrivs.toString() + " (false)");
-            } else if (!userIdent.isDomain()) {
-                // If this is not a domain user identity, it must have global priv entry.
-                // TODO(cmy): I don't know why previous comment said:
-                // This may happen when we grant non global privs to a non exist user via GRANT stmt.
-                LOG.warn("user identity does not have global priv entry: {}", userIdent);
-                userAuthInfo.add(FeConstants.null_string);
-                userAuthInfo.add(FeConstants.null_string);
-            } else {
-                // this is a domain user identity and fall in here, which means this user identity does not
-                // have global priv, we need to check user property to see if it has password.
-                userAuthInfo.add(propertyMgr.doesUserHasPassword(userIdent) ? "No" : "Yes");
-                userAuthInfo.add(FeConstants.null_string);
-            }
-        }
-
-        // catalog
-        String ctlPrivs = catalogPrivTable.entries.stream()
-                .filter(entry -> entry.match(userIdent, true))
-                .map(entry -> String.format("%s: %s (%b)",
-                        ((CatalogPrivEntry) entry).getOrigCtl(), entry.privSet, entry.isSetByDomainResolver()))
-                .collect(Collectors.joining("; "));
-        if (Strings.isNullOrEmpty(ctlPrivs)) {
-            ctlPrivs = FeConstants.null_string;
-        }
-        userAuthInfo.add(ctlPrivs);
-
-        // db
-        List<String> dbPrivs = Lists.newArrayList();
-        Set<String> addedDbs = Sets.newHashSet();
-        for (PrivEntry entry : dbPrivTable.entries) {
-            if (!entry.match(userIdent, true /* exact match */)) {
-                continue;
-            }
-            DbPrivEntry dEntry = (DbPrivEntry) entry;
-            /**
-             * Doris and Ldap may have different privs on one database.
-             * Merge these privs and add.
-             */
-            PrivBitSet savedPrivs = dEntry.getPrivSet().copy();
-            savedPrivs.or(LdapPrivsChecker.getDbPrivFromLdap(userIdent, dEntry.getOrigDb()));
-            addedDbs.add(dEntry.getOrigDb());
-            dbPrivs.add(String.format("%s.%s: %s (%b)", dEntry.getOrigCtl(), dEntry.getOrigDb(),
-                    savedPrivs, dEntry.isSetByDomainResolver()));
-        }
-        // Add privs from ldap groups that have not been added in Doris.
-        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
-            Map<TablePattern, PrivBitSet> ldapDbPrivs = LdapPrivsChecker.getLdapAllDbPrivs(userIdent);
-            for (Map.Entry<TablePattern, PrivBitSet> entry : ldapDbPrivs.entrySet()) {
-                if (!addedDbs.contains(entry.getKey().getQualifiedDb())) {
-                    dbPrivs.add(String.format("%s.%s: %s (%b)", entry.getKey().getQualifiedCtl(),
-                            entry.getKey().getQualifiedDb(), entry.getValue(), false));
-                }
-            }
-        }
-
-        if (dbPrivs.isEmpty()) {
-            userAuthInfo.add(FeConstants.null_string);
-        } else {
-            userAuthInfo.add(Joiner.on("; ").join(dbPrivs));
-        }
-
-        // tbl
-        List<String> tblPrivs = Lists.newArrayList();
-        Set<String> addedtbls = Sets.newHashSet();
-        for (PrivEntry entry : tablePrivTable.entries) {
-            if (!entry.match(userIdent, true /* exact match */)) {
-                continue;
-            }
-            TablePrivEntry tEntry = (TablePrivEntry) entry;
-            /**
-             * Doris and Ldap may have different privs on one table.
-             * Merge these privs and add.
-             */
-            PrivBitSet savedPrivs = tEntry.getPrivSet().copy();
-            savedPrivs.or(LdapPrivsChecker.getTblPrivFromLdap(userIdent, tEntry.getOrigDb(), tEntry.getOrigTbl()));
-            addedtbls.add(tEntry.getOrigDb().concat(".").concat(tEntry.getOrigTbl()));
-            tblPrivs.add(String.format("%s.%s.%s: %s (%b)", tEntry.getOrigCtl(), tEntry.getOrigDb(),
-                    tEntry.getOrigTbl(), savedPrivs, tEntry.isSetByDomainResolver()));
-        }
-        // Add privs from ldap groups that have not been added in Doris.
-        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
-            Map<TablePattern, PrivBitSet> ldapTblPrivs = LdapPrivsChecker.getLdapAllTblPrivs(userIdent);
-            for (Map.Entry<TablePattern, PrivBitSet> entry : ldapTblPrivs.entrySet()) {
-                if (!addedtbls.contains(entry.getKey().getQualifiedDb().concat(".").concat(entry.getKey().getTbl()))) {
-                    tblPrivs.add(String.format("%s: %s (%b)", entry.getKey(), entry.getValue(), false));
-                }
-            }
-        }
-
-        if (tblPrivs.isEmpty()) {
-            userAuthInfo.add(FeConstants.null_string);
-        } else {
-            userAuthInfo.add(Joiner.on("; ").join(tblPrivs));
-        }
-
-        // resource
-        List<String> resourcePrivs = Lists.newArrayList();
-        Set<String> addedResources = Sets.newHashSet();
-        for (PrivEntry entry : resourcePrivTable.entries) {
-            if (!entry.match(userIdent, true /* exact match */)) {
-                continue;
-            }
-            ResourcePrivEntry rEntry = (ResourcePrivEntry) entry;
-            /**
-             * Doris and Ldap may have different privs on one resource.
-             * Merge these privs and add.
-             */
-            PrivBitSet savedPrivs = rEntry.getPrivSet().copy();
-            savedPrivs.or(LdapPrivsChecker.getResourcePrivFromLdap(userIdent, rEntry.getOrigResource()));
-            addedResources.add(rEntry.getOrigResource());
-            resourcePrivs.add(rEntry.getOrigResource() + ": " + savedPrivs.toString()
-                                      + " (" + entry.isSetByDomainResolver() + ")");
-        }
-        // Add privs from ldap groups that have not been added in Doris.
-        if (LdapPrivsChecker.hasLdapPrivs(userIdent)) {
-            Map<ResourcePattern, PrivBitSet> ldapResourcePrivs = LdapPrivsChecker.getLdapAllResourcePrivs(userIdent);
-            for (Map.Entry<ResourcePattern, PrivBitSet> entry : ldapResourcePrivs.entrySet()) {
-                if (!addedResources.contains(entry.getKey().getResourceName())) {
-                    tblPrivs.add(entry.getKey().getResourceName().concat(": ").concat(entry.getValue().toString())
-                            .concat(" (false)"));
-                }
-            }
-        }
-
-        if (resourcePrivs.isEmpty()) {
-            userAuthInfo.add(FeConstants.null_string);
-        } else {
-            userAuthInfo.add(Joiner.on("; ").join(resourcePrivs));
-        }
-
-        userAuthInfos.add(userAuthInfo);
-    }
-
-    private Set<UserIdentity> getAllUserIdents(boolean includeEntrySetByResolver) {
-        Set<UserIdentity> userIdents = Sets.newHashSet();
-        for (PrivEntry entry : userPrivTable.entries) {
-            if (!includeEntrySetByResolver && entry.isSetByDomainResolver()) {
-                continue;
-            }
-            userIdents.add(entry.getUserIdent());
-        }
-        for (PrivEntry entry : dbPrivTable.entries) {
-            if (!includeEntrySetByResolver && entry.isSetByDomainResolver()) {
-                continue;
-            }
-            userIdents.add(entry.getUserIdent());
-        }
-        for (PrivEntry entry : tablePrivTable.entries) {
-            if (!includeEntrySetByResolver && entry.isSetByDomainResolver()) {
-                continue;
-            }
-            userIdents.add(entry.getUserIdent());
-        }
-        for (PrivEntry entry : resourcePrivTable.entries) {
-            if (!includeEntrySetByResolver && entry.isSetByDomainResolver()) {
-                continue;
-            }
-            userIdents.add(entry.getUserIdent());
-        }
-        return userIdents;
-    }
-
-    public List<List<String>> getUserProperties(String qualifiedUser) {
-        readLock();
-        try {
-            return propertyMgr.fetchUserProperty(qualifiedUser);
-        } catch (AnalysisException e) {
-            return Lists.newArrayList();
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public void dropUserOfCluster(String clusterName, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            Set<UserIdentity> allUserIdents = getAllUserIdents(true);
-            for (UserIdentity userIdent : allUserIdents) {
-                if (userIdent.getQualifiedUser().startsWith(clusterName)) {
-                    dropUserInternal(userIdent, false, isReplay);
-                }
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    public Pair<String, DppConfig> getLoadClusterInfo(String qualifiedUser, String cluster) throws DdlException {
-        readLock();
-        try {
-            return propertyMgr.getLoadClusterInfo(qualifiedUser, cluster);
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // user can enter a cluster, if it has any privs of database or table in this cluster.
-    public boolean checkCanEnterCluster(ConnectContext ctx, String clusterName) {
-        readLock();
-        try {
-            if (checkGlobalPriv(ctx, PrivPredicate.ALL)) {
-                return true;
-            }
-
-            if (dbPrivTable.hasClusterPriv(ctx, clusterName)) {
-                return true;
-            }
-
-            if (tablePrivTable.hasClusterPriv(ctx, clusterName)) {
-                return true;
-            }
-
-            return false;
-        } finally {
-            readUnlock();
-        }
-    }
-
-    private void initUser() {
-        try {
-            UserIdentity rootUser = new UserIdentity(ROOT_USER, "%");
-            rootUser.setIsAnalyzed();
-            createUserInternal(rootUser, PaloRole.OPERATOR_ROLE, new byte[0],
-                    false /* ignore if exists */, PasswordOptions.UNSET_OPTION, true /* is replay */);
-            UserIdentity adminUser = new UserIdentity(ADMIN_USER, "%");
-            adminUser.setIsAnalyzed();
-            createUserInternal(adminUser, PaloRole.ADMIN_ROLE, new byte[0],
-                    false /* ignore if exists */, PasswordOptions.UNSET_OPTION, true /* is replay */);
-        } catch (DdlException e) {
-            LOG.error("should not happened", e);
-        }
-    }
-
-    public TFetchResourceResult toResourceThrift() {
-        readLock();
-        try {
-            return propertyMgr.toResourceThrift();
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public List<List<String>> getRoleInfo() {
-        readLock();
-        try {
-            List<List<String>> results = Lists.newArrayList();
-            roleManager.getRoleInfo(results);
-            return results;
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // Used for creating table_privileges table in information_schema.
-    public void getTablePrivStatus(List<TPrivilegeStatus> tblPrivResult, UserIdentity currentUser) {
-        readLock();
-        try {
-            for (PrivEntry entry : tablePrivTable.getEntries()) {
-                TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
-                String dbName = ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigDb());
-                String tblName = tblPrivEntry.getOrigTbl();
-
-                if (dbName.equals("information_schema" /* Don't show privileges in information_schema */)
-                        || !checkTblPriv(currentUser, tblPrivEntry.getOrigDb(), tblName, PrivPredicate.SHOW)) {
-                    continue;
-                }
-
-                String grantee = new String("\'")
-                        .concat(ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigUser()))
-                        .concat("\'@\'").concat(tblPrivEntry.getOrigHost()).concat("\'");
-                String isGrantable = tblPrivEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
-                for (PaloPrivilege paloPriv : tblPrivEntry.getPrivSet().toPrivilegeList()) {
-                    if (!PaloPrivilege.privInPaloToMysql.containsKey(paloPriv)) {
-                        continue;
-                    }
-                    TPrivilegeStatus status = new TPrivilegeStatus();
-                    status.setTableName(tblName);
-                    status.setPrivilegeType(PaloPrivilege.privInPaloToMysql.get(paloPriv));
-                    status.setGrantee(grantee);
-                    status.setSchema(dbName);
-                    status.setIsGrantable(isGrantable);
-                    tblPrivResult.add(status);
-                }
-            }
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // Used for creating schema_privileges table in information_schema.
-    public void getSchemaPrivStatus(List<TPrivilegeStatus> dbPrivResult, UserIdentity currentUser) {
-        readLock();
-        try {
-            for (PrivEntry entry : dbPrivTable.getEntries()) {
-                DbPrivEntry dbPrivEntry = (DbPrivEntry) entry;
-                String origDb = dbPrivEntry.getOrigDb();
-                String dbName = ClusterNamespace.getNameFromFullName(dbPrivEntry.getOrigDb());
-
-                if (dbName.equals("information_schema" /* Don't show privileges in information_schema */)
-                        || !checkDbPriv(currentUser, origDb, PrivPredicate.SHOW)) {
-                    continue;
-                }
-
-                String grantee = new String("\'")
-                        .concat(ClusterNamespace.getNameFromFullName(dbPrivEntry.getOrigUser()))
-                        .concat("\'@\'").concat(dbPrivEntry.getOrigHost()).concat("\'");
-                String isGrantable = dbPrivEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
-                for (PaloPrivilege paloPriv : dbPrivEntry.getPrivSet().toPrivilegeList()) {
-                    if (!PaloPrivilege.privInPaloToMysql.containsKey(paloPriv)) {
-                        continue;
-                    }
-                    TPrivilegeStatus status = new TPrivilegeStatus();
-                    status.setPrivilegeType(PaloPrivilege.privInPaloToMysql.get(paloPriv));
-                    status.setGrantee(grantee);
-                    status.setSchema(dbName);
-                    status.setIsGrantable(isGrantable);
-                    dbPrivResult.add(status);
-                }
-            }
-        } finally {
-            readUnlock();
-        }
-    }
-
-    // Used for creating user_privileges table in information_schema.
-    public void getGlobalPrivStatus(List<TPrivilegeStatus> userPrivResult, UserIdentity currentUser) {
-        readLock();
-        try {
-            if (!checkGlobalPriv(currentUser, PrivPredicate.SHOW)) {
-                return;
-            }
-
-            for (PrivEntry userPrivEntry : userPrivTable.getEntries()) {
-                String grantee = new String("\'")
-                        .concat(ClusterNamespace.getNameFromFullName(userPrivEntry.getOrigUser()))
-                        .concat("\'@\'").concat(userPrivEntry.getOrigHost()).concat("\'");
-                String isGrantable = userPrivEntry.getPrivSet().get(2) ? "YES" : "NO"; // GRANT_PRIV
-                for (PaloPrivilege paloPriv : userPrivEntry.getPrivSet().toPrivilegeList()) {
-                    if (paloPriv == PaloPrivilege.ADMIN_PRIV) {
-                        // ADMIN_PRIV includes all privileges of table and resource.
-                        for (String priv : PaloPrivilege.privInPaloToMysql.values()) {
-                            TPrivilegeStatus status = new TPrivilegeStatus();
-                            status.setPrivilegeType(priv);
-                            status.setGrantee(grantee);
-                            status.setIsGrantable("YES");
-                            userPrivResult.add(status);
-                        }
-                        break;
-                    }
-                    if (!PaloPrivilege.privInPaloToMysql.containsKey(paloPriv)) {
-                        continue;
-                    }
-                    TPrivilegeStatus status = new TPrivilegeStatus();
-                    status.setPrivilegeType(PaloPrivilege.privInPaloToMysql.get(paloPriv));
-                    status.setGrantee(grantee);
-                    status.setIsGrantable(isGrantable);
-                    userPrivResult.add(status);
-                }
-            }
-        } finally {
-            readUnlock();
-        }
-    }
-
-    public List<List<String>> getPasswdPolicyInfo(UserIdentity userIdent) {
-        return passwdPolicyManager.getPolicyInfo(userIdent);
-    }
-
-    public void alterUser(AlterUserStmt stmt) throws DdlException {
-        alterUserInternal(stmt.isIfExist(), stmt.getOpType(), stmt.getUserIdent(), stmt.getPassword(), stmt.getRole(),
-                stmt.getPasswordOptions(), false);
-    }
-
-    public void replayAlterUser(AlterUserOperationLog log) {
-        try {
-            alterUserInternal(true, log.getOp(), log.getUserIdent(), log.getPassword(), log.getRole(),
-                    log.getPasswordOptions(), true);
-        } catch (DdlException e) {
-            LOG.error("should not happen", e);
-        }
-    }
-
-    private void alterUserInternal(boolean ifExists, OpType opType, UserIdentity userIdent, byte[] password,
-            String role, PasswordOptions passwordOptions, boolean isReplay) throws DdlException {
-        writeLock();
-        try {
-            if (!doesUserExist(userIdent)) {
-                if (ifExists) {
-                    return;
-                }
-                throw new DdlException("User " + userIdent + " does not exist");
-            }
-            switch (opType) {
-                case SET_PASSWORD:
-                    setPasswordInternal(userIdent, password, null, false, false, isReplay);
-                    break;
-                case SET_ROLE:
-                    setRoleToUser(userIdent, role);
-                    break;
-                case SET_PASSWORD_POLICY:
-                    passwdPolicyManager.updatePolicy(userIdent, null, passwordOptions);
-                    break;
-                case UNLOCK_ACCOUNT:
-                    passwdPolicyManager.unlockUser(userIdent);
-                    break;
-                default:
-                    throw new DdlException("Unknown alter user operation type: " + opType.name());
-            }
-            if (opType != OpType.SET_PASSWORD && !isReplay) {
-                // For SET_PASSWORD:
-                //      the edit log is wrote in "setPasswordInternal"
-                AlterUserOperationLog log = new AlterUserOperationLog(opType, userIdent, password, role,
-                        passwordOptions);
-                Env.getCurrentEnv().getEditLog().logAlterUser(log);
-            }
-        } finally {
-            writeUnlock();
-        }
-    }
-
-    private void setRoleToUser(UserIdentity userIdent, String role) throws DdlException {
-        // 1. check if role exist
-        PaloRole newRole = roleManager.getRole(role);
-        if (newRole == null) {
-            throw new DdlException("Role " + role + " does not exist");
-        }
-        // 2. find the origin role which the user belongs to
-        PaloRole originRole = roleManager.findRoleForUser(userIdent);
-        if (originRole != null) {
-            // User belong to a role, first revoke privs of origin role from user.
-            revokePrivsByRole(userIdent, originRole);
-        }
-        // 3. grant privs of new role to user
-        grantPrivsByRole(userIdent, newRole);
-    }
-
-    public static PaloAuth read(DataInput in) throws IOException {
-        PaloAuth auth = new PaloAuth();
-        auth.readFields(in);
-        return auth;
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        // role manager must be first, because role should be exist before any user
-        roleManager.write(out);
-        userPrivTable.write(out);
-        catalogPrivTable.write(out);
-        dbPrivTable.write(out);
-        tablePrivTable.write(out);
-        resourcePrivTable.write(out);
-        propertyMgr.write(out);
-        ldapInfo.write(out);
-        passwdPolicyManager.write(out);
-    }
-
-    public void readFields(DataInput in) throws IOException {
-        roleManager = RoleManager.read(in);
-        userPrivTable = (UserPrivTable) PrivTable.read(in);
-        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_111) {
-            catalogPrivTable = (CatalogPrivTable) PrivTable.read(in);
-        } else {
-            catalogPrivTable = userPrivTable.degradeToInternalCatalogPriv();
-            LOG.info("Load PaloAuth from meta version < {}, degrade UserPrivTable to CatalogPrivTable",
-                    FeMetaVersion.VERSION_111);
-        }
-        dbPrivTable = (DbPrivTable) PrivTable.read(in);
-        tablePrivTable = (TablePrivTable) PrivTable.read(in);
-        resourcePrivTable = (ResourcePrivTable) PrivTable.read(in);
-        propertyMgr = UserPropertyMgr.read(in);
-        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_106) {
-            ldapInfo = LdapInfo.read(in);
-        }
-
-        if (userPrivTable.isEmpty()) {
-            // init root and admin user
-            initUser();
-        }
-        if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_113) {
-            passwdPolicyManager = PasswordPolicyManager.read(in);
-        } else {
-            passwdPolicyManager = new PasswordPolicyManager();
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(userPrivTable).append("\n");
-        sb.append(dbPrivTable).append("\n");
-        sb.append(tablePrivTable).append("\n");
-        sb.append(resourcePrivTable).append("\n");
-        sb.append(roleManager).append("\n");
-        sb.append(propertyMgr).append("\n");
-        sb.append(ldapInfo).append("\n");
-        return sb.toString();
-    }
-}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloRole.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloRole.java
deleted file mode 100644
index c2e60c7eac..0000000000
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloRole.java
+++ /dev/null
@@ -1,194 +0,0 @@
-// 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.mysql.privilege;
-
-import org.apache.doris.analysis.ResourcePattern;
-import org.apache.doris.analysis.TablePattern;
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.io.Text;
-import org.apache.doris.common.io.Writable;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-public class PaloRole implements Writable {
-    // operator is responsible for operating cluster, such as add/drop node
-    public static String OPERATOR_ROLE = "operator";
-    // admin is like DBA, who has all privileges except for NODE privilege held by operator
-    public static String ADMIN_ROLE = "admin";
-
-    public static PaloRole OPERATOR = new PaloRole(OPERATOR_ROLE,
-            TablePattern.ALL, PrivBitSet.of(PaloPrivilege.NODE_PRIV, PaloPrivilege.ADMIN_PRIV),
-            ResourcePattern.ALL, PrivBitSet.of(PaloPrivilege.NODE_PRIV, PaloPrivilege.ADMIN_PRIV));
-    public static PaloRole ADMIN = new PaloRole(ADMIN_ROLE,
-            TablePattern.ALL, PrivBitSet.of(PaloPrivilege.ADMIN_PRIV),
-            ResourcePattern.ALL, PrivBitSet.of(PaloPrivilege.ADMIN_PRIV));
-
-    private String roleName;
-    private Map<TablePattern, PrivBitSet> tblPatternToPrivs = Maps.newConcurrentMap();
-    private Map<ResourcePattern, PrivBitSet> resourcePatternToPrivs = Maps.newConcurrentMap();
-    // users which this role
-    private Set<UserIdentity> users = Sets.newConcurrentHashSet();
-
-    private PaloRole() {
-
-    }
-
-    public PaloRole(String roleName) {
-        this.roleName = roleName;
-    }
-
-    public PaloRole(String roleName, TablePattern tablePattern, PrivBitSet privs) {
-        this.roleName = roleName;
-        this.tblPatternToPrivs.put(tablePattern, privs);
-    }
-
-    public PaloRole(String roleName, ResourcePattern resourcePattern, PrivBitSet privs) {
-        this.roleName = roleName;
-        this.resourcePatternToPrivs.put(resourcePattern, privs);
-    }
-
-    public PaloRole(String roleName, TablePattern tablePattern, PrivBitSet tablePrivs,
-            ResourcePattern resourcePattern, PrivBitSet resourcePrivs) {
-        this.roleName = roleName;
-        this.tblPatternToPrivs.put(tablePattern, tablePrivs);
-        this.resourcePatternToPrivs.put(resourcePattern, resourcePrivs);
-    }
-
-    public String getRoleName() {
-        return roleName;
-    }
-
-    public Map<TablePattern, PrivBitSet> getTblPatternToPrivs() {
-        return tblPatternToPrivs;
-    }
-
-    public Map<ResourcePattern, PrivBitSet> getResourcePatternToPrivs() {
-        return resourcePatternToPrivs;
-    }
-
-    public Set<UserIdentity> getUsers() {
-        return users;
-    }
-
-    // merge role not check role name.
-    public void mergeNotCheck(PaloRole other) {
-        for (Map.Entry<TablePattern, PrivBitSet> entry : other.getTblPatternToPrivs().entrySet()) {
-            if (tblPatternToPrivs.containsKey(entry.getKey())) {
-                PrivBitSet existPrivs = tblPatternToPrivs.get(entry.getKey());
-                existPrivs.or(entry.getValue());
-            } else {
-                tblPatternToPrivs.put(entry.getKey(), entry.getValue());
-            }
-        }
-        for (Map.Entry<ResourcePattern, PrivBitSet> entry : other.resourcePatternToPrivs.entrySet()) {
-            if (resourcePatternToPrivs.containsKey(entry.getKey())) {
-                PrivBitSet existPrivs = resourcePatternToPrivs.get(entry.getKey());
-                existPrivs.or(entry.getValue());
-            } else {
-                resourcePatternToPrivs.put(entry.getKey(), entry.getValue());
-            }
-        }
-    }
-
-    public void merge(PaloRole other) {
-        Preconditions.checkState(roleName.equalsIgnoreCase(other.getRoleName()));
-        mergeNotCheck(other);
-    }
-
-    public void addUser(UserIdentity userIdent) {
-        users.add(userIdent);
-    }
-
-    public void dropUser(UserIdentity userIdentity) {
-        Iterator<UserIdentity> iter = users.iterator();
-        while (iter.hasNext()) {
-            UserIdentity userIdent = iter.next();
-            if (userIdent.equals(userIdentity)) {
-                iter.remove();
-            }
-        }
-    }
-
-    public boolean containsUser(UserIdentity userIdent) {
-        return users.contains(userIdent);
-    }
-
-    public static PaloRole read(DataInput in) throws IOException {
-        PaloRole role = new PaloRole();
-        role.readFields(in);
-        return role;
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        Text.writeString(out, roleName);
-        out.writeInt(tblPatternToPrivs.size());
-        for (Map.Entry<TablePattern, PrivBitSet> entry : tblPatternToPrivs.entrySet()) {
-            entry.getKey().write(out);
-            entry.getValue().write(out);
-        }
-        out.writeInt(resourcePatternToPrivs.size());
-        for (Map.Entry<ResourcePattern, PrivBitSet> entry : resourcePatternToPrivs.entrySet()) {
-            entry.getKey().write(out);
-            entry.getValue().write(out);
-        }
-        out.writeInt(users.size());
-        for (UserIdentity userIdentity : users) {
-            userIdentity.write(out);
-        }
-    }
-
-    public void readFields(DataInput in) throws IOException {
-        roleName = Text.readString(in);
-        int size = in.readInt();
-        for (int i = 0; i < size; i++) {
-            TablePattern tblPattern = TablePattern.read(in);
-            PrivBitSet privs = PrivBitSet.read(in);
-            tblPatternToPrivs.put(tblPattern, privs);
-        }
-        size = in.readInt();
-        for (int i = 0; i < size; i++) {
-            ResourcePattern resourcePattern = ResourcePattern.read(in);
-            PrivBitSet privs = PrivBitSet.read(in);
-            resourcePatternToPrivs.put(resourcePattern, privs);
-        }
-        size = in.readInt();
-        for (int i = 0; i < size; i++) {
-            UserIdentity userIdentity = UserIdentity.read(in);
-            users.add(userIdentity);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("role: ").append(roleName).append(", db table privs: ").append(tblPatternToPrivs);
-        sb.append(", resource privs: ").append(resourcePatternToPrivs);
-        sb.append(", users: ").append(users);
-        return sb.toString();
-    }
-}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Password.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Password.java
new file mode 100644
index 0000000000..e35a3f44fb
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Password.java
@@ -0,0 +1,58 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class Password implements Writable {
+    @SerializedName(value = "pwd")
+    private byte[] password;
+
+    public Password() {
+    }
+
+    public Password(byte[] password) {
+        this.password = password;
+    }
+
+    public byte[] getPassword() {
+        return password;
+    }
+
+    public void setPassword(byte[] password) {
+        this.password = password;
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static Password read(DataInput in) throws IOException {
+        String json = Text.readString(in);
+        return GsonUtils.GSON.fromJson(json, Password.class);
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
index f6e31e217f..940a331fa9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
@@ -47,17 +47,17 @@ public class PrivBitSet implements Writable {
     }
 
     public void set(int index) {
-        Preconditions.checkState(index < PaloPrivilege.privileges.length, index);
+        Preconditions.checkState(index < Privilege.privileges.length, index);
         set |= 1 << index;
     }
 
     public void unset(int index) {
-        Preconditions.checkState(index < PaloPrivilege.privileges.length, index);
+        Preconditions.checkState(index < Privilege.privileges.length, index);
         set &= ~(1 << index);
     }
 
     public boolean get(int index) {
-        Preconditions.checkState(index < PaloPrivilege.privileges.length, index);
+        Preconditions.checkState(index < Privilege.privileges.length, index);
         return (set & (1 << index)) > 0;
     }
 
@@ -96,20 +96,20 @@ public class PrivBitSet implements Writable {
     }
 
     public boolean containsNodePriv() {
-        return containsPrivs(PaloPrivilege.NODE_PRIV);
+        return containsPrivs(Privilege.NODE_PRIV);
     }
 
     public boolean containsResourcePriv() {
-        return containsPrivs(PaloPrivilege.USAGE_PRIV);
+        return containsPrivs(Privilege.USAGE_PRIV);
     }
 
     public boolean containsDbTablePriv() {
-        return containsPrivs(PaloPrivilege.SELECT_PRIV, PaloPrivilege.LOAD_PRIV, PaloPrivilege.ALTER_PRIV,
-                PaloPrivilege.CREATE_PRIV, PaloPrivilege.DROP_PRIV);
+        return containsPrivs(Privilege.SELECT_PRIV, Privilege.LOAD_PRIV, Privilege.ALTER_PRIV,
+                Privilege.CREATE_PRIV, Privilege.DROP_PRIV);
     }
 
-    public boolean containsPrivs(PaloPrivilege... privs) {
-        for (PaloPrivilege priv : privs) {
+    public boolean containsPrivs(Privilege... privs) {
+        for (Privilege priv : privs) {
             if (get(priv.getIdx())) {
                 return true;
             }
@@ -117,27 +117,27 @@ public class PrivBitSet implements Writable {
         return false;
     }
 
-    public List<PaloPrivilege> toPrivilegeList() {
-        List<PaloPrivilege> privs = Lists.newArrayList();
-        for (int i = 0; i < PaloPrivilege.privileges.length; i++) {
+    public List<Privilege> toPrivilegeList() {
+        List<Privilege> privs = Lists.newArrayList();
+        for (int i = 0; i < Privilege.privileges.length; i++) {
             if (get(i)) {
-                privs.add(PaloPrivilege.getPriv(i));
+                privs.add(Privilege.getPriv(i));
             }
         }
         return privs;
     }
 
-    public static PrivBitSet of(PaloPrivilege... privs) {
+    public static PrivBitSet of(Privilege... privs) {
         PrivBitSet bitSet = new PrivBitSet();
-        for (PaloPrivilege priv : privs) {
+        for (Privilege priv : privs) {
             bitSet.set(priv.getIdx());
         }
         return bitSet;
     }
 
-    public static PrivBitSet of(List<PaloPrivilege> privs) {
+    public static PrivBitSet of(List<Privilege> privs) {
         PrivBitSet bitSet = new PrivBitSet();
-        for (PaloPrivilege priv : privs) {
+        for (Privilege priv : privs) {
             bitSet.set(priv.getIdx());
         }
         return bitSet;
@@ -152,9 +152,9 @@ public class PrivBitSet implements Writable {
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < PaloPrivilege.privileges.length; i++) {
+        for (int i = 0; i < Privilege.privileges.length; i++) {
             if (get(i)) {
-                sb.append(PaloPrivilege.getPriv(i)).append(" ");
+                sb.append(Privilege.getPriv(i)).append(" ");
             }
         }
         return sb.toString();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivEntry.java
index 022180d37c..d76248178e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivEntry.java
@@ -22,45 +22,75 @@ import org.apache.doris.common.CaseSensibility;
 import org.apache.doris.common.PatternMatcher;
 import org.apache.doris.common.PatternMatcherException;
 import org.apache.doris.common.io.Text;
-import org.apache.doris.common.io.Writable;
 
 import com.google.common.base.Preconditions;
 import org.apache.commons.lang.NotImplementedException;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-public abstract class PrivEntry implements Comparable<PrivEntry>, Writable {
+public abstract class PrivEntry implements Comparable<PrivEntry> {
+    @Deprecated
     protected static final String ANY_HOST = "%";
+    @Deprecated
     protected static final String ANY_USER = "%";
 
+    protected PrivBitSet privSet;
+
     // host is not case sensitive
+    @Deprecated
     protected PatternMatcher hostPattern;
+    @Deprecated
     protected String origHost;
+    @Deprecated
     protected boolean isAnyHost = false;
     // user name is case sensitive
+    @Deprecated
     protected PatternMatcher userPattern;
+    @Deprecated
     protected String origUser;
+    @Deprecated
     protected boolean isAnyUser = false;
-    protected PrivBitSet privSet;
     // true if this entry is set by domain resolver
+    @Deprecated
     protected boolean isSetByDomainResolver = false;
     // true if origHost is a domain name.
     // For global priv entry, if isDomain is true, it should only be used for priv checking, not password checking
+    @Deprecated
     protected boolean isDomain = false;
 
     // isClassNameWrote to guarantee the class name can only be written once when persisting.
     // see PrivEntry.read() for more details.
+    @Deprecated
     protected boolean isClassNameWrote = false;
-
-    private UserIdentity userIdentity;
+    @Deprecated
+    protected UserIdentity userIdentity;
 
     protected PrivEntry() {
     }
 
+    protected PrivEntry(PrivBitSet privSet) {
+        this.privSet = privSet;
+    }
+
+    public PrivBitSet getPrivSet() {
+        return privSet;
+    }
+
+    public void setPrivSet(PrivBitSet privSet) {
+        this.privSet = privSet;
+    }
+
+    @Deprecated
+    public void setSetByDomainResolver(boolean isSetByDomainResolver) {
+        this.isSetByDomainResolver = isSetByDomainResolver;
+    }
+
+    public abstract boolean keyMatch(PrivEntry other);
+
+    @Deprecated
     protected PrivEntry(PatternMatcher hostPattern, String origHost, PatternMatcher userPattern, String origUser,
             boolean isDomain, PrivBitSet privSet) {
         this.hostPattern = hostPattern;
@@ -82,121 +112,16 @@ public abstract class PrivEntry implements Comparable<PrivEntry>, Writable {
         }
     }
 
-    public PatternMatcher getHostPattern() {
-        return hostPattern;
-    }
-
-    public String getOrigHost() {
-        return origHost;
-    }
-
-    public boolean isAnyHost() {
-        return isAnyHost;
-    }
-
-    public PatternMatcher getUserPattern() {
-        return userPattern;
-    }
-
-    public String getOrigUser() {
-        return origUser;
-    }
-
-    public boolean isAnyUser() {
-        return isAnyUser;
-    }
-
-    public PrivBitSet getPrivSet() {
-        return privSet;
-    }
-
-    public void setPrivSet(PrivBitSet privSet) {
-        this.privSet = privSet;
-    }
-
-    public boolean isSetByDomainResolver() {
-        return isSetByDomainResolver;
-    }
-
-    public void setSetByDomainResolver(boolean isSetByDomainResolver) {
-        this.isSetByDomainResolver = isSetByDomainResolver;
-    }
-
-    public UserIdentity getUserIdent() {
-        return userIdentity;
-    }
-
-    public boolean match(UserIdentity userIdent, boolean exactMatch) {
-        if (exactMatch) {
-            return origUser.equals(userIdent.getQualifiedUser()) && origHost.equals(userIdent.getHost());
-        } else {
-            return origUser.equals(userIdent.getQualifiedUser()) && hostPattern.match(userIdent.getHost());
-        }
-    }
-
-    public abstract boolean keyMatch(PrivEntry other);
-
-    /*
-     * It's a bit complicated when persisting instance which its class has derived classes.
-     * eg: A (top class) -> B (derived) -> C (derived)
-     *
-     * Write process:
-     * C.write()
-     *      |
-     *      --- write class name
-     *      |
-     *      --- super.write()    -----> B.write()
-     *      |                               |
-     *      --- write C's self members      --- write class name (if not write before)
-     *                                      |
-     *                                      --- super.write()    -----> A.write()
-     *                                      |                               |
-     *                                      --- write B's self members      --- write class name (if not write before)
-     *                                                                      |
-     *                                                                      --- write A's self members
-     *
-     * So the final write order is:
-     *      1. C's class name
-     *      2. A's self members
-     *      3. B's self members
-     *      4. C's self members
-     *
-     * In case that class name should only be wrote once, we use isClassNameWrote flag.
-     *
-     * Read process:
-     * static A.read()
-     *      |
-     *      --- read class name and instantiated the class instance (eg. C class)
-     *      |
-     *      --- C.readFields()
-     *          |
-     *          --- super.readFields() --> B.readFields()
-     *          |                           |
-     *          --- read C's self members   --- super.readFields() --> A.readFields()
-     *                                      |                           |
-     *                                      --- read B's self members   --- read A's self members
-     *
-     *  So the final read order is:
-     *      1. C's class name
-     *      2. A's self members
-     *      3. B's self members
-     *      4. C's self members
-     *
-     *  Which is same as Write order.
-     */
+    @Deprecated
     public static PrivEntry read(DataInput in) throws IOException {
         String className = Text.readString(in);
-        if (className.startsWith("com.baidu.palo")) {
-            // we need to be compatible with former class name
-            className = className.replaceFirst("com.baidu.palo", "org.apache.doris");
-        }
         PrivEntry privEntry = null;
         try {
             Class<? extends PrivEntry> derivedClass = (Class<? extends PrivEntry>) Class.forName(className);
             privEntry = derivedClass.newInstance();
-            Class[] paramTypes = { DataInput.class };
+            Class[] paramTypes = {DataInput.class};
             Method readMethod = derivedClass.getMethod("readFields", paramTypes);
-            Object[] params = { in };
+            Object[] params = {in};
             readMethod.invoke(privEntry, params);
 
             return privEntry;
@@ -206,23 +131,7 @@ public abstract class PrivEntry implements Comparable<PrivEntry>, Writable {
         }
     }
 
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = PrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        Text.writeString(out, origHost);
-        Text.writeString(out, origUser);
-        privSet.write(out);
-
-        out.writeBoolean(isSetByDomainResolver);
-        out.writeBoolean(isDomain);
-
-        isClassNameWrote = false;
-    }
-
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         origHost = Text.readString(in);
         try {
@@ -250,6 +159,15 @@ public abstract class PrivEntry implements Comparable<PrivEntry>, Writable {
         }
     }
 
+    @Deprecated
+    public boolean match(UserIdentity userIdent, boolean exactMatch) {
+        if (exactMatch) {
+            return origUser.equals(userIdent.getQualifiedUser()) && origHost.equals(userIdent.getHost());
+        } else {
+            return origUser.equals(userIdent.getQualifiedUser()) && hostPattern.match(userIdent.getHost());
+        }
+    }
+
     @Override
     public int compareTo(PrivEntry o) {
         throw new NotImplementedException();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivPredicate.java
index 3bf80cd149..dc48fb2444 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivPredicate.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivPredicate.java
@@ -22,68 +22,68 @@ import org.apache.doris.analysis.CompoundPredicate.Operator;
 public class PrivPredicate {
 
     // user can 'see' this meta
-    public static final PrivPredicate SHOW = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.SELECT_PRIV,
-                    PaloPrivilege.LOAD_PRIV,
-                    PaloPrivilege.ALTER_PRIV,
-                    PaloPrivilege.CREATE_PRIV,
-                    PaloPrivilege.DROP_PRIV),
+    public static final PrivPredicate SHOW = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.SELECT_PRIV,
+            Privilege.LOAD_PRIV,
+            Privilege.ALTER_PRIV,
+            Privilege.CREATE_PRIV,
+            Privilege.DROP_PRIV),
             Operator.OR);
     //show resources
-    public static final PrivPredicate SHOW_RESOURCES = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-            PaloPrivilege.USAGE_PRIV),
+    public static final PrivPredicate SHOW_RESOURCES = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.USAGE_PRIV),
             Operator.OR);
     // create/drop/alter/show user
-    public static final PrivPredicate GRANT = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.GRANT_PRIV),
+    public static final PrivPredicate GRANT = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.GRANT_PRIV),
             Operator.OR);
     // admin user privs
-    public static final PrivPredicate ADMIN = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV),
+    public static final PrivPredicate ADMIN = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV),
             Operator.OR);
 
     // load
-    public static final PrivPredicate LOAD = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.LOAD_PRIV),
+    public static final PrivPredicate LOAD = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.LOAD_PRIV),
             Operator.OR);
 
     // alter
-    public static final PrivPredicate ALTER = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.ALTER_PRIV),
+    public static final PrivPredicate ALTER = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.ALTER_PRIV),
             Operator.OR);
 
     // create
-    public static final PrivPredicate CREATE = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.CREATE_PRIV),
+    public static final PrivPredicate CREATE = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.CREATE_PRIV),
             Operator.OR);
 
     // drop
-    public static final PrivPredicate DROP = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.DROP_PRIV),
+    public static final PrivPredicate DROP = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.DROP_PRIV),
             Operator.OR);
 
     // select
-    public static final PrivPredicate SELECT = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.SELECT_PRIV),
+    public static final PrivPredicate SELECT = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.SELECT_PRIV),
             Operator.OR);
 
     // operator
-    public static final PrivPredicate OPERATOR = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.NODE_PRIV),
+    public static final PrivPredicate OPERATOR = PrivPredicate.of(PrivBitSet.of(Privilege.NODE_PRIV),
             Operator.OR);
 
     // resource usage
-    public static final PrivPredicate USAGE = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.USAGE_PRIV),
+    public static final PrivPredicate USAGE = PrivPredicate.of(PrivBitSet.of(Privilege.ADMIN_PRIV,
+            Privilege.USAGE_PRIV),
             Operator.OR);
 
     // all
-    public static final PrivPredicate ALL = PrivPredicate.of(PrivBitSet.of(PaloPrivilege.NODE_PRIV,
-                    PaloPrivilege.ADMIN_PRIV,
-                    PaloPrivilege.SELECT_PRIV,
-                    PaloPrivilege.LOAD_PRIV,
-                    PaloPrivilege.ALTER_PRIV,
-                    PaloPrivilege.CREATE_PRIV,
-                    PaloPrivilege.DROP_PRIV,
-                    PaloPrivilege.USAGE_PRIV),
+    public static final PrivPredicate ALL = PrivPredicate.of(PrivBitSet.of(Privilege.NODE_PRIV,
+            Privilege.ADMIN_PRIV,
+            Privilege.SELECT_PRIV,
+            Privilege.LOAD_PRIV,
+            Privilege.ALTER_PRIV,
+            Privilege.CREATE_PRIV,
+            Privilege.DROP_PRIV,
+            Privilege.USAGE_PRIV),
             Operator.OR);
 
     private PrivBitSet privs;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivTable.java
index 054ca2e62e..a2162a1d9e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivTable.java
@@ -17,19 +17,16 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.UserIdentity;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.common.io.Text;
-import org.apache.doris.common.io.Writable;
 
 import com.google.common.collect.Lists;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -37,7 +34,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-public abstract class PrivTable implements Writable {
+public abstract class PrivTable {
     private static final Logger LOG = LogManager.getLogger(PrivTable.class);
 
     protected List<PrivEntry> entries = Lists.newArrayList();
@@ -48,16 +45,8 @@ public abstract class PrivTable implements Writable {
     /*
      * Check if user@host has specified privilege
      */
-    public boolean hasPriv(String host, String user, PrivPredicate wanted) {
+    public boolean hasPriv(PrivPredicate wanted) {
         for (PrivEntry entry : entries) {
-            // check host
-            if (!entry.isAnyHost() && !entry.getHostPattern().match(host)) {
-                continue;
-            }
-            // check user
-            if (!entry.isAnyUser() && !entry.getUserPattern().match(user)) {
-                continue;
-            }
             // check priv
             if (entry.privSet.satisfy(wanted)) {
                 return true;
@@ -72,11 +61,12 @@ public abstract class PrivTable implements Writable {
      * NOTICE, this method does not set password for the newly added entry if this is a user priv table, the caller
      * need to set password later.
      */
-    public PrivEntry addEntry(PrivEntry newEntry, boolean errOnExist, boolean errOnNonExist) throws DdlException {
+    public PrivEntry addEntry(PrivEntry newEntry,
+            boolean errOnExist, boolean errOnNonExist) throws DdlException {
         PrivEntry existingEntry = getExistingEntry(newEntry);
         if (existingEntry == null) {
             if (errOnNonExist) {
-                throw new DdlException("User " + newEntry.getUserIdent() + " does not exist");
+                throw new DdlException("entry does not exist");
             }
             entries.add(newEntry);
             Collections.sort(entries);
@@ -84,25 +74,16 @@ public abstract class PrivTable implements Writable {
             return newEntry;
         } else {
             if (errOnExist) {
-                throw new DdlException("User already exist");
+                throw new DdlException("entry already exist");
             } else {
-                checkOperationAllowed(existingEntry, newEntry, "ADD ENTRY");
-                // if existing entry is set by domain resolver, just replace it with the new entry.
-                // if existing entry is not set by domain resolver, merge the 2 entries.
-                if (existingEntry.isSetByDomainResolver()) {
-                    existingEntry.setPrivSet(newEntry.getPrivSet());
-                    existingEntry.setSetByDomainResolver(newEntry.isSetByDomainResolver());
-                    LOG.debug("reset priv entry: {}", existingEntry);
-                } else if (!newEntry.isSetByDomainResolver()) {
-                    mergePriv(existingEntry, newEntry);
-                    existingEntry.setSetByDomainResolver(false);
-                    LOG.debug("merge priv entry: {}", existingEntry);
-                }
+                mergePriv(existingEntry, newEntry);
+                LOG.debug("merge priv entry: {}", existingEntry);
             }
-            return existingEntry;
         }
+        return existingEntry;
     }
 
+
     public List<PrivEntry> getEntries() {
         return entries;
     }
@@ -119,48 +100,22 @@ public abstract class PrivTable implements Writable {
         }
     }
 
-    public void clearEntriesSetByResolver() {
-        Iterator<PrivEntry> iter = entries.iterator();
-        while (iter.hasNext()) {
-            PrivEntry privEntry = iter.next();
-            if (privEntry.isSetByDomainResolver()) {
-                iter.remove();
-                LOG.info("drop priv entry set by resolver: {}", privEntry);
-            }
-        }
-    }
-
-    // drop all entries which user name are matched, and is not set by resolver
-    public void dropUser(UserIdentity userIdentity) {
-        Iterator<PrivEntry> iter = entries.iterator();
-        while (iter.hasNext()) {
-            PrivEntry privEntry = iter.next();
-            if (privEntry.match(userIdentity, true /* exact match */) && !privEntry.isSetByDomainResolver()) {
-                iter.remove();
-                LOG.info("drop entry: {}", privEntry);
-            }
-        }
-    }
-
-    public void revoke(PrivEntry entry, boolean errOnNonExist, boolean deleteEntryWhenEmpty) throws DdlException {
+    public void revoke(PrivEntry entry, boolean errOnNonExist,
+            boolean deleteEntryWhenEmpty) throws DdlException {
         PrivEntry existingEntry = getExistingEntry(entry);
         if (existingEntry == null) {
             if (errOnNonExist) {
-                ErrorReport.reportDdlException(ErrorCode.ERR_NONEXISTING_GRANT, entry.getOrigUser(),
-                        entry.getOrigHost());
+                ErrorReport.reportDdlException(ErrorCode.ERR_NONEXISTING_GRANT);
             }
             return;
         }
 
-        checkOperationAllowed(existingEntry, entry, "REVOKE");
-
         // check if privs to be revoked exist in priv entry.
         PrivBitSet tmp = existingEntry.getPrivSet().copy();
         tmp.and(entry.getPrivSet());
         if (tmp.isEmpty()) {
             if (errOnNonExist) {
-                ErrorReport.reportDdlException(ErrorCode.ERR_NONEXISTING_GRANT, entry.getOrigUser(),
-                        entry.getOrigHost());
+                ErrorReport.reportDdlException(ErrorCode.ERR_NONEXISTING_GRANT);
             }
             // there is no such priv, nothing need to be done
             return;
@@ -168,7 +123,7 @@ public abstract class PrivTable implements Writable {
 
         // revoke privs from existing priv entry
         LOG.debug("before revoke: {}, privs to be revoked: {}",
-                  existingEntry.getPrivSet(), entry.getPrivSet());
+                existingEntry.getPrivSet(), entry.getPrivSet());
         tmp = existingEntry.getPrivSet().copy();
         tmp.xor(entry.getPrivSet());
         existingEntry.getPrivSet().and(tmp);
@@ -180,18 +135,6 @@ public abstract class PrivTable implements Writable {
         }
     }
 
-    /*
-     * the priv entry is classified by 'set by domain resolver'
-     * or 'NOT set by domain resolver'(other specified operations).
-     * if the existing entry is set by resolver, it can be reset by resolver or set by specified ops.
-     * in other word, if the existing entry is NOT set by resolver, it can not be set by resolver.
-     */
-    protected void checkOperationAllowed(PrivEntry existingEntry, PrivEntry newEntry, String op) throws DdlException {
-        if (!existingEntry.isSetByDomainResolver() && newEntry.isSetByDomainResolver()) {
-            throw new DdlException("the existing entry is NOT set by resolver: " + existingEntry + ","
-                    + " can not be set by resolver " + newEntry + ", op: " + op);
-        }
-    }
 
     // Get existing entry which is the keys match the given entry
     protected PrivEntry getExistingEntry(PrivEntry entry) {
@@ -203,18 +146,9 @@ public abstract class PrivTable implements Writable {
         return null;
     }
 
-    private void mergePriv(PrivEntry first, PrivEntry second) {
+    private void mergePriv(
+            PrivEntry first, PrivEntry second) {
         first.getPrivSet().or(second.getPrivSet());
-        first.setSetByDomainResolver(first.isSetByDomainResolver() || second.isSetByDomainResolver());
-    }
-
-    public boolean doesUsernameExist(String qualifiedUsername) {
-        for (PrivEntry entry : entries) {
-            if (entry.getOrigUser().equals(qualifiedUsername)) {
-                return true;
-            }
-        }
-        return false;
     }
 
     // for test only
@@ -226,19 +160,16 @@ public abstract class PrivTable implements Writable {
         return entries.isEmpty();
     }
 
+    @Deprecated
     public static PrivTable read(DataInput in) throws IOException {
         String className = Text.readString(in);
-        if (className.startsWith("com.baidu.palo")) {
-            // we need to be compatible with former class name
-            className = className.replaceFirst("com.baidu.palo", "org.apache.doris");
-        }
         PrivTable privTable = null;
         try {
             Class<? extends PrivTable> derivedClass = (Class<? extends PrivTable>) Class.forName(className);
             privTable = derivedClass.newInstance();
-            Class[] paramTypes = { DataInput.class };
+            Class[] paramTypes = {DataInput.class};
             Method readMethod = derivedClass.getMethod("readFields", paramTypes);
-            Object[] params = { in };
+            Object[] params = {in};
             readMethod.invoke(privTable, params);
 
             return privTable;
@@ -257,20 +188,7 @@ public abstract class PrivTable implements Writable {
         return sb.toString();
     }
 
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = PrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        out.writeInt(entries.size());
-        for (PrivEntry privEntry : entries) {
-            privEntry.write(out);
-        }
-        isClassNameWrote = false;
-    }
-
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         int size = in.readInt();
         for (int i = 0; i < size; i++) {
@@ -280,4 +198,14 @@ public abstract class PrivTable implements Writable {
         Collections.sort(entries);
     }
 
+    public void merge(PrivTable privTable) {
+        for (PrivEntry entry : privTable.entries) {
+            try {
+                addEntry(entry, false, false);
+            } catch (DdlException e) {
+                //will no exception
+                LOG.debug(e.getMessage());
+            }
+        }
+    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloPrivilege.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Privilege.java
similarity index 86%
rename from fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloPrivilege.java
rename to fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Privilege.java
index 7236165d63..412fd0aa56 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PaloPrivilege.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Privilege.java
@@ -21,7 +21,7 @@ import com.google.common.collect.ImmutableMap;
 
 import java.util.Map;
 
-public enum PaloPrivilege {
+public enum Privilege {
     NODE_PRIV("Node_priv", 0, "Privilege for cluster node operations"),
     ADMIN_PRIV("Admin_priv", 1, "Privilege for admin user"),
     GRANT_PRIV("Grant_priv", 2, "Privilege for granting privilege"),
@@ -32,7 +32,7 @@ public enum PaloPrivilege {
     DROP_PRIV("Drop_priv", 7, "Privilege for dropping database or table"),
     USAGE_PRIV("Usage_priv", 8, "Privilege for using resource");
 
-    public static PaloPrivilege[] privileges = {
+    public static Privilege[] privileges = {
             NODE_PRIV,
             ADMIN_PRIV,
             GRANT_PRIV,
@@ -44,8 +44,8 @@ public enum PaloPrivilege {
             USAGE_PRIV
     };
 
-    public static Map<PaloPrivilege, String> privInPaloToMysql =
-            ImmutableMap.<PaloPrivilege, String>builder() // No NODE_PRIV and ADMIN_PRIV in the mysql
+    public static Map<Privilege, String> privInDorisToMysql =
+            ImmutableMap.<Privilege, String>builder() // No NODE_PRIV and ADMIN_PRIV in the mysql
                     .put(SELECT_PRIV, "SELECT")
                     .put(LOAD_PRIV, "INSERT")
                     .put(ALTER_PRIV, "ALTER")
@@ -58,7 +58,7 @@ public enum PaloPrivilege {
     private int idx;
     private String desc;
 
-    private PaloPrivilege(String name, int index, String desc) {
+    private Privilege(String name, int index, String desc) {
         this.name = name;
         this.idx = index;
         this.desc = desc;
@@ -76,8 +76,8 @@ public enum PaloPrivilege {
         return desc;
     }
 
-    public static PaloPrivilege getPriv(int index) {
-        if (index < 0 || index > PaloPrivilege.values().length - 1) {
+    public static Privilege getPriv(int index) {
+        if (index < 0 || index > Privilege.values().length - 1) {
             return null;
         }
         return privileges[index];
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivEntry.java
index f7c393ed78..c85e01867e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivEntry.java
@@ -21,11 +21,9 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.CaseSensibility;
 import org.apache.doris.common.PatternMatcher;
 import org.apache.doris.common.PatternMatcherException;
-import org.apache.doris.common.PatternMatcherWrapper;
 import org.apache.doris.common.io.Text;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 
 public class ResourcePrivEntry extends PrivEntry {
@@ -38,9 +36,9 @@ public class ResourcePrivEntry extends PrivEntry {
     protected ResourcePrivEntry() {
     }
 
-    protected ResourcePrivEntry(PatternMatcher hostPattern, String origHost, PatternMatcher resourcePattern,
-            String origResource, PatternMatcher userPattern, String user, boolean isDomain, PrivBitSet privSet) {
-        super(hostPattern, origHost, userPattern, user, isDomain, privSet);
+    protected ResourcePrivEntry(PatternMatcher resourcePattern,
+            String origResource, PrivBitSet privSet) {
+        super(privSet);
         this.resourcePattern = resourcePattern;
         this.origResource = origResource;
         if (origResource.equals(ANY_RESOURCE)) {
@@ -48,21 +46,16 @@ public class ResourcePrivEntry extends PrivEntry {
         }
     }
 
-    public static ResourcePrivEntry create(String host, String resourceName,
-            String user, boolean isDomain, PrivBitSet privs)
-            throws AnalysisException {
-        PatternMatcher hostPattern = PatternMatcherWrapper.createMysqlPattern(host,
-                CaseSensibility.HOST.getCaseSensibility());
-        PatternMatcher resourcePattern = PatternMatcherWrapper.createMysqlPattern(
+    public static ResourcePrivEntry create(String resourceName, PrivBitSet privs)
+            throws AnalysisException, PatternMatcherException {
+        PatternMatcher resourcePattern = PatternMatcher.createMysqlPattern(
                 resourceName.equals(ANY_RESOURCE) ? "%" : resourceName,
                 CaseSensibility.RESOURCE.getCaseSensibility());
-        PatternMatcher userPattern = PatternMatcherWrapper.createMysqlPattern(user,
-                CaseSensibility.USER.getCaseSensibility());
         if (privs.containsNodePriv() || privs.containsDbTablePriv()) {
             throw new AnalysisException("Resource privilege can not contains node or db table privileges: " + privs);
         }
-        return new ResourcePrivEntry(hostPattern, host, resourcePattern,
-                resourceName, userPattern, user, isDomain, privs);
+        return new ResourcePrivEntry(resourcePattern,
+                resourceName, privs);
     }
 
     public PatternMatcher getResourcePattern() {
@@ -80,17 +73,8 @@ public class ResourcePrivEntry extends PrivEntry {
         }
 
         ResourcePrivEntry otherEntry = (ResourcePrivEntry) other;
-        int res = origHost.compareTo(otherEntry.origHost);
-        if (res != 0) {
-            return -res;
-        }
-
-        res = origResource.compareTo(otherEntry.origResource);
-        if (res != 0) {
-            return -res;
-        }
 
-        return -origUser.compareTo(otherEntry.origUser);
+        return origResource.compareTo(otherEntry.origResource);
     }
 
     @Override
@@ -100,8 +84,7 @@ public class ResourcePrivEntry extends PrivEntry {
         }
 
         ResourcePrivEntry otherEntry = (ResourcePrivEntry) other;
-        if (origHost.equals(otherEntry.origHost) && origUser.equals(otherEntry.origUser)
-                && origResource.equals(otherEntry.origResource) && isDomain == otherEntry.isDomain) {
+        if (origResource.equals(otherEntry.origResource)) {
             return true;
         }
         return false;
@@ -110,24 +93,11 @@ public class ResourcePrivEntry extends PrivEntry {
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("resource priv. host: ").append(origHost).append(", resource: ").append(origResource);
-        sb.append(", user: ").append(origUser);
-        sb.append(", priv: ").append(privSet).append(", set by resolver: ").append(isSetByDomainResolver);
+        sb.append("origResource:").append(origResource).append("priv:").append(privSet);
         return sb.toString();
     }
 
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = ResourcePrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        super.write(out);
-        Text.writeString(out, origResource);
-        isClassNameWrote = false;
-    }
-
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
         origResource = Text.readString(in);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivTable.java
index 945a9dd5c3..010d1026c9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/ResourcePrivTable.java
@@ -17,15 +17,9 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.io.Text;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
 /*
  * ResourcePrivTable saves all resources privs
  */
@@ -36,15 +30,10 @@ public class ResourcePrivTable extends PrivTable {
      * Return first priv which match the user@host on resourceName The returned priv will be
      * saved in 'savedPrivs'.
      */
-    public void getPrivs(UserIdentity currentUser, String resourceName, PrivBitSet savedPrivs) {
+    public void getPrivs(String resourceName, PrivBitSet savedPrivs) {
         ResourcePrivEntry matchedEntry = null;
         for (PrivEntry entry : entries) {
             ResourcePrivEntry resourcePrivEntry = (ResourcePrivEntry) entry;
-
-            if (!resourcePrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
             // check resource
             if (!resourcePrivEntry.getResourcePattern().match(resourceName)) {
                 continue;
@@ -59,15 +48,4 @@ public class ResourcePrivTable extends PrivTable {
 
         savedPrivs.or(matchedEntry.getPrivSet());
     }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = ResourcePrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        super.write(out);
-    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java
new file mode 100644
index 0000000000..39829afccb
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Role.java
@@ -0,0 +1,605 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.analysis.ResourcePattern;
+import org.apache.doris.analysis.TablePattern;
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.DdlException;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.PatternMatcherException;
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
+import org.apache.doris.persist.gson.GsonPostProcessable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.gson.annotations.SerializedName;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class Role implements Writable, GsonPostProcessable {
+    private static final Logger LOG = LogManager.getLogger(Role.class);
+
+    // operator is responsible for operating cluster, such as add/drop node
+    public static String OPERATOR_ROLE = "operator";
+    // admin is like DBA, who has all privileges except for NODE privilege held by operator
+    public static String ADMIN_ROLE = "admin";
+
+    public static Role OPERATOR = new Role(OPERATOR_ROLE,
+            TablePattern.ALL, PrivBitSet.of(Privilege.NODE_PRIV, Privilege.ADMIN_PRIV),
+            ResourcePattern.ALL, PrivBitSet.of(Privilege.NODE_PRIV, Privilege.ADMIN_PRIV));
+    public static Role ADMIN = new Role(ADMIN_ROLE,
+            TablePattern.ALL, PrivBitSet.of(Privilege.ADMIN_PRIV),
+            ResourcePattern.ALL, PrivBitSet.of(Privilege.ADMIN_PRIV));
+
+    @SerializedName(value = "roleName")
+    private String roleName;
+    // Will be persisted
+    @SerializedName(value = "tblPatternToPrivs")
+    private Map<TablePattern, PrivBitSet> tblPatternToPrivs = Maps.newConcurrentMap();
+    @SerializedName(value = "resourcePatternToPrivs")
+    private Map<ResourcePattern, PrivBitSet> resourcePatternToPrivs = Maps.newConcurrentMap();
+
+    // Will not be persisted,generage by tblPatternToPrivs and resourcePatternToPrivs
+    private GlobalPrivTable globalPrivTable = new GlobalPrivTable();
+    private CatalogPrivTable catalogPrivTable = new CatalogPrivTable();
+    private DbPrivTable dbPrivTable = new DbPrivTable();
+    private TablePrivTable tablePrivTable = new TablePrivTable();
+    private ResourcePrivTable resourcePrivTable = new ResourcePrivTable();
+
+    @Deprecated
+    private Set<UserIdentity> users = Sets.newConcurrentHashSet();
+
+    @Deprecated
+    public Set<UserIdentity> getUsers() {
+        return users;
+    }
+
+    private Role() {
+
+    }
+
+    public Role(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public Role(String roleName, TablePattern tablePattern, PrivBitSet privs) throws DdlException {
+        this.roleName = roleName;
+        this.tblPatternToPrivs.put(tablePattern, privs);
+        grantPrivs(tablePattern, privs.copy());
+    }
+
+    public Role(String roleName, ResourcePattern resourcePattern, PrivBitSet privs) throws DdlException {
+        this.roleName = roleName;
+        this.resourcePatternToPrivs.put(resourcePattern, privs);
+        grantPrivs(resourcePattern, privs.copy());
+    }
+
+    public Role(String roleName, TablePattern tablePattern, PrivBitSet tablePrivs,
+            ResourcePattern resourcePattern, PrivBitSet resourcePrivs) {
+        this.roleName = roleName;
+        this.tblPatternToPrivs.put(tablePattern, tablePrivs);
+        this.resourcePatternToPrivs.put(resourcePattern, resourcePrivs);
+        //for init admin role,will not generate exception
+        try {
+            grantPrivs(tablePattern, tablePrivs.copy());
+            grantPrivs(resourcePattern, resourcePrivs.copy());
+        } catch (DdlException e) {
+            LOG.warn("grant failed,", e);
+        }
+
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public Map<TablePattern, PrivBitSet> getTblPatternToPrivs() {
+        return tblPatternToPrivs;
+    }
+
+    public Map<ResourcePattern, PrivBitSet> getResourcePatternToPrivs() {
+        return resourcePatternToPrivs;
+    }
+
+    // merge role not check role name.
+    public void mergeNotCheck(Role other) throws DdlException {
+        for (Map.Entry<TablePattern, PrivBitSet> entry : other.getTblPatternToPrivs().entrySet()) {
+            if (tblPatternToPrivs.containsKey(entry.getKey())) {
+                PrivBitSet existPrivs = tblPatternToPrivs.get(entry.getKey());
+                existPrivs.or(entry.getValue());
+            } else {
+                tblPatternToPrivs.put(entry.getKey(), entry.getValue());
+            }
+            grantPrivs(entry.getKey(), entry.getValue().copy());
+        }
+        for (Map.Entry<ResourcePattern, PrivBitSet> entry : other.resourcePatternToPrivs.entrySet()) {
+            if (resourcePatternToPrivs.containsKey(entry.getKey())) {
+                PrivBitSet existPrivs = resourcePatternToPrivs.get(entry.getKey());
+                existPrivs.or(entry.getValue());
+            } else {
+                resourcePatternToPrivs.put(entry.getKey(), entry.getValue());
+            }
+            grantPrivs(entry.getKey(), entry.getValue().copy());
+        }
+    }
+
+    public void merge(Role other) throws DdlException {
+        Preconditions.checkState(roleName.equalsIgnoreCase(other.getRoleName()));
+        mergeNotCheck(other);
+    }
+
+    public boolean checkGlobalPriv(PrivPredicate wanted) {
+        PrivBitSet savedPrivs = PrivBitSet.of();
+        return checkGlobalInternal(wanted, savedPrivs);
+    }
+
+    public boolean checkCtlPriv(String ctl, PrivPredicate wanted) {
+        PrivBitSet savedPrivs = PrivBitSet.of();
+        if (checkGlobalInternal(wanted, savedPrivs)
+                || checkCatalogInternal(ctl, wanted, savedPrivs)) {
+            return true;
+        }
+        // if user has any privs of databases or tables in this catalog, and the wanted priv is SHOW, return true
+        if (ctl != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinCatalog(ctl)) {
+            return true;
+        }
+        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
+        return false;
+    }
+
+    private boolean checkGlobalInternal(PrivPredicate wanted, PrivBitSet savedPrivs) {
+        globalPrivTable.getPrivs(savedPrivs);
+        if (Privilege.satisfy(savedPrivs, wanted)) {
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * User may not have privs on a catalog, but have privs of databases or tables in this catalog.
+     * So we have to check if user has any privs of databases or tables in this catalog.
+     * if so, the catalog should be visible to this user.
+     */
+    private boolean checkAnyPrivWithinCatalog(String ctl) {
+        return dbPrivTable.hasPrivsOfCatalog(ctl)
+                || tablePrivTable.hasPrivsOfCatalog(ctl);
+
+    }
+
+    private boolean checkCatalogInternal(String ctl, PrivPredicate wanted, PrivBitSet savedPrivs) {
+        catalogPrivTable.getPrivs(ctl, savedPrivs);
+        if (Privilege.satisfy(savedPrivs, wanted)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public boolean checkDbPriv(String ctl, String db, PrivPredicate wanted) {
+        PrivBitSet savedPrivs = PrivBitSet.of();
+        if (checkGlobalInternal(wanted, savedPrivs)
+                || checkCatalogInternal(ctl, wanted, savedPrivs)
+                || checkDbInternal(ctl, db, wanted, savedPrivs)) {
+            return true;
+        }
+
+        // if user has any privs of table in this db, and the wanted priv is SHOW, return true
+        if (ctl != null && db != null && wanted == PrivPredicate.SHOW && checkAnyPrivWithinDb(ctl, db)) {
+            return true;
+        }
+
+        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
+        return false;
+    }
+
+    /*
+     * User may not have privs on a database, but have privs of tables in this database.
+     * So we have to check if user has any privs of tables in this database.
+     * if so, the database should be visible to this user.
+     */
+    private boolean checkAnyPrivWithinDb(String ctl, String db) {
+        return tablePrivTable.hasPrivsOfDb(ctl, db);
+
+    }
+
+    private boolean checkDbInternal(String ctl, String db, PrivPredicate wanted,
+            PrivBitSet savedPrivs) {
+        dbPrivTable.getPrivs(ctl, db, savedPrivs);
+        if (Privilege.satisfy(savedPrivs, wanted)) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkTblPriv(String ctl, String db, String tbl, PrivPredicate wanted) {
+        PrivBitSet savedPrivs = PrivBitSet.of();
+        if (checkGlobalInternal(wanted, savedPrivs)
+                || checkCatalogInternal(ctl, wanted, savedPrivs)
+                || checkDbInternal(ctl, db, wanted, savedPrivs)
+                || checkTblInternal(ctl, db, tbl, wanted, savedPrivs)) {
+            return true;
+        }
+        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
+        return false;
+    }
+
+    private boolean checkTblInternal(String ctl, String db, String tbl, PrivPredicate wanted, PrivBitSet savedPrivs) {
+        tablePrivTable.getPrivs(ctl, db, tbl, savedPrivs);
+        return Privilege.satisfy(savedPrivs, wanted);
+    }
+
+    public boolean checkResourcePriv(String resourceName, PrivPredicate wanted) {
+        PrivBitSet savedPrivs = PrivBitSet.of();
+        if (checkGlobalInternal(wanted, savedPrivs)
+                || checkResourceInternal(resourceName, wanted, savedPrivs)) {
+            return true;
+        }
+
+        LOG.debug("failed to get wanted privs: {}, granted: {}", wanted, savedPrivs);
+        return false;
+    }
+
+    private boolean checkResourceInternal(String resourceName, PrivPredicate wanted, PrivBitSet savedPrivs) {
+        resourcePrivTable.getPrivs(resourceName, savedPrivs);
+        return Privilege.satisfy(savedPrivs, wanted);
+    }
+
+    public boolean checkHasPriv(PrivPredicate priv, PrivLevel[] levels) {
+        for (PrivLevel privLevel : levels) {
+            switch (privLevel) {
+                case GLOBAL:
+                    if (globalPrivTable.hasPriv(priv)) {
+                        return true;
+                    }
+                    break;
+                case DATABASE:
+                    if (dbPrivTable.hasPriv(priv)) {
+                        return true;
+                    }
+                    break;
+                case TABLE:
+                    if (tablePrivTable.hasPriv(priv)) {
+                        return true;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+        return false;
+    }
+
+    public GlobalPrivTable getGlobalPrivTable() {
+        return globalPrivTable;
+    }
+
+    public CatalogPrivTable getCatalogPrivTable() {
+        return catalogPrivTable;
+    }
+
+    public DbPrivTable getDbPrivTable() {
+        return dbPrivTable;
+    }
+
+    public TablePrivTable getTablePrivTable() {
+        return tablePrivTable;
+    }
+
+    public ResourcePrivTable getResourcePrivTable() {
+        return resourcePrivTable;
+    }
+
+    public boolean checkCanEnterCluster(String clusterName) {
+        if (checkGlobalPriv(PrivPredicate.ALL)) {
+            return true;
+        }
+
+        if (dbPrivTable.hasClusterPriv(clusterName)) {
+            return true;
+        }
+
+        if (tablePrivTable.hasClusterPriv(clusterName)) {
+            return true;
+        }
+        return false;
+    }
+
+
+    private void grantPrivs(ResourcePattern resourcePattern, PrivBitSet privs) throws DdlException {
+
+        // grant privs to user
+        switch (resourcePattern.getPrivLevel()) {
+            case GLOBAL:
+                grantGlobalPrivs(privs);
+                break;
+            case RESOURCE:
+                grantResourcePrivs(resourcePattern.getResourceName(), privs);
+                break;
+            default:
+                Preconditions.checkNotNull(null, resourcePattern.getPrivLevel());
+        }
+
+    }
+
+    private void grantPrivs(TablePattern tblPattern, PrivBitSet privs) throws DdlException {
+        // grant privs to user
+        switch (tblPattern.getPrivLevel()) {
+            case GLOBAL:
+                grantGlobalPrivs(privs);
+                break;
+            case CATALOG:
+                grantCatalogPrivs(tblPattern.getQualifiedCtl(),
+                        privs);
+                break;
+            case DATABASE:
+                grantDbPrivs(tblPattern.getQualifiedCtl(),
+                        tblPattern.getQualifiedDb(),
+                        privs);
+                break;
+            case TABLE:
+                grantTblPrivs(tblPattern.getQualifiedCtl(),
+                        tblPattern.getQualifiedDb(),
+                        tblPattern.getTbl(),
+                        privs);
+                break;
+            default:
+                Preconditions.checkNotNull(null, tblPattern.getPrivLevel());
+        }
+
+    }
+
+    private GlobalPrivEntry grantGlobalPrivs(PrivBitSet privs) throws DdlException {
+        GlobalPrivEntry entry = GlobalPrivEntry.create(privs);
+        globalPrivTable.addEntry(entry, false, false);
+        return entry;
+    }
+
+    private void grantResourcePrivs(String resourceName, PrivBitSet privs) throws DdlException {
+        ResourcePrivEntry entry;
+        try {
+            entry = ResourcePrivEntry.create(resourceName, privs);
+        } catch (AnalysisException | PatternMatcherException e) {
+            throw new DdlException(e.getMessage());
+        }
+        resourcePrivTable.addEntry(entry, false, false);
+    }
+
+    private void grantCatalogPrivs(String ctl, PrivBitSet privs) throws DdlException {
+        CatalogPrivEntry entry;
+        try {
+            entry = CatalogPrivEntry.create(ctl, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+        catalogPrivTable.addEntry(entry, false, false);
+    }
+
+    private void grantDbPrivs(String ctl, String db,
+            PrivBitSet privs) throws DdlException {
+        DbPrivEntry entry;
+        try {
+            entry = DbPrivEntry.create(ctl, db, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+        dbPrivTable.addEntry(entry, false, false);
+    }
+
+    private void grantTblPrivs(String ctl, String db, String tbl, PrivBitSet privs) throws DdlException {
+        TablePrivEntry entry;
+        try {
+            entry = TablePrivEntry.create(ctl, db, tbl, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+        tablePrivTable.addEntry(entry, false, false);
+    }
+
+    public void revokePrivs(TablePattern tblPattern, PrivBitSet privs, boolean errOnNonExist) throws DdlException {
+        PrivBitSet existingPriv = tblPatternToPrivs.get(tblPattern);
+        if (existingPriv == null) {
+            if (errOnNonExist) {
+                throw new DdlException(tblPattern + " does not exist in role " + roleName);
+            }
+            return;
+        }
+        existingPriv.remove(privs);
+        revokePrivs(tblPattern, privs);
+    }
+
+    public void revokePrivs(ResourcePattern resourcePattern, PrivBitSet privs, boolean errOnNonExist)
+            throws DdlException {
+        PrivBitSet existingPriv = resourcePatternToPrivs.get(resourcePattern);
+        if (existingPriv == null) {
+            if (errOnNonExist) {
+                throw new DdlException(resourcePattern + " does not exist in role " + roleName);
+            }
+            return;
+        }
+        existingPriv.remove(privs);
+        revokePrivs(resourcePattern, privs);
+    }
+
+    private void revokePrivs(ResourcePattern resourcePattern, PrivBitSet privs) throws DdlException {
+        switch (resourcePattern.getPrivLevel()) { // CHECKSTYLE IGNORE THIS LINE: missing switch default
+            case GLOBAL:
+                revokeGlobalPrivs(privs);
+                break;
+            case RESOURCE:
+                revokeResourcePrivs(resourcePattern.getResourceName(), privs);
+                break;
+        }
+    }
+
+    private void revokeResourcePrivs(String resourceName, PrivBitSet privs) throws DdlException {
+        ResourcePrivEntry entry;
+        try {
+            entry = ResourcePrivEntry.create(resourceName, privs);
+        } catch (AnalysisException | PatternMatcherException e) {
+            throw new DdlException(e.getMessage());
+        }
+        resourcePrivTable.revoke(entry, false, true);
+    }
+
+    private void revokePrivs(TablePattern tblPattern, PrivBitSet privs) throws DdlException {
+        switch (tblPattern.getPrivLevel()) {
+            case GLOBAL:
+                revokeGlobalPrivs(privs);
+                break;
+            case CATALOG:
+                revokeCatalogPrivs(tblPattern.getQualifiedCtl(), privs);
+                break;
+            case DATABASE:
+                revokeDbPrivs(tblPattern.getQualifiedCtl(),
+                        tblPattern.getQualifiedDb(), privs);
+                break;
+            case TABLE:
+                revokeTblPrivs(tblPattern.getQualifiedCtl(), tblPattern.getQualifiedDb(),
+                        tblPattern.getTbl(), privs);
+                break;
+            default:
+                Preconditions.checkNotNull(null, tblPattern.getPrivLevel());
+        }
+
+    }
+
+    private void revokeGlobalPrivs(PrivBitSet privs)
+            throws DdlException {
+        GlobalPrivEntry entry = GlobalPrivEntry.create(privs);
+        globalPrivTable.revoke(entry, false, false);
+    }
+
+    private void revokeCatalogPrivs(String ctl,
+            PrivBitSet privs) throws DdlException {
+        CatalogPrivEntry entry;
+        try {
+            entry = CatalogPrivEntry.create(
+                    ctl, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+        catalogPrivTable.revoke(entry, false, true);
+    }
+
+    private void revokeDbPrivs(String ctl, String db, PrivBitSet privs) throws DdlException {
+        DbPrivEntry entry;
+        try {
+            entry = DbPrivEntry.create(ctl, db, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+
+        dbPrivTable.revoke(entry, false, true);
+    }
+
+    private void revokeTblPrivs(String ctl, String db, String tbl,
+            PrivBitSet privs) throws DdlException {
+        TablePrivEntry entry;
+        try {
+            entry = TablePrivEntry.create(ctl, db, tbl, privs);
+        } catch (AnalysisException e) {
+            throw new DdlException(e.getMessage());
+        }
+        tablePrivTable.revoke(entry, false, true);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("role: ").append(roleName).append(", db table privs: ").append(tblPatternToPrivs);
+        sb.append(", resource privs: ").append(resourcePatternToPrivs);
+        return sb.toString();
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static Role read(DataInput in) throws IOException {
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_116) {
+            Role role = new Role();
+            try {
+                role.readFields(in);
+            } catch (DdlException e) {
+                LOG.warn("grant failed,", e);
+            }
+            return role;
+        } else {
+            String json = Text.readString(in);
+            return GsonUtils.GSON.fromJson(json, Role.class);
+        }
+    }
+
+    @Deprecated
+    private void readFields(DataInput in) throws IOException, DdlException {
+        roleName = Text.readString(in);
+        int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            TablePattern tblPattern = TablePattern.read(in);
+            PrivBitSet privs = PrivBitSet.read(in);
+            tblPatternToPrivs.put(tblPattern, privs);
+            grantPrivs(tblPattern, privs.copy());
+        }
+        size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            ResourcePattern resourcePattern = ResourcePattern.read(in);
+            PrivBitSet privs = PrivBitSet.read(in);
+            resourcePatternToPrivs.put(resourcePattern, privs);
+            grantPrivs(resourcePattern, privs.copy());
+        }
+        size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            UserIdentity userIdentity = UserIdentity.read(in);
+            users.add(userIdentity);
+        }
+
+    }
+
+    @Override
+    public void gsonPostProcess() throws IOException {
+        for (Entry<TablePattern, PrivBitSet> entry : tblPatternToPrivs.entrySet()) {
+            try {
+                grantPrivs(entry.getKey(), entry.getValue().copy());
+            } catch (DdlException e) {
+                LOG.warn("grant failed,", e);
+            }
+        }
+        for (Entry<ResourcePattern, PrivBitSet> entry : resourcePatternToPrivs.entrySet()) {
+            try {
+                grantPrivs(entry.getKey(), entry.getValue().copy());
+            } catch (DdlException e) {
+                LOG.warn("grant failed,", e);
+            }
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java
index 0a31786b84..851c19b3e0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RoleManager.java
@@ -20,15 +20,25 @@ package org.apache.doris.mysql.privilege;
 import org.apache.doris.analysis.ResourcePattern;
 import org.apache.doris.analysis.TablePattern;
 import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
-import org.apache.doris.mysql.privilege.PaloAuth.PrivLevel;
+import org.apache.doris.mysql.privilege.Auth.PrivLevel;
+import org.apache.doris.persist.gson.GsonUtils;
+import org.apache.doris.system.SystemInfoService;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.gson.annotations.SerializedName;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -40,19 +50,27 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class RoleManager implements Writable {
-    private Map<String, PaloRole> roles = Maps.newHashMap();
+    private static final Logger LOG = LogManager.getLogger(RoleManager.class);
+    //prefix of each user default role
+    public static String DEFAULT_ROLE_PREFIX = "default_role_rbac_";
+
+    // Concurrency control is delegated by Auth, so not concurrentMap
+    @SerializedName(value = "roles")
+    private Map<String, Role> roles = Maps.newHashMap();
 
     public RoleManager() {
-        roles.put(PaloRole.OPERATOR.getRoleName(), PaloRole.OPERATOR);
-        roles.put(PaloRole.ADMIN.getRoleName(), PaloRole.ADMIN);
+        roles.put(
+                Role.OPERATOR.getRoleName(), Role.OPERATOR);
+        roles.put(
+                Role.ADMIN.getRoleName(), Role.ADMIN);
     }
 
-    public PaloRole getRole(String role) {
-        return roles.get(role);
+    public Role getRole(String name) {
+        return roles.get(name);
     }
 
-    public PaloRole addRole(PaloRole newRole, boolean errOnExist) throws DdlException {
-        PaloRole existingRole = roles.get(newRole.getRoleName());
+    public Role addOrMergeRole(Role newRole, boolean errOnExist) throws DdlException {
+        Role existingRole = roles.get(newRole.getRoleName());
         if (existingRole != null) {
             if (errOnExist) {
                 throw new DdlException("Role " + newRole + " already exists");
@@ -78,90 +96,60 @@ public class RoleManager implements Writable {
         roles.remove(qualifiedRole);
     }
 
-    public PaloRole revokePrivs(String role, TablePattern tblPattern, PrivBitSet privs, boolean errOnNonExist)
+    public Role revokePrivs(String name, TablePattern tblPattern, PrivBitSet privs, boolean errOnNonExist)
             throws DdlException {
-        PaloRole existingRole = roles.get(role);
+        Role existingRole = roles.get(name);
         if (existingRole == null) {
             if (errOnNonExist) {
-                throw new DdlException("Role " + role + " does not exist");
-            }
-            return null;
-        }
-
-        Map<TablePattern, PrivBitSet> map = existingRole.getTblPatternToPrivs();
-        PrivBitSet existingPriv = map.get(tblPattern);
-        if (existingPriv == null) {
-            if (errOnNonExist) {
-                throw new DdlException(tblPattern + " does not exist in role " + role);
+                throw new DdlException("Role " + name + " does not exist");
             }
             return null;
         }
-
-        existingPriv.remove(privs);
+        existingRole.revokePrivs(tblPattern, privs, errOnNonExist);
         return existingRole;
     }
 
-    public PaloRole revokePrivs(String role, ResourcePattern resourcePattern, PrivBitSet privs, boolean errOnNonExist)
+    public Role revokePrivs(String role, ResourcePattern resourcePattern, PrivBitSet privs, boolean errOnNonExist)
             throws DdlException {
-        PaloRole existingRole = roles.get(role);
+        Role existingRole = roles.get(role);
         if (existingRole == null) {
             if (errOnNonExist) {
                 throw new DdlException("Role " + role + " does not exist");
             }
             return null;
         }
-
-        Map<ResourcePattern, PrivBitSet> map = existingRole.getResourcePatternToPrivs();
-        PrivBitSet existingPriv = map.get(resourcePattern);
-        if (existingPriv == null) {
-            if (errOnNonExist) {
-                throw new DdlException(resourcePattern + " does not exist in role " + role);
-            }
-            return null;
-        }
-
-        existingPriv.remove(privs);
+        existingRole.revokePrivs(resourcePattern, privs, errOnNonExist);
         return existingRole;
     }
 
-    public void dropUser(UserIdentity userIdentity) {
-        for (PaloRole role : roles.values()) {
-            role.dropUser(userIdentity);
-        }
-    }
-
-    public PaloRole findRoleForUser(UserIdentity userIdent) {
-        for (PaloRole role : roles.values()) {
-            if (role.containsUser(userIdent)) {
-                return role;
-            }
-        }
-        return null;
-    }
 
     public void getRoleInfo(List<List<String>> results) {
-        for (PaloRole role : roles.values()) {
+        for (Role role : roles.values()) {
+            if (role.getRoleName().startsWith(DEFAULT_ROLE_PREFIX)) {
+                continue;
+            }
             List<String> info = Lists.newArrayList();
             info.add(role.getRoleName());
-            info.add(Joiner.on(", ").join(role.getUsers()));
-
+            info.add(Joiner.on(", ").join(Env.getCurrentEnv().getAuth().getRoleUsers(role.getRoleName())));
             Map<PrivLevel, String> infoMap =
                     Stream.concat(
-                        role.getTblPatternToPrivs().entrySet().stream()
-                            .collect(Collectors.groupingBy(entry -> entry.getKey().getPrivLevel())).entrySet().stream(),
-                        role.getResourcePatternToPrivs().entrySet().stream()
-                            .collect(Collectors.groupingBy(entry -> entry.getKey().getPrivLevel())).entrySet().stream()
+                            role.getTblPatternToPrivs().entrySet().stream()
+                                    .collect(Collectors.groupingBy(entry -> entry.getKey().getPrivLevel())).entrySet()
+                                    .stream(),
+                            role.getResourcePatternToPrivs().entrySet().stream()
+                                    .collect(Collectors.groupingBy(entry -> entry.getKey().getPrivLevel())).entrySet()
+                                    .stream()
                     ).collect(Collectors.toMap(Entry::getKey, entry -> {
-                        if (entry.getKey() == PrivLevel.GLOBAL) {
-                            return entry.getValue().stream().findFirst().map(priv -> priv.getValue().toString())
-                                    .orElse(FeConstants.null_string);
-                        } else {
-                            return entry.getValue().stream()
-                                    .map(priv -> priv.getKey() + ": " + priv.getValue())
-                                    .collect(Collectors.joining("; "));
-                        }
-                    }, (s1, s2) -> s1 + " " + s2
-                ));
+                                if (entry.getKey() == PrivLevel.GLOBAL) {
+                                    return entry.getValue().stream().findFirst().map(priv -> priv.getValue().toString())
+                                            .orElse(FeConstants.null_string);
+                                } else {
+                                    return entry.getValue().stream()
+                                            .map(priv -> priv.getKey() + ": " + priv.getValue())
+                                            .collect(Collectors.joining("; "));
+                                }
+                            }, (s1, s2) -> s1 + " " + s2
+                    ));
             Stream.of(PrivLevel.GLOBAL, PrivLevel.CATALOG, PrivLevel.DATABASE, PrivLevel.TABLE, PrivLevel.RESOURCE)
                     .forEach(level -> {
                         String infoItem = infoMap.get(level);
@@ -174,38 +162,67 @@ public class RoleManager implements Writable {
         }
     }
 
-    public static RoleManager read(DataInput in) throws IOException {
-        RoleManager roleManager = new RoleManager();
-        roleManager.readFields(in);
-        return roleManager;
+    public Role createDefaultRole(UserIdentity userIdent) throws DdlException {
+        String userDefaultRoleName = getUserDefaultRoleName(userIdent);
+        if (roles.containsKey(userDefaultRoleName)) {
+            return roles.get(userDefaultRoleName);
+        }
+        // grant read privs to database information_schema
+        TablePattern tblPattern = new TablePattern(Auth.DEFAULT_CATALOG, InfoSchemaDb.DATABASE_NAME, "*");
+        try {
+            tblPattern.analyze(SystemInfoService.DEFAULT_CLUSTER);
+        } catch (AnalysisException e) {
+            LOG.warn("should not happen", e);
+        }
+        Role role = new Role(userDefaultRoleName, tblPattern,
+                PrivBitSet.of(Privilege.SELECT_PRIV));
+        roles.put(role.getRoleName(), role);
+        return role;
     }
 
-    @Override
-    public void write(DataOutput out) throws IOException {
-        // minus 2 to ignore ADMIN and OPERATOR role
-        out.writeInt(roles.size() - 2);
-        for (PaloRole role : roles.values()) {
-            if (role == PaloRole.ADMIN || role == PaloRole.OPERATOR) {
-                continue;
-            }
-            role.write(out);
-        }
+    public Role removeDefaultRole(UserIdentity userIdent) {
+        return roles.remove(getUserDefaultRoleName(userIdent));
     }
 
-    public void readFields(DataInput in) throws IOException {
-        int size = in.readInt();
-        for (int i = 0; i < size; i++) {
-            PaloRole role = PaloRole.read(in);
-            roles.put(role.getRoleName(), role);
-        }
+    public String getUserDefaultRoleName(UserIdentity userIdentity) {
+        return DEFAULT_ROLE_PREFIX + userIdentity.toString();
+    }
+
+    public Map<String, Role> getRoles() {
+        return roles;
     }
 
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("Roles: ");
-        for (PaloRole role : roles.values()) {
+        for (Role role : roles.values()) {
             sb.append(role).append("\n");
         }
         return sb.toString();
     }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static RoleManager read(DataInput in) throws IOException {
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_116) {
+            RoleManager roleManager = new RoleManager();
+            roleManager.readFields(in);
+            return roleManager;
+        } else {
+            String json = Text.readString(in);
+            return GsonUtils.GSON.fromJson(json, RoleManager.class);
+        }
+    }
+
+    @Deprecated
+    private void readFields(DataInput in) throws IOException {
+        int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            Role role = Role.read(in);
+            roles.put(role.getRoleName(), role);
+        }
+    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
index 165e531185..ce1b5a2ca2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
@@ -21,11 +21,9 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.CaseSensibility;
 import org.apache.doris.common.PatternMatcher;
 import org.apache.doris.common.PatternMatcherException;
-import org.apache.doris.common.PatternMatcherWrapper;
 import org.apache.doris.common.io.Text;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 
 public class TablePrivEntry extends DbPrivEntry {
@@ -38,13 +36,12 @@ public class TablePrivEntry extends DbPrivEntry {
     protected TablePrivEntry() {
     }
 
-    private TablePrivEntry(PatternMatcher userPattern, String user,
-                           PatternMatcher hostPattern, String origHost,
-                           PatternMatcher ctlPattern, String origCtl,
-                           PatternMatcher dbPattern, String origDb,
-                           PatternMatcher tblPattern, String origTbl,
-                           boolean isDomain, PrivBitSet privSet) {
-        super(userPattern, user, hostPattern, origHost, ctlPattern, origCtl, dbPattern, origDb, isDomain, privSet);
+    private TablePrivEntry(
+            PatternMatcher ctlPattern, String origCtl,
+            PatternMatcher dbPattern, String origDb,
+            PatternMatcher tblPattern, String origTbl,
+            PrivBitSet privSet) {
+        super(ctlPattern, origCtl, dbPattern, origDb, privSet);
         this.tblPattern = tblPattern;
         this.origTbl = origTbl;
         if (origTbl.equals(ANY_TBL)) {
@@ -52,14 +49,11 @@ public class TablePrivEntry extends DbPrivEntry {
         }
     }
 
-    public static TablePrivEntry create(String user, String host,
+    public static TablePrivEntry create(
             String ctl, String db, String tbl,
-            boolean isDomain, PrivBitSet privs) throws AnalysisException {
-        PatternMatcher hostPattern = PatternMatcherWrapper.createMysqlPattern(host,
-                CaseSensibility.HOST.getCaseSensibility());
+            PrivBitSet privs) throws AnalysisException {
         PatternMatcher dbPattern = PatternMatcher.createFlatPattern(
                 db, CaseSensibility.DATABASE.getCaseSensibility(), db.equals(ANY_DB));
-        PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
         PatternMatcher ctlPattern = PatternMatcher.createFlatPattern(
                 ctl, CaseSensibility.CATALOG.getCaseSensibility(), ctl.equals(ANY_CTL));
 
@@ -70,8 +64,8 @@ public class TablePrivEntry extends DbPrivEntry {
             throw new AnalysisException("Table privilege can not contains global or resource privileges: " + privs);
         }
 
-        return new TablePrivEntry(userPattern, user, hostPattern, host,
-                ctlPattern, ctl, dbPattern, db, tblPattern, tbl, isDomain, privs);
+        return new TablePrivEntry(
+                ctlPattern, ctl, dbPattern, db, tblPattern, tbl, privs);
     }
 
     public PatternMatcher getTblPattern() {
@@ -93,11 +87,10 @@ public class TablePrivEntry extends DbPrivEntry {
         }
 
         TablePrivEntry otherEntry = (TablePrivEntry) other;
-        return compareAssist(origUser, otherEntry.origUser,
-                             origHost, otherEntry.origHost,
-                             origCtl, otherEntry.origCtl,
-                             origDb, otherEntry.origDb,
-                             origTbl, otherEntry.origTbl);
+        return compareAssist(
+                origCtl, otherEntry.origCtl,
+                origDb, otherEntry.origDb,
+                origTbl, otherEntry.origTbl);
     }
 
     @Override
@@ -107,32 +100,17 @@ public class TablePrivEntry extends DbPrivEntry {
         }
 
         TablePrivEntry otherEntry = (TablePrivEntry) other;
-        return origUser.equals(otherEntry.origUser) && origHost.equals(otherEntry.origHost)
-                && origCtl.equals(otherEntry.origCtl) && origDb.equals(otherEntry.origDb)
-                && origTbl.equals(otherEntry.origTbl) && isDomain == otherEntry.isDomain;
+        return origCtl.equals(otherEntry.origCtl) && origDb.equals(otherEntry.origDb)
+                && origTbl.equals(otherEntry.origTbl);
     }
 
     @Override
     public String toString() {
-        return String.format("table privilege. user: %s, host: %s, "
-                        + "ctl: %s, db: %s, tbl: %s, priv: %s, set by resolver: %b",
-                origUser, origHost, origCtl, origDb, origTbl, privSet.toString(), isSetByDomainResolver);
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = TablePrivEntry.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-        super.write(out);
-
-        Text.writeString(out, origTbl);
-
-        isClassNameWrote = false;
+        return String.format("table privilege.ctl: %s, db: %s, tbl: %s, priv: %s", origCtl, origDb, origTbl,
+                privSet.toString());
     }
 
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java
index c4ded036f1..da31fa203a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivTable.java
@@ -17,15 +17,8 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.common.io.Text;
-import org.apache.doris.qe.ConnectContext;
-
 import com.google.common.base.Preconditions;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
 /*
  * TablePrivTable saves all table level privs
  */
@@ -35,14 +28,10 @@ public class TablePrivTable extends PrivTable {
      * Return first priv which match the user@host on ctl.db.tbl The returned priv will
      * be saved in 'savedPrivs'.
      */
-    public void getPrivs(UserIdentity currentUser, String ctl, String db, String tbl, PrivBitSet savedPrivs) {
+    public void getPrivs(String ctl, String db, String tbl, PrivBitSet savedPrivs) {
         TablePrivEntry matchedEntry = null;
         for (PrivEntry entry : entries) {
             TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
-            if (!tblPrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
             // check catalog
             if (!tblPrivEntry.isAnyCtl() && !tblPrivEntry.getCtlPattern().match(ctl)) {
                 continue;
@@ -69,14 +58,9 @@ public class TablePrivTable extends PrivTable {
         savedPrivs.or(matchedEntry.getPrivSet());
     }
 
-    public boolean hasPrivsOfCatalog(UserIdentity currentUser, String ctl) {
+    public boolean hasPrivsOfCatalog(String ctl) {
         for (PrivEntry entry : entries) {
             TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
-
-            if (!tblPrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
             // check catalog
             Preconditions.checkState(!tblPrivEntry.isAnyCtl());
             if (tblPrivEntry.getCtlPattern().match(ctl)) {
@@ -86,13 +70,10 @@ public class TablePrivTable extends PrivTable {
         return false;
     }
 
-    public boolean hasPrivsOfDb(UserIdentity currentUser, String ctl, String db) {
+    public boolean hasPrivsOfDb(String ctl, String db) {
         for (PrivEntry entry : entries) {
-            TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
-
-            if (!tblPrivEntry.match(currentUser, true)) {
-                continue;
-            }
+            TablePrivEntry
+                    tblPrivEntry = (TablePrivEntry) entry;
 
             // check catalog
             Preconditions.checkState(!tblPrivEntry.isAnyCtl());
@@ -111,18 +92,7 @@ public class TablePrivTable extends PrivTable {
         return false;
     }
 
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = TablePrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        super.write(out);
-    }
-
-    public boolean hasClusterPriv(ConnectContext ctx, String clusterName) {
+    public boolean hasClusterPriv(String clusterName) {
         for (PrivEntry entry : entries) {
             TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
             if (tblPrivEntry.getOrigDb().startsWith(clusterName)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/User.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/User.java
new file mode 100644
index 0000000000..afac0767e0
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/User.java
@@ -0,0 +1,163 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.common.CaseSensibility;
+import org.apache.doris.common.PatternMatcher;
+import org.apache.doris.common.PatternMatcherException;
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonPostProcessable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.gson.annotations.SerializedName;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+public class User implements Comparable<User>, Writable, GsonPostProcessable {
+    private static final Logger LOG = LogManager.getLogger(User.class);
+    @SerializedName(value = "userIdentity")
+    private UserIdentity userIdentity;
+    private UserIdentity domainUserIdentity;
+    private boolean isSetByDomainResolver = false;
+    // host is not case sensitive
+    protected PatternMatcher hostPattern;
+    protected boolean isAnyHost = false;
+    @SerializedName(value = "password")
+    private Password password;
+
+    public User() {
+    }
+
+    public User(UserIdentity userIdent, byte[] pwd, boolean setByResolver, UserIdentity domainUserIdent,
+            PatternMatcher hostPattern) {
+        this.isAnyHost = userIdent.getHost().equals(UserManager.ANY_HOST);
+        this.userIdentity = userIdent;
+        this.password = new Password(pwd);
+        this.hostPattern = hostPattern;
+        this.isSetByDomainResolver = setByResolver;
+        if (setByResolver) {
+            Preconditions.checkNotNull(domainUserIdent);
+            this.domainUserIdentity = domainUserIdent;
+        }
+    }
+
+
+    public Password getPassword() {
+        return password;
+    }
+
+    public void setPassword(Password password) {
+        this.password = password;
+    }
+
+    public void setPassword(byte[] password) {
+        this.password = new Password(password);
+    }
+
+    public UserIdentity getUserIdentity() {
+        return userIdentity;
+    }
+
+    public void setUserIdentity(UserIdentity userIdentity) {
+        this.userIdentity = userIdentity;
+    }
+
+    public UserIdentity getDomainUserIdentity() {
+        if (isSetByDomainResolver()) {
+            return domainUserIdentity;
+        } else {
+            return userIdentity;
+        }
+
+    }
+
+    public void setDomainUserIdentity(UserIdentity domainUserIdentity) {
+        this.domainUserIdentity = domainUserIdentity;
+    }
+
+    public boolean isSetByDomainResolver() {
+        return isSetByDomainResolver;
+    }
+
+    public void setSetByDomainResolver(boolean setByDomainResolver) {
+        isSetByDomainResolver = setByDomainResolver;
+    }
+
+    public PatternMatcher getHostPattern() {
+        return hostPattern;
+    }
+
+    public void setHostPattern(PatternMatcher hostPattern) {
+        this.hostPattern = hostPattern;
+    }
+
+    public boolean isAnyHost() {
+        return isAnyHost;
+    }
+
+    public void setAnyHost(boolean anyHost) {
+        isAnyHost = anyHost;
+    }
+
+    public boolean hasPassword() {
+        return password != null && password.getPassword() != null && password.getPassword().length != 0;
+    }
+
+    @Override
+    public int compareTo(@NotNull User o) {
+        return -userIdentity.getHost().compareTo(o.userIdentity.getHost());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("userIdentity: ").append(userIdentity).append(", isSetByDomainResolver: ")
+                .append(isSetByDomainResolver).append(", domainUserIdentity: ").append(domainUserIdentity);
+        return sb.toString();
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static User read(DataInput in) throws IOException {
+        String json = Text.readString(in);
+        return GsonUtils.GSON.fromJson(json, User.class);
+    }
+
+    @Override
+    public void gsonPostProcess() throws IOException {
+        try {
+            hostPattern = PatternMatcher
+                    .createMysqlPattern(userIdentity.getHost(), CaseSensibility.HOST.getCaseSensibility());
+        } catch (PatternMatcherException e) {
+            // will not happen
+            LOG.warn("readFields error,", e);
+        }
+        isAnyHost = userIdentity.getHost().equals(UserManager.ANY_HOST);
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserManager.java
new file mode 100644
index 0000000000..5dcd08080a
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserManager.java
@@ -0,0 +1,302 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.AuthenticationException;
+import org.apache.doris.common.CaseSensibility;
+import org.apache.doris.common.DdlException;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.PatternMatcher;
+import org.apache.doris.common.PatternMatcherException;
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.mysql.MysqlPassword;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.gson.annotations.SerializedName;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class UserManager implements Writable {
+    public static final String ANY_HOST = "%";
+    private static final Logger LOG = LogManager.getLogger(UserManager.class);
+    // Concurrency control is delegated by Auth, so not concurrentMap
+    //One name may have multiple User,because host can be different
+    @SerializedName(value = "nameToUsers")
+    private Map<String, List<User>> nameToUsers = Maps.newHashMap();
+
+    public boolean userIdentityExist(UserIdentity userIdentity, boolean includeByDomain) {
+        List<User> users = nameToUsers.get(userIdentity.getQualifiedUser());
+        if (CollectionUtils.isEmpty(users)) {
+            return false;
+        }
+        for (User user : users) {
+            if (user.getUserIdentity().getHost().equalsIgnoreCase(userIdentity.getHost())) {
+                if (includeByDomain || !user.isSetByDomainResolver()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public List<User> getUserByName(String name) {
+        List<User> users = nameToUsers.get(name);
+        return users == null ? Collections.EMPTY_LIST : users;
+    }
+
+    public void checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString,
+            List<UserIdentity> currentUser) throws AuthenticationException {
+        checkPasswordInternal(remoteUser, remoteHost, remotePasswd, randomString, null, currentUser, false);
+    }
+
+    public void checkPlainPassword(String remoteUser, String remoteHost, String remotePasswd,
+            List<UserIdentity> currentUser) throws AuthenticationException {
+        checkPasswordInternal(remoteUser, remoteHost, null, null, remotePasswd, currentUser, true);
+    }
+
+    private void checkPasswordInternal(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString,
+            String remotePasswdStr, List<UserIdentity> currentUser, boolean plain) throws AuthenticationException {
+        PasswordPolicyManager passwdPolicyMgr = Env.getCurrentEnv().getAuth().getPasswdPolicyManager();
+        List<User> users = nameToUsers.get(remoteUser);
+        if (CollectionUtils.isEmpty(users)) {
+            throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
+                    "YES");
+        }
+
+        for (User user : users) {
+            if (user.getUserIdentity().isDomain()) {
+                continue;
+            }
+            // check host
+            if (!user.isAnyHost() && !user.getHostPattern().match(remoteHost)) {
+                continue;
+            }
+            UserIdentity curUser = user.getDomainUserIdentity();
+            if (comparePassword(user.getPassword(), remotePasswd, randomString, remotePasswdStr, plain)) {
+                passwdPolicyMgr.checkAccountLockedAndPasswordExpiration(curUser);
+                if (currentUser != null) {
+                    currentUser.add(curUser);
+                }
+                return;
+            } else {
+                // case A. this means we already matched a entry by user@host, but password is incorrect.
+                // return false, NOT continue matching other entries.
+                // For example, there are 2 entries in order:
+                // 1. cmy@"192.168.%" identified by '123';
+                // 2. cmy@"%" identified by 'abc';
+                // if user cmy@'192.168.1.1' try to login with password 'abc', it will be denied.
+                passwdPolicyMgr.onFailedLogin(curUser);
+                throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
+                        hasRemotePasswd(plain, remotePasswd));
+            }
+        }
+        throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
+                hasRemotePasswd(plain, remotePasswd));
+    }
+
+    private String hasRemotePasswd(boolean plain, byte[] remotePasswd) {
+        if (plain) {
+            return "YES";
+        }
+        return remotePasswd.length == 0 ? "NO" : "YES";
+    }
+
+    private boolean comparePassword(Password curUserPassword, byte[] remotePasswd,
+            byte[] randomString, String remotePasswdStr, boolean plain) {
+        // check password
+        if (plain) {
+            return MysqlPassword.checkPlainPass(curUserPassword.getPassword(), remotePasswdStr);
+        } else {
+            byte[] saltPassword = MysqlPassword.getSaltFromPassword(curUserPassword.getPassword());
+            // when the length of password is zero, the user has no password
+            return ((remotePasswd.length == saltPassword.length)
+                    && (remotePasswd.length == 0
+                    || MysqlPassword.checkScramble(remotePasswd, randomString, saltPassword)));
+        }
+    }
+
+
+    public void clearEntriesSetByResolver() {
+        Iterator<Entry<String, List<User>>> iterator = nameToUsers.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Entry<String, List<User>> next = iterator.next();
+            Iterator<User> iter = next.getValue().iterator();
+            while (iter.hasNext()) {
+                User user = iter.next();
+                if (user.isSetByDomainResolver()) {
+                    iter.remove();
+                }
+            }
+            if (CollectionUtils.isEmpty(next.getValue())) {
+                iterator.remove();
+            } else {
+                Collections.sort(next.getValue());
+            }
+        }
+
+    }
+
+    public User createUser(UserIdentity userIdent, byte[] pwd, UserIdentity domainUserIdent, boolean setByResolver)
+            throws PatternMatcherException {
+        if (userIdentityExist(userIdent, true)) {
+            User userByUserIdentity = getUserByUserIdentity(userIdent);
+            userByUserIdentity.setPassword(pwd);
+            userByUserIdentity.setSetByDomainResolver(setByResolver);
+            return userByUserIdentity;
+        }
+
+        PatternMatcher hostPattern = PatternMatcher
+                .createMysqlPattern(userIdent.getHost(), CaseSensibility.HOST.getCaseSensibility());
+        User user = new User(userIdent, pwd, setByResolver, domainUserIdent, hostPattern);
+        List<User> nameToLists = nameToUsers.get(userIdent.getQualifiedUser());
+        if (CollectionUtils.isEmpty(nameToLists)) {
+            nameToLists = Lists.newArrayList(user);
+            nameToUsers.put(userIdent.getQualifiedUser(), nameToLists);
+        } else {
+            nameToLists.add(user);
+            Collections.sort(nameToLists);
+        }
+        return user;
+    }
+
+    public User getUserByUserIdentity(UserIdentity userIdent) {
+        List<User> nameToLists = nameToUsers.get(userIdent.getQualifiedUser());
+        if (CollectionUtils.isEmpty(nameToLists)) {
+            return null;
+        }
+        Iterator<User> iter = nameToLists.iterator();
+        while (iter.hasNext()) {
+            User user = iter.next();
+            if (user.getUserIdentity().equals(userIdent)) {
+                return user;
+            }
+        }
+        return null;
+    }
+
+    public void removeUser(UserIdentity userIdent) {
+        List<User> nameToLists = nameToUsers.get(userIdent.getQualifiedUser());
+        if (CollectionUtils.isEmpty(nameToLists)) {
+            return;
+        }
+        Iterator<User> iter = nameToLists.iterator();
+        while (iter.hasNext()) {
+            User user = iter.next();
+            if (user.getUserIdentity().equals(userIdent)) {
+                iter.remove();
+            }
+        }
+        if (CollectionUtils.isEmpty(nameToLists)) {
+            nameToUsers.remove(userIdent.getQualifiedUser());
+        } else {
+            Collections.sort(nameToLists);
+        }
+    }
+
+    public Map<String, List<User>> getNameToUsers() {
+        return nameToUsers;
+    }
+
+    public void setPassword(UserIdentity userIdentity, byte[] password, boolean errOnNonExist) throws DdlException {
+        User user = getUserByUserIdentity(userIdentity);
+        if (user == null) {
+            if (errOnNonExist) {
+                throw new DdlException("user " + userIdentity + " does not exist");
+            }
+            return;
+        }
+        user.setPassword(password);
+    }
+
+    public void getAllDomains(Set<String> allDomains) {
+        for (Entry<String, List<User>> entry : nameToUsers.entrySet()) {
+            for (User user : entry.getValue()) {
+                if (user.getUserIdentity().isDomain()) {
+                    allDomains.add(user.getUserIdentity().getHost());
+                }
+            }
+        }
+    }
+
+    // handle new resolved IPs.
+    // it will only modify password entry of these resolved IPs. All other privileges are binded
+    // to the domain, so no need to modify.
+    public void addUserPrivEntriesByResolvedIPs(Map<String, Set<String>> resolvedIPsMap) {
+        for (Entry<String, List<User>> userEntry : nameToUsers.entrySet()) {
+            for (Map.Entry<String, Set<String>> entry : resolvedIPsMap.entrySet()) {
+                User domainUser = getDomainUser(userEntry.getValue(), entry.getKey());
+                if (domainUser == null) {
+                    continue;
+                }
+                // this user ident will be saved along with each resolved "IP" user ident, so that when checking
+                // password, this "domain" user ident will be returned as "current user".
+                for (String newIP : entry.getValue()) {
+                    UserIdentity userIdent = UserIdentity.createAnalyzedUserIdentWithIp(userEntry.getKey(), newIP);
+                    byte[] password = domainUser.getPassword().getPassword();
+                    Preconditions.checkNotNull(password, entry.getKey());
+                    try {
+                        createUser(userIdent, password, domainUser.getUserIdentity(), true);
+                    } catch (PatternMatcherException e) {
+                        LOG.info("failed to create user for user ident: {}, {}", userIdent, e.getMessage());
+                    }
+                }
+            }
+        }
+    }
+
+    private User getDomainUser(List<User> users, String domain) {
+        for (User user : users) {
+            if (user.getUserIdentity().isDomain() && user.getUserIdentity().getHost().equals(domain)) {
+                return user;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return nameToUsers.toString();
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static UserManager read(DataInput in) throws IOException {
+        String json = Text.readString(in);
+        return GsonUtils.GSON.fromJson(json, UserManager.class);
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java
index 35736b29fe..ff5d9e2e34 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPrivTable.java
@@ -18,181 +18,23 @@
 package org.apache.doris.mysql.privilege;
 
 import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.common.AuthenticationException;
-import org.apache.doris.common.DdlException;
-import org.apache.doris.common.ErrorCode;
-import org.apache.doris.common.io.Text;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.mysql.MysqlPassword;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.DataOutput;
 import java.io.IOException;
-import java.util.List;
 
 /*
  * UserPrivTable saves all global privs and also password for users
  */
+@Deprecated
 public class UserPrivTable extends PrivTable {
     private static final Logger LOG = LogManager.getLogger(UserPrivTable.class);
 
     public UserPrivTable() {
     }
 
-    public void getPrivs(UserIdentity currentUser, PrivBitSet savedPrivs) {
-        GlobalPrivEntry matchedEntry = null;
-        for (PrivEntry entry : entries) {
-            GlobalPrivEntry globalPrivEntry = (GlobalPrivEntry) entry;
-
-            if (!globalPrivEntry.match(currentUser, true)) {
-                continue;
-            }
-
-            matchedEntry = globalPrivEntry;
-            break;
-        }
-        if (matchedEntry == null) {
-            return;
-        }
-
-        savedPrivs.or(matchedEntry.getPrivSet());
-    }
-
-    // validate the connection by host, user and password.
-    // return true if this connection is valid, and 'savedPrivs' save all global privs got from user table.
-    // if currentUser is not null, save the current user identity
-    public void checkPassword(String remoteUser, String remoteHost, byte[] remotePasswd, byte[] randomString,
-            List<UserIdentity> currentUser) throws AuthenticationException {
-        LOG.debug("check password for user: {} from {}, password: {}, random string: {}",
-                remoteUser, remoteHost, remotePasswd, randomString);
-
-        PasswordPolicyManager passwdPolicyMgr = Env.getCurrentEnv().getAuth().getPasswdPolicyManager();
-        // TODO(cmy): for now, we check user table from first entry to last,
-        // This may not efficient, but works.
-        for (PrivEntry entry : entries) {
-            GlobalPrivEntry globalPrivEntry = (GlobalPrivEntry) entry;
-
-            // check host
-            if (!globalPrivEntry.isAnyHost() && !globalPrivEntry.getHostPattern().match(remoteHost)) {
-                continue;
-            }
-
-            // check user
-            if (!globalPrivEntry.isAnyUser() && !globalPrivEntry.getUserPattern().match(remoteUser)) {
-                continue;
-            }
-
-            UserIdentity curUser = globalPrivEntry.getDomainUserIdent();
-            // check password
-            byte[] saltPassword = MysqlPassword.getSaltFromPassword(globalPrivEntry.getPassword());
-            // when the length of password is zero, the user has no password
-            if ((remotePasswd.length == saltPassword.length)
-                    && (remotePasswd.length == 0
-                            || MysqlPassword.checkScramble(remotePasswd, randomString, saltPassword))) {
-                passwdPolicyMgr.checkAccountLockedAndPasswordExpiration(curUser);
-                // found the matched entry
-                if (currentUser != null) {
-                    currentUser.add(curUser);
-                }
-                return;
-            } else {
-                // case A. this means we already matched a entry by user@host, but password is incorrect.
-                // return false, NOT continue matching other entries.
-                // For example, there are 2 entries in order:
-                // 1. cmy@"192.168.%" identified by '123';
-                // 2. cmy@"%" identified by 'abc';
-                // if user cmy@'192.168.1.1' try to login with password 'abc', it will be denied.
-                passwdPolicyMgr.onFailedLogin(curUser);
-                throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
-                        remotePasswd.length == 0 ? "NO" : "YES");
-            }
-        }
-
-        throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
-                remotePasswd.length == 0 ? "NO" : "YES");
-    }
-
-    public void checkPlainPassword(String remoteUser, String remoteHost, String remotePasswd,
-            List<UserIdentity> currentUser) throws AuthenticationException {
-        PasswordPolicyManager passwdPolicyMgr = Env.getCurrentEnv().getAuth().getPasswdPolicyManager();
-
-        for (PrivEntry entry : entries) {
-            GlobalPrivEntry globalPrivEntry = (GlobalPrivEntry) entry;
-
-            // check host
-            if (!globalPrivEntry.isAnyHost() && !globalPrivEntry.getHostPattern().match(remoteHost)) {
-                continue;
-            }
-
-            // check user
-            if (!globalPrivEntry.isAnyUser() && !globalPrivEntry.getUserPattern().match(remoteUser)) {
-                continue;
-            }
-
-            UserIdentity curUser = globalPrivEntry.getDomainUserIdent();
-            if (MysqlPassword.checkPlainPass(globalPrivEntry.getPassword(), remotePasswd)) {
-                passwdPolicyMgr.checkAccountLockedAndPasswordExpiration(curUser);
-                if (currentUser != null) {
-                    currentUser.add(globalPrivEntry.getDomainUserIdent());
-                }
-                return;
-            } else {
-                // set case A. in checkPassword()
-                passwdPolicyMgr.onFailedLogin(curUser);
-                throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
-                        "YES");
-            }
-        }
-        throw new AuthenticationException(ErrorCode.ERR_ACCESS_DENIED_ERROR, remoteUser + "@" + remoteHost,
-                "YES");
-    }
-
-
-    /*
-     * set password for specified entry. It is same as adding an entry to the user priv table.
-     */
-    public void setPassword(GlobalPrivEntry passwdEntry, boolean errOnNonExist) throws DdlException {
-        GlobalPrivEntry addedEntry = (GlobalPrivEntry) addEntry(passwdEntry, false /* err on exist */,
-                errOnNonExist /* err on non exist */);
-        addedEntry.setPassword(passwdEntry.getPassword());
-    }
-
-    // return true only if user exist and not set by domain
-    // user set by domain should be checked in property manager
-    public boolean doesUserExist(UserIdentity userIdent) {
-        for (PrivEntry privEntry : entries) {
-            if (privEntry.match(userIdent, true /* exact match */) && !privEntry.isSetByDomainResolver()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // Check whether the user exists and return the UserIdentity.
-    public UserIdentity getCurrentUserIdentity(UserIdentity userIdent) {
-        for (PrivEntry privEntry : entries) {
-            GlobalPrivEntry globalPrivEntry = (GlobalPrivEntry) privEntry;
-            if (globalPrivEntry.match(userIdent, false)) {
-                return globalPrivEntry.getDomainUserIdent();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        if (!isClassNameWrote) {
-            String className = UserPrivTable.class.getCanonicalName();
-            Text.writeString(out, className);
-            isClassNameWrote = true;
-        }
-
-        super.write(out);
-    }
-
     /**
      * When replay UserPrivTable from journal whose FeMetaVersion < VERSION_111, the global-level privileges should
      * degrade to internal-catalog-level privileges.
@@ -207,15 +49,15 @@ public class UserPrivTable extends PrivTable {
                 try {
                     // USAGE_PRIV is no need to degrade.
                     PrivBitSet removeUsagePriv = globalPrivEntry.privSet.copy();
-                    removeUsagePriv.unset(PaloPrivilege.USAGE_PRIV.getIdx());
-                    removeUsagePriv.unset(PaloPrivilege.NODE_PRIV.getIdx());
+                    removeUsagePriv.unset(Privilege.USAGE_PRIV.getIdx());
+                    removeUsagePriv.unset(Privilege.NODE_PRIV.getIdx());
                     CatalogPrivEntry entry = CatalogPrivEntry.create(globalPrivEntry.origUser, globalPrivEntry.origHost,
                             InternalCatalog.INTERNAL_CATALOG_NAME, globalPrivEntry.isDomain, removeUsagePriv);
                     entry.setSetByDomainResolver(false);
                     catalogPrivTable.addEntry(entry, false, false);
                     if (globalPrivEntry.privSet.containsResourcePriv()) {
                         // Should only keep the USAGE_PRIV in userPrivTable, and remove other privs and entries.
-                        globalPrivEntry.privSet.and(PrivBitSet.of(PaloPrivilege.USAGE_PRIV));
+                        globalPrivEntry.privSet.and(PrivBitSet.of(Privilege.USAGE_PRIV));
                     } else {
                         // Remove all other privs
                         globalPrivEntry.privSet.clean();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserProperty.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserProperty.java
index 741493a4c4..703c699739 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserProperty.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserProperty.java
@@ -90,6 +90,7 @@ public class UserProperty implements Writable {
      *  Each frontend will periodically resolve the domain name to ip, and update the privilege table.
      *  We never persist the resolved IPs.
      */
+    @Deprecated
     private WhiteList whiteList = new WhiteList();
 
     public static final Set<Tag> INVALID_RESOURCE_TAGS;
@@ -148,6 +149,7 @@ public class UserProperty implements Writable {
         return commonProperties.getCpuResourceLimit();
     }
 
+    @Deprecated
     public WhiteList getWhiteList() {
         return whiteList;
     }
@@ -160,20 +162,6 @@ public class UserProperty implements Writable {
         return commonProperties.getExecMemLimit();
     }
 
-    public void setPasswordForDomain(String domain, byte[] password, boolean errOnExist) throws DdlException {
-        if (errOnExist && whiteList.containsDomain(domain)) {
-            throw new DdlException("Domain " + domain + " of user " + qualifiedUser + " already exists");
-        }
-
-        if (password != null) {
-            whiteList.setPassword(domain, password);
-        }
-    }
-
-    public void removeDomain(String domain) {
-        whiteList.removeDomain(domain);
-    }
-
     public void update(List<Pair<String, String>> properties) throws UserException {
         // copy
         long newMaxConn = this.commonProperties.getMaxConn();
@@ -524,16 +512,6 @@ public class UserProperty implements Writable {
                     String.valueOf(dppConfig.getPriority())));
         }
 
-        // get resolved ips if user has domain
-        Map<String, Set<String>> resolvedIPs = whiteList.getResolvedIPs();
-        List<String> ips = Lists.newArrayList();
-        for (Map.Entry<String, Set<String>> entry : resolvedIPs.entrySet()) {
-            ips.add(entry.getKey() + ":" + Joiner.on(",").join(entry.getValue()));
-        }
-        if (!ips.isEmpty()) {
-            result.add(Lists.newArrayList("resolved IPs", Joiner.on(";").join(ips)));
-        }
-
         // sort
         Collections.sort(result, new Comparator<List<String>>() {
             @Override
@@ -572,9 +550,6 @@ public class UserProperty implements Writable {
             entry.getValue().write(out);
         }
 
-        // whiteList
-        whiteList.write(out);
-
         // common properties
         commonProperties.write(out);
     }
@@ -604,7 +579,11 @@ public class UserProperty implements Writable {
         }
 
         // whiteList
-        whiteList.readFields(in);
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_116) {
+            whiteList.readFields(in);
+        } else {
+            whiteList = new WhiteList();
+        }
 
         // common properties
         if (Env.getCurrentEnvJournalVersion() >= FeMetaVersion.VERSION_100) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
index df666e7ea5..79c38b5bb0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserPropertyMgr.java
@@ -30,7 +30,6 @@ import org.apache.doris.resource.Tag;
 import org.apache.doris.thrift.TAgentServiceVersion;
 import org.apache.doris.thrift.TFetchResourceResult;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -90,31 +89,6 @@ public class UserPropertyMgr implements Writable {
         resourceVersion.incrementAndGet();
     }
 
-    public void setPasswordForDomain(UserIdentity userIdentity, byte[] password, boolean errOnExist,
-            boolean errOnNonExist) throws DdlException {
-        Preconditions.checkArgument(userIdentity.isDomain());
-        UserProperty property = propertyMap.get(userIdentity.getQualifiedUser());
-        if (property == null) {
-            if (errOnNonExist) {
-                throw new DdlException("user " + userIdentity + " does not exist");
-            }
-            property = new UserProperty(userIdentity.getQualifiedUser());
-        }
-        property.setPasswordForDomain(userIdentity.getHost(), password, errOnExist);
-        // update propertyMap after setPasswordForDomain, cause setPasswordForDomain may throw exception
-        propertyMap.put(userIdentity.getQualifiedUser(), property);
-    }
-
-    public void removeDomainFromUser(UserIdentity userIdentity) {
-        Preconditions.checkArgument(userIdentity.isDomain());
-        UserProperty userProperty = propertyMap.get(userIdentity.getQualifiedUser());
-        if (userProperty == null) {
-            return;
-        }
-        userProperty.removeDomain(userIdentity.getHost());
-        resourceVersion.incrementAndGet();
-    }
-
     public void dropUser(UserIdentity userIdent) {
         if (propertyMap.remove(userIdent.getQualifiedUser()) != null) {
             LOG.info("drop user {} from user property manager", userIdent.getQualifiedUser());
@@ -223,39 +197,6 @@ public class UserPropertyMgr implements Writable {
         return property.fetchProperty();
     }
 
-    // return a map from domain name -> set of user names
-    public void getAllDomains(Set<String> allDomains) {
-        LOG.debug("get property map: {}", propertyMap);
-        for (Map.Entry<String, UserProperty> entry : propertyMap.entrySet()) {
-            Set<String> domains = entry.getValue().getWhiteList().getAllDomains();
-            allDomains.addAll(domains);
-        }
-    }
-
-    // check if specified user identity has password
-    public boolean doesUserHasPassword(UserIdentity userIdent) {
-        Preconditions.checkState(userIdent.isDomain());
-        if (!propertyMap.containsKey(userIdent.getQualifiedUser())) {
-            return false;
-        }
-        return propertyMap.get(userIdent.getQualifiedUser()).getWhiteList().hasPassword(userIdent.getHost());
-    }
-
-    public boolean doesUserExist(UserIdentity userIdent) {
-        Preconditions.checkState(userIdent.isDomain());
-        if (!propertyMap.containsKey(userIdent.getQualifiedUser())) {
-            return false;
-        }
-        return propertyMap.get(userIdent.getQualifiedUser()).getWhiteList().containsDomain(userIdent.getHost());
-    }
-
-    public void addUserPrivEntriesByResolvedIPs(Map<String, Set<String>> resolvedIPsMap) {
-        for (UserProperty userProperty : propertyMap.values()) {
-            userProperty.getWhiteList()
-                    .addUserPrivEntriesByResolvedIPs(userProperty.getQualifiedUser(), resolvedIPsMap);
-        }
-    }
-
     public String[] getSqlBlockRules(String qualifiedUser) {
         UserProperty existProperty = propertyMap.get(qualifiedUser);
         existProperty = getLdapPropertyIfNull(qualifiedUser, existProperty);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserRoleManager.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserRoleManager.java
new file mode 100644
index 0000000000..60939a370d
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/UserRoleManager.java
@@ -0,0 +1,134 @@
+// 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.mysql.privilege;
+
+import org.apache.doris.analysis.UserIdentity;
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonPostProcessable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.gson.annotations.SerializedName;
+import org.apache.commons.collections.CollectionUtils;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class UserRoleManager implements Writable, GsonPostProcessable {
+    // Concurrency control is delegated by Auth, so not concurrentMap
+    @SerializedName(value = "userToRoles")
+    private Map<UserIdentity, Set<String>> userToRoles = Maps.newHashMap();
+    // Will not be persisted,generage by userToRoles
+    private Map<String, Set<UserIdentity>> roleToUsers = Maps.newHashMap();
+
+    public void addUserRole(UserIdentity userIdentity, String roleName) {
+        Set<String> roles = userToRoles.get(userIdentity);
+        if (CollectionUtils.isEmpty(roles)) {
+            roles = Sets.newHashSet();
+        }
+        roles.add(roleName);
+        userToRoles.put(userIdentity, roles);
+        Set<UserIdentity> userIdentities = roleToUsers.get(roleName);
+        if (CollectionUtils.isEmpty(userIdentities)) {
+            userIdentities = Sets.newHashSet();
+        }
+        userIdentities.add(userIdentity);
+        roleToUsers.put(roleName, userIdentities);
+    }
+
+    public void dropUser(UserIdentity userIdentity) {
+        if (!userToRoles.containsKey(userIdentity)) {
+            return;
+        }
+        Set<String> roles = userToRoles.remove(userIdentity);
+        for (String roleName : roles) {
+            Set<UserIdentity> userIdentities = roleToUsers.get(roleName);
+            if (CollectionUtils.isEmpty(userIdentities)) {
+                continue;
+            }
+            userIdentities.remove(userIdentity);
+            if (CollectionUtils.isEmpty(userIdentities)) {
+                roleToUsers.remove(roleName);
+            }
+        }
+    }
+
+    public void dropRole(String roleName) {
+        if (!roleToUsers.containsKey(roleName)) {
+            return;
+        }
+        Set<UserIdentity> remove = roleToUsers.remove(roleName);
+        for (UserIdentity userIdentity : remove) {
+            Set<String> roles = userToRoles.get(userIdentity);
+            if (CollectionUtils.isEmpty(roles)) {
+                continue;
+            }
+            roles.remove(roleName);
+            if (CollectionUtils.isEmpty(roles)) {
+                userToRoles.remove(userIdentity);
+            }
+        }
+    }
+
+    public Set<String> getRolesByUser(UserIdentity user) {
+        Set<String> roles = userToRoles.get(user);
+        return roles == null ? Collections.EMPTY_SET : roles;
+    }
+
+    public Set<UserIdentity> getUsersByRole(String roleName) {
+        Set<UserIdentity> userIdentities = roleToUsers.get(roleName);
+        return userIdentities == null ? Collections.EMPTY_SET : userIdentities;
+    }
+
+    @Override
+    public String toString() {
+        return userToRoles.toString();
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
+
+    public static UserRoleManager read(DataInput in) throws IOException {
+        String json = Text.readString(in);
+        return GsonUtils.GSON.fromJson(json, UserRoleManager.class);
+    }
+
+    @Override
+    public void gsonPostProcess() throws IOException {
+        roleToUsers = Maps.newHashMap();
+        for (Entry<UserIdentity, Set<String>> entry : userToRoles.entrySet()) {
+            for (String roleName : entry.getValue()) {
+                Set<UserIdentity> userIdentities = roleToUsers.get(roleName);
+                if (CollectionUtils.isEmpty(userIdentities)) {
+                    userIdentities = Sets.newHashSet();
+                }
+                userIdentities.add(entry.getKey());
+                roleToUsers.put(roleName, userIdentities);
+            }
+        }
+    }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/WhiteList.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/WhiteList.java
index 00e1dd8f66..b007958678 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/WhiteList.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/WhiteList.java
@@ -17,118 +17,25 @@
 
 package org.apache.doris.mysql.privilege;
 
-import org.apache.doris.analysis.TablePattern;
-import org.apache.doris.analysis.UserIdentity;
-import org.apache.doris.catalog.Env;
-import org.apache.doris.common.DdlException;
 import org.apache.doris.common.io.Text;
-import org.apache.doris.common.io.Writable;
 
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.io.DataInput;
-import java.io.DataOutput;
 import java.io.IOException;
 import java.util.Map;
-import java.util.Set;
 
-// grant privs.. on db.tbl to user@['domain.name']
-// revoke privs on db.tbl from user@['domain.name']
-public class WhiteList implements Writable {
+//only for compatible version before VERSION_116
+@Deprecated
+public class WhiteList {
     private static final Logger LOG = LogManager.getLogger(WhiteList.class);
 
     private Map<String, byte[]> passwordMap = Maps.newConcurrentMap();
 
-    // Domain name to resolved IPs, generated by DomainResolver
-    private Map<String, Set<String>> resolvedIPsMap = Maps.newConcurrentMap();
-
-    // this 2 variables are deprecated and only be used for converting
-    @Deprecated
-    private Map<String, Map<TablePattern, PrivBitSet>> oldDomainPrivsMap = Maps.newHashMap();
-    @Deprecated
-    private byte[] oldPassword;
-
-    public void removeDomain(String domain) {
-        passwordMap.remove(domain);
-        resolvedIPsMap.remove(domain);
-    }
-
-    public void setPassword(String domain, byte[] password) {
-        this.passwordMap.put(domain, password);
-    }
-
-    // handle new resolved IPs.
-    // it will only modify password entry of these resolved IPs. All other privileges are binded
-    // to the domain, so no need to modify.
-    public void addUserPrivEntriesByResolvedIPs(String user, Map<String, Set<String>> resolvedIPsMap) {
-        // the parameter "resolvedIPsMap" contains all resolved domains.
-        // "newResolvedIPsMap" will only save the domains contained in this white list.
-        Map<String, Set<String>> newResolvedIPsMap = Maps.newHashMap();
-        for (Map.Entry<String, Set<String>> entry : resolvedIPsMap.entrySet()) {
-            if (!containsDomain(entry.getKey())) {
-                continue;
-            }
-
-            newResolvedIPsMap.put(entry.getKey(), entry.getValue());
-
-            // this user ident will be saved along with each resolved "IP" user ident, so that when checking
-            // password, this "domain" user ident will be returned as "current user".
-            UserIdentity domainUserIdent = UserIdentity.createAnalyzedUserIdentWithDomain(user, entry.getKey());
-            for (String newIP : entry.getValue()) {
-                UserIdentity userIdent = UserIdentity.createAnalyzedUserIdentWithIp(user, newIP);
-                byte[] password = passwordMap.get(entry.getKey());
-                Preconditions.checkNotNull(password, entry.getKey());
-                // set password
-                try {
-                    Env.getCurrentEnv().getAuth().setPasswordInternal(userIdent, password, domainUserIdent,
-                            false /* err on non exist */, true /* set by resolver */, true /* is replay */);
-                } catch (DdlException e) {
-                    // this may happen when this user ident is already set by user, so that resolver can not
-                    // overwrite it. just add a debug log to observer.
-                    LOG.debug("failed to set password for user ident: {}, {}", userIdent, e.getMessage());
-                }
-            }
-        }
-
-        // set new resolved IPs
-        this.resolvedIPsMap = newResolvedIPsMap;
-    }
-
-    public Map<String, Set<String>> getResolvedIPs() {
-        return resolvedIPsMap;
-    }
-
-    public boolean containsDomain(String domain) {
-        return passwordMap.containsKey(domain);
-    }
-
-    public Set<String> getAllDomains() {
-        return Sets.newHashSet(passwordMap.keySet());
-    }
-
-    public boolean hasPassword(String domain) {
-        return passwordMap.containsKey(domain) && passwordMap.get(domain).length > 0;
-    }
-
-    @Override
-    public String toString() {
-        return Joiner.on(", ").join(passwordMap.keySet());
-    }
-
-    @Override
-    public void write(DataOutput out) throws IOException {
-        out.writeInt(passwordMap.size());
-        for (Map.Entry<String, byte[]> entry : passwordMap.entrySet()) {
-            Text.writeString(out, entry.getKey());
-            byte[] password = entry.getValue();
-            out.writeInt(password.length);
-            out.write(password);
-        }
+    public Map<String, byte[]> getPasswordMap() {
+        return passwordMap;
     }
 
     public void readFields(DataInput in) throws IOException {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AccessTestUtil.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AccessTestUtil.java
index a45c590bac..d14d27cbca 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AccessTestUtil.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AccessTestUtil.java
@@ -36,7 +36,7 @@ import org.apache.doris.common.jmockit.Deencapsulation;
 import org.apache.doris.datasource.CatalogMgr;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.load.Load;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.persist.EditLog;
 import org.apache.doris.qe.ConnectContext;
@@ -59,8 +59,8 @@ public class AccessTestUtil {
         return clusterInfo;
     }
 
-    public static PaloAuth fetchAdminAccess() {
-        PaloAuth auth = new PaloAuth();
+    public static Auth fetchAdminAccess() {
+        Auth auth = new Auth();
         try {
             new Expectations(auth) {
                 {
@@ -94,7 +94,7 @@ public class AccessTestUtil {
         try {
             Env env = Deencapsulation.newInstance(Env.class);
 
-            PaloAuth auth = fetchAdminAccess();
+            Auth auth = fetchAdminAccess();
 
             fakeEditLog = new FakeEditLog();
             EditLog editLog = new EditLog("name");
@@ -211,8 +211,8 @@ public class AccessTestUtil {
         }
     }
 
-    public static PaloAuth fetchBlockAccess() {
-        PaloAuth auth = new PaloAuth();
+    public static Auth fetchBlockAccess() {
+        Auth auth = new Auth();
         new Expectations(auth) {
             {
                 auth.checkGlobalPriv((ConnectContext) any, (PrivPredicate) any);
@@ -336,7 +336,7 @@ public class AccessTestUtil {
         try {
             Env env = Deencapsulation.newInstance(Env.class);
 
-            PaloAuth auth = fetchBlockAccess();
+            Auth auth = fetchBlockAccess();
             Database db = mockDb("testCluster:testDb");
 
             InternalCatalog catalog = Deencapsulation.newInstance(InternalCatalog.class);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminCancelRebalanceDiskStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminCancelRebalanceDiskStmtTest.java
index 9e565caacd..498234427b 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminCancelRebalanceDiskStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminCancelRebalanceDiskStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.catalog.Env;
 import org.apache.doris.clone.RebalancerTestUtil;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -38,7 +38,7 @@ public class AdminCancelRebalanceDiskStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminRebalanceDiskStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminRebalanceDiskStmtTest.java
index 9e720815e2..0c192fd7b9 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminRebalanceDiskStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AdminRebalanceDiskStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.catalog.Env;
 import org.apache.doris.clone.RebalancerTestUtil;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -38,7 +38,7 @@ public class AdminRebalanceDiskStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java
index dd1099ad6e..22accaa160 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogNameStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -33,7 +33,7 @@ import org.junit.Test;
 public class AlterCatalogNameStmtTest {
     private Analyzer analyzer;
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
index ad4c394abb..8ff1ed74fb 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterCatalogPropsStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Maps;
@@ -36,7 +36,7 @@ import java.util.Map;
 public class AlterCatalogPropsStmtTest {
     private Analyzer analyzer;
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterClusterStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterClusterStmtTest.java
index e631cb22b6..7ac5ef3588 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterClusterStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterClusterStmtTest.java
@@ -20,8 +20,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -37,7 +37,7 @@ public class AlterClusterStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterDatabaseQuotaStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterDatabaseQuotaStmtTest.java
index 19b2365e25..1405439743 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterDatabaseQuotaStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterDatabaseQuotaStmtTest.java
@@ -20,7 +20,7 @@ package org.apache.doris.analysis;
 import org.apache.doris.analysis.AlterDatabaseQuotaStmt.QuotaType;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -34,7 +34,7 @@ public class AlterDatabaseQuotaStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Before
     public void setUp() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterRoutineLoadStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterRoutineLoadStmtTest.java
index 66fb6ba992..a2c9d47bd5 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterRoutineLoadStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterRoutineLoadStmtTest.java
@@ -20,7 +20,7 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -43,7 +43,7 @@ public class AlterRoutineLoadStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Before
     public void setUp() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterSqlBlockRuleStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterSqlBlockRuleStmtTest.java
index 8a0f209514..7c233c700e 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterSqlBlockRuleStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterSqlBlockRuleStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.blockrule.SqlBlockRule;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -38,7 +38,7 @@ public class AlterSqlBlockRuleStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Mocked
     private ConnectContext ctx;
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterTableStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterTableStmtTest.java
index 8bfa801760..32b7f179fc 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterTableStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/AlterTableStmtTest.java
@@ -20,7 +20,7 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -40,7 +40,7 @@ public class AlterTableStmtTest {
     private String internalCtl = InternalCatalog.INTERNAL_CATALOG_NAME;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Before
     public void setUp() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java
index 3000ecdcfc..86c1f7783f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateCatalogStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Maps;
@@ -37,7 +37,7 @@ public class CreateCatalogStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateClusterStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateClusterStmtTest.java
index bd19be7f07..5a7c757cec 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateClusterStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateClusterStmtTest.java
@@ -20,8 +20,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -37,7 +37,7 @@ public class CreateClusterStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDataSyncJobStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDataSyncJobStmtTest.java
index a8d28e1b9e..bd6c5db45a 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDataSyncJobStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDataSyncJobStmtTest.java
@@ -24,7 +24,7 @@ import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.load.sync.DataSyncJobType;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -57,7 +57,7 @@ public class CreateDataSyncJobStmtTest {
     @Mocked
     Analyzer analyzer;
     @Mocked
-    PaloAuth auth;
+    Auth auth;
     @Injectable
     Database database;
     @Injectable
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDbStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDbStmtTest.java
index cb8647f0c9..9c2e62d9ce 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDbStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateDbStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -35,7 +35,7 @@ public class CreateDbStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateResourceStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateResourceStmtTest.java
index 0e0ab1f200..56698e8733 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateResourceStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateResourceStmtTest.java
@@ -22,7 +22,7 @@ import org.apache.doris.catalog.Resource;
 import org.apache.doris.catalog.Resource.ResourceType;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -51,7 +51,7 @@ public class CreateResourceStmtTest {
     }
 
     @Test
-    public void testNormal(@Mocked Env env, @Injectable PaloAuth auth) throws UserException {
+    public void testNormal(@Mocked Env env, @Injectable Auth auth) throws UserException {
         new Expectations() {
             {
                 env.getAuth();
@@ -88,7 +88,7 @@ public class CreateResourceStmtTest {
     }
 
     @Test(expected = AnalysisException.class)
-    public void testUnsupportedResourceType(@Mocked Env env, @Injectable PaloAuth auth) throws UserException {
+    public void testUnsupportedResourceType(@Mocked Env env, @Injectable Auth auth) throws UserException {
         new Expectations() {
             {
                 env.getAuth();
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateSqlBlockRuleStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateSqlBlockRuleStmtTest.java
index 379ebd327a..f3a296e633 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateSqlBlockRuleStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateSqlBlockRuleStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.blockrule.SqlBlockRule;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -38,7 +38,7 @@ public class CreateSqlBlockRuleStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Mocked
     private ConnectContext ctx;
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableStmtTest.java
index 1f357b2a8d..ae931471d0 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateTableStmtTest.java
@@ -28,8 +28,8 @@ import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.util.PropertyAnalyzer;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -65,7 +65,7 @@ public class CreateTableStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateUserStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateUserStmtTest.java
index 2282bfa668..aefc4dac14 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateUserStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateUserStmtTest.java
@@ -19,7 +19,7 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -45,13 +45,13 @@ public class CreateUserStmtTest {
 
     @Test
     public void testToString(@Injectable Analyzer analyzer,
-            @Mocked PaloAuth auth) throws UserException, AnalysisException {
+            @Mocked Auth auth) throws UserException, AnalysisException {
 
         new Expectations() {
             {
                 analyzer.getClusterName();
                 result = "testCluster";
-                auth.checkHasPriv((ConnectContext) any, PrivPredicate.GRANT, PaloAuth.PrivLevel.GLOBAL, PaloAuth
+                auth.checkHasPriv((ConnectContext) any, PrivPredicate.GRANT, Auth.PrivLevel.GLOBAL, Auth
                         .PrivLevel.DATABASE);
                 result = true;
             }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DataDescriptionTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DataDescriptionTest.java
index d79770c9c7..0d7a45b12f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DataDescriptionTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DataDescriptionTest.java
@@ -26,8 +26,8 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.jmockit.Deencapsulation;
 import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.load.loadv2.LoadTask;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.system.SystemInfoService;
 
@@ -48,7 +48,7 @@ import java.util.Map;
 public class DataDescriptionTest {
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
     @Mocked
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DeleteStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DeleteStmtTest.java
index 30372dcb9e..f3064c442f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DeleteStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DeleteStmtTest.java
@@ -21,8 +21,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.analysis.BinaryPredicate.Operator;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -39,7 +39,7 @@ public class DeleteStmtTest {
     Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java
index 749994963d..477f9f94af 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropCatalogStmtTest.java
@@ -21,8 +21,8 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DdlException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -34,7 +34,7 @@ public class DropCatalogStmtTest {
     Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropClusterStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropClusterStmtTest.java
index 98ca1d9502..af4abdd5f9 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropClusterStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropClusterStmtTest.java
@@ -20,7 +20,7 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -35,7 +35,7 @@ public class DropClusterStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Before
     public void setUp() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropDbStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropDbStmtTest.java
index b726bc30a6..c54d752410 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropDbStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropDbStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -32,7 +32,7 @@ public class DropDbStmtTest {
     Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
index 3e9c5c0637..6d757fa85e 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropMaterializedViewStmtTest.java
@@ -18,7 +18,7 @@
 package org.apache.doris.analysis;
 
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -33,7 +33,7 @@ public class DropMaterializedViewStmtTest {
     @Mocked
     Analyzer analyzer;
     @Mocked
-    PaloAuth auth;
+    Auth auth;
 
     @Test
     public void testEmptyMVName(@Injectable TableName tableName) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropTableStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropTableStmtTest.java
index 3dba549c88..37035e8036 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropTableStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropTableStmtTest.java
@@ -20,8 +20,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.datasource.InternalCatalog;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Expectations;
@@ -40,7 +40,7 @@ public class DropTableStmtTest {
     private Analyzer noDbAnalyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropUserStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropUserStmtTest.java
index 7c994c2f5d..02190bffe1 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DropUserStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DropUserStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -32,7 +32,7 @@ public class DropUserStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/GrantStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/GrantStmtTest.java
index 46eddb2fe7..fbd46cbb40 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/GrantStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/GrantStmtTest.java
@@ -21,7 +21,7 @@ import org.apache.doris.catalog.AccessPrivilege;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -36,7 +36,7 @@ import java.util.List;
 public class GrantStmtTest {
     private Analyzer analyzer;
 
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
@@ -46,7 +46,7 @@ public class GrantStmtTest {
     @Before
     public void setUp() {
         analyzer = AccessTestUtil.fetchAdminAnalyzer(true);
-        auth = new PaloAuth();
+        auth = new Auth();
 
         new Expectations() {
             {
@@ -99,11 +99,11 @@ public class GrantStmtTest {
         GrantStmt stmt = new GrantStmt(new UserIdentity("testUser", "%"), null, new ResourcePattern(resourceName), privileges);
         stmt.analyze(analyzer);
         Assert.assertEquals(resourceName, stmt.getResourcePattern().getResourceName());
-        Assert.assertEquals(PaloAuth.PrivLevel.RESOURCE, stmt.getResourcePattern().getPrivLevel());
+        Assert.assertEquals(Auth.PrivLevel.RESOURCE, stmt.getResourcePattern().getPrivLevel());
 
         stmt = new GrantStmt(new UserIdentity("testUser", "%"), null, new ResourcePattern("*"), privileges);
         stmt.analyze(analyzer);
-        Assert.assertEquals(PaloAuth.PrivLevel.GLOBAL, stmt.getResourcePattern().getPrivLevel());
+        Assert.assertEquals(Auth.PrivLevel.GLOBAL, stmt.getResourcePattern().getPrivLevel());
         Assert.assertEquals("GRANT Usage_priv ON RESOURCE '*' TO 'testCluster:testUser'@'%'", stmt.toSql());
     }
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/InstallPluginStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/InstallPluginStmtTest.java
index d7e09f2f2a..7214d58f06 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/InstallPluginStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/InstallPluginStmtTest.java
@@ -18,7 +18,7 @@
 package org.apache.doris.analysis;
 
 import org.apache.doris.common.UserException;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
@@ -35,7 +35,7 @@ public class InstallPluginStmtTest {
 
     private Analyzer analyzer;
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
 
     @Before
     public void setUp() {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/LinkDbStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/LinkDbStmtTest.java
index fbf993dc81..92b4541dbd 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/LinkDbStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/LinkDbStmtTest.java
@@ -20,8 +20,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -34,7 +34,7 @@ public class LinkDbStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/LoadStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/LoadStmtTest.java
index f027f13daf..b8a9da5874 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/LoadStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/LoadStmtTest.java
@@ -26,7 +26,7 @@ import org.apache.doris.common.util.SqlParserUtils;
 import org.apache.doris.load.EtlJobType;
 import org.apache.doris.load.Load;
 import org.apache.doris.load.loadv2.LoadTask;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.task.LoadTaskInfo;
@@ -50,7 +50,7 @@ public class LoadStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
     @Mocked
@@ -80,7 +80,7 @@ public class LoadStmtTest {
 
     @Test
     public void testNormal(@Injectable DataDescription desc, @Mocked Env env,
-            @Injectable ResourceMgr resourceMgr, @Injectable PaloAuth auth) throws UserException, AnalysisException {
+            @Injectable ResourceMgr resourceMgr, @Injectable Auth auth) throws UserException, AnalysisException {
         List<DataDescription> dataDescriptionList = Lists.newArrayList();
         dataDescriptionList.add(desc);
         String resourceName = "spark0";
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/MigrateDbStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/MigrateDbStmtTest.java
index d88146e335..9e855ba33c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/MigrateDbStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/MigrateDbStmtTest.java
@@ -20,8 +20,8 @@ package org.apache.doris.analysis;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -34,7 +34,7 @@ public class MigrateDbStmtTest {
     private static Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetOperationStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetOperationStmtTest.java
index 25b881f934..481a58f1b3 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetOperationStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetOperationStmtTest.java
@@ -18,8 +18,8 @@
 package org.apache.doris.analysis;
 
 import org.apache.doris.common.util.SqlParserUtils;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -33,7 +33,7 @@ public class SetOperationStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetPassVarTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetPassVarTest.java
index 60ceca0798..10eb21d08a 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetPassVarTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetPassVarTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -32,7 +32,7 @@ public class SetPassVarTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetStmtTest.java
index 2b2eed78cd..f62412fd50 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -35,7 +35,7 @@ public class SetStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetUserPropertyStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetUserPropertyStmtTest.java
index 16ebf06c42..a0c6060842 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetUserPropertyStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetUserPropertyStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Lists;
@@ -35,7 +35,7 @@ public class SetUserPropertyStmtTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
index 48c0fef3b7..9854c6ef41 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -32,7 +32,7 @@ public class SetVarTest {
     private Analyzer analyzer;
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateDbStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateDbStmtTest.java
index 00d672c64d..d8dfa8593f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateDbStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateDbStmtTest.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
 
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.MockedAuth;
-import org.apache.doris.mysql.privilege.PaloAuth;
 import org.apache.doris.qe.ConnectContext;
 
 import mockit.Mocked;
@@ -31,7 +31,7 @@ import org.junit.Test;
 public class ShowCreateDbStmtTest {
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private ConnectContext ctx;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowDataStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowDataStmtTest.java
index c77fc7923c..f7a6a16a7f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowDataStmtTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowDataStmtTest.java
@@ -25,7 +25,7 @@ import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.jmockit.Deencapsulation;
 import org.apache.doris.datasource.InternalCatalog;
-import org.apache.doris.mysql.privilege.PaloAuth;
+import org.apache.doris.mysql.privilege.Auth;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.system.SystemInfoService;
@@ -41,7 +41,7 @@ import java.util.Arrays;
 public class ShowDataStmtTest {
 
     @Mocked
-    private PaloAuth auth;
+    private Auth auth;
     @Mocked
     private Analyzer analyzer;
     @Mocked
@@ -57,7 +57,7 @@ public class ShowDataStmtTest {
 
     @Before
     public void setUp() throws UserException {
-        auth = new PaloAuth();
+        auth = new Auth();
         new Expectations() {
             {
                 Env.getCurrentInvertedIndex();
@@ -130,6 +130,10 @@ public class ShowDataStmtTest {
                 auth.checkTblPriv((ConnectContext) any, anyString, anyString, (PrivPredicate) any);
                 minTimes = 0;
                 result = true;
+
+                auth.checkTblPriv((ConnectContext) any, anyString, anyString, anyString, (PrivPredicate) any);
+                minTimes = 0;
+                result = true;
             }
         };
... 1234 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org