RANGER-3846: Ranger DB patch 058 failing when multiple policies having same resourceSignature
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
index 238fecd..e94c37f 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyRetriever.java
@@ -343,7 +343,7 @@
ret = userScreenNames.get(userId);
if(ret == null) {
- XXPortalUser user = daoMgr.getXXPortalUser().getById(userId);
+ XXPortalUser user = daoMgr.getXXPortalUser().findById(userId);
if(user != null) {
ret = user.getPublicScreenName();
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
index 4677c37..dc58be3 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
@@ -18,7 +18,9 @@
package org.apache.ranger.db;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.persistence.NoResultException;
@@ -356,4 +358,34 @@
}
return ret;
}
+
+ public Map<String, Long> findDuplicatePoliciesByServiceAndResourceSignature() {
+ Map<String, Long> policies = new HashMap<String, Long>();
+ try {
+ List<Object[]> rows = (List<Object[]>) getEntityManager().createNamedQuery("XXPolicy.findDuplicatePoliciesByServiceAndResourceSignature").getResultList();
+ if (rows != null) {
+ for (Object[] row : rows) {
+ policies.put((String) row[0], (Long) row[1]);
+ }
+ }
+ } catch (NoResultException e) {
+ return null;
+ } catch (Exception ex) {
+ }
+ return policies;
+ }
+
+ public List<XXPolicy> findByServiceIdAndResourceSignature(Long serviceId, String policySignature) {
+ if (policySignature == null || serviceId == null) {
+ return new ArrayList<XXPolicy>();
+ }
+ try {
+ return getEntityManager().createNamedQuery("XXPolicy.findByServiceIdAndResourceSignature", tClass)
+ .setParameter("serviceId", serviceId)
+ .setParameter("resSignature", policySignature)
+ .getResultList();
+ } catch (NoResultException e) {
+ return new ArrayList<XXPolicy>();
+ }
+ }
}
\ No newline at end of file
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
index 8d15a32..1787eea 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPortalUserDao.java
@@ -128,4 +128,25 @@
return null;
}
}
+
+ public XXPortalUser findById(Long id) {
+ XXPortalUser xXPortalUser = null;
+ if (id == null) {
+ return xXPortalUser;
+ }
+ try {
+ xXPortalUser = new XXPortalUser();
+ Object[] row = (Object[]) getEntityManager().createNamedQuery("XXPortalUser.findById").setParameter("id", id).getSingleResult();
+ if (row != null) {
+ xXPortalUser.setFirstName((String) row[0]);
+ xXPortalUser.setLastName((String) row[1]);
+ xXPortalUser.setPublicScreenName((String) row[2]);
+ xXPortalUser.setLoginId((String) row[3]);
+ return xXPortalUser;
+ }
+ } catch (NoResultException e) {
+ return null;
+ }
+ return xXPortalUser;
+ }
}
diff --git a/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java b/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
index 0227298..fb7e5fd 100644
--- a/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
+++ b/security-admin/src/main/java/org/apache/ranger/patch/PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053.java
@@ -17,14 +17,18 @@
package org.apache.ranger.patch;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ranger.authorization.utils.JsonUtils;
import org.apache.ranger.biz.ServiceDBStore;
import org.apache.ranger.common.RangerFactory;
import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXPolicyLabelMapDao;
import org.apache.ranger.entity.XXPolicy;
+import org.apache.ranger.entity.XXPolicyLabelMap;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
import org.apache.ranger.util.CLIUtil;
@@ -89,6 +93,7 @@
try {
updateDisabledPolicyResourceSignature();
+ removeDuplicateResourceSignaturesPolicies();
} catch (Exception e) {
logger.error("Error while PatchPreSql_058_ForUpdateToUniqueResoureceSignature_J10053()", e);
System.exit(1);
@@ -128,4 +133,49 @@
}
}
+ private void removeDuplicateResourceSignaturesPolicies() throws Exception {
+ logger.info("==> removeDuplicateResourceSignaturesPolicies() ");
+ Map<String, Long> duplicateEntries = daoMgr.getXXPolicy().findDuplicatePoliciesByServiceAndResourceSignature();
+ if (duplicateEntries != null && duplicateEntries.size() > 0) {
+ logger.info("Total number of possible duplicate policies:" + duplicateEntries.size());
+ for (Map.Entry<String, Long> entry : duplicateEntries.entrySet()) {
+ logger.info("Duplicate policy Entry - {ResourceSignature:" + entry.getKey() + ", ServiceId:" + entry.getValue() + "}");
+ List<XXPolicy> xxPolicyList = daoMgr.getXXPolicy().findByServiceIdAndResourceSignature(entry.getValue(), entry.getKey());
+ if (CollectionUtils.isNotEmpty(xxPolicyList) && xxPolicyList.size() > 1) {
+ Iterator<XXPolicy> duplicatePolicies = xxPolicyList.iterator();
+ duplicatePolicies.next();
+ while (duplicatePolicies.hasNext()) {
+ XXPolicy xxPolicy = duplicatePolicies.next();
+ if (xxPolicy != null) {
+ logger.info("Attempting to Remove duplicate policy:{" + xxPolicy.getId() + ":" + xxPolicy.getName() + "}");
+ if (cleanupRefTables(xxPolicy.getId())) {
+ daoMgr.getXXPolicy().remove(xxPolicy.getId());
+ }
+ }
+ }
+ }
+ }
+ } else {
+ logger.info("no duplicate Policy found");
+ }
+ }
+
+ private Boolean cleanupRefTables(Long policyId) {
+ if (policyId == null) {
+ return false;
+ }
+ daoMgr.getXXPolicyRefResource().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefRole().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefGroup().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefUser().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefAccessType().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefCondition().deleteByPolicyId(policyId);
+ daoMgr.getXXPolicyRefDataMaskType().deleteByPolicyId(policyId);
+ XXPolicyLabelMapDao policyLabelMapDao = daoMgr.getXXPolicyLabelMap();
+ List<XXPolicyLabelMap> xxPolicyLabelMaps = policyLabelMapDao.findByPolicyId(policyId);
+ for (XXPolicyLabelMap xxPolicyLabelMap : xxPolicyLabelMaps) {
+ policyLabelMapDao.remove(xxPolicyLabelMap);
+ }
+ return true;
+ }
}
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 7e69cc4..e4a2354 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
@@ -418,6 +418,14 @@
<query>select obj from XXPolicy obj, XXService svc, XXSecurityZone zone where obj.guid = :guid and obj.service = svc.id and svc.name = :serviceName and obj.zoneId = zone.id and zone.name = :zoneName</query>
</named-query>
+ <named-query name="XXPolicy.findDuplicatePoliciesByServiceAndResourceSignature">
+ <query>select obj.resourceSignature, obj.service from XXPolicy obj GROUP BY obj.resourceSignature, obj.service HAVING COUNT(obj.resourceSignature) > 1</query>
+ </named-query>
+
+ <named-query name="XXPolicy.findByServiceIdAndResourceSignature">
+ <query>select obj from XXPolicy obj where obj.service = :serviceId and obj.resourceSignature = :resSignature</query>
+ </named-query>
+
<!-- XXServiceDef -->
<named-query name="XXServiceDef.findByName">
<query>select obj from XXServiceDef obj where obj.name = :name</query>
@@ -1192,6 +1200,10 @@
<query>SELECT obj FROM XXPortalUser obj WHERE obj.userSource=:userSource and obj.status=:status</query>
</named-query>
+ <named-query name="XXPortalUser.findById">
+ <query>SELECT obj.firstName, obj.lastName, obj.publicScreenName, obj.loginId FROM XXPortalUser obj WHERE obj.id=:id</query>
+ </named-query>
+
<!-- VXModuleDef -->
<named-query name="XXModuleDef.findByModuleId">
<query>SELECT obj FROM XXModuleDef obj