Repository: sentry Updated Branches: refs/heads/master d89955bd6 -> 0db74b863
SENTRY-1222: Improve SentryIniPolicyFileFormatter to support user section in .ini file(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/0db74b86 Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/0db74b86 Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/0db74b86 Branch: refs/heads/master Commit: 0db74b863824c03a2d0164b86c7a1330afc76b97 Parents: d89955b Author: Colin Ma <[email protected]> Authored: Sun May 8 19:27:42 2016 +0800 Committer: Colin Ma <[email protected]> Committed: Sun May 8 19:27:42 2016 +0800 ---------------------------------------------------------------------- .../hive/SentryIniPolicyFileFormatter.java | 80 +++++++++++--------- .../hive/TestSentryIniPolicyFileFormatter.java | 40 +++++++++- .../provider/common/PolicyFileConstants.java | 1 + .../SentryPolicyServiceClientDefaultImpl.java | 4 +- .../thrift/TestSentryServiceImportExport.java | 6 +- 5 files changed, 88 insertions(+), 43 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sentry/blob/0db74b86/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/SentryIniPolicyFileFormatter.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/SentryIniPolicyFileFormatter.java b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/SentryIniPolicyFileFormatter.java index 06fe1fe..dd5781a 100644 --- a/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/SentryIniPolicyFileFormatter.java +++ b/sentry-binding/sentry-binding-hive-common/src/main/java/org/apache/sentry/binding/hive/SentryIniPolicyFileFormatter.java @@ -23,11 +23,15 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.collect.Sets; +import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.sentry.core.common.SentryConfigurationException; import org.apache.sentry.core.common.utils.SentryConstants; import org.apache.sentry.provider.common.PolicyFileConstants; -import org.apache.sentry.provider.common.ProviderBackendContext; -import org.apache.sentry.provider.file.SimpleFileProviderBackend; +import org.apache.sentry.provider.file.PolicyFiles; +import org.apache.shiro.config.Ini; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,8 +39,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.collect.Table; import com.google.common.io.Files; /** @@ -61,6 +63,8 @@ public class SentryIniPolicyFileFormatter implements SentryPolicyFileFormatter { * @param sentryMappingData * The map for sentry mapping data, eg: * for the following mapping data: + * user1=role1,role2 + * user2=role2,role3 * group1=role1,role2 * group2=role2,role3 * role1=server=server1->db=db1 @@ -69,6 +73,7 @@ public class SentryIniPolicyFileFormatter implements SentryPolicyFileFormatter { * * The sentryMappingData will be inputed as: * { + * users={[user1={role1, role2}], group2=[role2, role3]}, * 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], @@ -86,6 +91,8 @@ public class SentryIniPolicyFileFormatter implements SentryPolicyFileFormatter { String contents = Joiner .on(NL) .join( + generateSection(PolicyFileConstants.USER_ROLES, + sentryMappingData.get(PolicyFileConstants.USER_ROLES)), generateSection(PolicyFileConstants.GROUPS, sentryMappingData.get(PolicyFileConstants.GROUPS)), generateSection(PolicyFileConstants.ROLES, @@ -105,45 +112,48 @@ public class SentryIniPolicyFileFormatter implements SentryPolicyFileFormatter { * @return the result of sentry mapping data in map structure. */ @Override - public Map<String, Map<String, Set<String>>> parse(String resourcePath, Configuration conf) - throws Exception { + public Map<String, Map<String, Set<String>>> parse(String resourcePath, Configuration conf) { Map<String, Map<String, Set<String>>> resultMap = Maps.newHashMap(); - // SimpleFileProviderBackend is used for parse the ini file - SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, resourcePath); - ProviderBackendContext context = new ProviderBackendContext(); - context.setAllowPerDatabase(true); - // parse the ini file - policyFileBackend.initialize(context); + Path path = new Path(resourcePath); + Ini ini; - // SimpleFileProviderBackend parsed the input file and output the data in Table format. - Table<String, String, Set<String>> groupRolePrivilegeTable = policyFileBackend - .getGroupRolePrivilegeTable(); - Map<String, Set<String>> groupRolesMap = Maps.newHashMap(); - Map<String, Set<String>> rolePrivilegesMap = Maps.newHashMap(); - for (String groupName : groupRolePrivilegeTable.rowKeySet()) { - for (String roleName : groupRolePrivilegeTable.columnKeySet()) { - // get the roles set for the current groupName - Set<String> tempRoles = groupRolesMap.get(groupName); - if (tempRoles == null) { - tempRoles = Sets.newHashSet(); - } - Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName); - // if there has privilege for [group,role], if no privilege exist, the [group, role] info - // will be discard. - if (privileges != null) { - // update [group, role] mapping data - tempRoles.add(roleName); - groupRolesMap.put(groupName, tempRoles); - // update [role, privilege] mapping data - rolePrivilegesMap.put(roleName, privileges); - } - } + try { + ini = PolicyFiles.loadFromPath(path.getFileSystem(conf), path); + } catch (Exception e) { + throw new SentryConfigurationException("Error loading policy file " + + resourcePath, e); } + Map<String, Set<String>> userRolesMap = parseSection(ini, + PolicyFileConstants.USER_ROLES); + Map<String, Set<String>> groupRolesMap = parseSection(ini, + PolicyFileConstants.GROUPS); + Map<String, Set<String>> rolePrivilegesMap = parseSection(ini, + PolicyFileConstants.ROLES); + resultMap.put(PolicyFileConstants.USER_ROLES, userRolesMap); resultMap.put(PolicyFileConstants.GROUPS, groupRolesMap); resultMap.put(PolicyFileConstants.ROLES, rolePrivilegesMap); return resultMap; } + private Map<String, Set<String>> parseSection(Ini ini, String sctionName) { + Map<String, Set<String>> resultMap = Maps.newHashMap(); + Ini.Section sction = ini.getSection(sctionName); + if (sction == null) { + return resultMap; + } + for (String key : sction.keySet()) { + String value = sction.get(key); + Set<String> roles = Sets.newHashSet(); + for (String role : value.split(SentryConstants.ROLE_SEPARATOR)) { + if (StringUtils.isNotEmpty(role)) { + roles.add(role); + } + } + resultMap.put(key, roles); + } + return resultMap; + } + // generate the ini section according to the mapping data. private String generateSection(String name, Map<String, Set<String>> mappingData) { if (mappingData.isEmpty()) { http://git-wip-us.apache.org/repos/asf/sentry/blob/0db74b86/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryIniPolicyFileFormatter.java ---------------------------------------------------------------------- diff --git a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryIniPolicyFileFormatter.java b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryIniPolicyFileFormatter.java index 0e7ee3d..6fd1aa5 100644 --- a/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryIniPolicyFileFormatter.java +++ b/sentry-binding/sentry-binding-hive/src/test/java/org/apache/sentry/binding/hive/TestSentryIniPolicyFileFormatter.java @@ -55,6 +55,10 @@ public class TestSentryIniPolicyFileFormatter { private void prepareTestData() { // test data for: + // [users] + // user1=role1,role2,role3 + // user2=role1,role2,role3 + // user3=role1,role2,role3 // [groups] // group1=role1,role2,role3 // group2=role1,role2,role3 @@ -64,9 +68,13 @@ public class TestSentryIniPolicyFileFormatter { // role2=privilege1,privilege2,privilege3,privilege4,privilege5,privilege6,privilege7,privilege8 // role3=privilege1,privilege2,privilege3,privilege4,privilege5,privilege6,privilege7,privilege8 policyFileMappingData1 = Maps.newHashMap(); + Map<String, Set<String>> userRolesMap = Maps.newHashMap(); Map<String, Set<String>> groupRolesMap = Maps.newHashMap(); Map<String, Set<String>> rolePrivilegesMap = Maps.newHashMap(); Set<String> roles = Sets.newHashSet("role1", "role2", "role3"); + userRolesMap.put("user1", roles); + userRolesMap.put("user2", roles); + userRolesMap.put("user3", roles); groupRolesMap.put("group1", roles); groupRolesMap.put("group2", roles); groupRolesMap.put("group3", roles); @@ -74,10 +82,15 @@ public class TestSentryIniPolicyFileFormatter { rolePrivilegesMap.put(roleName, Sets.newHashSet(PRIVILIEGE1, PRIVILIEGE2, PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7, PRIVILIEGE8)); } + policyFileMappingData1.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData1.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData1.put(PolicyFileConstants.ROLES, rolePrivilegesMap); // test data for: + // [users] + // user1=role1 + // user2=role2 + // user3=role3 // [groups] // group1=role1 // group2=role2 @@ -87,18 +100,27 @@ public class TestSentryIniPolicyFileFormatter { // role2=privilege4,privilege5,privilege6 // role3=privilege7,privilege8 policyFileMappingData2 = Maps.newHashMap(); + userRolesMap = Maps.newHashMap(); groupRolesMap = Maps.newHashMap(); rolePrivilegesMap = Maps.newHashMap(); + userRolesMap.put("user1", Sets.newHashSet("role1")); + userRolesMap.put("user2", Sets.newHashSet("role2")); + userRolesMap.put("user3", Sets.newHashSet("role3")); groupRolesMap.put("group1", Sets.newHashSet("role1")); groupRolesMap.put("group2", Sets.newHashSet("role2")); groupRolesMap.put("group3", Sets.newHashSet("role3")); rolePrivilegesMap.put("role1", Sets.newHashSet(PRIVILIEGE1, PRIVILIEGE2, PRIVILIEGE3)); rolePrivilegesMap.put("role2", Sets.newHashSet(PRIVILIEGE4, PRIVILIEGE5, PRIVILIEGE6)); rolePrivilegesMap.put("role3", Sets.newHashSet(PRIVILIEGE7, PRIVILIEGE8)); + policyFileMappingData2.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData2.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData2.put(PolicyFileConstants.ROLES, rolePrivilegesMap); // test data for: + // [users] + // user1=role1,role2 + // user2=role1,role2,role3 + // user3=role2,role3 // [groups] // group1=role1,role2 // group2=role1,role2,role3 @@ -108,8 +130,12 @@ public class TestSentryIniPolicyFileFormatter { // role2=privilege3,privilege4,privilege5,privilege6 // role3=privilege5,privilege6,privilege7,privilege8 policyFileMappingData3 = Maps.newHashMap(); + userRolesMap = Maps.newHashMap(); groupRolesMap = Maps.newHashMap(); rolePrivilegesMap = Maps.newHashMap(); + userRolesMap.put("user1", Sets.newHashSet("role1", "role2")); + userRolesMap.put("user2", Sets.newHashSet("role1", "role2", "role3")); + userRolesMap.put("user3", Sets.newHashSet("role2", "role3")); groupRolesMap.put("group1", Sets.newHashSet("role1", "role2")); groupRolesMap.put("group2", Sets.newHashSet("role1", "role2", "role3")); groupRolesMap.put("group3", Sets.newHashSet("role2", "role3")); @@ -119,21 +145,27 @@ public class TestSentryIniPolicyFileFormatter { Sets.newHashSet(PRIVILIEGE3, PRIVILIEGE4, PRIVILIEGE5, PRIVILIEGE6)); rolePrivilegesMap.put("role3", Sets.newHashSet(PRIVILIEGE5, PRIVILIEGE6, PRIVILIEGE7, PRIVILIEGE8)); + policyFileMappingData3.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData3.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData3.put(PolicyFileConstants.ROLES, rolePrivilegesMap); - // test data for groups only + // test data for users, groups only policyFileMappingData4 = Maps.newHashMap(); + userRolesMap = Maps.newHashMap(); groupRolesMap = Maps.newHashMap(); rolePrivilegesMap = Maps.newHashMap(); + userRolesMap.put("user1", Sets.newHashSet("role1", "role2")); groupRolesMap.put("group1", Sets.newHashSet("role1", "role2")); + policyFileMappingData4.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData4.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData4.put(PolicyFileConstants.ROLES, rolePrivilegesMap); // test empty data policyFileMappingData5 = Maps.newHashMap(); + userRolesMap = Maps.newHashMap(); groupRolesMap = Maps.newHashMap(); rolePrivilegesMap = Maps.newHashMap(); + policyFileMappingData5.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData5.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData5.put(PolicyFileConstants.ROLES, rolePrivilegesMap); } @@ -165,12 +197,12 @@ public class TestSentryIniPolicyFileFormatter { // test data4 iniFormatter.write(resourcePath, policyFileMappingData4); parsedMappingData = iniFormatter.parse(resourcePath, authzConf); - assertTrue(parsedMappingData.get(PolicyFileConstants.GROUPS).isEmpty()); - assertTrue(parsedMappingData.get(PolicyFileConstants.ROLES).isEmpty()); + validateSentryMappingData(parsedMappingData, policyFileMappingData4); // test data5 iniFormatter.write(resourcePath, policyFileMappingData5); parsedMappingData = iniFormatter.parse(resourcePath, authzConf); + assertTrue(parsedMappingData.get(PolicyFileConstants.USER_ROLES).isEmpty()); assertTrue(parsedMappingData.get(PolicyFileConstants.GROUPS).isEmpty()); assertTrue(parsedMappingData.get(PolicyFileConstants.ROLES).isEmpty()); (new File(baseDir, RESOURCE_PATH)).delete(); @@ -179,6 +211,8 @@ public class TestSentryIniPolicyFileFormatter { // verify the mapping data public void validateSentryMappingData(Map<String, Map<String, Set<String>>> actualMappingData, Map<String, Map<String, Set<String>>> expectedMappingData) { + validateGroupRolesMap(actualMappingData.get(PolicyFileConstants.USER_ROLES), + expectedMappingData.get(PolicyFileConstants.USER_ROLES)); validateGroupRolesMap(actualMappingData.get(PolicyFileConstants.GROUPS), expectedMappingData.get(PolicyFileConstants.GROUPS)); validateRolePrivilegesMap(actualMappingData.get(PolicyFileConstants.ROLES), http://git-wip-us.apache.org/repos/asf/sentry/blob/0db74b86/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/PolicyFileConstants.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/PolicyFileConstants.java b/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/PolicyFileConstants.java index dfe4fe0..5627fa2 100644 --- a/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/PolicyFileConstants.java +++ b/sentry-provider/sentry-provider-common/src/main/java/org/apache/sentry/provider/common/PolicyFileConstants.java @@ -21,6 +21,7 @@ public class PolicyFileConstants { public static final String GROUPS = "groups"; public static final String ROLES = "roles"; public static final String USERS = "users"; + public static final String USER_ROLES = "userroles"; public static final String PRIVILEGE_SERVER_NAME = "server"; public static final String PRIVILEGE_DATABASE_NAME = "db"; public static final String PRIVILEGE_TABLE_NAME = "table"; http://git-wip-us.apache.org/repos/asf/sentry/blob/0db74b86/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 a52ad8f..616553f 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 @@ -940,7 +940,7 @@ public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyService // convert the mapping data for [group,role] from map structure to // TSentryMappingData.GroupRolesMap tSentryMappingData.setGroupRolesMap(policyFileMappingData.get(PolicyFileConstants.GROUPS)); - tSentryMappingData.setUserRolesMap(policyFileMappingData.get(PolicyFileConstants.USERS)); + tSentryMappingData.setUserRolesMap(policyFileMappingData.get(PolicyFileConstants.USER_ROLES)); // convert the mapping data for [role,privilege] from map structure to // TSentryMappingData.RolePrivilegesMap tSentryMappingData @@ -985,7 +985,7 @@ public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyService Status.throwIfNotOk(response.getStatus()); TSentryMappingData tSentryMappingData = response.getMappingData(); Map<String, Map<String, Set<String>>> resultMap = Maps.newHashMap(); - resultMap.put(PolicyFileConstants.USERS, tSentryMappingData.getUserRolesMap()); + resultMap.put(PolicyFileConstants.USER_ROLES, tSentryMappingData.getUserRolesMap()); resultMap.put(PolicyFileConstants.GROUPS, tSentryMappingData.getGroupRolesMap()); resultMap.put(PolicyFileConstants.ROLES, convertRolePrivilegesMapForPolicyFile(tSentryMappingData.getRolePrivilegesMap())); http://git-wip-us.apache.org/repos/asf/sentry/blob/0db74b86/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 2665db1..5aec49c 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 @@ -690,7 +690,7 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase rolePrivilegesMap.put(roleName, Sets.newHashSet(PRIVILIEGE1, PRIVILIEGE2, PRIVILIEGE3, PRIVILIEGE4)); } - policyFileMappingData.put(PolicyFileConstants.USERS, userRolesMap); + policyFileMappingData.put(PolicyFileConstants.USER_ROLES, userRolesMap); policyFileMappingData.put(PolicyFileConstants.GROUPS, groupRolesMap); policyFileMappingData.put(PolicyFileConstants.ROLES, rolePrivilegesMap); client.importPolicy(policyFileMappingData, ADMIN_USER, false); @@ -698,8 +698,8 @@ public class TestSentryServiceImportExport extends SentryServiceIntegrationBase Map<String, Map<String, Set<String>>> sentryMappingData = client.exportPolicy(ADMIN_USER, null); // validate the [user, role] mapping - validateRolesMap(sentryMappingData.get(PolicyFileConstants.USERS), - policyFileMappingData.get(PolicyFileConstants.USERS)); + validateRolesMap(sentryMappingData.get(PolicyFileConstants.USER_ROLES), + policyFileMappingData.get(PolicyFileConstants.USER_ROLES)); validateSentryMappingData(sentryMappingData, policyFileMappingData); }
