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 2015/07/30 03:02:58 UTC
[3/6] incubator-sentry git commit: SENTRY-197: Create tool to dump
and load of entire Sentry service (Colin Ma, Reviewed by:Sravya Tirukkovalur,
Guoquan Shen, Dapeng Sun, Anne Yu)
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
index 81adec2..fbb611e 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
@@ -65,6 +65,7 @@ import org.apache.sentry.provider.db.service.thrift.TSentryActiveRoleSet;
import org.apache.sentry.provider.db.service.thrift.TSentryAuthorizable;
import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption;
import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryMappingData;
import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
import org.apache.sentry.provider.db.service.thrift.TSentryPrivilegeMap;
import org.apache.sentry.provider.db.service.thrift.TSentryRole;
@@ -76,9 +77,11 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.Gauge;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
+import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -310,16 +313,10 @@ public class SentryStore {
PersistenceManager pm = null;
try {
pm = openTransaction();
- MSentryRole mSentryRole = getMSentryRole(pm, roleName);
- if (mSentryRole == null) {
- MSentryRole mRole = new MSentryRole(roleName, System.currentTimeMillis());
- pm.makePersistent(mRole);
- CommitContext commit = commitUpdateTransaction(pm);
- rollbackTransaction = false;
- return commit;
- } else {
- throw new SentryAlreadyExistsException("Role: " + roleName);
- }
+ createSentryRoleCore(pm, roleName);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
} finally {
if (rollbackTransaction) {
rollbackTransaction(pm);
@@ -327,6 +324,17 @@ public class SentryStore {
}
}
+ private void createSentryRoleCore(PersistenceManager pm, String roleName)
+ throws SentryAlreadyExistsException {
+ MSentryRole mSentryRole = getMSentryRole(pm, roleName);
+ if (mSentryRole == null) {
+ MSentryRole mRole = new MSentryRole(roleName, System.currentTimeMillis());
+ pm.makePersistent(mRole);
+ } else {
+ throw new SentryAlreadyExistsException("Role: " + roleName);
+ }
+ }
+
private <T> Long getCount(Class<T> tClass) {
PersistenceManager pm = null;
Long size = new Long(-1);
@@ -444,7 +452,8 @@ public class SentryStore {
|| (!isNULL(privilege.getDbName()))) {
// If Grant is for ALL and Either INSERT/SELECT already exists..
// need to remove it and GRANT ALL..
- if (privilege.getAction().equalsIgnoreCase("*")) {
+ if (AccessConstants.ALL.equalsIgnoreCase(privilege.getAction())
+ || AccessConstants.ACTION_ALL.equalsIgnoreCase(privilege.getAction())) {
TSentryPrivilege tNotAll = new TSentryPrivilege(privilege);
tNotAll.setAction(AccessConstants.SELECT);
MSentryPrivilege mSelect = getMSentryPrivilege(tNotAll, pm);
@@ -465,8 +474,13 @@ public class SentryStore {
// do nothing..
TSentryPrivilege tAll = new TSentryPrivilege(privilege);
tAll.setAction(AccessConstants.ALL);
- MSentryPrivilege mAll = getMSentryPrivilege(tAll, pm);
- if ((mAll != null) && (mRole.getPrivileges().contains(mAll))) {
+ MSentryPrivilege mAll1 = getMSentryPrivilege(tAll, pm);
+ tAll.setAction(AccessConstants.ACTION_ALL);
+ MSentryPrivilege mAll2 = getMSentryPrivilege(tAll, pm);
+ if ((mAll1 != null) && (mRole.getPrivileges().contains(mAll1))) {
+ return null;
+ }
+ if ((mAll2 != null) && (mRole.getPrivileges().contains(mAll2))) {
return null;
}
}
@@ -763,25 +777,9 @@ public class SentryStore {
throws SentryNoSuchObjectException {
boolean rollbackTransaction = true;
PersistenceManager pm = null;
- roleName = roleName.trim().toLowerCase();
try {
pm = openTransaction();
- Query query = pm.newQuery(MSentryRole.class);
- query.setFilter("this.roleName == t");
- query.declareParameters("java.lang.String t");
- query.setUnique(true);
- MSentryRole sentryRole = (MSentryRole) query.execute(roleName);
- if (sentryRole == null) {
- throw new SentryNoSuchObjectException("Role " + roleName);
- } else {
- pm.retrieve(sentryRole);
- int numPrivs = sentryRole.getPrivileges().size();
- sentryRole.removePrivileges();
- //with SENTRY-398 generic model
- sentryRole.removeGMPrivileges();
- privCleaner.incPrivRemoval(numPrivs);
- pm.deletePersistent(sentryRole);
- }
+ dropSentryRoleCore(pm, roleName);
CommitContext commit = commitUpdateTransaction(pm);
rollbackTransaction = false;
return commit;
@@ -792,42 +790,38 @@ public class SentryStore {
}
}
+ private void dropSentryRoleCore(PersistenceManager pm, String roleName)
+ throws SentryNoSuchObjectException {
+ String lRoleName = roleName.trim().toLowerCase();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole sentryRole = (MSentryRole) query.execute(lRoleName);
+ if (sentryRole == null) {
+ throw new SentryNoSuchObjectException("Role " + lRoleName);
+ } else {
+ pm.retrieve(sentryRole);
+ int numPrivs = sentryRole.getPrivileges().size();
+ sentryRole.removePrivileges();
+ // with SENTRY-398 generic model
+ sentryRole.removeGMPrivileges();
+ privCleaner.incPrivRemoval(numPrivs);
+ pm.deletePersistent(sentryRole);
+ }
+ }
+
public CommitContext alterSentryRoleAddGroups( String grantorPrincipal, String roleName,
Set<TSentryGroup> groupNames)
throws SentryNoSuchObjectException {
boolean rollbackTransaction = true;
PersistenceManager pm = null;
- roleName = roleName.trim().toLowerCase();
try {
pm = openTransaction();
- Query query = pm.newQuery(MSentryRole.class);
- query.setFilter("this.roleName == t");
- query.declareParameters("java.lang.String t");
- query.setUnique(true);
- MSentryRole role = (MSentryRole) query.execute(roleName);
- if (role == null) {
- throw new SentryNoSuchObjectException("Role: " + roleName);
- } else {
- query = pm.newQuery(MSentryGroup.class);
- query.setFilter("this.groupName == t");
- query.declareParameters("java.lang.String t");
- query.setUnique(true);
- List<MSentryGroup> groups = Lists.newArrayList();
- for (TSentryGroup tGroup : groupNames) {
- String groupName = tGroup.getGroupName().trim();
- MSentryGroup group = (MSentryGroup) query.execute(groupName);
- if (group == null) {
- group = new MSentryGroup(groupName, System.currentTimeMillis(),
- Sets.newHashSet(role));
- }
- group.appendRole(role);
- groups.add(group);
- }
- pm.makePersistentAll(groups);
- CommitContext commit = commitUpdateTransaction(pm);
- rollbackTransaction = false;
- return commit;
- }
+ alterSentryRoleAddGroupsCore(pm, roleName, groupNames);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
} finally {
if (rollbackTransaction) {
rollbackTransaction(pm);
@@ -835,6 +829,35 @@ public class SentryStore {
}
}
+ private void alterSentryRoleAddGroupsCore(PersistenceManager pm, String roleName,
+ Set<TSentryGroup> groupNames) throws SentryNoSuchObjectException {
+ String lRoleName = roleName.trim().toLowerCase();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole role = (MSentryRole) query.execute(lRoleName);
+ if (role == null) {
+ throw new SentryNoSuchObjectException("Role: " + lRoleName);
+ } else {
+ query = pm.newQuery(MSentryGroup.class);
+ query.setFilter("this.groupName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ List<MSentryGroup> groups = Lists.newArrayList();
+ for (TSentryGroup tGroup : groupNames) {
+ String groupName = tGroup.getGroupName().trim();
+ MSentryGroup group = (MSentryGroup) query.execute(groupName);
+ if (group == null) {
+ group = new MSentryGroup(groupName, System.currentTimeMillis(), Sets.newHashSet(role));
+ }
+ group.appendRole(role);
+ groups.add(group);
+ }
+ pm.makePersistentAll(groups);
+ }
+ }
+
public CommitContext alterSentryRoleDeleteGroups(String roleName,
Set<TSentryGroup> groupNames)
throws SentryNoSuchObjectException {
@@ -1341,7 +1364,7 @@ public class SentryStore {
return group;
}
- private TSentryPrivilege convertToTSentryPrivilege(MSentryPrivilege mSentryPrivilege) {
+ protected TSentryPrivilege convertToTSentryPrivilege(MSentryPrivilege mSentryPrivilege) {
TSentryPrivilege privilege = new TSentryPrivilege();
convertToTSentryPrivilege(mSentryPrivilege, privilege);
return privilege;
@@ -1979,4 +2002,319 @@ public class SentryStore {
}
}
}
+
+ // get all mapping data for [group,role]
+ public Map<String, Set<String>> getGroupNameRoleNamesMap() {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryGroup.class);
+ List<MSentryGroup> mSentryGroups = (List<MSentryGroup>) query.execute();
+ Map<String, Set<String>> sentryGroupNameRoleNamesMap = Maps.newHashMap();
+ if (mSentryGroups != null) {
+ // change the List<MSentryGroup> -> Map<groupName, Set<roleName>>
+ for (MSentryGroup mSentryGroup : mSentryGroups) {
+ String groupName = mSentryGroup.getGroupName();
+ Set<String> roleNames = Sets.newHashSet();
+ for (MSentryRole mSentryRole : mSentryGroup.getRoles()) {
+ roleNames.add(mSentryRole.getRoleName());
+ }
+ if (roleNames.size() > 0) {
+ sentryGroupNameRoleNamesMap.put(groupName, roleNames);
+ }
+ }
+ }
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ return sentryGroupNameRoleNamesMap;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ // get all mapping data for [role,privilege]
+ public Map<String, Set<TSentryPrivilege>> getRoleNameTPrivilegesMap() throws Exception {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryRole.class);
+ List<MSentryRole> mSentryRoles = (List<MSentryRole>) query.execute();
+ Map<String, Set<TSentryPrivilege>> sentryRolePrivilegesMap = Maps.newHashMap();
+ if (mSentryRoles != null) {
+ // change the List<MSentryRole> -> Map<roleName, Set<TSentryPrivilege>>
+ for (MSentryRole mSentryRole : mSentryRoles) {
+ Set<TSentryPrivilege> privilegeSet = convertToTSentryPrivileges(mSentryRole
+ .getPrivileges());
+ if (privilegeSet != null && !privilegeSet.isEmpty()) {
+ sentryRolePrivilegesMap.put(mSentryRole.getRoleName(), privilegeSet);
+ }
+ }
+ }
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ return sentryRolePrivilegesMap;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ // get the all exist role names
+ private Set<String> getAllRoleNames(PersistenceManager pm) {
+ Query query = pm.newQuery(MSentryRole.class);
+ List<MSentryRole> mSentryRoles = (List<MSentryRole>) query.execute();
+ Set<String> existRoleNames = Sets.newHashSet();
+ if (mSentryRoles != null) {
+ for (MSentryRole mSentryRole : mSentryRoles) {
+ existRoleNames.add(mSentryRole.getRoleName());
+ }
+ }
+ return existRoleNames;
+ }
+
+ // get the all exist groups
+ private Map<String, MSentryGroup> getGroupNameTGroupMap(PersistenceManager pm) {
+ Query query = pm.newQuery(MSentryGroup.class);
+ List<MSentryGroup> mSentryGroups = (List<MSentryGroup>) query.execute();
+ Map<String, MSentryGroup> existGroupsMap = Maps.newHashMap();
+ if (mSentryGroups != null) {
+ // change the List<MSentryGroup> -> Map<roleName, Set<MSentryGroup>>
+ for (MSentryGroup mSentryGroup : mSentryGroups) {
+ existGroupsMap.put(mSentryGroup.getGroupName(), mSentryGroup);
+ }
+ }
+ return existGroupsMap;
+ }
+
+ // get the all exist privileges
+ private List<MSentryPrivilege> getPrivilegesList(PersistenceManager pm) {
+ Query query = pm.newQuery(MSentryPrivilege.class);
+ List<MSentryPrivilege> resultList = (List<MSentryPrivilege>) query.execute();
+ if (resultList == null) {
+ resultList = Lists.newArrayList();
+ }
+ return resultList;
+ }
+
+ @VisibleForTesting
+ protected Map<String, MSentryRole> getRolesMap() {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+
+ Query query = pm.newQuery(MSentryRole.class);
+ List<MSentryRole> mSentryRoles = (List<MSentryRole>) query.execute();
+ Map<String, MSentryRole> existRolesMap = Maps.newHashMap();
+ if (mSentryRoles != null) {
+ // change the List<MSentryRole> -> Map<roleName, Set<MSentryRole>>
+ for (MSentryRole mSentryRole : mSentryRoles) {
+ existRolesMap.put(mSentryRole.getRoleName(), mSentryRole);
+ }
+ }
+
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ return existRolesMap;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ protected Map<String, MSentryGroup> getGroupNameTGroupMap() {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Map<String, MSentryGroup> resultMap = getGroupNameTGroupMap(pm);
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ return resultMap;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ protected List<MSentryPrivilege> getPrivilegesList() {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ List<MSentryPrivilege> resultList = getPrivilegesList(pm);
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ return resultList;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ /**
+ * Import the sentry mapping data.
+ *
+ * @param tSentryMappingData
+ * 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 GroupRolesMap in TSentryMappingData will be saved as:
+ * {
+ * TSentryGroup(group1)={role1, role2},
+ * TSentryGroup(group2)={role2, role3}
+ * }
+ * The RolePrivilegesMap in TSentryMappingData will be saved as:
+ * {
+ * role1={TSentryPrivilege(server=server1->db=db1)},
+ * role2={TSentryPrivilege(server=server1->db=db1->table=tbl1),
+ * TSentryPrivilege(server=server1->db=db1->table=tbl2)},
+ * role3={TSentryPrivilege(server=server1->url=hdfs://localhost/path)}
+ * }
+ * @param isOverwriteForRole
+ * The option for merging or overwriting the existing data during import, true for
+ * overwriting, false for merging
+ */
+ public void importSentryMetaData(TSentryMappingData tSentryMappingData, boolean isOverwriteForRole)
+ throws Exception {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ // change all role name in lowercase
+ TSentryMappingData mappingData = lowercaseRoleName(tSentryMappingData);
+ try {
+ pm = openTransaction();
+ Set<String> existRoleNames = getAllRoleNames(pm);
+ //
+ Map<String, Set<TSentryGroup>> importedRoleGroupsMap = covertToRoleNameTGroupsMap(mappingData
+ .getGroupRolesMap());
+ Set<String> importedRoleNames = importedRoleGroupsMap.keySet();
+ // if import with overwrite role, drop the duplicated roles in current DB first.
+ if (isOverwriteForRole) {
+ dropDuplicatedRoleForImport(pm, existRoleNames, importedRoleNames);
+ // refresh the existRoleNames for the drop role
+ existRoleNames = getAllRoleNames(pm);
+ }
+
+ // import the mapping data for [role,privilege], the existRoleNames will be updated
+ importSentryRolePrivilegeMapping(pm, existRoleNames, mappingData.getRolePrivilegesMap());
+
+ importSentryGroupRoleMapping(pm, existRoleNames, importedRoleGroupsMap);
+
+ commitTransaction(pm);
+ rollbackTransaction = false;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ // covert the Map[group->roles] to Map[role->groups]
+ private Map<String, Set<TSentryGroup>> covertToRoleNameTGroupsMap(
+ Map<String, Set<String>> groupRolesMap) {
+ Map<String, Set<TSentryGroup>> roleGroupsMap = Maps.newHashMap();
+ if (groupRolesMap != null) {
+ for (String groupName : groupRolesMap.keySet()) {
+ Set<String> roleNames = groupRolesMap.get(groupName);
+ if (roleNames != null) {
+ for (String roleName : roleNames) {
+ Set<TSentryGroup> tSentryGroups = roleGroupsMap.get(roleName);
+ if (tSentryGroups == null) {
+ tSentryGroups = Sets.newHashSet();
+ }
+ tSentryGroups.add(new TSentryGroup(groupName));
+ roleGroupsMap.put(roleName, tSentryGroups);
+ }
+ }
+ }
+ }
+ return roleGroupsMap;
+ }
+
+ private void importSentryGroupRoleMapping(PersistenceManager pm, Set<String> existRoleNames,
+ Map<String, Set<TSentryGroup>> importedRoleGroupsMap) throws Exception {
+ if (importedRoleGroupsMap == null || importedRoleGroupsMap.keySet() == null) {
+ return;
+ }
+ for (String roleName : importedRoleGroupsMap.keySet()) {
+ if (!existRoleNames.contains(roleName)) {
+ createSentryRoleCore(pm, roleName);
+ }
+ alterSentryRoleAddGroupsCore(pm, roleName, importedRoleGroupsMap.get(roleName));
+ }
+ }
+
+ // drop all duplicated with the imported role
+ private void dropDuplicatedRoleForImport(PersistenceManager pm, Set<String> existRoleNames,
+ Set<String> importedRoleNames) throws Exception {
+ Set<String> duplicatedRoleNames = Sets.intersection(existRoleNames, importedRoleNames);
+ for (String droppedRoleName : duplicatedRoleNames) {
+ dropSentryRoleCore(pm, droppedRoleName);
+ }
+ }
+
+ // change all role name in lowercase
+ private TSentryMappingData lowercaseRoleName(TSentryMappingData tSentryMappingData) {
+ Map<String, Set<String>> sentryGroupRolesMap = tSentryMappingData.getGroupRolesMap();
+ Map<String, Set<TSentryPrivilege>> sentryRolePrivilegesMap = tSentryMappingData
+ .getRolePrivilegesMap();
+
+ Map<String, Set<String>> newSentryGroupRolesMap = Maps.newHashMap();
+ Map<String, Set<TSentryPrivilege>> newSentryRolePrivilegesMap = Maps.newHashMap();
+ // for mapping data [group,role]
+ for (String groupName : sentryGroupRolesMap.keySet()) {
+ Collection<String> lowcaseRoles = Collections2.transform(sentryGroupRolesMap.get(groupName),
+ new Function<String, String>() {
+ @Override
+ public String apply(String input) {
+ return input.toString().toLowerCase();
+ }
+ });
+ newSentryGroupRolesMap.put(groupName, Sets.newHashSet(lowcaseRoles));
+ }
+
+ // for mapping data [role,privilege]
+ for (String roleName : sentryRolePrivilegesMap.keySet()) {
+ newSentryRolePrivilegesMap.put(roleName.toLowerCase(), sentryRolePrivilegesMap.get(roleName));
+ }
+
+ tSentryMappingData.setGroupRolesMap(newSentryGroupRolesMap);
+ tSentryMappingData.setRolePrivilegesMap(newSentryRolePrivilegesMap);
+ return tSentryMappingData;
+ }
+
+ // import the mapping data for [role,privilege]
+ private void importSentryRolePrivilegeMapping(PersistenceManager pm, Set<String> existRoleNames,
+ Map<String, Set<TSentryPrivilege>> sentryRolePrivilegesMap) throws Exception {
+ if (sentryRolePrivilegesMap != null) {
+ for (String roleName : sentryRolePrivilegesMap.keySet()) {
+ // if the rolenName doesn't exist, create it.
+ if (!existRoleNames.contains(roleName)) {
+ createSentryRoleCore(pm, roleName);
+ existRoleNames.add(roleName);
+ }
+ // get the privileges for the role
+ Set<TSentryPrivilege> tSentryPrivileges = sentryRolePrivilegesMap.get(roleName);
+ for (TSentryPrivilege tSentryPrivilege : tSentryPrivileges) {
+ alterSentryRoleGrantPrivilegeCore(pm, roleName, tSentryPrivilege);
+ }
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/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 05cbfb6..9c2d384 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
@@ -178,4 +178,12 @@ public interface SentryPolicyServiceClient {
public String getConfigValue(String propertyName, String defaultValue) throws SentryUserException;
public void close();
+
+ // Import the sentry mapping data with map structure
+ public void importPolicy(Map<String, Map<String, Set<String>>> policyFileMappingData,
+ String requestorUserName, boolean isOverwriteRole) throws SentryUserException;
+
+ // export the sentry mapping data with map structure
+ public Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName)
+ throws SentryUserException;
}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/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 533a28c..09b3d99 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
@@ -27,6 +27,7 @@ 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;
@@ -38,6 +39,8 @@ import org.apache.sentry.core.common.ActiveRoleSet;
import org.apache.sentry.core.common.Authorizable;
import org.apache.sentry.core.model.db.AccessConstants;
import org.apache.sentry.core.model.db.DBModelAuthorizable;
+import org.apache.sentry.provider.common.PolicyFileConstants;
+import org.apache.sentry.service.thrift.SentryServiceUtil;
import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig;
import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope;
import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
@@ -58,6 +61,7 @@ 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;
public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyServiceClient {
@@ -816,4 +820,111 @@ public class SentryPolicyServiceClientDefaultImpl implements SentryPolicyService
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 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));
+ // 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 (String tempRoleName : rolePrivilegesMap.keySet()) {
+ Set<TSentryPrivilege> tempTSentryPrivileges = Sets.newHashSet();
+ Set<String> tempPrivileges = rolePrivilegesMap.get(tempRoleName);
+ for (String tempPrivilege : tempPrivileges) {
+ tempTSentryPrivileges.add(SentryServiceUtil.convertToTSentryPrivilege(tempPrivilege));
+ }
+ rolePrivilegesMapResult.put(tempRoleName, tempTSentryPrivileges);
+ }
+ }
+ return rolePrivilegesMapResult;
+ }
+
+ // export the sentry mapping data with map structure
+ public Map<String, Map<String, Set<String>>> exportPolicy(String requestorUserName)
+ throws SentryUserException {
+ TSentryExportMappingDataRequest request = new TSentryExportMappingDataRequest(
+ ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT, requestorUserName);
+ 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.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 (String tempRoleName : rolePrivilegesMap.keySet()) {
+ Set<TSentryPrivilege> tempSentryPrivileges = rolePrivilegesMap.get(tempRoleName);
+ 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(tempRoleName, tempStrPrivileges);
+ }
+ }
+ return rolePrivilegesMapForFile;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/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 406daa0..ea9fae9 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
@@ -857,4 +857,57 @@ public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface {
}
}
+ // get the sentry mapping data and return the data with map structure
+ @Override
+ public TSentryExportMappingDataResponse export_sentry_mapping_data(
+ TSentryExportMappingDataRequest request) throws TException {
+ TSentryExportMappingDataResponse response = new TSentryExportMappingDataResponse();
+ try {
+ String requestor = request.getRequestorUserName();
+ Set<String> memberGroups = getRequestorGroups(requestor);
+ 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());
+ response.setMappingData(tSentryMappingData);
+ response.setStatus(Status.OK());
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setMappingData(new TSentryMappingData());
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ // import the sentry mapping data
+ @Override
+ public TSentryImportMappingDataResponse import_sentry_mapping_data(
+ TSentryImportMappingDataRequest request) throws TException {
+ TSentryImportMappingDataResponse response = new TSentryImportMappingDataResponse();
+ try {
+ String requestor = request.getRequestorUserName();
+ Set<String> memberGroups = getRequestorGroups(requestor);
+ if (!inAdminGroups(memberGroups)) {
+ // disallow non-admin to import the metadata of sentry
+ throw new SentryAccessDeniedException("Access denied to " + requestor
+ + " for import the metadata of sentry.");
+ }
+ sentryStore.importSentryMetaData(request.getMappingData(), request.isOverwriteRole());
+ response.setStatus(Status.OK());
+ } catch (SentryInvalidInputException e) {
+ String msg = "Invalid input privilege object";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.InvalidInput(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/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
new file mode 100644
index 0000000..46798a0
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/service/thrift/SentryServiceUtil.java
@@ -0,0 +1,127 @@
+/**
+ * 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.service.thrift;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.provider.common.KeyValue;
+import org.apache.sentry.provider.common.PolicyFileConstants;
+import org.apache.sentry.provider.common.ProviderConstants;
+import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope;
+
+import com.google.common.collect.Lists;
+
+public class SentryServiceUtil {
+
+ // parse the privilege in String and get the TSentryPrivilege as result
+ public static TSentryPrivilege convertToTSentryPrivilege(String privilegeStr) {
+ TSentryPrivilege tSentryPrivilege = new TSentryPrivilege();
+ for (String authorizable : ProviderConstants.AUTHORIZABLE_SPLITTER.split(privilegeStr)) {
+ KeyValue tempKV = new KeyValue(authorizable);
+ String key = tempKV.getKey();
+ String value = tempKV.getValue();
+
+ if (PolicyFileConstants.PRIVILEGE_SERVER_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setServerName(value);
+ } else if (PolicyFileConstants.PRIVILEGE_DATABASE_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setDbName(value);
+ } else if (PolicyFileConstants.PRIVILEGE_TABLE_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setTableName(value);
+ } else if (PolicyFileConstants.PRIVILEGE_COLUMN_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setColumnName(value);
+ } else if (PolicyFileConstants.PRIVILEGE_URI_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setURI(value);
+ } else if (PolicyFileConstants.PRIVILEGE_ACTION_NAME.equalsIgnoreCase(key)) {
+ tSentryPrivilege.setAction(value);
+ } else if (PolicyFileConstants.PRIVILEGE_GRANT_OPTION_NAME.equalsIgnoreCase(key)) {
+ TSentryGrantOption grantOption = "true".equalsIgnoreCase(value) ? TSentryGrantOption.TRUE
+ : TSentryGrantOption.FALSE;
+ tSentryPrivilege.setGrantOption(grantOption);
+ }
+ }
+ tSentryPrivilege.setPrivilegeScope(getPrivilegeScope(tSentryPrivilege));
+ return tSentryPrivilege;
+ }
+
+ // for the different hierarchy for hive:
+ // 1: server->url
+ // 2: server->database->table->column
+ // if both of them are found in the privilege string, the privilege scope will be set as
+ // PrivilegeScope.URI
+ public static String getPrivilegeScope(TSentryPrivilege tSentryPrivilege) {
+ PrivilegeScope privilegeScope = PrivilegeScope.SERVER;
+ if (!StringUtils.isEmpty(tSentryPrivilege.getURI())) {
+ privilegeScope = PrivilegeScope.URI;
+ } else if (!StringUtils.isEmpty(tSentryPrivilege.getColumnName())) {
+ privilegeScope = PrivilegeScope.COLUMN;
+ } else if (!StringUtils.isEmpty(tSentryPrivilege.getTableName())) {
+ privilegeScope = PrivilegeScope.TABLE;
+ } else if (!StringUtils.isEmpty(tSentryPrivilege.getDbName())) {
+ privilegeScope = PrivilegeScope.DATABASE;
+ }
+ return privilegeScope.toString();
+ }
+
+ // convert TSentryPrivilege to privilege in string
+ public static String convertTSentryPrivilegeToStr(TSentryPrivilege tSentryPrivilege) {
+ List<String> privileges = Lists.newArrayList();
+ if (tSentryPrivilege != null) {
+ String serverName = tSentryPrivilege.getServerName();
+ String dbName = tSentryPrivilege.getDbName();
+ String tableName = tSentryPrivilege.getTableName();
+ String columnName = tSentryPrivilege.getColumnName();
+ String uri = tSentryPrivilege.getURI();
+ String action = tSentryPrivilege.getAction();
+ String grantOption = (tSentryPrivilege.getGrantOption() == TSentryGrantOption.TRUE ? "true"
+ : "false");
+ if (!StringUtils.isEmpty(serverName)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(PolicyFileConstants.PRIVILEGE_SERVER_NAME,
+ serverName));
+ if (!StringUtils.isEmpty(uri)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(PolicyFileConstants.PRIVILEGE_URI_NAME,
+ uri));
+ } else if (!StringUtils.isEmpty(dbName)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(
+ PolicyFileConstants.PRIVILEGE_DATABASE_NAME, dbName));
+ if (!StringUtils.isEmpty(tableName)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(
+ PolicyFileConstants.PRIVILEGE_TABLE_NAME, tableName));
+ if (!StringUtils.isEmpty(columnName)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(
+ PolicyFileConstants.PRIVILEGE_COLUMN_NAME, columnName));
+ }
+ }
+ }
+ if (!StringUtils.isEmpty(action)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(
+ PolicyFileConstants.PRIVILEGE_ACTION_NAME, action));
+ }
+ }
+ // only append the grant option to privilege string if it's true
+ if ("true".equals(grantOption)) {
+ privileges.add(ProviderConstants.KV_JOINER.join(
+ PolicyFileConstants.PRIVILEGE_GRANT_OPTION_NAME, grantOption));
+ }
+ }
+ return ProviderConstants.AUTHORIZABLE_JOINER.join(privileges);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/92cde111/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift b/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift
index 5803cc4..40889e8 100644
--- a/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift
+++ b/sentry-provider/sentry-provider-db/src/main/resources/sentry_policy_service.thrift
@@ -232,6 +232,33 @@ struct TSentryConfigValueResponse {
2: optional string value
}
+# struct for the mapping data like group to role, role to privilege
+struct TSentryMappingData {
+1: optional map<string, set<string>> groupRolesMap, # for the groupName -> role mapping
+2: optional map<string, set<TSentryPrivilege>> rolePrivilegesMap # for the roleName -> privilege mapping
+}
+
+struct TSentryExportMappingDataRequest {
+1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V1,
+2: required string requestorUserName # user on whose behalf the request is issued
+}
+
+struct TSentryExportMappingDataResponse {
+1: required sentry_common_service.TSentryResponseStatus status,
+2: required TSentryMappingData mappingData
+}
+
+struct TSentryImportMappingDataRequest {
+1: required i32 protocol_version = sentry_common_service.TSENTRY_SERVICE_V1,
+2: required string requestorUserName, # user on whose behalf the request is issued
+3: required bool overwriteRole = false, # if overwrite the exist role with the imported privileges, default is false
+4: required TSentryMappingData mappingData
+}
+
+struct TSentryImportMappingDataResponse {
+1: required sentry_common_service.TSentryResponseStatus status
+}
+
service SentryPolicyService
{
TCreateSentryRoleResponse create_sentry_role(1:TCreateSentryRoleRequest request)
@@ -250,11 +277,17 @@ service SentryPolicyService
# For use with ProviderBackend.getPrivileges only
TListSentryPrivilegesForProviderResponse list_sentry_privileges_for_provider(1:TListSentryPrivilegesForProviderRequest request)
- TDropPrivilegesResponse drop_sentry_privilege(1:TDropPrivilegesRequest request);
+ TDropPrivilegesResponse drop_sentry_privilege(1:TDropPrivilegesRequest request);
+
+ TRenamePrivilegesResponse rename_sentry_privilege(1:TRenamePrivilegesRequest request);
+
+ TListSentryPrivilegesByAuthResponse list_sentry_privileges_by_authorizable(1:TListSentryPrivilegesByAuthRequest request);
- TRenamePrivilegesResponse rename_sentry_privilege(1:TRenamePrivilegesRequest request);
+ TSentryConfigValueResponse get_sentry_config_value(1:TSentryConfigValueRequest request);
- TListSentryPrivilegesByAuthResponse list_sentry_privileges_by_authorizable(1:TListSentryPrivilegesByAuthRequest request);
+ # export the mapping data in sentry
+ TSentryExportMappingDataResponse export_sentry_mapping_data(1:TSentryExportMappingDataRequest request);
- TSentryConfigValueResponse get_sentry_config_value(1:TSentryConfigValueRequest request)
+ # import the mapping data in sentry
+ TSentryImportMappingDataResponse import_sentry_mapping_data(1:TSentryImportMappingDataRequest request);
}