Repository: sentry
Updated Branches:
  refs/heads/master 6d2ad5fa5 -> bee44c28a


SENTRY-2224: Support SHOW GRANT on HIVE_OBJECT (Arjun Mishra, reviewed by 
Sergio Pena)


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/bee44c28
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/bee44c28
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/bee44c28

Branch: refs/heads/master
Commit: bee44c28adac869ccf9972854d31e88adcc5f251
Parents: 6d2ad5f
Author: Sergio Pena <[email protected]>
Authored: Tue Jun 19 17:43:28 2018 -0500
Committer: Sergio Pena <[email protected]>
Committed: Tue Jun 19 17:43:28 2018 -0500

----------------------------------------------------------------------
 .../SentryHiveAuthorizationTaskFactoryImpl.java |  59 +++--
 .../authz/DefaultSentryAccessController.java    |  78 +++++++
 .../TestSentryHiveAuthorizationTaskFactory.java |  46 ++++
 .../service/thrift/SentryObjectPrivileges.java  |  54 +++++
 .../thrift/SentryPolicyServiceClient.java       |  22 ++
 .../SentryPolicyServiceClientDefaultImpl.java   |  33 ++-
 .../tests/e2e/dbprovider/TestShowGrants.java    | 227 +++++++++++++++++++
 7 files changed, 500 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/SentryHiveAuthorizationTaskFactoryImpl.java
----------------------------------------------------------------------
diff --git 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/SentryHiveAuthorizationTaskFactoryImpl.java
 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/SentryHiveAuthorizationTaskFactoryImpl.java
index 0518938..660bef1 100644
--- 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/SentryHiveAuthorizationTaskFactoryImpl.java
+++ 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/SentryHiveAuthorizationTaskFactoryImpl.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hive.SentryHiveConstants;
 import org.apache.hadoop.hive.conf.HiveConf;
