[Improvement](auth)(step-2) add ranger authorizer for hms catalog (#17424)
This commit is contained in:
@ -18,9 +18,12 @@
|
||||
package org.apache.doris.catalog.authorizer;
|
||||
|
||||
import org.apache.doris.analysis.UserIdentity;
|
||||
import org.apache.doris.cluster.ClusterNamespace;
|
||||
import org.apache.doris.common.AuthorizationException;
|
||||
import org.apache.doris.common.ThreadPoolManager;
|
||||
import org.apache.doris.mysql.privilege.CatalogAccessController;
|
||||
import org.apache.doris.mysql.privilege.PrivPredicate;
|
||||
import org.apache.doris.mysql.privilege.Role;
|
||||
|
||||
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAccessControlException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -33,13 +36,18 @@ import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RangerHiveAccessController implements CatalogAccessController {
|
||||
public static final String CLIENT_TYPE_DORIS = "doris";
|
||||
private static final Logger LOG = LogManager.getLogger(RangerHiveAccessController.class);
|
||||
private static ScheduledThreadPoolExecutor logFlushTimer = ThreadPoolManager.newDaemonScheduledThreadPool(1,
|
||||
"ranger-hive-audit-log-flusher-timer", true);
|
||||
private RangerHivePlugin hivePlugin;
|
||||
private RangerHiveAuditHandler auditHandler;
|
||||
|
||||
@ -47,12 +55,24 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
String serviceName = properties.get("ranger.service.name");
|
||||
hivePlugin = new RangerHivePlugin(serviceName);
|
||||
auditHandler = new RangerHiveAuditHandler(hivePlugin.getConfig());
|
||||
//start a timed log flusher
|
||||
logFlushTimer.scheduleAtFixedRate(new RangerHiveAuditLogFlusher(auditHandler), 10, 20L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private RangerAccessRequestImpl createRequest(UserIdentity currentUser, HiveAccessType accessType) {
|
||||
RangerAccessRequestImpl request = new RangerAccessRequestImpl();
|
||||
request.setUser(currentUser.getQualifiedUser());
|
||||
request.setUserRoles(currentUser.getRoles());
|
||||
// currentUser.getQualifiedUser() is as of form: default_cluster:user1, only use `user1`
|
||||
String[] userArray = currentUser.getQualifiedUser().split(":");
|
||||
request.setUser(userArray[1]);
|
||||
request.setClusterName(userArray[0]);
|
||||
Set<String> roles = new HashSet<>();
|
||||
for (String role : currentUser.getRoles()) {
|
||||
// default role is as of form: default_role_rbac_xxx@%, not useful for Ranger
|
||||
if (!Role.isDefaultRoleName(role)) {
|
||||
roles.add(role);
|
||||
}
|
||||
}
|
||||
request.setUserRoles(roles);
|
||||
request.setAction(accessType.name());
|
||||
if (accessType == HiveAccessType.USE) {
|
||||
request.setAccessType(RangerPolicyEngine.ANY_ACCESS);
|
||||
@ -60,6 +80,7 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
request.setAccessType(accessType.name().toLowerCase());
|
||||
}
|
||||
request.setClientIPAddress(currentUser.getHost());
|
||||
request.setClusterType(CLIENT_TYPE_DORIS);
|
||||
request.setClientType(CLIENT_TYPE_DORIS);
|
||||
request.setAccessTime(new Date());
|
||||
|
||||
@ -68,28 +89,24 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
|
||||
private void checkPrivileges(UserIdentity currentUser, HiveAccessType accessType,
|
||||
List<RangerHiveResource> hiveResources) throws AuthorizationException {
|
||||
try {
|
||||
List<RangerAccessRequest> requests = new ArrayList<>();
|
||||
for (RangerHiveResource resource : hiveResources) {
|
||||
RangerAccessRequestImpl request = createRequest(currentUser, accessType);
|
||||
request.setResource(resource);
|
||||
List<RangerAccessRequest> requests = new ArrayList<>();
|
||||
for (RangerHiveResource resource : hiveResources) {
|
||||
RangerAccessRequestImpl request = createRequest(currentUser, accessType);
|
||||
request.setResource(resource);
|
||||
|
||||
requests.add(request);
|
||||
}
|
||||
requests.add(request);
|
||||
}
|
||||
|
||||
Collection<RangerAccessResult> results = hivePlugin.isAccessAllowed(requests, auditHandler);
|
||||
for (RangerAccessResult result : results) {
|
||||
LOG.debug("match policy:" + result.getPolicyId());
|
||||
if (!result.getIsAllowed()) {
|
||||
LOG.debug(result.getReason());
|
||||
throw new AuthorizationException(String.format(
|
||||
"Permission denied: user [%s] does not have privilege for [%s] command on [%s]",
|
||||
currentUser.getQualifiedUser(), accessType.name(),
|
||||
result.getAccessRequest().getResource().getAsString()));
|
||||
}
|
||||
Collection<RangerAccessResult> results = hivePlugin.isAccessAllowed(requests, auditHandler);
|
||||
for (RangerAccessResult result : results) {
|
||||
LOG.debug(String.format("request %s match policy %s", result.getAccessRequest(), result.getPolicyId()));
|
||||
if (!result.getIsAllowed()) {
|
||||
LOG.debug(result.getReason());
|
||||
throw new AuthorizationException(String.format(
|
||||
"Permission denied: user [%s] does not have privilege for [%s] command on [%s]",
|
||||
result.getAccessRequest().getUser(), accessType.name(),
|
||||
result.getAccessRequest().getResource().getAsString()));
|
||||
}
|
||||
} finally {
|
||||
auditHandler.flushAudit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,20 +116,20 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
request.setResource(resource);
|
||||
|
||||
RangerAccessResult result = hivePlugin.isAccessAllowed(request, auditHandler);
|
||||
auditHandler.flushAudit();
|
||||
|
||||
if (result == null) {
|
||||
LOG.warn(String.format("Error getting authorizer result, please check your ranger config. Request: %s",
|
||||
request));
|
||||
LOG.warn(String.format("Error getting authorizer result, please check your ranger config. Make sure "
|
||||
+ "ranger policy engine is initialized. Request: %s", request));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.getIsAllowed()) {
|
||||
LOG.debug(String.format("request %s match policy %s", request, result.getPolicyId()));
|
||||
return true;
|
||||
} else {
|
||||
LOG.debug(String.format(
|
||||
"Permission denied: user [%s] does not have privilege for [%s] command on [%s]",
|
||||
currentUser.getQualifiedUser(), accessType.name(),
|
||||
result.getAccessRequest().getUser(), accessType.name(),
|
||||
result.getAccessRequest().getResource().getAsString()));
|
||||
return false;
|
||||
}
|
||||
@ -123,7 +140,6 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
RangerAccessRequestImpl request = createRequest(currentUser, accessType);
|
||||
request.setResource(resource);
|
||||
RangerAccessResult result = hivePlugin.isAccessAllowed(request, auditHandler);
|
||||
auditHandler.flushAudit();
|
||||
|
||||
return result.getFilterExpr();
|
||||
}
|
||||
@ -133,7 +149,6 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
RangerAccessRequestImpl request = createRequest(currentUser, accessType);
|
||||
request.setResource(resource);
|
||||
RangerAccessResult result = hivePlugin.isAccessAllowed(request, auditHandler);
|
||||
auditHandler.flushAudit();
|
||||
|
||||
LOG.debug(String.format("maskType: %s, maskTypeDef: %s, maskedValue: %s", result.getMaskType(),
|
||||
result.getMaskTypeDef(), result.getMaskedValue()));
|
||||
@ -142,7 +157,9 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
public HiveAccessType convertToAccessType(PrivPredicate predicate) {
|
||||
if (predicate == PrivPredicate.SHOW) {
|
||||
return HiveAccessType.USE;
|
||||
} else if (predicate == PrivPredicate.ADMIN) {
|
||||
} else if (predicate == PrivPredicate.SELECT) {
|
||||
return HiveAccessType.SELECT;
|
||||
} else if (predicate == PrivPredicate.ADMIN || predicate == PrivPredicate.ALL) {
|
||||
return HiveAccessType.ALL;
|
||||
} else if (predicate == PrivPredicate.LOAD) {
|
||||
return HiveAccessType.UPDATE;
|
||||
@ -152,8 +169,6 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
return HiveAccessType.CREATE;
|
||||
} else if (predicate == PrivPredicate.DROP) {
|
||||
return HiveAccessType.DROP;
|
||||
} else if (predicate == PrivPredicate.SELECT) {
|
||||
return HiveAccessType.SELECT;
|
||||
} else {
|
||||
return HiveAccessType.NONE;
|
||||
}
|
||||
@ -161,18 +176,20 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
|
||||
@Override
|
||||
public boolean checkCtlPriv(UserIdentity currentUser, String ctl, PrivPredicate wanted) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkDbPriv(UserIdentity currentUser, String ctl, String db, PrivPredicate wanted) {
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.DATABASE, db);
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.DATABASE,
|
||||
ClusterNamespace.getNameFromFullName(db));
|
||||
return checkPrivilege(currentUser, convertToAccessType(wanted), resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTblPriv(UserIdentity currentUser, String ctl, String db, String tbl, PrivPredicate wanted) {
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.TABLE, db, tbl);
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.TABLE,
|
||||
ClusterNamespace.getNameFromFullName(db), tbl);
|
||||
return checkPrivilege(currentUser, convertToAccessType(wanted), resource);
|
||||
}
|
||||
|
||||
@ -181,7 +198,8 @@ public class RangerHiveAccessController implements CatalogAccessController {
|
||||
PrivPredicate wanted) throws AuthorizationException {
|
||||
List<RangerHiveResource> resources = new ArrayList<>();
|
||||
for (String col : cols) {
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.COLUMN, db, tbl, col);
|
||||
RangerHiveResource resource = new RangerHiveResource(HiveObjectType.COLUMN,
|
||||
ClusterNamespace.getNameFromFullName(db), tbl, col);
|
||||
resources.add(resource);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
// 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.catalog.authorizer;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class RangerHiveAuditLogFlusher extends TimerTask {
|
||||
|
||||
private RangerHiveAuditHandler auditHandler;
|
||||
|
||||
public RangerHiveAuditLogFlusher(RangerHiveAuditHandler auditHandler) {
|
||||
this.auditHandler = auditHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
this.auditHandler.flushAudit();
|
||||
|
||||
try {
|
||||
Thread.sleep(20000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,6 +118,10 @@ public class Role implements Writable, GsonPostProcessable {
|
||||
|
||||
}
|
||||
|
||||
public static boolean isDefaultRoleName(String roleName) {
|
||||
return roleName.startsWith(RoleManager.DEFAULT_ROLE_PREFIX);
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user