blob: 5db796dd45fcc026bfbbd17173b4c54d8051611e [file] [log] [blame]
/**
* 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.sentry.binding.hive.authz;
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hive.SentryHiveConstants;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.ql.metadata.AuthorizationException;
import org.apache.hadoop.hive.ql.plan.HiveOperation;
import org.apache.hadoop.hive.ql.security.HiveAuthenticationProvider;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAccessControlException;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzPluginException;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzSessionContext.CLIENT_TYPE;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrincipal;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrincipal.HivePrincipalType;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilege;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeInfo;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveRoleGrant;
import org.apache.sentry.api.service.thrift.SentryObjectPrivileges;
import org.apache.sentry.api.service.thrift.TSentryAuthorizable;
import org.apache.sentry.api.service.thrift.TSentryPrivilegeMap;
import org.apache.sentry.binding.hive.SentryOnFailureHookContext;
import org.apache.sentry.binding.hive.SentryOnFailureHookContextImpl;
import org.apache.sentry.binding.hive.authz.HiveAuthzBinding.HiveHook;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf.AuthzConfVars;
import org.apache.sentry.binding.util.SentryAuthorizerUtil;
import org.apache.sentry.core.common.ActiveRoleSet;
import org.apache.sentry.core.common.Authorizable;
import org.apache.sentry.core.common.exception.SentryAccessDeniedException;
import org.apache.sentry.core.common.exception.SentryNoSuchObjectException;
import org.apache.sentry.core.common.exception.SentryUserException;
import org.apache.sentry.core.model.db.AccessConstants;
import org.apache.sentry.core.model.db.DBModelAuthorizable;
import org.apache.sentry.core.model.db.Server;
import org.apache.sentry.api.service.thrift.SentryPolicyServiceClient;
import org.apache.sentry.api.service.thrift.TSentryPrivilege;
import org.apache.sentry.api.service.thrift.TSentryRole;
import org.apache.sentry.service.thrift.SentryServiceClientFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DefaultSentryAccessController extends SentryHiveAccessController {
public static final Logger LOG = LoggerFactory.getLogger(DefaultSentryAccessController.class);
public static final String REQUIRED_AUTHZ_SERVER_NAME = "Config "
+ AuthzConfVars.AUTHZ_SERVER_NAME.getVar() + " is required";
private HiveAuthenticationProvider authenticator;
private String serverName;
private HiveConf conf;
private HiveAuthzConf authzConf;
private HiveAuthzSessionContext ctx;
private HiveHook hiveHook;
private HiveAuthzBinding hiveAuthzBinding;
protected SentryPolicyServiceClient sentryClient;
public DefaultSentryAccessController(HiveConf conf, HiveAuthzConf authzConf,
HiveAuthenticationProvider authenticator, HiveAuthzSessionContext ctx) throws Exception {
initilize(conf, authzConf, authenticator, ctx);
this.hiveHook = HiveHook.HiveServer2;
}
public DefaultSentryAccessController(HiveHook hiveHook, HiveConf conf, HiveAuthzConf authzConf,
HiveAuthenticationProvider authenticator, HiveAuthzSessionContext ctx) throws Exception {
initilize(conf, authzConf, authenticator, ctx);
this.hiveHook = hiveHook;
}
/**
* initialize authenticator and hiveAuthzBinding.
*/
protected void initilize(HiveConf conf, HiveAuthzConf authzConf,
HiveAuthenticationProvider authenticator, HiveAuthzSessionContext ctx) throws Exception {
Preconditions.checkNotNull(conf, "HiveConf cannot be null");
Preconditions.checkNotNull(authzConf, "HiveAuthzConf cannot be null");
Preconditions.checkNotNull(authenticator, "Hive authenticator provider cannot be null");
Preconditions.checkNotNull(ctx, "HiveAuthzSessionContext cannot be null");
this.conf = conf;
this.authzConf = authzConf;
this.authenticator = authenticator;
this.ctx = ctx;
this.serverName =
Preconditions.checkNotNull(authzConf.get(AuthzConfVars.AUTHZ_SERVER_NAME.getVar()),
REQUIRED_AUTHZ_SERVER_NAME);
}
@Override
public void createRole(String roleName, HivePrincipal adminGrantor)
throws HiveAuthzPluginException, HiveAccessControlException {
if (AccessConstants.RESERVED_ROLE_NAMES.contains(roleName.toUpperCase())) {
String msg =
"Roles cannot be one of the reserved roles: " + AccessConstants.RESERVED_ROLE_NAMES;
throw new HiveAccessControlException(msg);
}
try {
sentryClient = getSentryClient();
sentryClient.createRole(authenticator.getUserName(), roleName);
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.CREATEROLE;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Sentry failed to create role: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
}
@Override
public void dropRole(String roleName) throws HiveAuthzPluginException, HiveAccessControlException {
if (AccessConstants.RESERVED_ROLE_NAMES.contains(roleName.toUpperCase())) {
String msg =
"Roles cannot be one of the reserved roles: " + AccessConstants.RESERVED_ROLE_NAMES;
throw new HiveAccessControlException(msg);
}
try {
sentryClient = getSentryClient();
sentryClient.dropRole(authenticator.getUserName(), roleName);
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.DROPROLE;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Sentry failed to drop role: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
}
@Override
public List<String> getAllRoles() throws HiveAccessControlException, HiveAuthzPluginException {
List<String> roles = new ArrayList<String>();
try {
sentryClient = getSentryClient();
roles = convert2RoleList(sentryClient.listAllRoles(authenticator.getUserName()));
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.SHOW_ROLES;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient listRoles: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
return roles;
}
@Override
public void grantPrivileges(List<HivePrincipal> hivePrincipals,
List<HivePrivilege> hivePrivileges, HivePrivilegeObject hivePrivObject,
HivePrincipal grantorPrincipal, boolean grantOption) throws HiveAuthzPluginException,
HiveAccessControlException {
grantOrRevokePrivlegeOnRole(hivePrincipals, hivePrivileges, hivePrivObject, grantOption, true);
}
@Override
public void revokePrivileges(List<HivePrincipal> hivePrincipals,
List<HivePrivilege> hivePrivileges, HivePrivilegeObject hivePrivObject,
HivePrincipal grantorPrincipal, boolean grantOption) throws HiveAuthzPluginException,
HiveAccessControlException {
grantOrRevokePrivlegeOnRole(hivePrincipals, hivePrivileges, hivePrivObject, grantOption, false);
}
@Override
public void grantRole(List<HivePrincipal> hivePrincipals, List<String> roles,
boolean grantOption, HivePrincipal grantorPrinc) throws HiveAuthzPluginException,
HiveAccessControlException {
grantOrRevokeRoleOnGroup(hivePrincipals, roles, grantorPrinc, true);
}
@Override
public void revokeRole(List<HivePrincipal> hivePrincipals, List<String> roles,
boolean grantOption, HivePrincipal grantorPrinc) throws HiveAuthzPluginException,
HiveAccessControlException {
grantOrRevokeRoleOnGroup(hivePrincipals, roles, grantorPrinc, false);
}
@Override
public List<HivePrivilegeInfo> showPrivileges(HivePrincipal principal, HivePrivilegeObject privObj)
throws HiveAuthzPluginException, HiveAccessControlException {
if(principal.getName().isEmpty()) {
return showPriviliegesForObject(privObj);
} else {
return showPrivilegesByPrincipal(principal, privObj);
}
}
public List<HivePrivilegeInfo> showPrivilegesByPrincipal(HivePrincipal principal,
HivePrivilegeObject privObj) throws HiveAuthzPluginException, HiveAccessControlException {
if (principal.getType() != HivePrincipalType.ROLE && principal.getType() != HivePrincipalType.USER) {
String msg =
SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + principal.getType();
throw new HiveAuthzPluginException(msg);
}
List<HivePrivilegeInfo> infoList = new ArrayList<HivePrivilegeInfo>();
try {
sentryClient = getSentryClient();
List<List<DBModelAuthorizable>> authorizables =
SentryAuthorizerUtil.getAuthzHierarchy(new Server(serverName), privObj);
Set<TSentryPrivilege> tPrivilges = new HashSet<TSentryPrivilege>();
if (authorizables != null && !authorizables.isEmpty()) {
for (List<? extends Authorizable> authorizable : authorizables) {
switch (principal.getType()) {
case ROLE:
tPrivilges.addAll(sentryClient.listPrivilegesByRoleName(authenticator.getUserName(),
principal.getName(), authorizable));
break;
case USER:
try {
tPrivilges.addAll(sentryClient.listPrivilegesByUserName(authenticator.getUserName(),
principal.getName(), authorizable));
} catch (SentryNoSuchObjectException e) {
// SentryNoSuchObjectException is thrown by Sentry when the user name requested
// is not found in the Sentry database. Sentry only stores user information when
// privileges are granted, and deletes the user when privileges are deleted to avoid
// stale data.
// To avoid throwing a nasty exception in Hive, then we return an empty list instead
// to let Hive execute the SHOW GRANT USER without errors.
LOG.info("User {} requested does not exist in Sentry", authenticator.getUserName());
}
break;
}
}
} else {
switch (principal.getType()) {
case ROLE:
tPrivilges.addAll(sentryClient.listPrivilegesByRoleName(authenticator.getUserName(),
principal.getName(), null));
break;
case USER:
try {
tPrivilges.addAll(sentryClient.listPrivilegesByUserName(authenticator.getUserName(),
principal.getName(), null));
} catch (SentryNoSuchObjectException e) {
// SentryNoSuchObjectException is thrown by Sentry when the user name requested
// is not found in the Sentry database. Sentry only stores user information when
// privileges are granted, and deletes the user when privileges are deleted to avoid
// stale data.
// To avoid throwing a nasty exception in Hive, then we return an empty list instead
// to let Hive execute the SHOW GRANT USER without errors.
LOG.info("User {} requested does not exist in Sentry", authenticator.getUserName());
}
break;
}
}
if (tPrivilges != null && !tPrivilges.isEmpty()) {
for (TSentryPrivilege privilege : tPrivilges) {
infoList.add(SentryAuthorizerUtil.convert2HivePrivilegeInfo(privilege, principal));
}
}
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.SHOW_GRANT;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient listPrivilegesByRoleName: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
return infoList;
}
private List<HivePrivilegeInfo> showPriviliegesForObject(HivePrivilegeObject privObj)
throws HiveAuthzPluginException, HiveAccessControlException {
List<HivePrivilegeInfo> infoList = new ArrayList<HivePrivilegeInfo>();
if (privObj == null) {
String msg =
SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + "unspecified object name";
throw new HiveAuthzPluginException(msg);
}
try {
sentryClient = getSentryClient();
Set<List<? extends Authorizable>> authorizableSet =
Sets.newHashSet(SentryAuthorizerUtil.getAuthzHierarchy(new Server(serverName), privObj));
Set<String> users = Collections.singleton(authenticator.getUserName());
SentryObjectPrivileges sentryObjectPrivileges = null;
if (authorizableSet != null && !authorizableSet.isEmpty()) {
hiveAuthzBinding = new HiveAuthzBinding(hiveHook, this.conf, authzConf);
sentryObjectPrivileges = sentryClient
.getAllPrivilegsbyAuthorizable(authenticator.getUserName(), authorizableSet, null, users, hiveAuthzBinding.getActiveRoleSet());
} else {
String msg =
SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + "object name [" + privObj.getObjectName() + "] does not exist";
throw new HiveAuthzPluginException(msg);
}
Map<TSentryAuthorizable, TSentryPrivilegeMap> rolePrivilegesMap = sentryObjectPrivileges.getPrivilegesForRoles();
generateHivePrincipalInfo(infoList, rolePrivilegesMap, HivePrincipalType.ROLE);
Map<TSentryAuthorizable, TSentryPrivilegeMap> userPrivilegesMap = sentryObjectPrivileges.getPrivilegesForUsers();
generateHivePrincipalInfo(infoList, userPrivilegesMap, HivePrincipalType.USER);
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.SHOW_GRANT;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient listPrivilegsbyAuthorizable: " + e;
executeOnErrorHooks(msg, e);
} catch (Exception e) {
String msg = "Error when sentryClient listPrivilegsbyAuthorizable: " + e;
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
return infoList;
}
private void generateHivePrincipalInfo(List<HivePrivilegeInfo> infoList,
Map<TSentryAuthorizable, TSentryPrivilegeMap> privilegesMap,
HivePrincipalType principalType) {
if (privilegesMap != null && !privilegesMap.isEmpty()) {
for (TSentryPrivilegeMap map : privilegesMap.values()) {
Map<String, Set<TSentryPrivilege>> principalNameToPrivilegeMap = map.getPrivilegeMap();
for (String principalName : principalNameToPrivilegeMap.keySet()) {
for (TSentryPrivilege priv : principalNameToPrivilegeMap.get(principalName)) {
infoList.add(SentryAuthorizerUtil
.convert2HivePrivilegeInfo(priv, new HivePrincipal(principalName,
principalType)));//For now only roles are retrieved
}
}
}
}
}
@Override
public void setCurrentRole(String roleName) throws HiveAccessControlException,
HiveAuthzPluginException {
try {
sentryClient = getSentryClient();
hiveAuthzBinding = new HiveAuthzBinding(hiveHook, conf, authzConf);
hiveAuthzBinding.setActiveRoleSet(roleName,
sentryClient.listUserRoles(authenticator.getUserName()));
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.GRANT_ROLE;
executeOnFailureHooks(hiveOp, e);
} catch (Exception e) {
String msg = "Error when sentryClient setCurrentRole: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
if (hiveAuthzBinding != null) {
hiveAuthzBinding.close();
}
}
}
@Override
public List<String> getCurrentRoleNames() throws HiveAuthzPluginException {
List<String> roles = new ArrayList<String>();
try {
sentryClient = getSentryClient();
hiveAuthzBinding = new HiveAuthzBinding(hiveHook, conf, authzConf);
ActiveRoleSet roleSet = hiveAuthzBinding.getActiveRoleSet();
if (roleSet.isAll()) {
roles = convert2RoleList(sentryClient.listUserRoles(authenticator.getUserName()));
} else {
roles.addAll(roleSet.getRoles());
}
} catch (Exception e) {
String msg = "Error when sentryClient listUserRoles: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
if (hiveAuthzBinding != null) {
hiveAuthzBinding.close();
}
}
return roles;
}
@Override
public List<HiveRoleGrant> getPrincipalGrantInfoForRole(String roleName)
throws HiveAuthzPluginException {
// TODO we will support in future
throw new HiveAuthzPluginException("Not supported of SHOW_ROLE_PRINCIPALS in Sentry");
}
@Override
public List<HiveRoleGrant> getRoleGrantInfoForPrincipal(HivePrincipal principal)
throws HiveAccessControlException, HiveAuthzPluginException {
List<HiveRoleGrant> hiveRoleGrants = new ArrayList<HiveRoleGrant>();
try {
sentryClient = getSentryClient();
Set<TSentryRole> roles = null;
if (principal.getType() == HivePrincipalType.GROUP) {
roles = sentryClient.listRolesByGroupName(authenticator.getUserName(), principal.getName());
} else if (principal.getType() == HivePrincipalType.USER) {
roles = sentryClient.listRolesByUserName(authenticator.getUserName(), principal.getName());
} else {
String msg =
SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + principal.getType();
throw new HiveAuthzPluginException(msg);
}
if (roles != null && !roles.isEmpty()) {
for (TSentryRole role : roles) {
hiveRoleGrants.add(SentryAuthorizerUtil.convert2HiveRoleGrant(role));
}
}
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = HiveOperation.SHOW_ROLE_GRANT;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient listRolesByGroupName: " + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
return hiveRoleGrants;
}
@Override
public void applyAuthorizationConfigPolicy(HiveConf hiveConf) throws HiveAuthzPluginException {
// Apply rest of the configuration only to HiveServer2
if (ctx.getClientType() != CLIENT_TYPE.HIVESERVER2
|| !hiveConf.getBoolVar(ConfVars.HIVE_AUTHORIZATION_ENABLED)) {
throw new HiveAuthzPluginException("Sentry only supports hiveserver2");
}
}
/**
* Grant(isGrant is true) or revoke(isGrant is false) db privileges to/from role via sentryClient,
* which is a instance of SentryPolicyServiceClientV2
*
* @param hivePrincipals
* @param hivePrivileges
* @param hivePrivObject
* @param grantOption
* @param isGrant
*/
private void grantOrRevokePrivlegeOnRole(List<HivePrincipal> hivePrincipals,
List<HivePrivilege> hivePrivileges, HivePrivilegeObject hivePrivObject, boolean grantOption,
boolean isGrant) throws HiveAuthzPluginException, HiveAccessControlException {
try {
sentryClient = getSentryClient();
for (HivePrincipal principal : hivePrincipals) {
// Sentry only support grant privilege to ROLE
if (principal.getType() != HivePrincipalType.ROLE) {
String msg =
SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL + principal.getType();
throw new HiveAuthzPluginException(msg);
}
for (HivePrivilege privilege : hivePrivileges) {
String grantorName = authenticator.getUserName();
String roleName = principal.getName();
String action = SentryAuthorizerUtil.convert2SentryAction(privilege);
List<String> columnNames = privilege.getColumns();
Boolean grantOp = null;
if (isGrant) {
grantOp = grantOption;
}
switch (hivePrivObject.getType()) {
case GLOBAL:
if (isGrant) {
sentryClient.grantServerPrivilege(grantorName, roleName,
hivePrivObject.getObjectName(), action, grantOp);
} else {
sentryClient.revokeServerPrivilege(grantorName, roleName,
hivePrivObject.getObjectName(), action, grantOp);
}
break;
case DATABASE:
if (isGrant) {
sentryClient.grantDatabasePrivilege(grantorName, roleName, serverName,
hivePrivObject.getDbname(), action, grantOp);
} else {
sentryClient.revokeDatabasePrivilege(grantorName, roleName, serverName,
hivePrivObject.getDbname(), action, grantOp);
}
break;
case TABLE_OR_VIEW:
// For column level security
if (columnNames != null && !columnNames.isEmpty()) {
// Columns accept only SELECT privileges
if (!action.equalsIgnoreCase(AccessConstants.SELECT)) {
String msg =
SentryHiveConstants.PRIVILEGE_NOT_SUPPORTED + privilege.getName()
+ " on Column";
throw new HiveAuthzPluginException(msg);
}
if (isGrant) {
sentryClient.grantColumnsPrivileges(grantorName, roleName, serverName,
hivePrivObject.getDbname(), hivePrivObject.getObjectName(), columnNames,
action, grantOp);
} else {
sentryClient.revokeColumnsPrivilege(grantorName, roleName, serverName,
hivePrivObject.getDbname(), hivePrivObject.getObjectName(), columnNames,
action, grantOp);
}
} else {
// Table does not accept CREATE privileges
if (action.equalsIgnoreCase(AccessConstants.CREATE)) {
String msg =
SentryHiveConstants.PRIVILEGE_NOT_SUPPORTED + privilege.getName()
+ " on Table";
throw new HiveAuthzPluginException(msg);
}
if (isGrant) {
sentryClient.grantTablePrivilege(grantorName, roleName, serverName,
hivePrivObject.getDbname(), hivePrivObject.getObjectName(), action, grantOp);
} else {
sentryClient.revokeTablePrivilege(grantorName, roleName, serverName,
hivePrivObject.getDbname(), hivePrivObject.getObjectName(), action, grantOp);
}
}
break;
case LOCAL_URI:
case DFS_URI:
if(StringUtils.isBlank(hivePrivObject.getObjectName())) {
throw new HiveAuthzPluginException("Null or Empty locations not supported by " + hivePrivObject.getType().name());
}
String uRIString = hivePrivObject.getObjectName().replace("'", "").replace("\"", "");
if (isGrant) {
sentryClient.grantURIPrivilege(grantorName, roleName, serverName,
uRIString, grantOp);
} else {
sentryClient.revokeURIPrivilege(grantorName, roleName, serverName,
uRIString, grantOp);
}
break;
case FUNCTION:
case PARTITION:
case COLUMN:
case COMMAND_PARAMS:
// not support these type
throw new HiveAuthzPluginException(hivePrivObject.getType().name()
+ " are not supported in sentry");
default:
break;
}
}
}
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp =
isGrant ? HiveOperation.GRANT_PRIVILEGE : HiveOperation.REVOKE_PRIVILEGE;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient grant/revoke privilege:" + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
}
/**
* Grant(isGrant is true) or revoke(isGrant is false) role to/from group via sentryClient, which
* is a instance of SentryPolicyServiceClientV2
*
* @param hivePrincipals
* @param roles
* @param grantorPrinc
* @param isGrant
*/
private void grantOrRevokeRoleOnGroup(List<HivePrincipal> hivePrincipals, List<String> roles,
HivePrincipal grantorPrinc, boolean isGrant) throws HiveAuthzPluginException,
HiveAccessControlException {
try {
sentryClient = getSentryClient();
// get principals
Set<String> groups = Sets.newHashSet();
Set<String> users = Sets.newHashSet();
for (HivePrincipal principal : hivePrincipals) {
if (principal.getType() == HivePrincipalType.GROUP) {
groups.add(principal.getName());
} else if (principal.getType() == HivePrincipalType.USER) {
users.add(principal.getName());
} else {
String msg =
SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL + principal.getType();
throw new HiveAuthzPluginException(msg);
}
}
// grant/revoke role to/from principals
for (String roleName : roles) {
if (isGrant) {
if (groups.size() > 0) {
sentryClient.grantRoleToGroups(grantorPrinc.getName(), roleName, groups);
}
if (users.size() > 0) {
sentryClient.grantRoleToUsers(grantorPrinc.getName(), roleName, users);
}
} else {
if (groups.size() > 0) {
sentryClient.revokeRoleFromGroups(grantorPrinc.getName(), roleName, groups);
}
if (users.size() > 0) {
sentryClient.revokeRoleFromUsers(grantorPrinc.getName(), roleName, users);
}
}
}
} catch (SentryAccessDeniedException e) {
HiveOperation hiveOp = isGrant ? HiveOperation.GRANT_ROLE : HiveOperation.REVOKE_ROLE;
executeOnFailureHooks(hiveOp, e);
} catch (SentryUserException e) {
String msg = "Error when sentryClient grant/revoke role:" + e.getMessage();
executeOnErrorHooks(msg, e);
} finally {
closeClient();
}
}
private void executeOnFailureHooks(HiveOperation hiveOp, SentryAccessDeniedException e)
throws HiveAccessControlException {
// With Hive 2.x cmd information is not available from SessionState. More over cmd information
// is not used in SentryOnFailureHookContextImpl. If this information is really needed an issue
// should be raised with Hive community to update HiveAccessController interface to pass
// HiveSemanticAnalyzerHookContext, which has cmd information. For now, empty string is used for
// cmd.
SentryOnFailureHookContext hookCtx =
new SentryOnFailureHookContextImpl("", null, null, hiveOp, null,
null, null, null, authenticator.getUserName(), null, new AuthorizationException(e),
authzConf);
SentryAuthorizerUtil.executeOnFailureHooks(hookCtx, authzConf);
throw new HiveAccessControlException(e.getMessage(), e);
}
private void executeOnErrorHooks(String msg, Exception e) throws HiveAuthzPluginException {
LOG.error(msg, e);
throw new HiveAuthzPluginException(msg, e);
}
private List<String> convert2RoleList(Set<TSentryRole> roleSet) {
List<String> roles = new ArrayList<String>();
if (roleSet != null && !roleSet.isEmpty()) {
for (TSentryRole tRole : roleSet) {
roles.add(tRole.getRoleName());
}
}
return roles;
}
private SentryPolicyServiceClient getSentryClient() throws HiveAuthzPluginException {
try {
Preconditions.checkNotNull(authzConf, "HiveAuthConf cannot be null");
return SentryServiceClientFactory.create(authzConf);
} catch (Exception e) {
String msg = "Error occurred when creating Sentry client: " + e.getMessage();
throw new HiveAuthzPluginException(msg, e);
}
}
private void closeClient() {
if (sentryClient != null) {
try {
sentryClient.close();
} catch (Exception e) {
LOG.error("Error while closing the connection with sentry server", e);
}
}
}
}