@@ -188,30 +189,56 @@ public class SentryHiveAuthorizationTaskFactoryImpl 
implements HiveAuthorization
       HashSet<WriteEntity> outputs) throws SemanticException {
     SentryHivePrivilegeObjectDesc privHiveObj = null;
 
-    ASTNode principal = (ASTNode) ast.getChild(0);
+    PrincipalDesc principalDesc = null;
     PrincipalType type = null;
+
+    ASTNode principal = (ASTNode) ast.getChild(0);
     switch (principal.getType()) {
-    case HiveParser.TOK_USER:
-      type = PrincipalType.USER;
-      break;
-    case HiveParser.TOK_GROUP:
-      type = PrincipalType.GROUP;
-      break;
-    case HiveParser.TOK_ROLE:
-      type = PrincipalType.ROLE;
-      break;
-    default:
-      type = PrincipalType.USER;
+      case HiveParser.TOK_USER:
+        type = PrincipalType.USER;
+        break;
+      case HiveParser.TOK_GROUP:
+        type = PrincipalType.GROUP;
+        break;
+      case HiveParser.TOK_ROLE:
+        type = PrincipalType.ROLE;
+        break;
+      case HiveParser.TOK_PRIV_OBJECT_COL:
+        //Set type as null for SHOW GRANT ON <hive_object>
+        type = null;
+        break;
     }
-    if (type != PrincipalType.ROLE) {
+    if (type != null && type != PrincipalType.ROLE) {
       String msg = SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + type;
       throw new SemanticException(msg);
     }
-    String principalName = 
BaseSemanticAnalyzer.unescapeIdentifier(principal.getChild(0).getText());
-    PrincipalDesc principalDesc = new PrincipalDesc(principalName, type);
+
+    if(type != null) {
+      String principalName = BaseSemanticAnalyzer
+          .unescapeIdentifier(principal.getChild(0).getText());
+      principalDesc = new PrincipalDesc(principalName, type);
+    } else {
+      /**
+       * Commands like SHOW GRANT ON <hive_object
+       *   Eg: ASTNode structure: TOK_SHOW_GRANT -> TOK_PRIV_OBJECT_COL -> 
TOK_TABLE_TYPE -> TOK_TABNAME -> <hive_object>
+       */
+      privHiveObj = analyzePrivilegeObject(principal);
+      if(privHiveObj == null) {
+        String msg =
+            SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + 
"unspecified object name";
+        throw new SemanticException(msg);
+      }
+      //Principal name is list of all users or roles granted privilege to the 
object
+      principalDesc = new PrincipalDesc(StringUtils.EMPTY, type);
+    }
 
     // Partition privileges are not supported by Sentry
-    if (ast.getChildCount() > 1) {
+    if (type != null && ast.getChildCount() > 1) {
+      /**
+       *  Support for SHOW GRANT ROLE/USER/GROUP <name> ON <hive_o
+       *  bject>
+       *    Eg: ASTNode structure: TOK_SHOW_GRANT -> 
{TOK_ROLE/TOK_GROUP/TOK_USER, TOK_PRIV_OBJECT_COL} -> TOK_TABLE_TYPE -> 
TOK_TABNAME -> <hive_object>
+       */
       ASTNode child = (ASTNode) ast.getChild(1);
       if (child.getToken().getType() == HiveParser.TOK_PRIV_OBJECT_COL) {
         privHiveObj = analyzePrivilegeObject(child);

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryAccessController.java
----------------------------------------------------------------------
diff --git 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryAccessController.java
 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryAccessController.java
index 321701d..318c1e8 100644
--- 
a/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryAccessController.java
+++ 
b/sentry-binding/sentry-binding-hive/src/main/java/org/apache/sentry/binding/hive/authz/DefaultSentryAccessController.java
@@ -17,8 +17,10 @@ package org.apache.sentry.binding.hive.authz;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.hive.SentryHiveConstants;
@@ -37,6 +39,9 @@ import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilege;
 import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeInfo;
 import 
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
 import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveRoleGrant;
+import org.apache.sentry.api.service.thrift.SentryObjectPrivileges;
+import org.apache.sentry.api.service.thrift.TSentryAuthorizable;
+import org.apache.sentry.api.service.thrift.TSentryPrivilegeMap;
 import org.apache.sentry.binding.hive.SentryOnFailureHookContext;
 import org.apache.sentry.binding.hive.SentryOnFailureHookContextImpl;
 import org.apache.sentry.binding.hive.authz.HiveAuthzBinding.HiveHook;
@@ -201,6 +206,15 @@ public class DefaultSentryAccessController extends 
SentryHiveAccessController {
   @Override
   public List<HivePrivilegeInfo> showPrivileges(HivePrincipal principal, 
HivePrivilegeObject privObj)
       throws HiveAuthzPluginException, HiveAccessControlException {
+    if(principal.getName().isEmpty()) {
+      return showPriviliegesForObject(privObj);
+    } else {
+      return showPrivilegesByPrincipal(principal, privObj);
+    }
+  }
+
+  public List<HivePrivilegeInfo> showPrivilegesByPrincipal(HivePrincipal 
principal,
+      HivePrivilegeObject privObj) throws HiveAuthzPluginException, 
HiveAccessControlException {
     if (principal.getType() != HivePrincipalType.ROLE && principal.getType() 
!= HivePrincipalType.USER) {
       String msg =
           SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + 
principal.getType();
@@ -255,6 +269,70 @@ public class DefaultSentryAccessController extends 
SentryHiveAccessController {
     return infoList;
   }
 
+  private List<HivePrivilegeInfo> showPriviliegesForObject(HivePrivilegeObject 
privObj)
+      throws HiveAuthzPluginException, HiveAccessControlException {
+    List<HivePrivilegeInfo> infoList = new ArrayList<HivePrivilegeInfo>();
+
+    if (privObj == null) {
+      String msg =
+          SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + "unspecified 
object name";
+      throw new HiveAuthzPluginException(msg);
+    }
+
+    try {
+      sentryClient = getSentryClient();
+      Set<List<? extends Authorizable>> authorizableSet =
+          Sets.newHashSet(SentryAuthorizerUtil.getAuthzHierarchy(new 
Server(serverName), privObj));
+
+      Set<String> users = Collections.singleton(authenticator.getUserName());
+      SentryObjectPrivileges sentryObjectPrivileges = null;
+      if (authorizableSet != null && !authorizableSet.isEmpty()) {
+        hiveAuthzBinding = new HiveAuthzBinding(hiveHook, this.conf, 
authzConf);
+        sentryObjectPrivileges = sentryClient
+            .getAllPrivilegsbyAuthorizable(authenticator.getUserName(), 
authorizableSet, null, users, hiveAuthzBinding.getActiveRoleSet());
+      } else {
+        String msg =
+            SentryHiveConstants.SHOW_NOT_SUPPORTED_FOR_PRINCIPAL + "object 
name [" + privObj.getObjectName() + "] does not exist";
+        throw new HiveAuthzPluginException(msg);
+      }
+
+      Map<TSentryAuthorizable, TSentryPrivilegeMap> rolePrivilegesMap = 
sentryObjectPrivileges.getPrivilegesForRoles();
+      generateHivePrincipalInfo(infoList, rolePrivilegesMap, 
HivePrincipalType.ROLE);
+      Map<TSentryAuthorizable, TSentryPrivilegeMap> userPrivilegesMap = 
sentryObjectPrivileges.getPrivilegesForUsers();
+      generateHivePrincipalInfo(infoList, userPrivilegesMap, 
HivePrincipalType.USER);
+
+    } catch (SentryAccessDeniedException e) {
+      HiveOperation hiveOp = HiveOperation.SHOW_GRANT;
+      executeOnFailureHooks(hiveOp, e);
+    } catch (SentryUserException e) {
+      String msg = "Error when sentryClient listPrivilegsbyAuthorizable: " + e;
+      executeOnErrorHooks(msg, e);
+    } catch (Exception e) {
+      String msg = "Error when sentryClient listPrivilegsbyAuthorizable: " + e;
+      executeOnErrorHooks(msg, e);
+    } finally {
+      closeClient();
+    }
+    return infoList;
+  }
+
+  private void generateHivePrincipalInfo(List<HivePrivilegeInfo> infoList,
+      Map<TSentryAuthorizable, TSentryPrivilegeMap> privilegesMap,
+      HivePrincipalType principalType) {
+    if (privilegesMap != null && !privilegesMap.isEmpty()) {
+      for (TSentryPrivilegeMap map : privilegesMap.values()) {
+        Map<String, Set<TSentryPrivilege>> principalNameToPrivilegeMap = 
map.getPrivilegeMap();
+        for (String principalName : principalNameToPrivilegeMap.keySet()) {
+          for (TSentryPrivilege priv : 
principalNameToPrivilegeMap.get(principalName)) {
+            infoList.add(SentryAuthorizerUtil
+                .convert2HivePrivilegeInfo(priv, new 
HivePrincipal(principalName,
+                    principalType)));//For now only roles are retrieved
+          }
+        }
+      }
+    }
+  }
+
   @Override
   public void setCurrentRole(String roleName) throws 
HiveAccessControlException,
       HiveAuthzPluginException {

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryHiveAuthorizationTaskFactory.java
----------------------------------------------------------------------
diff --git 
a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryHiveAuthorizationTaskFactory.java
 
b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryHiveAuthorizationTaskFactory.java
index 2e3fd7f..8b6b223 100644
--- 
a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryHiveAuthorizationTaskFactory.java
+++ 
b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryHiveAuthorizationTaskFactory.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.util.HashMap;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.hive.ql.QueryState;
 import org.junit.Assert;
 
@@ -472,6 +473,51 @@ public class TestSentryHiveAuthorizationTaskFactory {
     Assert.assertEquals(SERVER, privilegeDesc.getObject());
   }
 
+
+  /**
+   * SHOW GRANT ... ON SERVER ...
+   */
+  @Test
+  public void testShowGrantOnServer() throws Exception {
+    DDLWork work = analyze(parse("SHOW GRANT ON SERVER " + SERVER));
+    ShowGrantDesc grantDesc = work.getShowGrantDesc();
+    Assert.assertNotNull("Show grant should not be null", grantDesc);
+    Assert.assertEquals(null, grantDesc.getPrincipalDesc().getType());
+    Assert.assertEquals(StringUtils.EMPTY, 
grantDesc.getPrincipalDesc().getName());
+    Assert.assertEquals(SERVER, grantDesc.getHiveObj().getObject());
+    Assert.assertTrue("Expected server", 
((SentryHivePrivilegeObjectDesc)grantDesc.getHiveObj()).getServer());
+  }
+
+  /**
+   * SHOW GRANT ... ON DATABASE ...
+   */
+  @Test
+  public void testShowGrantOnDatabase() throws Exception {
+    DDLWork work = analyze(parse("SHOW GRANT ON DATABASE " + DB));
+    ShowGrantDesc grantDesc = work.getShowGrantDesc();
+    Assert.assertNotNull("Show grant should not be null", grantDesc);
+    Assert.assertEquals(null, grantDesc.getPrincipalDesc().getType());
+    Assert.assertEquals(StringUtils.EMPTY, 
grantDesc.getPrincipalDesc().getName());
+    Assert.assertEquals(DB, grantDesc.getHiveObj().getObject());
+    //TODO - Part of SENTRY-2238 commit
+//    Assert.assertTrue("Expected database", 
((SentryHivePrivilegeObjectDesc)grantDesc.getHiveObj()).getDatabase());
+  }
+
+  /**
+   * SHOW GRANT ... ON TABLE ...
+   */
+  @Test
+  public void testShowGrantOnTable() throws Exception {
+    DDLWork work = analyze(parse("SHOW GRANT ON TABLE " + TABLE));
+    ShowGrantDesc grantDesc = work.getShowGrantDesc();
+    Assert.assertNotNull("Show grant should not be null", grantDesc);
+    Assert.assertEquals(null, grantDesc.getPrincipalDesc().getType());
+    Assert.assertEquals(StringUtils.EMPTY, 
grantDesc.getPrincipalDesc().getName());
+    Assert.assertEquals(TABLE, grantDesc.getHiveObj().getObject());
+    Assert.assertTrue("Expected table", 
((SentryHivePrivilegeObjectDesc)grantDesc.getHiveObj()).getTable());
+  }
+
+
   /*
   Db prefix in grant
    */

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryObjectPrivileges.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryObjectPrivileges.java
 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryObjectPrivileges.java
new file mode 100644
index 0000000..631857c
--- /dev/null
+++ 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryObjectPrivileges.java
@@ -0,0 +1,54 @@
+/**
+ * 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.api.service.thrift;
+
+import java.util.Map;
+
+/**
+ * Wrapper around TListSentryPrivilegesByAuthResponse.
+ * <p>
+ * Allows getting all the results associated with the response
+ * in a single fetch
+ */
+public class SentryObjectPrivileges {
+
+  private Map<TSentryAuthorizable, TSentryPrivilegeMap> privilegesForRoles;
+  private  Map<TSentryAuthorizable, TSentryPrivilegeMap> privilegesForUsers;
+
+  SentryObjectPrivileges(TListSentryPrivilegesByAuthResponse response) {
+
+    privilegesForRoles = response.getPrivilegesMapByAuth();
+    privilegesForUsers = response.getPrivilegesMapByAuthForUsers();
+  }
+
+  /**
+   * Return a map of authorizable to a mapping of roleNames to 
TSentryPrivileges
+   * @return
+   */
+  public Map<TSentryAuthorizable, TSentryPrivilegeMap> getPrivilegesForRoles() 
{
+    return privilegesForRoles;
+  }
+
+  /**
+   * Return a map of authorizable to a mapping of userNames to 
TSentryPrivileges
+   * @return
+   */
+  public Map<TSentryAuthorizable, TSentryPrivilegeMap> getPrivilegesForUsers() 
{
+    return privilegesForUsers;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClient.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClient.java
 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClient.java
index 6f38ed2..3950ea5 100644
--- 
a/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClient.java
+++ 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClient.java
@@ -243,6 +243,28 @@ public interface SentryPolicyServiceClient extends 
AutoCloseable {
     Set<String> groups, Set<String> users, ActiveRoleSet roleSet) throws 
SentryUserException;
 
   /**
+   * Returns an encapsulation of objects for all types assigned to a set of 
users and/or groups available in a
+   * set of authorizable objects.
+   *
+   * @param requestorUserName The user who is requesting the list of 
privileges.
+   * @param authorizables A list of authorizable objects to look for 
privileges.
+   *                      If null, then privileges of any authorizable object 
should be returned.
+   * @param groups A list of groups to look for privileges assigned.
+   *               If null, then privileges of any group on the specified 
authorizable object
+   *               should be returned.
+   * @param users A list of users to look for privileges assigned.
+   *              If null, then privileges of any user on the specified 
authorizable object
+   *              should be returned.
+   * @param roleSet The active role the group and/or user has. If null, then 
privileges of
+   *                any role on the specified group or user should be returned.
+   * @return A an instance of SentryObjectPrivileges on the specified 
authorizable object.
+   * @throws SentryUserException In case an error occurs while getting the 
list of privileges.
+   */
+  SentryObjectPrivileges getAllPrivilegsbyAuthorizable(
+      String requestorUserName, Set<List<? extends Authorizable>> 
authorizables,
+      Set<String> groups, Set<String> users, 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.

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClientDefaultImpl.java
----------------------------------------------------------------------
diff --git 
a/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClientDefaultImpl.java
 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClientDefaultImpl.java
index 45dce0e..28d345e 100644
--- 
a/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClientDefaultImpl.java
+++ 
b/sentry-service/sentry-service-api/src/main/java/org/apache/sentry/api/service/thrift/SentryPolicyServiceClientDefaultImpl.java
@@ -939,14 +939,37 @@ public class SentryPolicyServiceClientDefaultImpl 
implements SentryPolicyService
       String requestorUserName,
       Set<List<? extends Authorizable>> authorizables, Set<String> groups,
       Set<String> users, ActiveRoleSet roleSet) throws SentryUserException {
+
+    TListSentryPrivilegesByAuthResponse response =
+        getSentryPrivilegeByAuthResponse(requestorUserName, authorizables, 
groups, users, roleSet);
+
+    return response.getPrivilegesMapByAuth();
+  }
+
+  @Override
+  public SentryObjectPrivileges getAllPrivilegsbyAuthorizable
+  (
+    String requestorUserName,
+    Set<List<? extends Authorizable>> authorizables, Set<String> groups,
+    Set<String> users, ActiveRoleSet roleSet) throws SentryUserException {
+
+    TListSentryPrivilegesByAuthResponse response =
+        getSentryPrivilegeByAuthResponse(requestorUserName, authorizables, 
groups, users, roleSet);
+
+    return new SentryObjectPrivileges(response);
+  }
+
+  public TListSentryPrivilegesByAuthResponse 
getSentryPrivilegeByAuthResponse(String requestorUserName,
+      Set<List<? extends Authorizable>> authorizables, Set<String> groups, 
Set<String> users,
+      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);
+        ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName,
+        authSet);
     if (groups != null) {
       request.setGroups(groups);
     }
@@ -961,7 +984,11 @@ public class SentryPolicyServiceClientDefaultImpl 
implements SentryPolicyService
       TListSentryPrivilegesByAuthResponse response = client
         .list_sentry_privileges_by_authorizable(request);
       Status.throwIfNotOk(response.getStatus());
-      return response.getPrivilegesMapByAuth();
+
+      if(response == null) {
+        throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE + ": received a 
NULL response while requesting for sentry privileges by authorizable");
+      }
+      return response;
     } catch (TException e) {
       throw new SentryUserException(THRIFT_EXCEPTION_MESSAGE, e);
     }

http://git-wip-us.apache.org/repos/asf/sentry/blob/bee44c28/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestShowGrants.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestShowGrants.java
 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestShowGrants.java
new file mode 100644
index 0000000..500b38b
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/dbprovider/TestShowGrants.java
@@ -0,0 +1,227 @@
+/*
+ * 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.tests.e2e.dbprovider;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.junit.Assert;
+
+import org.apache.sentry.binding.hive.conf.HiveAuthzConf;
+import org.apache.sentry.tests.e2e.hive.AbstractTestWithStaticConfiguration;
+import org.apache.sentry.tests.e2e.hive.DummySentryOnFailureHook;
+import org.apache.sentry.tests.e2e.hive.hiveserver.HiveServerFactory;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestShowGrants extends AbstractTestWithStaticConfiguration {
+
+  private static int SHOW_GRANT_DB_POSITION = 1;
+  private static int SHOW_GRANT_TABLE_POSITION = 2;
+
+  @BeforeClass
+  public static void setupTestStaticConfiguration() throws Exception {
+    useSentryService = true;
+    String hiveServer2Type = System
+        .getProperty(HiveServerFactory.HIVESERVER2_TYPE);
+    if ((hiveServer2Type == null)
+        || HiveServerFactory.isInternalServer(HiveServerFactory.HiveServer2Type
+        .valueOf(hiveServer2Type.trim()))) {
+      System.setProperty(
+          HiveAuthzConf.AuthzConfVars.AUTHZ_ONFAILURE_HOOKS.getVar(),
+          DummySentryOnFailureHook.class.getName());
+    }
+    AbstractTestWithStaticConfiguration.setupTestStaticConfiguration();
+  }
+
+  @Override
+  @Before
+  public void setup() throws Exception {
+    DummySentryOnFailureHook.invoked = false;
+    super.setupAdmin();
+    super.setup();
+    setupTestCase();
+  }
+
+  private void setupTestCase() throws Exception {
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+
+    statement.execute("DROP DATABASE IF EXISTS db_1 CASCADE");
+    statement.execute("CREATE DATABASE db_1");
+    statement.execute("CREATE DATABASE db_2");
+    statement.execute("USE db_1");
+    statement.execute("CREATE TABLE foo (id int)");
+    statement.execute("USE db_2");
+    statement.execute("CREATE TABLE bar (id int)");
+
+    statement.execute("CREATE ROLE role1");
+    statement.execute("CREATE ROLE role2");
+    statement.execute("CREATE ROLE role3");
+    statement.execute("CREATE ROLE role4");
+
+    statement.execute("GRANT ROLE role1 TO GROUP " + USERGROUP1);
+    statement.execute("GRANT ROLE role1 TO GROUP " + USERGROUP2);
+    statement.execute("GRANT ROLE role2 TO GROUP " + USERGROUP2);
+    statement.execute("GRANT ROLE role3 TO GROUP " + USERGROUP2);
+    statement.execute("GRANT ROLE role4 TO GROUP " + USERGROUP3);
+    statement.execute("GRANT ROLE role4 TO GROUP " + USERGROUP4);
+
+    //Grant on server to role 1
+    statement.execute("GRANT ALL ON SERVER server1 TO ROLE role1");
+
+    // Grant select on database db_1 to role2
+    // Grant insert on database db_1 to role3
+    // Grant all on database db_2 to role3
+    statement.execute("GRANT SELECT ON DATABASE db_1 TO ROLE role2");
+    statement.execute("GRANT INSERT ON DATABASE db_1 TO ROLE role3");
+    statement.execute("GRANT ALL ON DATABASE db_2 TO ROLE role4");
+
+    // Grant select on table db_2.bar to role role2
+    // Grant insert on table db_2.bar to role role3
+    // Grant all on table db_1.foo to role role4
+    statement.execute("GRANT ALL ON TABLE db_1.foo TO ROLE role4");
+    statement.execute("GRANT ALL ON TABLE db_1.foo TO ROLE role3");
+    statement.execute("GRANT SELECT ON TABLE db_2.bar TO ROLE role2");
+    statement.execute("GRANT INSERT ON TABLE db_2.bar TO ROLE role3");
+
+    //Grant all on uri '/a/b/c' to role1
+    //Grant all on uri '/x/y/z' to role2, role3, role4
+    statement.execute("GRANT ALL ON URI \"file:///a/b/c\" TO ROLE role1");
+    statement.execute("GRANT ALL ON URI \"file:///x/y/z\" TO ROLE role3");
+    statement.execute("GRANT ALL ON URI \"file:///x/y/z\" TO ROLE role4");
+
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Test show grants on objects for admin users
+   * @throws Exception
+   */
+  @Test
+  public void testShowGrantsOnObjectsForAdmin() throws Exception {
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+
+    ResultSet resultSet = null;
+    resultSet = statement.executeQuery("SHOW GRANT ON SERVER server1");
+    assertResultSize(resultSet, 2);//Role1 + Admin
+    Assert.assertEquals("*", resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_1");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("db_1", resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_2");
+    assertResultSize(resultSet, 1);
+    Assert.assertEquals("db_2", resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON TABLE db_1.foo");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("foo", resultSet.getString(SHOW_GRANT_TABLE_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON TABLE db_2.bar");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("bar", resultSet.getString(SHOW_GRANT_TABLE_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON URI \"file:///a/b/c\"");
+    assertResultSize(resultSet, 1);
+    Assert.assertEquals("file:///a/b/c", 
resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON URI \"file:///x/y/z\"");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("file:///x/y/z", 
resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Test show grants on objects for non-admin users
+   * @throws Exception
+   */
+  @Test
+  public void testShowGrantsOnObjectsForNonAdmins() throws Exception {
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+
+    ResultSet resultSet = null;
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_1");
+    assertResultSize(resultSet, 0);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_2");
+    assertResultSize(resultSet, 0);
+
+    statement.close();
+    connection.close();
+
+    // setup db objects needed by the test
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_1");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("db_1", resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON DATABASE db_2");
+    assertResultSize(resultSet, 0);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON TABLE db_1.foo");
+    assertResultSize(resultSet, 2);
+
+    statement.close();
+    connection.close();
+
+    // setup db objects needed by the test
+    connection = context.createConnection(USER4_1);
+    statement = context.createStatement(connection);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON TABLE db_1.foo");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("foo", resultSet.getString(SHOW_GRANT_TABLE_POSITION));
+
+    resultSet = statement.executeQuery("SHOW GRANT ON TABLE db_2.bar");
+    assertResultSize(resultSet, 0);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON URI \"file:///a/b/c\"");
+    assertResultSize(resultSet, 0);
+
+    resultSet = statement.executeQuery("SHOW GRANT ON URI \"file:///x/y/z\"");
+    assertResultSize(resultSet, 2);
+    Assert.assertEquals("file:///x/y/z", 
resultSet.getString(SHOW_GRANT_DB_POSITION));
+
+    statement.close();
+    connection.close();
+  }
+
+  private void assertResultSize(ResultSet resultSet, int expected) throws 
SQLException{
+    int count = 0;
+    while(resultSet.next()) {
+      count++;
+    }
+    Assert.assertEquals(count, expected);
+  }
+
+}

Reply via email to