[refactor](cluster)(step-3) remove cluster related to Auth (#27718)

Remove `default_cluster` prefix related to:
1. User
2. Role
3. UserManager
4. RoleManager
5. UserRoleManager
6. UserProperty
7. Create/Drop user Stmt
8. Create/Drop role Stmt
9. Grant/Revoke
This commit is contained in:
Mingyu Chen
2023-11-30 12:46:08 +08:00
committed by GitHub
parent 112ae59aa4
commit 7f13dcc726
35 changed files with 174 additions and 182 deletions

View File

@ -18,7 +18,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
@ -95,7 +94,7 @@ public class AlterUserStmt extends DdlStmt {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
userDesc.getUserIdent().analyze(analyzer.getClusterName());
userDesc.getUserIdent().analyze();
userDesc.getPassVar().analyze();
if (userDesc.hasPassword()) {
@ -103,7 +102,6 @@ public class AlterUserStmt extends DdlStmt {
}
if (!Strings.isNullOrEmpty(role)) {
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
ops.add(OpType.SET_ROLE);
}

View File

@ -106,7 +106,7 @@ public class CreatePolicyStmt extends DdlStmt {
default:
tableName.analyze(analyzer);
if (user != null) {
user.analyze(analyzer.getClusterName());
user.analyze();
if (user.isRootUser() || user.isAdminUser()) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "CreatePolicyStmt",
user.getQualifiedUser(), user.getHost(), tableName.getTbl());

View File

@ -18,7 +18,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
@ -44,7 +43,7 @@ public class CreateRoleStmt extends DdlStmt {
return ifNotExists;
}
public String getQualifiedRole() {
public String getRole() {
return role;
}
@ -52,7 +51,6 @@ public class CreateRoleStmt extends DdlStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
FeNameFormat.checkRoleName(role, false /* can not be admin */, "Can not create role");
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
// check if current user has GRANT priv on GLOBAL level.
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.GRANT)) {

View File

@ -18,7 +18,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
@ -109,7 +108,7 @@ public class CreateUserStmt extends DdlStmt {
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
if (userIdent.isRootUser()) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_COMMON_ERROR, "Can not create root user");
@ -124,7 +123,6 @@ public class CreateUserStmt extends DdlStmt {
role = Role.ADMIN_ROLE;
}
FeNameFormat.checkRoleName(role, true /* can be admin */, "Can not granted user to role");
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
}
passwordOptions.analyze();

View File

@ -18,7 +18,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.FeNameFormat;
@ -44,7 +43,7 @@ public class DropRoleStmt extends DdlStmt {
return ifExists;
}
public String getQualifiedRole() {
public String getRole() {
return role;
}
@ -52,7 +51,6 @@ public class DropRoleStmt extends DdlStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
FeNameFormat.checkRoleName(role, false /* can not be superuser */, "Can not drop role");
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
// check if current user has GRANT priv on GLOBAL level.
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.GRANT)) {

View File

@ -53,7 +53,7 @@ public class DropUserStmt extends DdlStmt {
@Override
public void analyze(Analyzer analyzer) throws AnalysisException, UserException {
super.analyze(analyzer);
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
if (userIdent.isRootUser()) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_COMMON_ERROR, "Can not drop root user");

View File

@ -19,7 +19,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.AccessPrivilegeWithCols;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.ErrorCode;
@ -135,10 +134,9 @@ public class GrantStmt extends DdlStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (userIdent != null) {
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
} else {
FeNameFormat.checkRoleName(role, false /* can not be admin */, "Can not grant to role");
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
}
if (tblPattern != null) {
@ -151,11 +149,9 @@ public class GrantStmt extends DdlStmt {
for (int i = 0; i < roles.size(); i++) {
String originalRoleName = roles.get(i);
FeNameFormat.checkRoleName(originalRoleName, true /* can be admin */, "Can not grant role");
roles.set(i, ClusterNamespace.getFullName(analyzer.getClusterName(), originalRoleName));
}
}
if (!CollectionUtils.isEmpty(accessPrivileges)) {
checkAccessPrivileges(accessPrivileges);

View File

@ -18,7 +18,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.AccessPrivilegeWithCols;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.FeNameFormat;
import org.apache.doris.mysql.privilege.ColPrivilegeKey;
@ -118,10 +117,9 @@ public class RevokeStmt extends DdlStmt {
@Override
public void analyze(Analyzer analyzer) throws AnalysisException {
if (userIdent != null) {
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
} else {
FeNameFormat.checkRoleName(role, false /* can not be superuser */, "Can not revoke from role");
role = ClusterNamespace.getFullName(analyzer.getClusterName(), role);
}
if (tblPattern != null) {
@ -134,7 +132,6 @@ public class RevokeStmt extends DdlStmt {
for (int i = 0; i < roles.size(); i++) {
String originalRoleName = roles.get(i);
FeNameFormat.checkRoleName(originalRoleName, true /* can be admin */, "Can not revoke role");
roles.set(i, ClusterNamespace.getFullName(analyzer.getClusterName(), originalRoleName));
}
}
if (!CollectionUtils.isEmpty(accessPrivileges)) {

View File

@ -60,7 +60,7 @@ public class SetPassVar extends SetVar {
userIdent = ctx.getCurrentUserIdentity();
isSelf = true;
} else {
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
if (userIdent.equals(ctx.getCurrentUserIdentity())) {
isSelf = true;
}

View File

@ -73,7 +73,7 @@ public class ShowGrantsStmt extends ShowStmt {
if (isAll) {
throw new AnalysisException("Can not specified keyword ALL when specified user");
}
userIdent.analyze(analyzer.getClusterName());
userIdent.analyze();
} else {
if (!isAll) {
// self

View File

@ -57,7 +57,7 @@ public class ShowPolicyStmt extends ShowStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
if (user != null) {
user.analyze(analyzer.getClusterName());
user.analyze();
}
// check auth
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) {

View File

@ -124,7 +124,7 @@ public class UserIdentity implements Writable, GsonPostProcessable {
this.isAnalyzed = true;
}
public void analyze(String clusterName) throws AnalysisException {
public void analyze() throws AnalysisException {
if (isAnalyzed) {
return;
}
@ -133,10 +133,6 @@ public class UserIdentity implements Writable, GsonPostProcessable {
}
FeNameFormat.checkUserName(user);
if (!user.equals(Auth.ROOT_USER) && !user.equals(Auth.ADMIN_USER)) {
user = ClusterNamespace.getFullName(clusterName, user);
}
if (Strings.isNullOrEmpty(host)) {
if (!isDomain) {
host = "%";
@ -212,6 +208,11 @@ public class UserIdentity implements Writable, GsonPostProcessable {
return sb.toString();
}
// should be remove after version 3.0
public void removeClusterPrefix() {
user = ClusterNamespace.getNameFromFullName(user);
}
public static UserIdentity read(DataInput in) throws IOException {
// Use Gson in the VERSION_109
if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_109) {
@ -281,5 +282,6 @@ public class UserIdentity implements Writable, GsonPostProcessable {
@Override
public void gsonPostProcess() throws IOException {
isAnalyzed = true;
removeClusterPrefix();
}
}

View File

@ -266,11 +266,10 @@ public class BaseController {
authInfo.fullUserName = authString.substring(0, index);
final String[] elements = authInfo.fullUserName.split("@");
if (elements != null && elements.length < 2) {
authInfo.fullUserName = ClusterNamespace.getFullName(SystemInfoService.DEFAULT_CLUSTER,
authInfo.fullUserName);
authInfo.fullUserName = ClusterNamespace.getNameFromFullName(authInfo.fullUserName);
authInfo.cluster = SystemInfoService.DEFAULT_CLUSTER;
} else if (elements != null && elements.length == 2) {
authInfo.fullUserName = ClusterNamespace.getFullName(elements[1], elements[0]);
authInfo.fullUserName = ClusterNamespace.getNameFromFullName(elements[0]);
authInfo.cluster = elements[1];
}
authInfo.password = authString.substring(index + 1);

View File

@ -87,9 +87,8 @@ public class MysqlProto {
tmpUser = strList[0];
}
String qualifiedUser = ClusterNamespace.getFullName(SystemInfoService.DEFAULT_CLUSTER, tmpUser);
context.setQualifiedUser(qualifiedUser);
return qualifiedUser;
context.setQualifiedUser(tmpUser);
return tmpUser;
}
// send response packet(OK/EOF/ERR).

View File

@ -54,7 +54,6 @@ import org.apache.doris.common.io.Writable;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.ldap.LdapManager;
import org.apache.doris.ldap.LdapUserInfo;
import org.apache.doris.load.DppConfig;
import org.apache.doris.mysql.MysqlPassword;
import org.apache.doris.persist.AlterUserOperationLog;
import org.apache.doris.persist.LdapInfo;
@ -867,7 +866,7 @@ public class Auth implements Writable {
// create role
public void createRole(CreateRoleStmt stmt) throws DdlException {
createRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfNotExists(), false);
createRoleInternal(stmt.getRole(), stmt.isSetIfNotExists(), false);
}
public void replayCreateRole(PrivInfo info) {
@ -901,7 +900,7 @@ public class Auth implements Writable {
// drop role
public void dropRole(DropRoleStmt stmt) throws DdlException {
dropRoleInternal(stmt.getQualifiedRole(), stmt.isSetIfExists(), false);
dropRoleInternal(stmt.getRole(), stmt.isSetIfExists(), false);
}
public void replayDropRole(PrivInfo info) {
@ -1295,47 +1294,6 @@ public class Auth implements Writable {
}
}
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, "%");

View File

@ -835,10 +835,16 @@ public class Role implements Writable, GsonPostProcessable {
return role;
} else {
String json = Text.readString(in);
return GsonUtils.GSON.fromJson(json, Role.class);
Role r = GsonUtils.GSON.fromJson(json, Role.class);
return r;
}
}
// should be removed after version 3.0
private void removeClusterPrefix() {
roleName = ClusterNamespace.getNameFromFullName(roleName);
}
@Deprecated
private void readFields(DataInput in) throws IOException, DdlException {
roleName = Text.readString(in);
@ -866,6 +872,7 @@ public class Role implements Writable, GsonPostProcessable {
@Override
public void gsonPostProcess() {
removeClusterPrefix();
rebuildPrivTables();
}

View File

@ -32,6 +32,7 @@ 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.Auth.PrivLevel;
import org.apache.doris.persist.gson.GsonPostProcessable;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.resource.workloadgroup.WorkloadGroupMgr;
@ -55,7 +56,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class RoleManager implements Writable {
public class RoleManager implements Writable, GsonPostProcessable {
private static final Logger LOG = LogManager.getLogger(RoleManager.class);
//prefix of each user default role
public static String DEFAULT_ROLE_PREFIX = "default_role_rbac_";
@ -262,10 +263,21 @@ public class RoleManager implements Writable {
return roleManager;
} else {
String json = Text.readString(in);
return GsonUtils.GSON.fromJson(json, RoleManager.class);
RoleManager rm = GsonUtils.GSON.fromJson(json, RoleManager.class);
return rm;
}
}
// should be removed after version 3.0
private void removeClusterPrefix() {
Map<String, Role> newRoles = Maps.newHashMap();
for (Map.Entry<String, Role> entry : roles.entrySet()) {
String roleName = ClusterNamespace.getNameFromFullName(entry.getKey());
newRoles.put(roleName, entry.getValue());
}
roles = newRoles;
}
@Deprecated
private void readFields(DataInput in) throws IOException {
int size = in.readInt();
@ -274,4 +286,9 @@ public class RoleManager implements Writable {
roles.put(role.getRoleName(), role);
}
}
@Override
public void gsonPostProcess() throws IOException {
removeClusterPrefix();
}
}

View File

@ -19,6 +19,7 @@ package org.apache.doris.mysql.privilege;
import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AuthenticationException;
import org.apache.doris.common.CaseSensibility;
import org.apache.doris.common.DdlException;
@ -28,6 +29,7 @@ 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.GsonPostProcessable;
import org.apache.doris.persist.gson.GsonUtils;
import com.google.common.base.Preconditions;
@ -48,7 +50,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class UserManager implements Writable {
public class UserManager implements Writable, GsonPostProcessable {
public static final String ANY_HOST = "%";
private static final Logger LOG = LogManager.getLogger(UserManager.class);
// Concurrency control is delegated by Auth, so not concurrentMap
@ -314,6 +316,21 @@ public class UserManager implements Writable {
public static UserManager read(DataInput in) throws IOException {
String json = Text.readString(in);
return GsonUtils.GSON.fromJson(json, UserManager.class);
UserManager um = GsonUtils.GSON.fromJson(json, UserManager.class);
return um;
}
// should be removed after version 3.0
private void removeClusterPrefix() {
Map<String, List<User>> newNameToUsers = Maps.newHashMap();
for (Entry<String, List<User>> entry : nameToUsers.entrySet()) {
String user = entry.getKey();
newNameToUsers.put(ClusterNamespace.getNameFromFullName(user), entry.getValue());
}
}
@Override
public void gsonPostProcess() throws IOException {
removeClusterPrefix();
}
}

View File

@ -19,6 +19,7 @@ package org.apache.doris.mysql.privilege;
import org.apache.doris.analysis.SetUserPropertyVar;
import org.apache.doris.catalog.Env;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeMetaVersion;
@ -537,6 +538,8 @@ public class UserProperty implements Writable {
public void readFields(DataInput in) throws IOException {
qualifiedUser = Text.readString(in);
// should be removed after version 3.0
qualifiedUser = ClusterNamespace.getNameFromFullName(qualifiedUser);
if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_100) {
long maxConn = in.readLong();

View File

@ -160,8 +160,21 @@ public class UserRoleManager implements Writable, GsonPostProcessable {
return GsonUtils.GSON.fromJson(json, UserRoleManager.class);
}
private void removeClusterPrefix() {
Map<UserIdentity, Set<String>> newUserToRoles = Maps.newHashMap();
for (Entry<UserIdentity, Set<String>> entry : userToRoles.entrySet()) {
Set<String> newRoles = Sets.newHashSet();
for (String role : entry.getValue()) {
newRoles.add(ClusterNamespace.getNameFromFullName(role));
}
newUserToRoles.put(entry.getKey(), newRoles);
}
userToRoles = newUserToRoles;
}
@Override
public void gsonPostProcess() throws IOException {
removeClusterPrefix();
roleToUsers = Maps.newHashMap();
for (Entry<UserIdentity, Set<String>> entry : userToRoles.entrySet()) {
for (String roleName : entry.getValue()) {

View File

@ -28,7 +28,6 @@ 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 org.apache.doris.qe.ConnectContext;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
@ -119,7 +118,7 @@ public abstract class Policy implements Writable, GsonPostProcessable {
.getDbOrAnalysisException(stmt.getTableName().getDb());
UserIdentity userIdent = stmt.getUser();
if (userIdent != null) {
userIdent.analyze(ConnectContext.get().getClusterName());
userIdent.analyze();
}
TableIf table = db.getTableOrAnalysisException(stmt.getTableName().getTbl());
return new RowPolicy(policyId, stmt.getPolicyName(), db.getId(), userIdent, stmt.getRoleName(),

View File

@ -1010,7 +1010,7 @@ public class FrontendServiceImpl implements FrontendService.Iface {
private void checkPasswordAndPrivs(String cluster, String user, String passwd, String db, List<String> tables,
String clientIp, PrivPredicate predicate) throws AuthenticationException {
final String fullUserName = ClusterNamespace.getFullName(cluster, user);
final String fullUserName = ClusterNamespace.getNameFromFullName(user);
final String fullDbName = ClusterNamespace.getFullName(cluster, db);
List<UserIdentity> currentUser = Lists.newArrayList();
Env.getCurrentEnv().getAuth().checkPlainPassword(fullUserName, clientIp, passwd, currentUser);
@ -1045,7 +1045,7 @@ public class FrontendServiceImpl implements FrontendService.Iface {
if (Strings.isNullOrEmpty(cluster)) {
cluster = SystemInfoService.DEFAULT_CLUSTER;
}
final String fullUserName = ClusterNamespace.getFullName(cluster, user);
final String fullUserName = ClusterNamespace.getNameFromFullName(user);
List<UserIdentity> currentUser = Lists.newArrayList();
Env.getCurrentEnv().getAuth().checkPlainPassword(fullUserName, clientIp, passwd, currentUser);
Preconditions.checkState(currentUser.size() == 1);
@ -2347,7 +2347,7 @@ public class FrontendServiceImpl implements FrontendService.Iface {
}
// check account and password
final String fullUserName = ClusterNamespace.getFullName(cluster, request.getUser());
final String fullUserName = ClusterNamespace.getNameFromFullName(request.getUser());
List<UserIdentity> currentUser = Lists.newArrayList();
try {
Env.getCurrentEnv().getAuth().checkPlainPassword(fullUserName, request.getUserIp(), request.getPasswd(),
@ -2938,7 +2938,7 @@ public class FrontendServiceImpl implements FrontendService.Iface {
}
ctx.setCluster(cluster);
ctx.setQualifiedUser(request.getUser());
String fullUserName = ClusterNamespace.getFullName(cluster, request.getUser());
String fullUserName = ClusterNamespace.getNameFromFullName(request.getUser());
UserIdentity currentUserIdentity = new UserIdentity(fullUserName, "%");
ctx.setCurrentUserIdentity(currentUserIdentity);