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/04/14 03:12:03 UTC

sentry git commit: SENTRY-1178: Update Sentry Policy Service for export with specific auth object (Colin Ma, reviewed by Dapeng Sun)

Repository: sentry
Updated Branches:
  refs/heads/master a3f7510bb -> 04881fa7a


SENTRY-1178: Update Sentry Policy Service for export with specific auth object (Colin Ma, reviewed by Dapeng Sun)


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

Branch: refs/heads/master
Commit: 04881fa7acbf11ab3118c5402f2473c5f1fc15b5
Parents: a3f7510
Author: Colin Ma <co...@apache.org>
Authored: Thu Apr 14 09:52:03 2016 +0800
Committer: Colin Ma <co...@apache.org>
Committed: Thu Apr 14 09:52:03 2016 +0800

----------------------------------------------------------------------
 .../binding/hive/authz/SentryConfigTool.java    |   2 +-
 .../thrift/SentryPolicyServiceClient.java       |   2 +-
 .../SentryPolicyServiceClientDefaultImpl.java   |   5 +-
 .../thrift/SentryPolicyStoreProcessor.java      |  24 ++-
 .../service/thrift/SentryServiceUtil.java       |  26 +++
 .../thrift/TestSentryServiceImportExport.java   | 188 ++++++++++++++++++-
 6 files changed, 232 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/SentryConfigTool.java
----------------------------------------------------------------------
diff --git a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/SentryConfigTool.java b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/SentryConfigTool.java
index 73b0941..18ba943 100644
--- a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/SentryConfigTool.java
+++ b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/authz/SentryConfigTool.java
@@ -293,7 +293,7 @@ public class SentryConfigTool {
     SentryPolicyServiceClient client = SentryServiceClientFactory.create(getAuthzConf());
     // export the sentry mapping data from database to map structure
     Map<String, Map<String, Set<String>>> policyFileMappingData = client
-        .exportPolicy(requestorUserName);
+        .exportPolicy(requestorUserName, null);
     // get the FileFormatter according to the configuration
     SentryPolicyFileFormatter sentryPolicyFileFormatter = SentryPolicyFileFormatFactory
         .createFileFormatter(authzConf);

http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
index de50adb..b6deadb 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
@@ -187,6 +187,6 @@ public interface SentryPolicyServiceClient {
       String requestorUserName, boolean isOverwriteRole) throws SentryUserException;
 
   // export the sentry mapping data with map structure
-  Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName)
+  Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName, String objectPath)
       throws SentryUserException;
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java
index edc5661..3f8e489 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClientDefaultImpl.java
@@ -903,10 +903,11 @@ public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyService
   }
 
   // export the sentry mapping data with map structure
-  public synchronized Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName)
-      throws SentryUserException {
+  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());

http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
index 8881d82..52af345 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
@@ -31,6 +31,7 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.sentry.SentryUserException;
 import org.apache.sentry.core.model.db.AccessConstants;
 import org.apache.sentry.provider.common.GroupMappingService;
+import org.apache.sentry.provider.common.PolicyFileConstants;
 import org.apache.sentry.provider.db.SentryAccessDeniedException;
 import org.apache.sentry.provider.db.SentryAlreadyExistsException;
 import org.apache.sentry.provider.db.SentryInvalidInputException;
@@ -46,6 +47,7 @@ import org.apache.sentry.provider.db.service.persistent.HAContext;
 import org.apache.sentry.provider.db.service.persistent.SentryStore;
 import org.apache.sentry.provider.db.service.persistent.ServiceRegister;
 import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants.PolicyStoreServerConfig;
+import org.apache.sentry.service.thrift.SentryServiceUtil;
 import org.apache.sentry.service.thrift.ServiceConstants;
 import org.apache.sentry.service.thrift.ServiceConstants.ConfUtilties;
 import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
