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