From 42bbf5c583d7f2dcbeb3e23d4df26badf130b5eb Mon Sep 17 00:00:00 2001 From: prashant Date: Fri, 12 Jan 2024 17:49:19 +0530 Subject: [PATCH] RANGER-4651: update GDS objects ACL for deletion of Ranger user/group/roles Signed-off-by: Madhan Neethiraj --- .../org/apache/ranger/biz/GdsDBStore.java | 59 +++++++++++++++++++ .../org/apache/ranger/biz/RoleDBStore.java | 21 +++---- .../java/org/apache/ranger/biz/XUserMgr.java | 7 +++ .../apache/ranger/db/XXGdsDataShareDao.java | 27 +++++++++ .../org/apache/ranger/db/XXGdsDatasetDao.java | 27 +++++++++ .../org/apache/ranger/db/XXGdsProjectDao.java | 27 +++++++++ .../resources/META-INF/jpa_named_queries.xml | 15 +++++ .../apache/ranger/biz/TestRoleDBStore.java | 33 +++-------- .../org/apache/ranger/biz/TestXUserMgr.java | 3 + 9 files changed, 182 insertions(+), 37 deletions(-) diff --git a/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java index a69647948f..69b43f2dc3 100755 --- a/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java @@ -22,6 +22,7 @@ import org.apache.http.HttpStatus; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.biz.ServiceDBStore.REMOVE_REF_TYPE; import org.apache.ranger.common.*; import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter; import org.apache.ranger.db.*; @@ -1339,6 +1340,48 @@ public PList getDshInDsSummary(SearchFilter filter) { return ret; } + public void deletePrincipalFromGdsAcl(String principalType, String principalName) { + Map datsetAcls = daoMgr.getXXGdsDataset().getDatasetIdsAndACLs(); + Map dataShareAcls = daoMgr.getXXGdsDataShare().getDataShareIdsAndACLs(); + Map projectAcls = daoMgr.getXXGdsProject().getProjectIdsAndACLs(); + + for (Map.Entry entry : datsetAcls.entrySet()) { + Long id = entry.getKey(); + RangerGdsObjectACL acl = entry.getValue(); + + if (deletePrincipalFromAcl(acl, principalName, principalType) != null) { + RangerDataset dataset = datasetService.read(id); + + dataset.setAcl(acl); + datasetService.update(dataset); + } + } + + for (Map.Entry entry : dataShareAcls.entrySet()) { + Long id = entry.getKey(); + RangerGdsObjectACL acl = entry.getValue(); + + if (deletePrincipalFromAcl(acl, principalName, principalType) != null) { + RangerDataShare dataShare = dataShareService.read(id); + + dataShare.setAcl(acl); + dataShareService.update(dataShare); + } + } + + for (Map.Entry entry : projectAcls.entrySet()) { + Long id = entry.getKey(); + RangerGdsObjectACL acl = entry.getValue(); + + if (deletePrincipalFromAcl(acl, principalName, principalType) != null) { + RangerProject project = projectService.read(id); + + project.setAcl(acl); + projectService.update(project); + } + } + } + private List getDshInDsSummary(List dataShares, List datasets, RangerDataShareInDatasetList dshInDsList) { Set ret = new LinkedHashSet<>(); Map datasetMap = toMap(datasets); @@ -2136,6 +2179,22 @@ private void updateGdsVersionForDataShare(Long dataShareId) { } } + private GdsPermission deletePrincipalFromAcl(RangerGdsObjectACL acl, String principalName, String principalType) { + final Map principalAcls; + + if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.USER.toString())) { + principalAcls = acl.getUsers(); + } else if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.GROUP.toString())) { + principalAcls = acl.getGroups(); + } else if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.ROLE.toString())) { + principalAcls = acl.getRoles(); + } else { + principalAcls = null; + } + + return principalAcls != null ? principalAcls.remove(principalName) : null; + } + private void copyExistingBaseFields(RangerGdsBaseModelObject objToUpdate, RangerGdsBaseModelObject existingObj) { if (objToUpdate != null && existingObj != null) { // retain existing values for: guid, createdBy, createTime diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java index abf2b0c8c5..0aa03e7c2e 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java @@ -86,6 +86,9 @@ public class RoleDBStore implements RoleStore { @Autowired ServiceDBStore svcStore; + @Autowired + GdsDBStore gdsStore; + RangerAdminConfig config; private Boolean populateExistingBaseFields = false; @@ -200,19 +203,7 @@ public void deleteRole(String roleName) throws Exception { throw restErrorUtil.createRESTException("Role with name: " + roleName + " does not exist"); } - ensureRoleDeleteAllowed(roleName); - - Runnable roleVersionUpdater = new RoleVersionUpdater(daoMgr); - transactionSynchronizationAdapter.executeOnTransactionCommit(roleVersionUpdater); - - RangerRole role = roleService.read(xxRole.getId()); - roleRefUpdater.cleanupRefTables(role); - // delete role from audit filter configs - svcStore.updateServiceAuditConfig(role.getName(), REMOVE_REF_TYPE.ROLE); - roleService.delete(role); - - List trxLogList = roleService.getTransactionLog(role, null, "delete"); - bizUtil.createTrxLog(trxLogList); + deleteRole(xxRole.getId()); } @Override @@ -227,6 +218,10 @@ public void deleteRole(Long roleId) throws Exception { roleRefUpdater.cleanupRefTables(role); // delete role from audit filter configs svcStore.updateServiceAuditConfig(role.getName(), REMOVE_REF_TYPE.ROLE); + + // delete gdsObject mapping of role + gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.ROLE.toString(), role.getName()); + roleService.delete(role); List trxLogList = roleService.getTransactionLog(role, null, "delete"); bizUtil.createTrxLog(trxLogList); diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java index d961bc50c6..2874002595 100755 --- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java @@ -165,6 +165,9 @@ public class XUserMgr extends XUserMgrBase { @Autowired RangerTransactionSynchronizationAdapter transactionSynchronizationAdapter; + @Autowired + GdsDBStore gdsStore; + @Autowired @Qualifier(value = "transactionManager") PlatformTransactionManager txManager; @@ -2169,6 +2172,8 @@ public void deleteXGroup(Long id, boolean force) { } //delete group from audit filter configs svcStore.updateServiceAuditConfig(vXGroup.getName(), REMOVE_REF_TYPE.GROUP); + // delete group from dataset,datashare,project + gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.GROUP.toString(), vXGroup.getName()); //delete XXGroup xXGroupDao.remove(id); //Create XXTrxLog @@ -2396,6 +2401,8 @@ public synchronized void deleteXUser(Long id, boolean force) { } //delete user from audit filter configs svcStore.updateServiceAuditConfig(vXUser.getName(), REMOVE_REF_TYPE.USER); + //delete gdsObject mapping of user + gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.USER.toString(),vXUser.getName()); //delete XXUser entry of user xXUserDao.remove(id); //delete XXPortal entry of user diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java index 8acca8f895..20084bcfbc 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java @@ -20,15 +20,19 @@ package org.apache.ranger.db; import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXGdsDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Service @@ -144,4 +148,27 @@ public List findServiceIdsForDataShareId(Long dataShareId) { return ret != null ? ret : Collections.emptyList(); } + + public Map getDataShareIdsAndACLs() { + Map ret = new HashMap<>(); + + try { + List rows = getEntityManager().createNamedQuery("XXGdsDataShare.getDataShareIdsAndACLs", Object[].class).getResultList(); + + if (rows != null) { + for (Object[] row : rows) { + Long id = (Long) row[0]; + RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class); + + if (acl != null) { + ret.put(id, acl); + } + } + } + } catch (NoResultException e) { + LOG.debug("getDataShareIdsAndACLs()", e); + } + + return ret; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java index 5743ad702a..4661b41187 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java @@ -20,6 +20,7 @@ package org.apache.ranger.db; import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXGdsDataset; import org.slf4j.Logger; @@ -28,8 +29,11 @@ import javax.persistence.NoResultException; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL; @Service public class XXGdsDatasetDao extends BaseDao { @@ -113,4 +117,27 @@ public List findServiceIdsForDataset(Long datasetId) { return ret != null ? ret : Collections.emptyList(); } + + public Map getDatasetIdsAndACLs() { + Map ret = new HashMap<>(); + + try { + List rows = getEntityManager().createNamedQuery("XXGdsDataset.getDatasetIdsAndACLs", Object[].class).getResultList(); + + if (rows != null) { + for (Object[] row : rows) { + Long id = (Long) row[0]; + RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class); + + if (acl != null) { + ret.put(id, acl); + } + } + } + } catch (NoResultException e) { + LOG.debug("getDatasetIdsAndACLs()", e); + } + + return ret; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java index 76bab86115..ba8f6c66ab 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java @@ -20,15 +20,19 @@ package org.apache.ranger.db; import org.apache.commons.lang.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXGdsProject; +import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.persistence.NoResultException; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Service @@ -98,4 +102,27 @@ public List findServiceIdsForProject(Long projectId) { return ret != null ? ret : Collections.emptyList(); } + + public Map getProjectIdsAndACLs() { + Map ret = new HashMap<>(); + + try { + List rows = getEntityManager().createNamedQuery("XXGdsProject.getProjectIdsAndACLs", Object[].class).getResultList(); + + if (rows != null) { + for (Object[] row : rows) { + Long id = (Long) row[0]; + RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class); + + if (acl != null) { + ret.put(id, acl); + } + } + } + } catch (NoResultException e) { + LOG.debug("getProjectIdsAndACLs()", e); + } + + return ret; + } } diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml index 52ecf8a3ea..b3557d5aea 100755 --- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml +++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml @@ -2178,6 +2178,11 @@ + + select obj.id, obj.acl from XXGdsDataset obj where obj.id is NOT null + + + select obj from XXGdsProject obj where obj.guid = :guid @@ -2200,6 +2205,11 @@ + + select obj.id, obj.acl from XXGdsProject obj where obj.id is NOT null + + + select obj from XXGdsDataShare obj where obj.guid = :guid @@ -2227,6 +2237,11 @@ + + select obj.id, obj.acl from XXGdsDataShare obj where obj.id is NOT null + + + select obj from XXGdsSharedResource obj where obj.guid = :guid diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java index 6d340f25ad..6df1f73695 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java @@ -77,6 +77,9 @@ public class TestRoleDBStore { @InjectMocks RoleDBStore roleDBStore = new RoleDBStore(); + @Mock + GdsDBStore gdsStore; + @Mock RangerBizUtil bizUtil; @@ -482,14 +485,11 @@ public void testDeleteRoleByRoleId() throws Exception { @Test public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMorePolices() throws Exception { - XXRole xxRole = getTestRole(); - XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); - XXPolicyRefRoleDao xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class); + XXRole xxRole = getTestRole(); + XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole); - Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao); Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao); - Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(1L); thrown.expect(Exception.class); roleDBStore.deleteRole(roleName); @@ -497,17 +497,11 @@ public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMorePolice @Test public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMoreRoles() throws Exception { - XXRole xxRole = getTestRole(); - XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); - XXPolicyRefRoleDao xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class); - XXRoleRefRoleDao xxRoleRefRoleDao = Mockito.mock(XXRoleRefRoleDao.class); + XXRole xxRole = getTestRole(); + XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao); Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole); - Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao); - Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(0L); - Mockito.when(daoMgr.getXXRoleRefRole()).thenReturn(xxRoleRefRoleDao); - Mockito.when(xxRoleRefRoleDao.findRoleRefRoleCount(roleName)).thenReturn(1L); thrown.expect(Exception.class); roleDBStore.deleteRole(roleName); @@ -515,20 +509,11 @@ public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMoreRoles( @Test public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMoreSecurityZones() throws Exception { - XXRole xxRole = getTestRole(); - XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); - XXPolicyRefRoleDao xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class); - XXRoleRefRoleDao xxRoleRefRoleDao = Mockito.mock(XXRoleRefRoleDao.class); - XXSecurityZoneRefRoleDao xxSzRefRoleDao = Mockito.mock(XXSecurityZoneRefRoleDao.class); + XXRole xxRole = getTestRole(); + XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class); Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao); Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole); - Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao); - Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(0L); - Mockito.when(daoMgr.getXXRoleRefRole()).thenReturn(xxRoleRefRoleDao); - Mockito.when(xxRoleRefRoleDao.findRoleRefRoleCount(roleName)).thenReturn(0L); - Mockito.when(daoMgr.getXXSecurityZoneRefRole()).thenReturn(xxSzRefRoleDao); - Mockito.when(xxSzRefRoleDao.findRoleRefZoneCount(roleName)).thenReturn(1L); thrown.expect(Exception.class); roleDBStore.deleteRole(roleName); diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java index 601dbe9185..ce48c82798 100644 --- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java +++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java @@ -219,6 +219,9 @@ public class TestXUserMgr { @Mock ServiceDBStore svcStore; + @Mock + GdsDBStore gdsStore; + @Mock XGroupGroupService xGroupGroupService;