@@ -902,14 +904,32 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface {
     try {
       String requestor = request.getRequestorUserName();
       Set<String> memberGroups = getRequestorGroups(requestor);
+      String objectPath = request.getObjectPath();
+      String databaseName = null;
+      String tableName = null;
+
+      Map<String, String> objectMap =
+          SentryServiceUtil.parseObjectPath(objectPath);
+      databaseName = objectMap.get(PolicyFileConstants.PRIVILEGE_DATABASE_NAME);
+      tableName = objectMap.get(PolicyFileConstants.PRIVILEGE_TABLE_NAME);
+
       if (!inAdminGroups(memberGroups)) {
         // disallow non-admin to import the metadata of sentry
         throw new SentryAccessDeniedException("Access denied to " + requestor
             + " for export the metadata of sentry.");
       }
       TSentryMappingData tSentryMappingData = new TSentryMappingData();
-      tSentryMappingData.setGroupRolesMap(sentryStore.getGroupNameRoleNamesMap());
-      tSentryMappingData.setRolePrivilegesMap(sentryStore.getRoleNameTPrivilegesMap());
+      Map<String, Set<TSentryPrivilege>> rolePrivileges =
+          sentryStore.getRoleNameTPrivilegesMap(databaseName, tableName);
+      tSentryMappingData.setRolePrivilegesMap(rolePrivileges);
+      Set<String> roleNames = rolePrivileges.keySet();
+      // roleNames should be null if databaseName == null and tableName == null
+      if (databaseName == null && tableName == null) {
+        roleNames = null;
+      }
+      tSentryMappingData.setGroupRolesMap(
+          sentryStore.getGroupNameRoleNamesMap(roleNames));
+
       response.setMappingData(tSentryMappingData);
       response.setStatus(Status.OK());
     } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
index 5b293ec..1da17ee 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
@@ -18,7 +18,9 @@
 
 package org.apache.sentry.service.thrift;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.sentry.policy.common.KeyValue;
@@ -62,6 +64,30 @@ public class SentryServiceUtil {
     return tSentryPrivilege;
   }
 
+  /**
+   * Parse the object path from string to map.
+   * @param objectPath the string format as db=db1->table=tbl1
+   * @return Map
+   */
+  public static Map<String, String> parseObjectPath(String objectPath) {
+    Map<String, String> objectMap = new HashMap<String, String>();
+    if (StringUtils.isEmpty(objectPath)) {
+      return objectMap;
+    }
+    for (String kvStr : PolicyConstants.AUTHORIZABLE_SPLITTER.split(objectPath)) {
+      KeyValue kv = new KeyValue(kvStr);
+      String key = kv.getKey();
+      String value = kv.getValue();
+
+      if (PolicyFileConstants.PRIVILEGE_DATABASE_NAME.equalsIgnoreCase(key)) {
+        objectMap.put(PolicyFileConstants.PRIVILEGE_DATABASE_NAME, value);
+      } else if (PolicyFileConstants.PRIVILEGE_TABLE_NAME.equalsIgnoreCase(key)) {
+        objectMap.put(PolicyFileConstants.PRIVILEGE_TABLE_NAME, value);
+      }
+    }
+    return objectMap;
+  }
+
   // for the different hierarchy for hive:
   // 1: server->url
   // 2: server->database->table->column

http://git-wip-us.apache.org/repos/asf/sentry/blob/04881fa7/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceImportExport.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceImportExport.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceImportExport.java
index dbe4a27..8d8f28c 100644
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceImportExport.java
+++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/service/thrift/TestSentryServiceImportExport.java
@@ -46,6 +46,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
   public static String PRIVILIEGE6 = "server=server1->db=db1->table=tbl3->column=col1->action=*->grantoption=true";
   public static String PRIVILIEGE7 = "server=server1->db=db1->table=tbl4->column=col1->action=all->grantoption=true";
   public static String PRIVILIEGE8 = "server=server1->uri=hdfs://testserver:9999/path2->action=insert";
+  public static String PRIVILIEGE9 = "server=server1->db=db2->table=tbl1->action=insert";
 
   @BeforeClass
   public static void setup() throws Exception {
@@ -92,7 +93,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         policyFileMappingData.put(PolicyFileConstants.ROLES, rolePrivilegesMap);
         client.importPolicy(policyFileMappingData, ADMIN_USER, false);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData,
             policyFileMappingData);
       }
@@ -148,7 +149,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         exceptedMappingData.get(PolicyFileConstants.ROLES).putAll(
             policyFileMappingData2.get(PolicyFileConstants.ROLES));
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
     });
@@ -216,7 +217,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         exceptedMappingData.put(PolicyFileConstants.GROUPS, exceptedRolesMap);
         exceptedMappingData.put(PolicyFileConstants.ROLES, exceptedPrivilegesMap);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
     });
@@ -238,7 +239,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         policyFileMappingData.put(PolicyFileConstants.ROLES, rolePrivilegesMap);
         client.importPolicy(policyFileMappingData, ADMIN_USER, false);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData,
             policyFileMappingData);
       }
@@ -293,7 +294,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         exceptedMappingData.put(PolicyFileConstants.GROUPS, exceptedRolesMap);
         exceptedMappingData.put(PolicyFileConstants.ROLES, exceptedPrivilegesMap);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
     });
@@ -362,7 +363,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         exceptedMappingData.put(PolicyFileConstants.GROUPS, exceptedRolesMap);
         exceptedMappingData.put(PolicyFileConstants.ROLES, exceptedPrivilegesMap);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
     });
@@ -409,7 +410,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         exceptedMappingData.put(PolicyFileConstants.GROUPS, exceptedRolesMap);
         exceptedMappingData.put(PolicyFileConstants.ROLES, exceptedPrivilegesMap);
 
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
     });
@@ -458,7 +459,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         client.importPolicy(policyFileMappingData2, ADMIN_USER, false);
 
         Map<String, Map<String, Set<String>>> exceptedMappingData = policyFileMappingData2;
