blob: 3f06cae2b025f97d2a579ea5a32d5d49f379129b [file] [log] [blame]
package org.apache.hadoop.hive.ql.exec;
/**
* 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.
*/
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.SentryHiveConstants;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.api.PrincipalType;
import org.apache.hadoop.hive.ql.DriverContext;
import org.apache.hadoop.hive.ql.QueryPlan;
import org.apache.hadoop.hive.ql.hooks.ReadEntity;
import org.apache.hadoop.hive.ql.hooks.WriteEntity;
import org.apache.hadoop.hive.ql.metadata.AuthorizationException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.plan.DDLWork;
import org.apache.hadoop.hive.ql.plan.GrantDesc;
import org.apache.hadoop.hive.ql.plan.GrantRevokeRoleDDL;
import org.apache.hadoop.hive.ql.plan.HiveOperation;
import org.apache.hadoop.hive.ql.plan.PrincipalDesc;
import org.apache.hadoop.hive.ql.plan.PrivilegeDesc;
import org.apache.hadoop.hive.ql.plan.PrivilegeObjectDesc;
import org.apache.hadoop.hive.ql.plan.RevokeDesc;
import org.apache.hadoop.hive.ql.plan.RoleDDLDesc;
import org.apache.hadoop.hive.ql.plan.ShowGrantDesc;
import org.apache.hadoop.hive.ql.plan.api.StageType;
import org.apache.hadoop.hive.ql.security.authorization.PrivilegeType;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hadoop.hive.ql.session.SessionState.LogHelper;
import org.apache.sentry.core.common.exception.SentryUserException;
import org.apache.sentry.binding.hive.HiveAuthzBindingHookBase;
import org.apache.sentry.binding.hive.SentryOnFailureHookContext;
import org.apache.sentry.binding.hive.SentryOnFailureHookContextImpl;
import org.apache.sentry.binding.hive.authz.HiveAuthzBinding;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
import org.apache.sentry.binding.hive.conf.HiveAuthzConf.AuthzConfVars;
import org.apache.sentry.core.common.ActiveRoleSet;
import org.apache.sentry.core.common.Authorizable;
import org.apache.sentry.core.common.Subject;
import org.apache.sentry.core.common.utils.PathUtils;
import org.apache.sentry.core.model.db.AccessConstants;
import org.apache.sentry.core.model.db.AccessURI;
import org.apache.sentry.core.model.db.Column;
import org.apache.sentry.core.model.db.Database;
import org.apache.sentry.core.model.db.Server;
import org.apache.sentry.core.model.db.Table;
import org.apache.sentry.core.common.exception.SentryAccessDeniedException;
import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption;
import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
import org.apache.sentry.provider.db.service.thrift.TSentryRole;
import org.apache.sentry.service.thrift.SentryServiceClientFactory;
import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
public class SentryGrantRevokeTask extends Task<DDLWork> implements Serializable {
private static final Logger LOG = LoggerFactory
.getLogger(SentryGrantRevokeTask.class);
private static final int RETURN_CODE_SUCCESS = 0;
private static final int RETURN_CODE_FAILURE = 1;
private static final Splitter DB_TBL_SPLITTER = Splitter.on(".").omitEmptyStrings().trimResults();
private static final int separator = Utilities.tabCode;
private static final int terminator = Utilities.newLineCode;
private static final long serialVersionUID = -7625118066790571999L;
private HiveConf conf;
private HiveAuthzBinding hiveAuthzBinding;
private HiveAuthzConf authzConf;
private String server;
private Subject subject;
private Set<String> subjectGroups;
private String ipAddress;
private HiveOperation stmtOperation;
@Override
public void initialize(HiveConf conf, QueryPlan queryPlan, DriverContext ctx) {
super.initialize(conf, queryPlan, driverContext);
this.conf = conf;
}
@Override
public int execute(DriverContext driverContext) {
try (SentryPolicyServiceClient sentryClient =
SentryServiceClientFactory.create(authzConf)) {
Preconditions.checkNotNull(hiveAuthzBinding, "HiveAuthzBinding cannot be null");
Preconditions.checkNotNull(authzConf, "HiveAuthConf cannot be null");
Preconditions.checkNotNull(subject, "Subject cannot be null");
server = Preconditions.checkNotNull(authzConf.get(AuthzConfVars.AUTHZ_SERVER_NAME.getVar()),
"Config " + AuthzConfVars.AUTHZ_SERVER_NAME.getVar() + " is required");
try {
if (work.getRoleDDLDesc() != null) {
return processRoleDDL(console, sentryClient, subject.getName(),
hiveAuthzBinding, work.getRoleDDLDesc());
}
if (work.getGrantDesc() != null) {
return processGrantDDL(console, sentryClient,
subject.getName(), server, work.getGrantDesc());
}
if (work.getRevokeDesc() != null) {
return processRevokeDDL(console, sentryClient,
subject.getName(), server, work.getRevokeDesc());
}
if (work.getShowGrantDesc() != null) {
return processShowGrantDDL(console, sentryClient, subject.getName(),
work.getShowGrantDesc());
}
if (work.getGrantRevokeRoleDDL() != null) {
return processGrantRevokeRoleDDL(console, sentryClient,
subject.getName(), work.getGrantRevokeRoleDDL());
}
throw new AssertionError(
"Unknown command passed to Sentry Grant/Revoke Task");
} catch (SentryAccessDeniedException e) {
String csHooks = authzConf.get(
HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(), "")
.trim();
SentryOnFailureHookContext hookContext = new SentryOnFailureHookContextImpl(
queryPlan.getQueryString(), new HashSet<ReadEntity>(),
new HashSet<WriteEntity>(), stmtOperation,
null, null, null, null, subject.getName(), ipAddress,
new AuthorizationException(e), conf);
HiveAuthzBindingHookBase.runFailureHook(hookContext, csHooks);
throw e; // rethrow the exception for logging
}
} catch(SentryUserException e) {
setException(new Exception(e.getClass().getSimpleName() + ": " + e.getReason(), e));
String msg = "Error processing Sentry command: " + e.getReason() + ".";
if (e instanceof SentryAccessDeniedException) {
msg += "Please grant admin privilege to " + subject.getName() + ".";
}
LOG.error(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
} catch(Throwable e) {
setException(e);
String msg = "Error processing Sentry command: " + e.getMessage();
LOG.error(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
} finally {
if (hiveAuthzBinding != null) {
hiveAuthzBinding.close();
}
}
}
public void setAuthzConf(HiveAuthzConf authzConf) {
Preconditions.checkState(this.authzConf == null,
"setAuthzConf should only be called once: " + this.authzConf);
this.authzConf = authzConf;
}
public void setHiveAuthzBinding(HiveAuthzBinding hiveAuthzBinding) {
Preconditions.checkState(this.hiveAuthzBinding == null,
"setHiveAuthzBinding should only be called once: " + this.hiveAuthzBinding);
this.hiveAuthzBinding = hiveAuthzBinding;
}
public void setSubject(Subject subject) {
Preconditions.checkState(this.subject == null,
"setSubject should only be called once: " + this.subject);
this.subject = subject;
}
public void setSubjectGroups(Set<String> subjectGroups) {
Preconditions.checkState(this.subjectGroups == null,
"setSubjectGroups should only be called once: " + this.subjectGroups);
this.subjectGroups = subjectGroups;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public void setOperation(HiveOperation stmtOperation) {
this.stmtOperation = stmtOperation;
}
private int processRoleDDL(LogHelper console,
SentryPolicyServiceClient sentryClient, String subject,
HiveAuthzBinding hiveAuthzBinding, RoleDDLDesc desc)
throws SentryUserException {
RoleDDLDesc.RoleOperation operation = desc.getOperation();
DataOutputStream outStream = null;
String name = desc.getName();
try {
if (operation.equals(RoleDDLDesc.RoleOperation.SET_ROLE)) {
hiveAuthzBinding.setActiveRoleSet(name, sentryClient.listUserRoles(subject));
return RETURN_CODE_SUCCESS;
} else if (operation.equals(RoleDDLDesc.RoleOperation.CREATE_ROLE)) {
sentryClient.createRole(subject, name);
return RETURN_CODE_SUCCESS;
} else if (operation.equals(RoleDDLDesc.RoleOperation.DROP_ROLE)) {
sentryClient.dropRole(subject, name);
return RETURN_CODE_SUCCESS;
} else if (operation.equals(RoleDDLDesc.RoleOperation.SHOW_ROLE_GRANT)) {
Set<TSentryRole> roles;
PrincipalType principalType = desc.getPrincipalType();
if (principalType == PrincipalType.GROUP) {
roles = sentryClient.listRolesByGroupName(subject, name);
} else if (principalType == PrincipalType.USER) {
roles = sentryClient.listRolesByUserName(subject, name);
} else {
String msg = SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL + principalType;
throw new HiveException(msg);
}
writeToFile(writeRoleGrantsInfo(roles), desc.getResFile());
return RETURN_CODE_SUCCESS;
} else if(operation.equals(RoleDDLDesc.RoleOperation.SHOW_ROLES)) {
Set<TSentryRole> roles = sentryClient.listRoles(subject);
writeToFile(writeRolesInfo(roles), desc.getResFile());
return RETURN_CODE_SUCCESS;
} else if(operation.equals(RoleDDLDesc.RoleOperation.SHOW_CURRENT_ROLE)) {
ActiveRoleSet roleSet = hiveAuthzBinding.getActiveRoleSet();
if( roleSet.isAll()) {
Set<TSentryRole> roles = sentryClient.listUserRoles(subject);
writeToFile(writeRolesInfo(roles), desc.getResFile());
return RETURN_CODE_SUCCESS;
} else {
Set<String> roles = roleSet.getRoles();
writeToFile(writeActiveRolesInfo(roles), desc.getResFile());
return RETURN_CODE_SUCCESS;
}
} else {
throw new HiveException("Unknown role operation "
+ operation.getOperationName());
}
} catch (HiveException e) {
String msg = "Error in role operation "
+ operation.getOperationName() + " on role name "
+ name + ", error message " + e.getMessage();
LOG.warn(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
} catch (IOException e) {
String msg = "IO Error in role operation " + e.getMessage();
LOG.info(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
} finally {
closeQuiet(outStream);
}
}
private int processGrantDDL(LogHelper console,
SentryPolicyServiceClient sentryClient, String subject,
String server, GrantDesc desc) throws SentryUserException {
return processGrantRevokeDDL(console, sentryClient, subject,
server, true, desc.getPrincipals(), desc.getPrivileges(),
desc.getPrivilegeSubjectDesc(), desc.isGrantOption());
}
// For grant option, we use null to stand for revoke the privilege ignore the grant option
private int processRevokeDDL(LogHelper console,
SentryPolicyServiceClient sentryClient, String subject,
String server, RevokeDesc desc) throws SentryUserException {
return processGrantRevokeDDL(console, sentryClient, subject,
server, false, desc.getPrincipals(), desc.getPrivileges(),
desc.getPrivilegeSubjectDesc(), null);
}
private int processShowGrantDDL(LogHelper console, SentryPolicyServiceClient sentryClient,
String subject, ShowGrantDesc desc) throws SentryUserException{
PrincipalDesc principalDesc = desc.getPrincipalDesc();
PrivilegeObjectDesc hiveObjectDesc = desc.getHiveObj();
String principalName = principalDesc.getName();
Set<TSentryPrivilege> privileges;
try {
if (principalDesc.getType() != PrincipalType.ROLE) {
String msg = SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL + principalDesc.getType();
throw new HiveException(msg);
}
if (hiveObjectDesc == null) {
privileges = sentryClient.listPrivilegesByRoleName(subject, principalName, null);
} else {
SentryHivePrivilegeObjectDesc privSubjectDesc = toSentryHivePrivilegeObjectDesc(hiveObjectDesc);
List<Authorizable> authorizableHeirarchy = toAuthorizable(privSubjectDesc);
if (privSubjectDesc.getColumns() != null && !privSubjectDesc.getColumns().isEmpty()) {
List<List<Authorizable>> ps = parseColumnToAuthorizable(authorizableHeirarchy, privSubjectDesc);
ImmutableSet.Builder<TSentryPrivilege> pbuilder = new ImmutableSet.Builder<TSentryPrivilege>();
for (List<Authorizable> p : ps) {
pbuilder.addAll(sentryClient.listPrivilegesByRoleName(subject, principalName, p));
}
privileges = pbuilder.build();
} else {
privileges = sentryClient.listPrivilegesByRoleName(subject, principalName, authorizableHeirarchy);
}
}
writeToFile(writeGrantInfo(privileges, principalName), desc.getResFile());
return RETURN_CODE_SUCCESS;
} catch (IOException e) {
String msg = "IO Error in show grant " + e.getMessage();
LOG.info(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
} catch (HiveException e) {
String msg = "Error in show grant operation, error message " + e.getMessage();
LOG.warn(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
}
}
private List<Authorizable> toAuthorizable(SentryHivePrivilegeObjectDesc privSubjectDesc) throws HiveException{
List<Authorizable> authorizableHeirarchy = new ArrayList<Authorizable>();
authorizableHeirarchy.add(new Server(server));
String dbName = null;
if (privSubjectDesc.getTable()) {
DatabaseTable dbTable = parseDBTable(privSubjectDesc.getObject());
dbName = dbTable.getDatabase();
String tableName = dbTable.getTable();
authorizableHeirarchy.add(new Table(tableName));
authorizableHeirarchy.add(new Database(dbName));
} else if (privSubjectDesc.getUri()) {
String uriPath = privSubjectDesc.getObject();
String warehouseDir = conf.getVar(HiveConf.ConfVars.METASTOREWAREHOUSE);
try {
authorizableHeirarchy.add(new AccessURI(PathUtils.parseDFSURI(warehouseDir, uriPath)));
} catch(URISyntaxException e) {
throw new HiveException(e.getMessage(), e);
}
} else {
dbName = privSubjectDesc.getObject();
authorizableHeirarchy.add(new Database(dbName));
}
return authorizableHeirarchy;
}
private List<List<Authorizable>> parseColumnToAuthorizable(List<Authorizable> authorizableHeirarchy,
SentryHivePrivilegeObjectDesc privSubjectDesc) {
ImmutableList.Builder<List<Authorizable>> listsBuilder = ImmutableList.builder();
List<String> cols = privSubjectDesc.getColumns();
if ( cols != null && !cols.isEmpty() ) {
for ( String col : cols ) {
ImmutableList.Builder<Authorizable> listBuilder = ImmutableList.builder();
listBuilder.addAll(authorizableHeirarchy);
listBuilder.add(new Column(col));
listsBuilder.add(listBuilder.build());
}
}
return listsBuilder.build();
}
private void writeToFile(String data, String file) throws IOException {
Path resFile = new Path(file);
FileSystem fs = resFile.getFileSystem(conf);
FSDataOutputStream out = fs.create(resFile);
try {
if (data != null && !data.isEmpty()) {
try (OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {
writer.write(data);
writer.write((char) terminator);
writer.flush();
}
}
} finally {
closeQuiet(out);
}
}
private int processGrantRevokeRoleDDL(LogHelper console,
SentryPolicyServiceClient sentryClient, String subject,
GrantRevokeRoleDDL desc) throws SentryUserException {
try {
boolean grantRole = desc.getGrant();
List<PrincipalDesc> principals = desc.getPrincipalDesc();
List<String> roles = desc.getRoles();
// get principals
Set<String> groups = Sets.newHashSet();
Set<String> users = Sets.newHashSet();
for (PrincipalDesc principal : principals) {
if (principal.getType() == PrincipalType.GROUP) {
groups.add(principal.getName());
} else if (principal.getType() == PrincipalType.USER) {
users.add(principal.getName());
} else {
String msg = SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL +
principal.getType();
throw new HiveException(msg);
}
}
// grant/revoke role to/from principals
for (String roleName : roles) {
if (grantRole) {
if (groups.size() > 0) {
sentryClient.grantRoleToGroups(subject, roleName, groups);
}
if (users.size() > 0) {
sentryClient.grantRoleToUsers(subject, roleName, users);
}
} else {
if (groups.size() > 0) {
sentryClient.revokeRoleFromGroups(subject, roleName, groups);
}
if (users.size() > 0) {
sentryClient.revokeRoleFromUsers(subject, roleName, users);
}
}
}
} catch (HiveException e) {
String msg = "Error in grant/revoke operation, error message " + e.getMessage();
LOG.warn(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
}
return RETURN_CODE_SUCCESS;
}
static String writeGrantInfo(Set<TSentryPrivilege> privileges, String roleName) {
if (privileges == null || privileges.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
for (TSentryPrivilege privilege : privileges) {
if (PrivilegeScope.URI.name().equalsIgnoreCase(
privilege.getPrivilegeScope())) {
appendNonNull(builder, privilege.getURI(), true);
} else if(PrivilegeScope.SERVER.name().equalsIgnoreCase(
privilege.getPrivilegeScope())) {
appendNonNull(builder, "*", true);//Db column would show * if it is a server level privilege
} else {
appendNonNull(builder, privilege.getDbName(), true);
}
appendNonNull(builder, privilege.getTableName());
appendNonNull(builder, null);//getPartValues()
appendNonNull(builder, privilege.getColumnName());//getColumnName()
appendNonNull(builder, roleName);//getPrincipalName()
appendNonNull(builder, "ROLE");//getPrincipalType()
appendNonNull(builder, privilege.getAction());
appendNonNull(builder,
TSentryGrantOption.TRUE.equals(privilege.getGrantOption()));
appendNonNull(builder, privilege.getCreateTime() * 1000L);
appendNonNull(builder, "--");
}
LOG.info("builder.toString(): " + builder.toString());
return builder.toString();
}
static String writeRoleGrantsInfo(Set<TSentryRole> roleGrants) {
if (roleGrants == null || roleGrants.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
for (TSentryRole roleGrant : roleGrants) {
appendNonNull(builder, roleGrant.getRoleName(), true);
appendNonNull(builder, false);//isGrantOption()
appendNonNull(builder, null);//roleGrant.getGrantTime() * 1000L
appendNonNull(builder, "--");
}
return builder.toString();
}
static String writeRolesInfo(Set<TSentryRole> roles) {
if (roles == null || roles.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
for (TSentryRole roleGrant : roles) {
appendNonNull(builder, roleGrant.getRoleName(), true);
}
return builder.toString();
}
static String writeActiveRolesInfo(Set<String> roles) {
if (roles == null || roles.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
for (String role : roles) {
appendNonNull(builder, role, true);
}
return builder.toString();
}
static StringBuilder appendNonNull(StringBuilder builder, Object value) {
return appendNonNull(builder, value, false);
}
static StringBuilder appendNonNull(StringBuilder builder, Object value, boolean firstColumn) {
if (!firstColumn) {
builder.append((char)separator);
} else if (builder.length() > 0) {
builder.append((char)terminator);
}
if (value != null) {
builder.append(value);
}
return builder;
}
private static int processGrantRevokeDDL(LogHelper console,
SentryPolicyServiceClient sentryClient, String subject, String server,
boolean isGrant, List<PrincipalDesc> principals,
List<PrivilegeDesc> privileges, PrivilegeObjectDesc privSubjectObjDesc,
Boolean grantOption) throws SentryUserException {
if (privileges == null || privileges.size() == 0) {
console.printError("No privilege found.");
return RETURN_CODE_FAILURE;
}
String dbName = null;
String tableName = null;
List<String> columnNames = null;
String uriPath = null;
String serverName = null;
try {
SentryHivePrivilegeObjectDesc privSubjectDesc = toSentryHivePrivilegeObjectDesc(privSubjectObjDesc);
if (privSubjectDesc == null) {
throw new HiveException("Privilege subject cannot be null");
}
if (privSubjectDesc.getPartSpec() != null) {
throw new HiveException(SentryHiveConstants.PARTITION_PRIVS_NOT_SUPPORTED);
}
String obj = privSubjectDesc.getObject();
if (privSubjectDesc.getTable()) {
DatabaseTable dbTable = parseDBTable(obj);
dbName = dbTable.getDatabase();
tableName = dbTable.getTable();
} else if (privSubjectDesc.getUri()) {
uriPath = privSubjectDesc.getObject();
} else if (privSubjectDesc.getServer()) {
serverName = privSubjectDesc.getObject();
} else {
dbName = privSubjectDesc.getObject();
}
for (PrivilegeDesc privDesc : privileges) {
List<String> columns = privDesc.getColumns();
if (columns != null && !columns.isEmpty()) {
columnNames = columns;
}
if (!SentryHiveConstants.ALLOWED_PRIVS.contains(privDesc.getPrivilege().getPriv())) {
String msg = SentryHiveConstants.PRIVILEGE_NOT_SUPPORTED + privDesc.getPrivilege().getPriv();
throw new HiveException(msg);
}
if (columnNames != null && (privDesc.getPrivilege().getPriv().equals(PrivilegeType.INSERT)
|| privDesc.getPrivilege().getPriv().equals(PrivilegeType.ALL))) {
String msg = SentryHiveConstants.PRIVILEGE_NOT_SUPPORTED
+ privDesc.getPrivilege().getPriv() + " on Column";
throw new SemanticException(msg);
}
}
for (PrincipalDesc princ : principals) {
if (princ.getType() != PrincipalType.ROLE) {
String msg = SentryHiveConstants.GRANT_REVOKE_NOT_SUPPORTED_FOR_PRINCIPAL + princ.getType();
throw new HiveException(msg);
}
for (PrivilegeDesc privDesc : privileges) {
if (isGrant) {
if (serverName != null) {
sentryClient.grantServerPrivilege(subject, princ.getName(), serverName,
toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else if (uriPath != null) {
sentryClient.grantURIPrivilege(subject, princ.getName(), server, uriPath, grantOption);
} else if (tableName == null) {
sentryClient.grantDatabasePrivilege(subject, princ.getName(), server, dbName,
toDbSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else if (columnNames == null) {
sentryClient.grantTablePrivilege(subject, princ.getName(), server, dbName,
tableName, toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else {
sentryClient.grantColumnsPrivileges(subject, princ.getName(), server, dbName,
tableName, columnNames, toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
}
} else {
if (serverName != null) {
sentryClient.revokeServerPrivilege(subject, princ.getName(), serverName,
toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else if (uriPath != null) {
sentryClient.revokeURIPrivilege(subject, princ.getName(), server, uriPath, grantOption);
} else if (tableName == null) {
sentryClient.revokeDatabasePrivilege(subject, princ.getName(), server, dbName,
toDbSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else if (columnNames == null) {
sentryClient.revokeTablePrivilege(subject, princ.getName(), server, dbName,
tableName, toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
} else {
sentryClient.revokeColumnsPrivilege(subject, princ.getName(), server, dbName,
tableName, columnNames, toSentryAction(privDesc.getPrivilege().getPriv()), grantOption);
}
}
}
}
return RETURN_CODE_SUCCESS;
} catch (HiveException e) {
String msg = "Error in grant/revoke operation, error message " + e.getMessage();
LOG.warn(msg, e);
console.printError(msg);
return RETURN_CODE_FAILURE;
}
}
private static String toDbSentryAction(PrivilegeType privilegeType) throws SentryUserException{
switch(privilegeType) {
case ALL:
return AccessConstants.ALL;
case SELECT:
return AccessConstants.SELECT;
case INSERT:
return AccessConstants.INSERT;
case CREATE:
return AccessConstants.CREATE;
case DROP:
return AccessConstants.DROP;
case ALTER_METADATA:
return AccessConstants.ALTER;
case INDEX:
return AccessConstants.INDEX;
case LOCK:
return AccessConstants.LOCK;
default:
throw new SentryUserException("Unknown privilege type: " + privilegeType);
//Exception is thrown here only for development purposes.
}
}
private static SentryHivePrivilegeObjectDesc toSentryHivePrivilegeObjectDesc(PrivilegeObjectDesc privSubjectObjDesc)
throws HiveException{
if (!(privSubjectObjDesc instanceof SentryHivePrivilegeObjectDesc)) {
throw new HiveException(
"Privilege subject not parsed correctly by Sentry");
}
return (SentryHivePrivilegeObjectDesc) privSubjectObjDesc;
}
private static String toSentryAction(PrivilegeType privilegeType) {
if (PrivilegeType.ALL.equals(privilegeType)) {
return AccessConstants.ALL;
} else {
return privilegeType.toString();
}
}
private static DatabaseTable parseDBTable(String obj) throws HiveException {
String[] dbTab = Iterables.toArray(DB_TBL_SPLITTER.split(obj), String.class);
if (dbTab.length == 2) {
return new DatabaseTable(dbTab[0], dbTab[1]);
} else if (dbTab.length == 1){
return new DatabaseTable(SessionState.get().getCurrentDatabase(), obj);
} else {
String msg = "Malformed database.table '" + obj + "'";
throw new HiveException(msg);
}
}
private static class DatabaseTable {
private final String database;
private final String table;
public DatabaseTable(String database, String table) {
this.database = database;
this.table = table;
}
public String getDatabase() {
return database;
}
public String getTable() {
return table;
}
}
/**
* Close to be used in the try block of a try-catch-finally
* statement. Returns null so the close/set to null idiom can be
* completed in a single line.
*/
private static DataOutputStream close(DataOutputStream out)
throws IOException {
if (out != null) {
out.close();
}
return null;
}
/**
* Close to be used in the finally block of a try-catch-finally
* statement.
*/
private static void closeQuiet(DataOutputStream out) {
try {
close(out);
} catch (IOException e) {
LOG.warn("Error closing output stream", e);
}
}
@Override
public boolean requireLock() {
return false;
}
@Override
public StageType getType() {
return StageType.DDL;
}
@Override
public String getName() {
return "SENTRY";
}
}