[Enhancement](HttpServer) Provide authentication interface for BE (#17073)

Add an authentication interface in FE for BE
This commit is contained in:
yongjinhou
2023-03-10 16:34:47 +08:00
committed by GitHub
parent 9ae5ec4dc5
commit 9cfa61b402
3 changed files with 174 additions and 1 deletions

View File

@ -20,6 +20,7 @@ package org.apache.doris.mysql.privilege;
import org.apache.doris.analysis.TableName;
import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.catalog.AuthorizationInfo;
import org.apache.doris.common.AuthorizationException;
import org.apache.doris.common.UserException;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.mysql.privilege.Auth.PrivLevel;
@ -32,6 +33,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;
import java.util.Set;
/**
* AccessControllerManager is the entry point of privilege authentication.
@ -101,7 +103,7 @@ public class AccessControllerManager {
return checkCtlPriv(ctx.getCurrentUserIdentity(), ctl, wanted);
}
private boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) {
public boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) {
boolean hasGlobal = sysAccessController.checkGlobalPriv(currentUser, wanted);
return getAccessControllerOrDefault(ctl).checkCtlPriv(hasGlobal, currentUser, ctl, wanted);
}
@ -159,6 +161,18 @@ public class AccessControllerManager {
}
}
public boolean checkColumnsPriv(UserIdentity currentUser, String db, String tbl, Set<String> cols,
PrivPredicate wanted) {
boolean hasGlobal = sysAccessController.checkGlobalPriv(currentUser, wanted);
CatalogAccessController accessController = getAccessControllerOrDefault(Auth.DEFAULT_CATALOG);
try {
accessController.checkColsPriv(hasGlobal, currentUser, Auth.DEFAULT_CATALOG, db, tbl, cols, wanted);
return true;
} catch (AuthorizationException e) {
return false;
}
}
// ==== Resource ====
public boolean checkResourcePriv(ConnectContext ctx, String resourceName, PrivPredicate wanted) {
return checkResourcePriv(ctx.getCurrentUserIdentity(), resourceName, wanted);

View File

@ -62,6 +62,7 @@ import org.apache.doris.datasource.ExternalCatalog;
import org.apache.doris.datasource.HMSExternalCatalog;
import org.apache.doris.datasource.InternalCatalog;
import org.apache.doris.master.MasterImpl;
import org.apache.doris.mysql.privilege.AccessControllerManager;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.planner.StreamLoadPlanner;
import org.apache.doris.qe.ConnectContext;
@ -78,6 +79,8 @@ import org.apache.doris.thrift.FrontendServiceVersion;
import org.apache.doris.thrift.TAddColumnsRequest;
import org.apache.doris.thrift.TAddColumnsResult;
import org.apache.doris.thrift.TCell;
import org.apache.doris.thrift.TCheckAuthRequest;
import org.apache.doris.thrift.TCheckAuthResult;
import org.apache.doris.thrift.TColumn;
import org.apache.doris.thrift.TColumnDef;
import org.apache.doris.thrift.TColumnDesc;
@ -119,7 +122,10 @@ import org.apache.doris.thrift.TMasterResult;
import org.apache.doris.thrift.TMetadataTableRequestParams;
import org.apache.doris.thrift.TMySqlLoadAcquireTokenResult;
import org.apache.doris.thrift.TNetworkAddress;
import org.apache.doris.thrift.TPrivilegeCtrl;
import org.apache.doris.thrift.TPrivilegeHier;
import org.apache.doris.thrift.TPrivilegeStatus;
import org.apache.doris.thrift.TPrivilegeType;
import org.apache.doris.thrift.TReportExecStatusParams;
import org.apache.doris.thrift.TReportExecStatusResult;
import org.apache.doris.thrift.TReportRequest;
@ -1629,5 +1635,110 @@ public class FrontendServiceImpl implements FrontendService.Iface {
return result;
}
@Override
public TCheckAuthResult checkAuth(TCheckAuthRequest request) throws TException {
String clientAddr = getClientAddrAsString();
LOG.debug("receive auth request: {}, backend: {}", request, clientAddr);
TCheckAuthResult result = new TCheckAuthResult();
TStatus status = new TStatus(TStatusCode.OK);
result.setStatus(status);
String cluster = request.getCluster();
if (Strings.isNullOrEmpty(cluster)) {
cluster = SystemInfoService.DEFAULT_CLUSTER;
}
// check account and password
final String fullUserName = ClusterNamespace.getFullName(cluster, request.getUser());
List<UserIdentity> currentUser = Lists.newArrayList();
try {
Env.getCurrentEnv().getAuth().checkPlainPassword(fullUserName, request.getUserIp(), request.getPasswd(),
currentUser);
} catch (AuthenticationException e) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs(Strings.nullToEmpty(e.getMessage()));
return result;
}
Preconditions.checkState(currentUser.size() == 1);
PrivPredicate predicate = getPrivPredicate(request.getPrivType());
if (predicate == null) {
return result;
}
// check privilege
AccessControllerManager accessManager = Env.getCurrentEnv().getAccessManager();
TPrivilegeCtrl privCtrl = request.getPrivCtrl();
TPrivilegeHier privHier = privCtrl.getPrivHier();
if (privHier == TPrivilegeHier.GLOBAL) {
if (!accessManager.checkGlobalPriv(currentUser.get(0), predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Global permissions error");
}
} else if (privHier == TPrivilegeHier.CATALOG) {
if (!accessManager.checkCtlPriv(currentUser.get(0), privCtrl.getCtl(), predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Catalog permissions error");
}
} else if (privHier == TPrivilegeHier.DATABASE) {
String fullDbName = ClusterNamespace.getFullName(cluster, privCtrl.getDb());
if (!accessManager.checkDbPriv(currentUser.get(0), fullDbName, predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Database permissions error");
}
} else if (privHier == TPrivilegeHier.TABLE) {
String fullDbName = ClusterNamespace.getFullName(cluster, privCtrl.getDb());
if (!accessManager.checkTblPriv(currentUser.get(0), fullDbName, privCtrl.getTbl(), predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Table permissions error");
}
} else if (privHier == TPrivilegeHier.COLUMNS) {
String fullDbName = ClusterNamespace.getFullName(cluster, privCtrl.getDb());
if (!accessManager.checkColumnsPriv(currentUser.get(0), fullDbName, privCtrl.getTbl(), privCtrl.getCols(),
predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Columns permissions error");
}
} else if (privHier == TPrivilegeHier.RESOURSE) {
if (!accessManager.checkResourcePriv(currentUser.get(0), privCtrl.getRes(), predicate)) {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Resourse permissions error");
}
} else {
status.setStatusCode(TStatusCode.ANALYSIS_ERROR);
status.addToErrorMsgs("Privilege control error");
}
return result;
}
private PrivPredicate getPrivPredicate(TPrivilegeType privType) {
switch (privType) {
case SHOW:
return PrivPredicate.SHOW;
case SHOW_RESOURCES:
return PrivPredicate.SHOW_RESOURCES;
case GRANT:
return PrivPredicate.GRANT;
case ADMIN:
return PrivPredicate.ADMIN;
case LOAD:
return PrivPredicate.LOAD;
case ALTER:
return PrivPredicate.ALTER;
case USAGE:
return PrivPredicate.USAGE;
case CREATE:
return PrivPredicate.CREATE;
case ALL:
return PrivPredicate.ALL;
case OPERATOR:
return PrivPredicate.OPERATOR;
case DROP:
return PrivPredicate.DROP;
default:
return null;
}
}
}