-        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER);
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
         // all and * should replace the select and insert
         validateSentryMappingData(sentryMappingData, exceptedMappingData);
       }
@@ -484,7 +485,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
         }
 
         try {
-          client.exportPolicy("no-admin-user");
+          client.exportPolicy("no-admin-user", null);
           fail("non-admin can't do the export.");
         } catch (Exception e) {
           // excepted exception
@@ -493,6 +494,175 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase
     });
   }
 
+  // The following data is imported:
+  // group1=role1
+  // group2=role1,role2
+  // group3=role2,role3
+  // group4=role1,role2,role3
+  // role1=privilege3,privilege4,privilege9
+  // role2=privilege3,privilege4,privilege5,privilege6,privilege7
+  // role3=privilege4,privilege5,privilege6,privilege7,privilege8
+  // Export APIs getRoleNameTPrivilegesMap, getGroupNameRoleNamesMap are tested.
+  @Test
+  public void testExportPolicyWithSpecificObject() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // import the test data
+        Map<String, Map<String, Set<String>>> policyFileMappingData = Maps.newHashMap();
+        Map<String, Set<String>> groupRolesMap = Maps.newHashMap();
+        groupRolesMap.put("group1", Sets.newHashSet("role1"));
+        groupRolesMap.put("group2", Sets.newHashSet("role1", "role2"));
+        groupRolesMap.put("group3", Sets.newHashSet("role2", "role3"));
+        groupRolesMap.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        Map<String, Set<String>> rolePrivilegesMap1 = Maps.newHashMap();
+        rolePrivilegesMap1.put("role1",
+            Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE9));
+        rolePrivilegesMap1.put("role2",
+            Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE5,
+            PRIVILIEGE6, PRIVILIEGE7));
+        rolePrivilegesMap1.put("role3",
+            Sets.newHashSet(PRIVILIEGE4, PRIVILIEGE5, PRIVILIEGE6,
+            PRIVILIEGE7, PRIVILIEGE8));
+        policyFileMappingData.put(PolicyFileConstants.GROUPS, groupRolesMap);
+        policyFileMappingData.put(PolicyFileConstants.ROLES, rolePrivilegesMap1);
+        client.importPolicy(policyFileMappingData, ADMIN_USER, true);
+
+        // verify the rolePrivilegesMap and groupRolesMap with null objectPath
+        Map<String, Map<String, Set<String>>> expectedMappingData = Maps.newHashMap();
+        Map<String, Set<String>> expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        Map<String, Set<String>> expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(
+            PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE9));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7, PRIVILIEGE8));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null);
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap with empty objectPath
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(
+            PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE9));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7, PRIVILIEGE8));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap for db=db1
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(PRIVILIEGE4));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE4,
+            PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "db=db1");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap for db=db2
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE9));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE3));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "db=db2");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap for db=db1->table=tbl1
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(PRIVILIEGE4));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE4));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE4));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "db=db1->table=tbl1");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap for db=db1->table=tbl2
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group2", Sets.newHashSet("role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role2", "role3"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE5));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE5));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "db=db1->table=tbl2");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the rolePrivilegesMap and groupRolesMap for db=db1->table=tbl1
+        expectedMappingData = Maps.newHashMap();
+        expectedGroupRoles = Maps.newHashMap();
+        expectedGroupRoles.put("group1", Sets.newHashSet("role1"));
+        expectedGroupRoles.put("group2", Sets.newHashSet("role1", "role2"));
+        expectedGroupRoles.put("group3", Sets.newHashSet("role2", "role3"));
+        expectedGroupRoles.put("group4", Sets.newHashSet("role1", "role2", "role3"));
+        expectedRolePrivileges = Maps.newHashMap();
+        expectedRolePrivileges.put("role1", Sets.newHashSet(PRIVILIEGE4, PRIVILIEGE9));
+        expectedRolePrivileges.put("role2", Sets.newHashSet(PRIVILIEGE4));
+        expectedRolePrivileges.put("role3", Sets.newHashSet(PRIVILIEGE4));
+        expectedMappingData.put(PolicyFileConstants.GROUPS, expectedGroupRoles);
+        expectedMappingData.put(PolicyFileConstants.ROLES, expectedRolePrivileges);
+
+        sentryMappingData = client.exportPolicy(ADMIN_USER, "table=tbl1");
+        validateSentryMappingData(sentryMappingData, expectedMappingData);
+
+        // verify the invalid exportObject string
+        try {
+          client.exportPolicy(ADMIN_USER, "invalidString");
+          fail("RuntimeException should be thrown.");
+        } catch (RuntimeException sue) {
+          // excepted exception
+        }
+      }
+    });
+  }
+
   // verify the mapping data
   public void validateSentryMappingData(
       Map<String, Map<String, Set<String>>> actualMappingData,