http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/RevokePrivilegeFromRoleCmd.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/RevokePrivilegeFromRoleCmd.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/RevokePrivilegeFromRoleCmd.java new file mode 100644 index 0000000..3e42e60 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/RevokePrivilegeFromRoleCmd.java @@ -0,0 +1,47 @@ +/** + * 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.provider.db.generic.tools.command; + +import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient; +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; + +/** + * The class for admin command to revoke privileges from role. + */ +public class RevokePrivilegeFromRoleCmd implements Command { + + private String roleName; + private String component; + private String privilegeStr; + private TSentryPrivilegeConverter converter; + + public RevokePrivilegeFromRoleCmd(String roleName, String component, String privilegeStr, + TSentryPrivilegeConverter converter) { + this.roleName = roleName; + this.component = component; + this.privilegeStr = privilegeStr; + this.converter = converter; + } + + @Override + public void execute(SentryGenericServiceClient client, String requestorName) throws Exception { + TSentryPrivilege privilege = converter.fromString(privilegeStr); + client.revokePrivilege(requestorName, roleName, component, privilege); + } + +}
http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java new file mode 100644 index 0000000..ab44895 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java @@ -0,0 +1,33 @@ +/** + * 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.provider.db.generic.tools.command; + +import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege; + +public interface TSentryPrivilegeConverter { + + /** + * Convert string to privilege + */ + TSentryPrivilege fromString(String privilegeStr) throws Exception; + + /** + * Convert privilege to string + */ + String toString(TSentryPrivilege tSentryPrivilege); +} http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java new file mode 100644 index 0000000..9f921d4 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceManager.java @@ -0,0 +1,97 @@ +/** + * 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.provider.db.service.persistent; + +import java.io.IOException; +import java.net.InetSocketAddress; + +import org.apache.curator.x.discovery.ServiceDiscovery; +import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; +import org.apache.curator.x.discovery.ServiceInstance; +import org.apache.curator.x.discovery.ServiceProvider; +import org.apache.curator.x.discovery.details.InstanceSerializer; +import org.apache.hadoop.net.NetUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/*** + * ServerManager handles registration of the Sentry service for Curator service + * discovery. Each server registers with ZK and add its host:port details which + * is used by the clients to discover available servers + */ +public class ServiceManager { + private static final Logger LOGGER = LoggerFactory + .getLogger(ServiceManager.class); + private HAContext haContext; + private ServiceProvider<Void> serviceProvider; + private ServiceDiscovery<Void> serviceDiscovery; + + public ServiceManager(HAContext haContext) throws IOException { + this.haContext = haContext; + init(); + } + + private void init() throws IOException { + try { + haContext.startCuratorFramework(); + InstanceSerializer<Void> instanceSerializer = new FixedJsonInstanceSerializer<Void>(Void.class); + serviceDiscovery = ServiceDiscoveryBuilder.<Void>builder(Void.class) + .basePath(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) + .serializer(instanceSerializer) + .client(haContext.getCuratorFramework()) + .build(); + serviceDiscovery.start(); + serviceProvider = serviceDiscovery + .serviceProviderBuilder() + .serviceName(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) + .build(); + serviceProvider.start(); + } catch (Exception e) { + throw new IOException(e); + } + } + + public ServiceInstance<Void> getServiceInstance() throws IOException { + ServiceInstance<Void> service; + try { + service = serviceProvider.getInstance(); + return service; + } catch (Exception e) { + throw new IOException(e); + } + } + + public void reportError(ServiceInstance<Void> instance) { + serviceProvider.noteError(instance); + } + + public static InetSocketAddress convertServiceInstance(ServiceInstance<?> service) { + return NetUtils.createSocketAddr(service.getAddress(),service.getPort()); + } + + public void close() { + try { + serviceProvider.close(); + serviceDiscovery.close(); + LOGGER.debug("Closed ZK resources"); + } catch (IOException e) { + LOGGER.warn("Error closing the service manager", e); + } + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java new file mode 100644 index 0000000..1e72b74 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java @@ -0,0 +1,207 @@ +/** + * 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.provider.db.service.thrift; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.core.common.ActiveRoleSet; +import org.apache.sentry.core.common.Authorizable; + +public interface SentryPolicyServiceClient { + + void createRole(String requestorUserName, String roleName) throws SentryUserException; + + void dropRole(String requestorUserName, String roleName) throws SentryUserException; + + void dropRoleIfExists(String requestorUserName, String roleName) + throws SentryUserException; + + Set<TSentryRole> listRolesByUserName(String requestorUserName, String userName) + throws SentryUserException; + + Set<TSentryRole> listRolesByGroupName(String requestorUserName, String groupName) + throws SentryUserException; + + Set<TSentryPrivilege> listAllPrivilegesByRoleName(String requestorUserName, String roleName) + throws SentryUserException; + + /** + * Gets sentry privilege objects for a given roleName using the Sentry service + * + * @param requestorUserName : user on whose behalf the request is issued + * @param roleName : roleName to look up + * @param authorizable : authorizable Hierarchy (server->db->table etc) + * @return Set of thrift sentry privilege objects + * @throws SentryUserException + */ + Set<TSentryPrivilege> listPrivilegesByRoleName(String requestorUserName, String roleName, + List<? extends Authorizable> authorizable) throws SentryUserException; + + Set<TSentryRole> listRoles(String requestorUserName) throws SentryUserException; + + Set<TSentryRole> listUserRoles(String requestorUserName) throws SentryUserException; + + TSentryPrivilege grantURIPrivilege(String requestorUserName, String roleName, + String server, String uri) throws SentryUserException; + + TSentryPrivilege grantURIPrivilege(String requestorUserName, String roleName, + String server, String uri, Boolean grantOption) throws SentryUserException; + + void grantServerPrivilege(String requestorUserName, String roleName, String server, + String action) throws SentryUserException; + + TSentryPrivilege grantServerPrivilege(String requestorUserName, String roleName, + String server, Boolean grantOption) throws SentryUserException; + + TSentryPrivilege grantServerPrivilege(String requestorUserName, String roleName, + String server, String action, Boolean grantOption) throws SentryUserException; + + TSentryPrivilege grantDatabasePrivilege(String requestorUserName, String roleName, + String server, String db, String action) throws SentryUserException; + + TSentryPrivilege grantDatabasePrivilege(String requestorUserName, String roleName, + String server, String db, String action, Boolean grantOption) throws SentryUserException; + + TSentryPrivilege grantTablePrivilege(String requestorUserName, String roleName, + String server, String db, String table, String action) throws SentryUserException; + + TSentryPrivilege grantTablePrivilege(String requestorUserName, String roleName, + String server, String db, String table, String action, Boolean grantOption) + throws SentryUserException; + + TSentryPrivilege grantColumnPrivilege(String requestorUserName, String roleName, + String server, String db, String table, String columnName, String action) + throws SentryUserException; + + TSentryPrivilege grantColumnPrivilege(String requestorUserName, String roleName, + String server, String db, String table, String columnName, String action, Boolean grantOption) + throws SentryUserException; + + Set<TSentryPrivilege> grantColumnsPrivileges(String requestorUserName, String roleName, + String server, String db, String table, List<String> columnNames, String action) + throws SentryUserException; + + Set<TSentryPrivilege> grantColumnsPrivileges(String requestorUserName, String roleName, + String server, String db, String table, List<String> columnNames, String action, + Boolean grantOption) throws SentryUserException; + + void revokeURIPrivilege(String requestorUserName, String roleName, String server, + String uri) throws SentryUserException; + + void revokeURIPrivilege(String requestorUserName, String roleName, String server, + String uri, Boolean grantOption) throws SentryUserException; + + void revokeServerPrivilege(String requestorUserName, String roleName, String server, + String action) throws SentryUserException; + + void revokeServerPrivilege(String requestorUserName, String roleName, String server, + String action, Boolean grantOption) throws SentryUserException; + + void revokeServerPrivilege(String requestorUserName, String roleName, String server, + boolean grantOption) throws SentryUserException; + + void revokeDatabasePrivilege(String requestorUserName, String roleName, String server, + String db, String action) throws SentryUserException; + + void revokeDatabasePrivilege(String requestorUserName, String roleName, String server, + String db, String action, Boolean grantOption) throws SentryUserException; + + void revokeTablePrivilege(String requestorUserName, String roleName, String server, + String db, String table, String action) throws SentryUserException; + + void revokeTablePrivilege(String requestorUserName, String roleName, String server, + String db, String table, String action, Boolean grantOption) throws SentryUserException; + + void revokeColumnPrivilege(String requestorUserName, String roleName, String server, + String db, String table, String columnName, String action) throws SentryUserException; + + void revokeColumnPrivilege(String requestorUserName, String roleName, String server, + String db, String table, String columnName, String action, Boolean grantOption) + throws SentryUserException; + + void revokeColumnsPrivilege(String requestorUserName, String roleName, String server, + String db, String table, List<String> columns, String action) throws SentryUserException; + + void revokeColumnsPrivilege(String requestorUserName, String roleName, String server, + String db, String table, List<String> columns, String action, Boolean grantOption) + throws SentryUserException; + + Set<String> listPrivilegesForProvider(Set<String> groups, Set<String> users, + ActiveRoleSet roleSet, Authorizable... authorizable) throws SentryUserException; + + void grantRoleToGroup(String requestorUserName, String groupName, String roleName) + throws SentryUserException; + + void revokeRoleFromGroup(String requestorUserName, String groupName, String roleName) + throws SentryUserException; + + void grantRoleToGroups(String requestorUserName, String roleName, Set<String> groups) + throws SentryUserException; + + void revokeRoleFromGroups(String requestorUserName, String roleName, Set<String> groups) + throws SentryUserException; + + void grantRoleToUser(String requestorUserName, String userName, String roleName) + throws SentryUserException; + + void revokeRoleFromUser(String requestorUserName, String userName, String roleName) + throws SentryUserException; + + void grantRoleToUsers(String requestorUserName, String roleName, Set<String> users) + throws SentryUserException; + + void revokeRoleFromUsers(String requestorUserName, String roleName, Set<String> users) + throws SentryUserException; + + void dropPrivileges(String requestorUserName, + List<? extends Authorizable> authorizableObjects) throws SentryUserException; + + void renamePrivileges(String requestorUserName, + List<? extends Authorizable> oldAuthorizables, List<? extends Authorizable> newAuthorizables) + throws SentryUserException; + + Map<TSentryAuthorizable, TSentryPrivilegeMap> listPrivilegsbyAuthorizable( + String requestorUserName, Set<List<? extends Authorizable>> authorizables, + Set<String> groups, ActiveRoleSet roleSet) throws SentryUserException; + + /** + * Returns the configuration value in the sentry server associated with propertyName, or if + * propertyName does not exist, the defaultValue. There is no "requestorUserName" because this is + * regarded as an internal interface. + * + * @param propertyName Config attribute to search for + * @param defaultValue String to return if not found + * @return The value of the propertyName + * @throws SentryUserException + */ + String getConfigValue(String propertyName, String defaultValue) throws SentryUserException; + + void close(); + + // Import the sentry mapping data with map structure + void importPolicy(Map<String, Map<String, Set<String>>> policyFileMappingData, + String requestorUserName, boolean isOverwriteRole) throws SentryUserException; + + // export the sentry mapping data with map structure + Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName, String objectPath) + throws SentryUserException; +} http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java new file mode 100644 index 0000000..cad39c1 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java @@ -0,0 +1,1054 @@ +/** + * 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.provider.db.service.thrift; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.security.PrivilegedExceptionAction; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.security.auth.callback.CallbackHandler; + +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.net.NetUtils; +import org.apache.hadoop.security.SaslRpcServer; +import org.apache.hadoop.security.SaslRpcServer.AuthMethod; +import org.apache.hadoop.security.SecurityUtil; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.sentry.core.common.exception.SentryUserException; +import org.apache.sentry.core.common.ActiveRoleSet; +import org.apache.sentry.core.common.Authorizable; +import org.apache.sentry.core.common.utils.SentryConstants; +import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.core.model.db.DBModelAuthorizable; +import org.apache.sentry.core.common.utils.PolicyFileConstants; +import org.apache.sentry.service.thrift.SentryServiceUtil; +import org.apache.sentry.service.thrift.ServiceConstants; +import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig; +import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.apache.sentry.service.thrift.ServiceConstants.ThriftConstants; +import org.apache.sentry.service.thrift.Status; +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TMultiplexedProtocol; +import org.apache.thrift.transport.TSaslClientTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +/* + A Sentry Client in which all the operations are synchronized for thread safety + Note: When using this client, if there is an exception in RPC, socket can get into an inconsistent state. + So it is important to recreate the client, which uses a new socket. + */ +public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyServiceClient { + + private final Configuration conf; + private final InetSocketAddress serverAddress; + private final boolean kerberos; + private final String[] serverPrincipalParts; + private SentryPolicyService.Client client; + private TTransport transport; + private int connectionTimeout; + private static final Logger LOGGER = LoggerFactory + .getLogger(SentryPolicyServiceClient.class); + private static final String THRIFT_EXCEPTION_MESSAGE = "Thrift exception occurred "; + + /** + * This transport wraps the Sasl transports to set up the right UGI context for open(). + */ + public static class UgiSaslClientTransport extends TSaslClientTransport { + protected UserGroupInformation ugi = null; + + public UgiSaslClientTransport(String mechanism, String authorizationId, + String protocol, String serverName, Map<String, String> props, + CallbackHandler cbh, TTransport transport, boolean wrapUgi) + throws IOException { + super(mechanism, authorizationId, protocol, serverName, props, cbh, + transport); + if (wrapUgi) { + ugi = UserGroupInformation.getLoginUser(); + } + } + + // open the SASL transport with using the current UserGroupInformation + // This is needed to get the current login context stored + @Override + public synchronized void open() throws TTransportException { + if (ugi == null) { + baseOpen(); + } else { + try { + if (ugi.isFromKeytab()) { + ugi.checkTGTAndReloginFromKeytab(); + } + ugi.doAs(new PrivilegedExceptionAction<Void>() { + public Void run() throws TTransportException { + baseOpen(); + return null; + } + }); + } catch (IOException e) { + throw new TTransportException("Failed to open SASL transport", e); + } catch (InterruptedException e) { + throw new TTransportException( + "Interrupted while opening underlying transport", e); + } + } + } + + private void baseOpen() throws TTransportException { + super.open(); + } + } + + public SentryPolicyServiceClientDefaultImpl(Configuration conf) throws IOException { + this.conf = conf; + Preconditions.checkNotNull(this.conf, "Configuration object cannot be null"); + this.serverAddress = NetUtils.createSocketAddr(Preconditions.checkNotNull( + conf.get(ClientConfig.SERVER_RPC_ADDRESS), "Config key " + + ClientConfig.SERVER_RPC_ADDRESS + " is required"), conf.getInt( + ClientConfig.SERVER_RPC_PORT, ClientConfig.SERVER_RPC_PORT_DEFAULT)); + this.connectionTimeout = conf.getInt(ClientConfig.SERVER_RPC_CONN_TIMEOUT, + ClientConfig.SERVER_RPC_CONN_TIMEOUT_DEFAULT); + kerberos = ServerConfig.SECURITY_MODE_KERBEROS.equalsIgnoreCase( + conf.get(ServerConfig.SECURITY_MODE, ServerConfig.SECURITY_MODE_KERBEROS).trim()); + transport = new TSocket(serverAddress.getHostName(), + serverAddress.getPort(), connectionTimeout); + if (kerberos) { + String serverPrincipal = Preconditions.checkNotNull(conf.get(ServerConfig.PRINCIPAL), ServerConfig.PRINCIPAL + " is required"); + + // Resolve server host in the same way as we are doing on server side + serverPrincipal = SecurityUtil.getServerPrincipal(serverPrincipal, serverAddress.getAddress()); + LOGGER.debug("Using server kerberos principal: " + serverPrincipal); + + serverPrincipalParts = SaslRpcServer.splitKerberosName(serverPrincipal); + Preconditions.checkArgument(serverPrincipalParts.length == 3, + "Kerberos principal should have 3 parts: " + serverPrincipal); + boolean wrapUgi = "true".equalsIgnoreCase(conf + .get(ServerConfig.SECURITY_USE_UGI_TRANSPORT, "true")); + transport = new UgiSaslClientTransport(AuthMethod.KERBEROS.getMechanismName(), + null, serverPrincipalParts[0], serverPrincipalParts[1], + ClientConfig.SASL_PROPERTIES, null, transport, wrapUgi); + } else { + serverPrincipalParts = null; + } + try { + transport.open(); + } catch (TTransportException e) { + throw new IOException("Transport exception while opening transport: " + e.getMessage(), e); + } + LOGGER.debug("Successfully opened transport: " + transport + " to " + serverAddress); + long maxMessageSize = conf.getLong(ServiceConstants.ClientConfig.SENTRY_POLICY_CLIENT_THRIFT_MAX_MESSAGE_SIZE, + ServiceConstants.ClientConfig.SENTRY_POLICY_CLIENT_THRIFT_MAX_MESSAGE_SIZE_DEFAULT); + TMultiplexedProtocol protocol = new TMultiplexedProtocol( + new TBinaryProtocol(transport, maxMessageSize, maxMessageSize, true, true), + ServiceConstants.SENTRY_POLICY_SERVICE_NAME); + client = new SentryPolicyService.Client(protocol); + LOGGER.debug("Successfully created client"); + } + + public synchronized void createRole(String requestorUserName, String roleName) + throws SentryUserException { + TCreateSentryRoleRequest request = new TCreateSentryRoleRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + try { + TCreateSentryRoleResponse response = client.create_sentry_role(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized void dropRole(String requestorUserName, + String roleName) + throws SentryUserException { + dropRole(requestorUserName, roleName, false); + } + + public synchronized void dropRoleIfExists(String requestorUserName, + String roleName) + throws SentryUserException { + dropRole(requestorUserName, roleName, true); + } + + private synchronized void dropRole(String requestorUserName, + String roleName, boolean ifExists) + throws SentryUserException { + TDropSentryRoleRequest request = new TDropSentryRoleRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + try { + TDropSentryRoleResponse response = client.drop_sentry_role(request); + Status status = Status.fromCode(response.getStatus().getValue()); + if (ifExists && status == Status.NO_SUCH_OBJECT) { + return; + } + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + /** + * Gets sentry role objects for a given groupName using the Sentry service + * @param requestorUserName : user on whose behalf the request is issued + * @param groupName : groupName to look up ( if null returns all roles for all groups) + * @return Set of thrift sentry role objects + * @throws SentryUserException + */ + public synchronized Set<TSentryRole> listRolesByGroupName( + String requestorUserName, + String groupName) + throws SentryUserException { + TListSentryRolesRequest request = new TListSentryRolesRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setGroupName(groupName); + TListSentryRolesResponse response; + try { + response = client.list_sentry_roles_by_group(request); + Status.throwIfNotOk(response.getStatus()); + return response.getRoles(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + /** + * Gets sentry role objects for a given userName using the Sentry service + * + * @param requestorUserName + * : user on whose behalf the request is issued + * @param userName + * : userName to look up (can't be empty) + * @return Set of thrift sentry role objects + * @throws SentryUserException + */ + public Set<TSentryRole> listRolesByUserName(String requestorUserName, String userName) + throws SentryUserException { + TListSentryRolesForUserRequest request = new TListSentryRolesForUserRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setUserName(userName); + TListSentryRolesResponse response; + try { + response = client.list_sentry_roles_by_user(request); + Status.throwIfNotOk(response.getStatus()); + return response.getRoles(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized Set<TSentryPrivilege> listAllPrivilegesByRoleName(String requestorUserName, + String roleName) + throws SentryUserException { + return listPrivilegesByRoleName(requestorUserName, roleName, null); + } + + /** + * Gets sentry privilege objects for a given roleName using the Sentry service + * @param requestorUserName : user on whose behalf the request is issued + * @param roleName : roleName to look up + * @param authorizable : authorizable Hierarchy (server->db->table etc) + * @return Set of thrift sentry privilege objects + * @throws SentryUserException + */ + public synchronized Set<TSentryPrivilege> listPrivilegesByRoleName(String requestorUserName, + String roleName, List<? extends Authorizable> authorizable) + throws SentryUserException { + TListSentryPrivilegesRequest request = new TListSentryPrivilegesRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + if (authorizable != null && !authorizable.isEmpty()) { + TSentryAuthorizable tSentryAuthorizable = setupSentryAuthorizable(authorizable); + request.setAuthorizableHierarchy(tSentryAuthorizable); + } + TListSentryPrivilegesResponse response; + try { + response = client.list_sentry_privileges_by_role(request); + Status.throwIfNotOk(response.getStatus()); + return response.getPrivileges(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized Set<TSentryRole> listRoles(String requestorUserName) + throws SentryUserException { + return listRolesByGroupName(requestorUserName, null); + } + + public synchronized Set<TSentryRole> listUserRoles(String requestorUserName) + throws SentryUserException { + Set<TSentryRole> tSentryRoles = Sets.newHashSet(); + tSentryRoles.addAll(listRolesByGroupName(requestorUserName, SentryConstants.RESOURCE_WILDCARD_VALUE)); + tSentryRoles.addAll(listRolesByUserName(requestorUserName, requestorUserName)); + return tSentryRoles; + } + + public synchronized TSentryPrivilege grantURIPrivilege(String requestorUserName, + String roleName, String server, String uri) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, + PrivilegeScope.URI, server, uri, null, null, null, SentryConstants.RESOURCE_WILDCARD_VALUE); + } + + public synchronized TSentryPrivilege grantURIPrivilege(String requestorUserName, + String roleName, String server, String uri, Boolean grantOption) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, + PrivilegeScope.URI, server, uri, null, null, null, SentryConstants.RESOURCE_WILDCARD_VALUE, grantOption); + } + + public synchronized void grantServerPrivilege(String requestorUserName, + String roleName, String server, String action) + throws SentryUserException { + + // "ALL" and "*" should be synonyms for action and need to be unified with grantServerPrivilege without + // action explicitly specified. + if (SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equalsIgnoreCase(action) + || SentryConstants.RESOURCE_WILDCARD_VALUE.equals(action)) { + action = SentryConstants.RESOURCE_WILDCARD_VALUE; + } + + grantPrivilege(requestorUserName, roleName, + PrivilegeScope.SERVER, server, null, null, null, null, action); + } + + @Deprecated + /*** + * Should use grantServerPrivilege(String requestorUserName, + * String roleName, String server, String action, Boolean grantOption) + */ + public synchronized TSentryPrivilege grantServerPrivilege(String requestorUserName, + String roleName, String server, Boolean grantOption) throws SentryUserException { + return grantServerPrivilege(requestorUserName, roleName, server, + SentryConstants.RESOURCE_WILDCARD_VALUE, grantOption); + } + + public synchronized TSentryPrivilege grantServerPrivilege(String requestorUserName, + String roleName, String server, String action, Boolean grantOption) + throws SentryUserException { + + // "ALL" and "*" should be synonyms for action and need to be unified with grantServerPrivilege without + // action explicitly specified. + if (SentryConstants.RESOURCE_WILDCARD_VALUE_ALL.equalsIgnoreCase(action) + || SentryConstants.RESOURCE_WILDCARD_VALUE.equals(action)) { + action = SentryConstants.RESOURCE_WILDCARD_VALUE; + } + + return grantPrivilege(requestorUserName, roleName, + PrivilegeScope.SERVER, server, null, null, null, null, action, grantOption); + } + + public synchronized TSentryPrivilege grantDatabasePrivilege(String requestorUserName, + String roleName, String server, String db, String action) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, + PrivilegeScope.DATABASE, server, null, db, null, null, action); + } + + public synchronized TSentryPrivilege grantDatabasePrivilege(String requestorUserName, + String roleName, String server, String db, String action, Boolean grantOption) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, + PrivilegeScope.DATABASE, server, null, db, null, null, action, grantOption); + } + + public synchronized TSentryPrivilege grantTablePrivilege(String requestorUserName, + String roleName, String server, String db, String table, String action) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, PrivilegeScope.TABLE, server, + null, + db, table, null, action); + } + + public synchronized TSentryPrivilege grantTablePrivilege(String requestorUserName, + String roleName, String server, String db, String table, String action, Boolean grantOption) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, PrivilegeScope.TABLE, server, + null, db, table, null, action, grantOption); + } + + public synchronized TSentryPrivilege grantColumnPrivilege(String requestorUserName, + String roleName, String server, String db, String table, String columnName, String action) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, PrivilegeScope.COLUMN, server, + null, + db, table, columnName, action); + } + + public synchronized TSentryPrivilege grantColumnPrivilege(String requestorUserName, + String roleName, String server, String db, String table, String columnName, String action, Boolean grantOption) + throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, PrivilegeScope.COLUMN, server, + null, db, table, columnName, action, grantOption); + } + + public synchronized Set<TSentryPrivilege> grantColumnsPrivileges(String requestorUserName, + String roleName, String server, String db, String table, List<String> columnNames, String action) + throws SentryUserException { + return grantPrivileges(requestorUserName, roleName, PrivilegeScope.COLUMN, server, + null, + db, table, columnNames, action); + } + + public synchronized Set<TSentryPrivilege> grantColumnsPrivileges(String requestorUserName, + String roleName, String server, String db, String table, List<String> columnNames, String action, Boolean grantOption) + throws SentryUserException { + return grantPrivileges(requestorUserName, roleName, PrivilegeScope.COLUMN, + server, + null, db, table, columnNames, action, grantOption); + } + + @VisibleForTesting + public static TSentryAuthorizable setupSentryAuthorizable( + List<? extends Authorizable> authorizable) { + TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable(); + + for (Authorizable authzble : authorizable) { + if (authzble.getTypeName().equalsIgnoreCase( + DBModelAuthorizable.AuthorizableType.Server.toString())) { + tSentryAuthorizable.setServer(authzble.getName()); + } else if (authzble.getTypeName().equalsIgnoreCase( + DBModelAuthorizable.AuthorizableType.URI.toString())) { + tSentryAuthorizable.setUri(authzble.getName()); + } else if (authzble.getTypeName().equalsIgnoreCase( + DBModelAuthorizable.AuthorizableType.Db.toString())) { + tSentryAuthorizable.setDb(authzble.getName()); + } else if (authzble.getTypeName().equalsIgnoreCase( + DBModelAuthorizable.AuthorizableType.Table.toString())) { + tSentryAuthorizable.setTable(authzble.getName()); + } else if (authzble.getTypeName().equalsIgnoreCase( + DBModelAuthorizable.AuthorizableType.Column.toString())) { + tSentryAuthorizable.setColumn(authzble.getName()); + } + } + return tSentryAuthorizable; + } + + private TSentryPrivilege grantPrivilege(String requestorUserName, + String roleName, + PrivilegeScope scope, String serverName, String uri, String db, + String table, String column, String action) throws SentryUserException { + return grantPrivilege(requestorUserName, roleName, scope, serverName, uri, + db, table, column, action, false); + } + + private TSentryPrivilege grantPrivilege(String requestorUserName, + String roleName, PrivilegeScope scope, String serverName, String uri, String db, String table, + String column, String action, Boolean grantOption) + throws SentryUserException { + TAlterSentryRoleGrantPrivilegeRequest request = new TAlterSentryRoleGrantPrivilegeRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + Set<TSentryPrivilege> privileges = convertColumnPrivilege(scope, + serverName, uri, db, table, column, action, grantOption); + request.setPrivileges(privileges); + try { + TAlterSentryRoleGrantPrivilegeResponse response = client.alter_sentry_role_grant_privilege(request); + Status.throwIfNotOk(response.getStatus()); + if (response.isSetPrivileges() + && response.getPrivilegesSize()>0 ) { + return response.getPrivileges().iterator().next(); + } else { + return new TSentryPrivilege(); + } + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + private Set<TSentryPrivilege> grantPrivileges(String requestorUserName, + String roleName, + PrivilegeScope scope, String serverName, String uri, String db, + String table, List<String> columns, String action) throws SentryUserException { + return grantPrivileges(requestorUserName, roleName, scope, serverName, uri, + db, table, columns, action, false); + } + + private Set<TSentryPrivilege> grantPrivileges(String requestorUserName, + String roleName, PrivilegeScope scope, String serverName, String uri, String db, String table, + List<String> columns, String action, Boolean grantOption) + throws SentryUserException { + TAlterSentryRoleGrantPrivilegeRequest request = new TAlterSentryRoleGrantPrivilegeRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + Set<TSentryPrivilege> privileges = convertColumnPrivileges(scope, + serverName, uri, db, table, columns, action, grantOption); + request.setPrivileges(privileges); + try { + TAlterSentryRoleGrantPrivilegeResponse response = client.alter_sentry_role_grant_privilege(request); + Status.throwIfNotOk(response.getStatus()); + return response.getPrivileges(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized void revokeURIPrivilege(String requestorUserName, + String roleName, String server, String uri) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.URI, server, uri, null, null, null, AccessConstants.ALL); + } + + public synchronized void revokeURIPrivilege(String requestorUserName, + String roleName, String server, String uri, Boolean grantOption) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.URI, server, uri, null, null, null, AccessConstants.ALL, grantOption); + } + + public synchronized void revokeServerPrivilege(String requestorUserName, + String roleName, String server, String action) + throws SentryUserException { + + // "ALL" and "*" should be synonyms for action and need to be unified with revokeServerPrivilege without + // action explicitly specified. + if (AccessConstants.ACTION_ALL.equalsIgnoreCase(action) || AccessConstants.ALL.equals(action)) { + action = AccessConstants.ALL; + } + + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.SERVER, server, null, null, null, null, action); + } + + public synchronized void revokeServerPrivilege(String requestorUserName, + String roleName, String server, String action, Boolean grantOption) + throws SentryUserException { + + // "ALL" and "*" should be synonyms for action and need to be unified with revokeServerPrivilege without + // action explicitly specified. + if (AccessConstants.ACTION_ALL.equalsIgnoreCase(action) || AccessConstants.ALL.equals(action)) { + action = AccessConstants.ALL; + } + + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.SERVER, server, null, null, null, null, action, grantOption); + } + + @Deprecated + /*** + * Should use revokeServerPrivilege(String requestorUserName, + * String roleName, String server, String action, Boolean grantOption) + */ + public synchronized void revokeServerPrivilege(String requestorUserName, + String roleName, String server, boolean grantOption) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.SERVER, server, null, null, null, null, AccessConstants.ALL, grantOption); + } + + public synchronized void revokeDatabasePrivilege(String requestorUserName, + String roleName, String server, String db, String action) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.DATABASE, server, null, db, null, null, action); + } + + public synchronized void revokeDatabasePrivilege(String requestorUserName, + String roleName, String server, String db, String action, Boolean grantOption) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.DATABASE, server, null, db, null, null, action, grantOption); + } + + public synchronized void revokeTablePrivilege(String requestorUserName, + String roleName, String server, String db, String table, String action) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.TABLE, server, null, + db, table, null, action); + } + + public synchronized void revokeTablePrivilege(String requestorUserName, + String roleName, String server, String db, String table, String action, Boolean grantOption) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.TABLE, server, null, + db, table, null, action, grantOption); + } + + public synchronized void revokeColumnPrivilege(String requestorUserName, String roleName, + String server, String db, String table, String columnName, String action) + throws SentryUserException { + ImmutableList.Builder<String> listBuilder = ImmutableList.builder(); + listBuilder.add(columnName); + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.COLUMN, server, null, + db, table, listBuilder.build(), action); + } + + public synchronized void revokeColumnPrivilege(String requestorUserName, String roleName, + String server, String db, String table, String columnName, String action, Boolean grantOption) + throws SentryUserException { + ImmutableList.Builder<String> listBuilder = ImmutableList.builder(); + listBuilder.add(columnName); + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.COLUMN, server, null, + db, table, listBuilder.build(), action, grantOption); + } + + public synchronized void revokeColumnsPrivilege(String requestorUserName, String roleName, + String server, String db, String table, List<String> columns, String action) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.COLUMN, server, null, + db, table, columns, action); + } + + public synchronized void revokeColumnsPrivilege(String requestorUserName, String roleName, + String server, String db, String table, List<String> columns, String action, Boolean grantOption) + throws SentryUserException { + revokePrivilege(requestorUserName, roleName, + PrivilegeScope.COLUMN, server, null, + db, table, columns, action, grantOption); + } + + private void revokePrivilege(String requestorUserName, + String roleName, PrivilegeScope scope, String serverName, String uri, + String db, String table, List<String> columns, String action) + throws SentryUserException { + this.revokePrivilege(requestorUserName, roleName, scope, serverName, uri, db, table, columns, action, false); + } + + private void revokePrivilege(String requestorUserName, String roleName, + PrivilegeScope scope, String serverName, String uri, String db, String table, List<String> columns, + String action, Boolean grantOption) + throws SentryUserException { + TAlterSentryRoleRevokePrivilegeRequest request = new TAlterSentryRoleRevokePrivilegeRequest(); + request.setProtocol_version(ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT); + request.setRequestorUserName(requestorUserName); + request.setRoleName(roleName); + Set<TSentryPrivilege> privileges = convertColumnPrivileges(scope, + serverName, uri, db, table, columns, action, grantOption); + request.setPrivileges(privileges); + try { + TAlterSentryRoleRevokePrivilegeResponse response = client.alter_sentry_role_revoke_privilege(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + private Set<TSentryPrivilege> convertColumnPrivileges( + PrivilegeScope scope, String serverName, String uri, String db, String table, List<String> columns, + String action, Boolean grantOption) { + ImmutableSet.Builder<TSentryPrivilege> setBuilder = ImmutableSet.builder(); + if (columns == null || columns.isEmpty()) { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope(scope.toString()); + privilege.setServerName(serverName); + privilege.setURI(uri); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(null); + privilege.setAction(action); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(convertTSentryGrantOption(grantOption)); + setBuilder.add(privilege); + } else { + for (String column : columns) { + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope(scope.toString()); + privilege.setServerName(serverName); + privilege.setURI(uri); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(column); + privilege.setAction(action); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(convertTSentryGrantOption(grantOption)); + setBuilder.add(privilege); + } + } + return setBuilder.build(); + } + + private Set<TSentryPrivilege> convertColumnPrivilege( + PrivilegeScope scope, String serverName, String uri, String db, String table, String column, + String action, Boolean grantOption) { + ImmutableSet.Builder<TSentryPrivilege> setBuilder = ImmutableSet.builder(); + TSentryPrivilege privilege = new TSentryPrivilege(); + privilege.setPrivilegeScope(scope.toString()); + privilege.setServerName(serverName); + privilege.setURI(uri); + privilege.setDbName(db); + privilege.setTableName(table); + privilege.setColumnName(column); + privilege.setAction(action); + privilege.setCreateTime(System.currentTimeMillis()); + privilege.setGrantOption(convertTSentryGrantOption(grantOption)); + setBuilder.add(privilege); + return setBuilder.build(); + } + + private TSentryGrantOption convertTSentryGrantOption(Boolean grantOption) { + if (grantOption == null) { + return TSentryGrantOption.UNSET; + } else if (grantOption.equals(true)) { + return TSentryGrantOption.TRUE; + } else if (grantOption.equals(false)) { + return TSentryGrantOption.FALSE; + } + return TSentryGrantOption.FALSE; + } + + public synchronized Set<String> listPrivilegesForProvider(Set<String> groups, Set<String> users, + ActiveRoleSet roleSet, Authorizable... authorizable) throws SentryUserException { + TSentryActiveRoleSet thriftRoleSet = new TSentryActiveRoleSet(roleSet.isAll(), roleSet.getRoles()); + TListSentryPrivilegesForProviderRequest request = + new TListSentryPrivilegesForProviderRequest(ThriftConstants. + TSENTRY_SERVICE_VERSION_CURRENT, groups, thriftRoleSet); + if (authorizable != null && authorizable.length > 0) { + TSentryAuthorizable tSentryAuthorizable = setupSentryAuthorizable(Lists + .newArrayList(authorizable)); + request.setAuthorizableHierarchy(tSentryAuthorizable); + } + if (users != null) { + request.setUsers(users); + } + try { + TListSentryPrivilegesForProviderResponse response = client.list_sentry_privileges_for_provider(request); + Status.throwIfNotOk(response.getStatus()); + return response.getPrivileges(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + @Override + public synchronized void grantRoleToGroup(String requestorUserName, + String groupName, String roleName) + throws SentryUserException { + grantRoleToGroups(requestorUserName, roleName, Sets.newHashSet(groupName)); + } + + @Override + public synchronized void revokeRoleFromGroup(String requestorUserName, + String groupName, String roleName) + throws SentryUserException { + revokeRoleFromGroups(requestorUserName, roleName, Sets.newHashSet(groupName)); + } + + @Override + public synchronized void grantRoleToGroups(String requestorUserName, + String roleName, Set<String> groups) + throws SentryUserException { + TAlterSentryRoleAddGroupsRequest request = new TAlterSentryRoleAddGroupsRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, + roleName, convert2TGroups(groups)); + try { + TAlterSentryRoleAddGroupsResponse response = client.alter_sentry_role_add_groups(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + @Override + public synchronized void revokeRoleFromGroups(String requestorUserName, + String roleName, Set<String> groups) + throws SentryUserException { + TAlterSentryRoleDeleteGroupsRequest request = new TAlterSentryRoleDeleteGroupsRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, + roleName, convert2TGroups(groups)); + try { + TAlterSentryRoleDeleteGroupsResponse response = client.alter_sentry_role_delete_groups(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + @Override + public synchronized void grantRoleToUser(String requestorUserName, String userName, + String roleName) throws SentryUserException { + grantRoleToUsers(requestorUserName, roleName, Sets.newHashSet(userName)); + } + + @Override + public synchronized void revokeRoleFromUser(String requestorUserName, String userName, + String roleName) throws SentryUserException { + revokeRoleFromUsers(requestorUserName, roleName, Sets.newHashSet(userName)); + } + + @Override + public synchronized void grantRoleToUsers(String requestorUserName, String roleName, + Set<String> users) throws SentryUserException { + TAlterSentryRoleAddUsersRequest request = new TAlterSentryRoleAddUsersRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, roleName, users); + try { + TAlterSentryRoleAddUsersResponse response = client.alter_sentry_role_add_users(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + @Override + public synchronized void revokeRoleFromUsers(String requestorUserName, String roleName, + Set<String> users) throws SentryUserException { + TAlterSentryRoleDeleteUsersRequest request = new TAlterSentryRoleDeleteUsersRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, roleName, users); + try { + TAlterSentryRoleDeleteUsersResponse response = client.alter_sentry_role_delete_users(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + private Set<TSentryGroup> convert2TGroups(Set<String> groups) { + Set<TSentryGroup> tGroups = Sets.newHashSet(); + if (groups != null) { + for (String groupName : groups) { + tGroups.add(new TSentryGroup(groupName)); + } + } + return tGroups; + } + + public synchronized void dropPrivileges(String requestorUserName, + List<? extends Authorizable> authorizableObjects) + throws SentryUserException { + TSentryAuthorizable tSentryAuthorizable = setupSentryAuthorizable(authorizableObjects); + + TDropPrivilegesRequest request = new TDropPrivilegesRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, + tSentryAuthorizable); + try { + TDropPrivilegesResponse response = client.drop_sentry_privilege(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized void renamePrivileges(String requestorUserName, + List<? extends Authorizable> oldAuthorizables, + List<? extends Authorizable> newAuthorizables) throws SentryUserException { + TSentryAuthorizable tOldSentryAuthorizable = setupSentryAuthorizable(oldAuthorizables); + TSentryAuthorizable tNewSentryAuthorizable = setupSentryAuthorizable(newAuthorizables); + + TRenamePrivilegesRequest request = new TRenamePrivilegesRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, + tOldSentryAuthorizable, tNewSentryAuthorizable); + try { + TRenamePrivilegesResponse response = client + .rename_sentry_privilege(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized Map<TSentryAuthorizable, TSentryPrivilegeMap> listPrivilegsbyAuthorizable( + String requestorUserName, + Set<List<? extends Authorizable>> authorizables, Set<String> groups, + ActiveRoleSet roleSet) throws SentryUserException { + Set<TSentryAuthorizable> authSet = Sets.newTreeSet(); + + for (List<? extends Authorizable> authorizableHierarchy : authorizables) { + authSet.add(setupSentryAuthorizable(authorizableHierarchy)); + } + TListSentryPrivilegesByAuthRequest request = new TListSentryPrivilegesByAuthRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, + authSet); + if (groups != null) { + request.setGroups(groups); + } + if (roleSet != null) { + request.setRoleSet(new TSentryActiveRoleSet(roleSet.isAll(), roleSet.getRoles())); + } + + try { + TListSentryPrivilegesByAuthResponse response = client + .list_sentry_privileges_by_authorizable(request); + Status.throwIfNotOk(response.getStatus()); + return response.getPrivilegesMapByAuth(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + /** + * Returns the configuration value in the sentry server associated with + * propertyName, or if propertyName does not exist, the defaultValue. + * There is no "requestorUserName" because this is regarded as an + * internal interface. + * @param propertyName Config attribute to search for + * @param defaultValue String to return if not found + * @return The value of the propertyName + * @throws SentryUserException + */ + public synchronized String getConfigValue(String propertyName, String defaultValue) + throws SentryUserException { + TSentryConfigValueRequest request = new TSentryConfigValueRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, propertyName); + if (defaultValue != null) { + request.setDefaultValue(defaultValue); + } + try { + TSentryConfigValueResponse response = client.get_sentry_config_value(request); + Status.throwIfNotOk(response.getStatus()); + return response.getValue(); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + public synchronized void close() { + if (transport != null) { + transport.close(); + } + } + + /** + * Import the sentry mapping data, convert the mapping data from map structure to + * TSentryMappingData, and call the import API. + * + * @param policyFileMappingData + * Include 2 maps to save the mapping data, the following is the example of the data + * structure: + * for the following mapping data: + * group1=role1,role2 + * group2=role2,role3 + * role1=server=server1->db=db1 + * role2=server=server1->db=db1->table=tbl1,server=server1->db=db1->table=tbl2 + * role3=server=server1->url=hdfs://localhost/path + * + * The policyFileMappingData will be inputed as: + * { + * groups={[group1={role1, role2}], group2=[role2, role3]}, + * roles={role1=[server=server1->db=db1], + * role2=[server=server1->db=db1->table=tbl1,server=server1->db=db1->table=tbl2], + * role3=[server=server1->url=hdfs://localhost/path] + * } + * } + * @param requestorUserName + * The name of the request user + */ + public synchronized void importPolicy(Map<String, Map<String, Set<String>>> policyFileMappingData, + String requestorUserName, boolean isOverwriteRole) + throws SentryUserException { + try { + TSentryMappingData tSentryMappingData = new TSentryMappingData(); + // convert the mapping data for [group,role] from map structure to + // TSentryMappingData.GroupRolesMap + tSentryMappingData.setGroupRolesMap(policyFileMappingData.get(PolicyFileConstants.GROUPS)); + tSentryMappingData.setUserRolesMap(policyFileMappingData.get(PolicyFileConstants.USER_ROLES)); + // convert the mapping data for [role,privilege] from map structure to + // TSentryMappingData.RolePrivilegesMap + tSentryMappingData + .setRolePrivilegesMap(convertRolePrivilegesMapForSentryDB(policyFileMappingData + .get(PolicyFileConstants.ROLES))); + TSentryImportMappingDataRequest request = new TSentryImportMappingDataRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName, isOverwriteRole, + tSentryMappingData); + TSentryImportMappingDataResponse response = client.import_sentry_mapping_data(request); + Status.throwIfNotOk(response.getStatus()); + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + // convert the mapping data for [role,privilege] from map structure to + // TSentryMappingData.RolePrivilegesMap + private Map<String, Set<TSentryPrivilege>> convertRolePrivilegesMapForSentryDB( + Map<String, Set<String>> rolePrivilegesMap) { + Map<String, Set<TSentryPrivilege>> rolePrivilegesMapResult = Maps.newHashMap(); + if (rolePrivilegesMap != null) { + for (Map.Entry<String, Set<String>> entry : rolePrivilegesMap.entrySet()) { + Set<TSentryPrivilege> tempTSentryPrivileges = Sets.newHashSet(); + Set<String> tempPrivileges = entry.getValue(); + for (String tempPrivilege : tempPrivileges) { + tempTSentryPrivileges.add(SentryServiceUtil.convertToTSentryPrivilege(tempPrivilege)); + } + rolePrivilegesMapResult.put(entry.getKey(), tempTSentryPrivileges); + } + } + return rolePrivilegesMapResult; + } + + // export the sentry mapping data with map structure + public synchronized Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName, + String objectPath) throws SentryUserException { + TSentryExportMappingDataRequest request = new TSentryExportMappingDataRequest( + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName); + request.setObjectPath(objectPath); + try { + TSentryExportMappingDataResponse response = client.export_sentry_mapping_data(request); + Status.throwIfNotOk(response.getStatus()); + TSentryMappingData tSentryMappingData = response.getMappingData(); + Map<String, Map<String, Set<String>>> resultMap = Maps.newHashMap(); + resultMap.put(PolicyFileConstants.USER_ROLES, tSentryMappingData.getUserRolesMap()); + resultMap.put(PolicyFileConstants.GROUPS, tSentryMappingData.getGroupRolesMap()); + resultMap.put(PolicyFileConstants.ROLES, convertRolePrivilegesMapForPolicyFile(tSentryMappingData.getRolePrivilegesMap())); + return resultMap; + } catch (TException e) { + throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e); + } + } + + // convert the mapping data for [roleName,privilege] from TSentryMappingData.RolePrivilegesMap to + // map structure + private Map<String, Set<String>> convertRolePrivilegesMapForPolicyFile( + Map<String, Set<TSentryPrivilege>> rolePrivilegesMap) { + Map<String, Set<String>> rolePrivilegesMapForFile = Maps.newHashMap(); + if (rolePrivilegesMap != null) { + for (Map.Entry<String, Set<TSentryPrivilege>> entry : rolePrivilegesMap.entrySet()) { + Set<TSentryPrivilege> tempSentryPrivileges = entry.getValue(); + Set<String> tempStrPrivileges = Sets.newHashSet(); + for (TSentryPrivilege tSentryPrivilege : tempSentryPrivileges) { + // convert TSentryPrivilege to privilege in string + String privilegeStr = SentryServiceUtil.convertTSentryPrivilegeToStr(tSentryPrivilege); + if (!StringUtils.isEmpty(privilegeStr)) { + tempStrPrivileges.add(privilegeStr); + } + } + rolePrivilegesMapForFile.put(entry.getKey(), tempStrPrivileges); + } + } + return rolePrivilegesMapForFile; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java new file mode 100644 index 0000000..6ddc1de --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java @@ -0,0 +1,247 @@ +/** + * 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.provider.db.tools; + +import com.google.common.annotations.VisibleForTesting; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.Parser; +import org.apache.commons.lang.StringUtils; + +/** + * SentryShellCommon provides the function for parsing the argument. + * For hive model and generic model, child class should be implemented as a sentry admin tool. + */ +abstract public class SentryShellCommon { + + protected String roleName; + protected String groupName; + protected String privilegeStr; + protected String confPath; + // flag for the command + protected boolean isCreateRole = false; + protected boolean isDropRole = false; + protected boolean isAddRoleGroup = false; + protected boolean isDeleteRoleGroup = false; + protected boolean isGrantPrivilegeRole = false; + protected boolean isRevokePrivilegeRole = false; + protected boolean isListRole = false; + protected boolean isListPrivilege = false; + protected boolean isPrintHelp = false; + // flag for the parameter check + protected boolean roleNameRequired = false; + protected boolean groupNameRequired = false; + protected boolean privilegeStrRequired = false; + + public final static String OPTION_DESC_HELP = "Shell usage"; + public final static String OPTION_DESC_CONF = "sentry-site file path"; + public final static String OPTION_DESC_ROLE_NAME = "Role name"; + public final static String OPTION_DESC_GROUP_NAME = "Group name"; + public final static String OPTION_DESC_PRIVILEGE = "Privilege string"; + public final static String PREFIX_MESSAGE_MISSING_OPTION = "Missing required option: "; + + public final static String GROUP_SPLIT_CHAR = ","; + + /** + * parse arguments + * + * <pre> + * -conf,--sentry_conf <filepath> sentry config file path + * -cr,--create_role -r <rolename> create role + * -dr,--drop_role -r <rolename> drop role + * -arg,--add_role_group -r <rolename> -g <groupname> add role to group + * -drg,--delete_role_group -r <rolename> -g <groupname> delete role from group + * -gpr,--grant_privilege_role -r <rolename> -p <privilege> grant privilege to role + * -rpr,--revoke_privilege_role -r <rolename> -p <privilege> revoke privilege from role + * -lr,--list_role -g <groupname> list roles for group + * -lp,--list_privilege -r <rolename> list privilege for role + * -t,--type <typeame> the shell for hive model or generic model + * </pre> + * + * @param args + */ + protected boolean parseArgs(String[] args) { + Options simpleShellOptions = new Options(); + + Option crOpt = new Option("cr", "create_role", false, "Create role"); + crOpt.setRequired(false); + + Option drOpt = new Option("dr", "drop_role", false, "Drop role"); + drOpt.setRequired(false); + + Option argOpt = new Option("arg", "add_role_group", false, "Add role to group"); + argOpt.setRequired(false); + + Option drgOpt = new Option("drg", "delete_role_group", false, "Delete role from group"); + drgOpt.setRequired(false); + + Option gprOpt = new Option("gpr", "grant_privilege_role", false, "Grant privilege to role"); + gprOpt.setRequired(false); + + Option rprOpt = new Option("rpr", "revoke_privilege_role", false, "Revoke privilege from role"); + rprOpt.setRequired(false); + + Option lrOpt = new Option("lr", "list_role", false, "List role"); + lrOpt.setRequired(false); + + Option lpOpt = new Option("lp", "list_privilege", false, "List privilege"); + lpOpt.setRequired(false); + + // required args group + OptionGroup simpleShellOptGroup = new OptionGroup(); + simpleShellOptGroup.addOption(crOpt); + simpleShellOptGroup.addOption(drOpt); + simpleShellOptGroup.addOption(argOpt); + simpleShellOptGroup.addOption(drgOpt); + simpleShellOptGroup.addOption(gprOpt); + simpleShellOptGroup.addOption(rprOpt); + simpleShellOptGroup.addOption(lrOpt); + simpleShellOptGroup.addOption(lpOpt); + simpleShellOptGroup.setRequired(true); + simpleShellOptions.addOptionGroup(simpleShellOptGroup); + + // optional args + Option pOpt = new Option("p", "privilege", true, OPTION_DESC_PRIVILEGE); + pOpt.setRequired(false); + simpleShellOptions.addOption(pOpt); + + Option gOpt = new Option("g", "groupname", true, OPTION_DESC_GROUP_NAME); + gOpt.setRequired(false); + simpleShellOptions.addOption(gOpt); + + Option rOpt = new Option("r", "rolename", true, OPTION_DESC_ROLE_NAME); + rOpt.setRequired(false); + simpleShellOptions.addOption(rOpt); + + // this argument should be parsed in the bin/sentryShell + Option tOpt = new Option("t", "type", true, "[hive|solr|sqoop|.....]"); + tOpt.setRequired(false); + simpleShellOptions.addOption(tOpt); + + // file path of sentry-site + Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, OPTION_DESC_CONF); + sentrySitePathOpt.setRequired(true); + simpleShellOptions.addOption(sentrySitePathOpt); + + // help option + Option helpOpt = new Option("h", "help", false, OPTION_DESC_HELP); + helpOpt.setRequired(false); + simpleShellOptions.addOption(helpOpt); + + // this Options is parsed first for help option + Options helpOptions = new Options(); + helpOptions.addOption(helpOpt); + + try { + Parser parser = new GnuParser(); + + // parse help option first + CommandLine cmd = parser.parse(helpOptions, args, true); + for (Option opt : cmd.getOptions()) { + if (opt.getOpt().equals("h")) { + // get the help option, print the usage and exit + usage(simpleShellOptions); + return false; + } + } + + // without help option + cmd = parser.parse(simpleShellOptions, args); + + for (Option opt : cmd.getOptions()) { + if (opt.getOpt().equals("p")) { + privilegeStr = opt.getValue(); + } else if (opt.getOpt().equals("g")) { + groupName = opt.getValue(); + } else if (opt.getOpt().equals("r")) { + roleName = opt.getValue(); + } else if (opt.getOpt().equals("cr")) { + isCreateRole = true; + roleNameRequired = true; + } else if (opt.getOpt().equals("dr")) { + isDropRole = true; + roleNameRequired = true; + } else if (opt.getOpt().equals("arg")) { + isAddRoleGroup = true; + roleNameRequired = true; + groupNameRequired = true; + } else if (opt.getOpt().equals("drg")) { + isDeleteRoleGroup = true; + roleNameRequired = true; + groupNameRequired = true; + } else if (opt.getOpt().equals("gpr")) { + isGrantPrivilegeRole = true; + roleNameRequired = true; + privilegeStrRequired = true; + } else if (opt.getOpt().equals("rpr")) { + isRevokePrivilegeRole = true; + roleNameRequired = true; + privilegeStrRequired = true; + } else if (opt.getOpt().equals("lr")) { + isListRole = true; + } else if (opt.getOpt().equals("lp")) { + isListPrivilege = true; + roleNameRequired = true; + } else if (opt.getOpt().equals("conf")) { + confPath = opt.getValue(); + } + } + checkRequiredParameter(roleNameRequired, roleName, OPTION_DESC_ROLE_NAME); + checkRequiredParameter(groupNameRequired, groupName, OPTION_DESC_GROUP_NAME); + checkRequiredParameter(privilegeStrRequired, privilegeStr, OPTION_DESC_PRIVILEGE); + } catch (ParseException pe) { + System.out.println(pe.getMessage()); + usage(simpleShellOptions); + return false; + } + return true; + } + + private void checkRequiredParameter(boolean isRequired, String paramValue, String paramName) throws ParseException { + if (isRequired && StringUtils.isEmpty(paramValue)) { + throw new ParseException(PREFIX_MESSAGE_MISSING_OPTION + paramName); + } + } + + // print usage + private void usage(Options sentryOptions) { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("sentryShell", sentryOptions); + } + + // hive model and generic model should implement this method + public abstract void run() throws Exception; + + @VisibleForTesting + public boolean executeShell(String[] args) throws Exception { + boolean result = true; + if (parseArgs(args)) { + run(); + } else { + result = false; + } + return result; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java new file mode 100644 index 0000000..dc7f829 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java @@ -0,0 +1,98 @@ +/** + * 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.provider.db.tools; + +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient; +import org.apache.sentry.provider.db.tools.command.hive.*; +import org.apache.sentry.service.thrift.SentryServiceClientFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * SentryShellHive is an admin tool, and responsible for the management of repository. + * The following function are supported: + * create role, drop role, add group to role, delete group from role, grant privilege to role, + * revoke privilege from role, list roles for group, list privilege for role. + */ +public class SentryShellHive extends SentryShellCommon { + + private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellHive.class); + + public void run() throws Exception { + Command command = null; + SentryPolicyServiceClient client = SentryServiceClientFactory.create(getSentryConf()); + UserGroupInformation ugi = UserGroupInformation.getLoginUser(); + String requestorName = ugi.getShortUserName(); + + if (isCreateRole) { + command = new CreateRoleCmd(roleName); + } else if (isDropRole) { + command = new DropRoleCmd(roleName); + } else if (isAddRoleGroup) { + command = new GrantRoleToGroupsCmd(roleName, groupName); + } else if (isDeleteRoleGroup) { + command = new RevokeRoleFromGroupsCmd(roleName, groupName); + } else if (isGrantPrivilegeRole) { + command = new GrantPrivilegeToRoleCmd(roleName, privilegeStr); + } else if (isRevokePrivilegeRole) { + command = new RevokePrivilegeFromRoleCmd(roleName, privilegeStr); + } else if (isListRole) { + command = new ListRolesCmd(groupName); + } else if (isListPrivilege) { + command = new ListPrivilegesCmd(roleName); + } + + // check the requestor name + if (StringUtils.isEmpty(requestorName)) { + // The exception message will be recoreded in log file. + throw new Exception("The requestor name is empty."); + } + + if (command != null) { + command.execute(client, requestorName); + } + } + + private Configuration getSentryConf() { + Configuration conf = new Configuration(); + conf.addResource(new Path(confPath)); + return conf; + } + + public static void main(String[] args) throws Exception { + SentryShellHive sentryShell = new SentryShellHive(); + try { + sentryShell.executeShell(args); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + Throwable current = e; + // find the first printable message; + while (current != null && current.getMessage() == null) { + current = current.getCause(); + } + System.out.println("The operation failed." + + (current.getMessage() == null ? "" : " Message: " + current.getMessage())); + } + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/01875092/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/command/hive/Command.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/command/hive/Command.java b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/command/hive/Command.java new file mode 100644 index 0000000..79aed49 --- /dev/null +++ b/sentry-service/sentry-service-client/src/main/java/org/apache/sentry/provider/db/tools/command/hive/Command.java @@ -0,0 +1,27 @@ +/** + * 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.provider.db.tools.command.hive; + +import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient; + +/** + * The interface for all admin commands, eg, CreateRoleCmd. + */ +public interface Command { + void execute(SentryPolicyServiceClient client, String requestorName) throws Exception; +}
