You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2016/06/27 01:27:24 UTC

[2/6] sentry git commit: SENTRY-1288: Create sentry-service-client module(Colin Ma, reviewed by Dapeng Sun)

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;
+}