This is an automated email from the ASF dual-hosted git repository. dhavalshah9131 pushed a commit to branch RANGER-5199 in repository https://gitbox.apache.org/repos/asf/ranger.git
commit f8f0721684d5091d7a04d12bd4d30d605ae8b423 Author: Radhika Kundam <radhika.kun...@gmail.com> AuthorDate: Fri May 9 19:28:03 2025 -0700 RANGER-5170: enhanced GDS admin audits to record the changes on impacted objects as well Signed-off-by: Madhan Neethiraj <mad...@apache.org> --- .../main/java/org/apache/ranger/biz/AssetMgr.java | 133 ++++++++++++++++-- .../java/org/apache/ranger/db/XXGdsDatasetDao.java | 17 +++ .../apache/ranger/db/XXGdsDatasetPolicyMapDao.java | 16 +++ .../java/org/apache/ranger/db/XXGdsProjectDao.java | 29 ++++ .../apache/ranger/db/XXGdsProjectPolicyMapDao.java | 16 +++ .../java/org/apache/ranger/rest/AssetREST.java | 45 ++++-- .../ranger/service/RangerAuditedModelService.java | 152 +++++++++++++++++++-- .../main/resources/META-INF/jpa_named_queries.xml | 32 +++++ .../java/org/apache/ranger/rest/TestAssetREST.java | 37 +++++ 9 files changed, 447 insertions(+), 30 deletions(-) diff --git a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java index ec39448f3..919e2d656 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/AssetMgr.java @@ -67,6 +67,7 @@ import org.apache.ranger.view.VXTrxLogV2; import org.apache.ranger.view.VXTrxLogV2.AttributeChangeInfo; import org.apache.ranger.view.VXTrxLogV2.ObjectChangeInfo; +import org.apache.ranger.view.VXTrxLogV2List; import org.apache.ranger.view.VXUgsyncAuditInfoList; import org.apache.ranger.view.VXUser; import org.slf4j.Logger; @@ -84,6 +85,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -606,6 +608,46 @@ public void createPluginInfo(String serviceName, String pluginId, HttpServletReq } public VXTrxLogList getReportLogs(SearchCriteria searchCriteria) { + VXTrxLogList ret; + PList<VXTrxLogV2> vXTrxLogsV2 = getVXTrxLogsV2(searchCriteria); + List<VXTrxLog> vxTrxLogs = vXTrxLogsV2.getList().stream().map(VXTrxLogV2::toVXTrxLog).collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(vxTrxLogs)) { + ret = new VXTrxLogList(Collections.emptyList()); + } else { + ret = new VXTrxLogList(validateXXTrxLogList(vxTrxLogs)); + + ret.setStartIndex(vXTrxLogsV2.getStartIndex()); + ret.setPageSize(vXTrxLogsV2.getPageSize()); + ret.setTotalCount(vXTrxLogsV2.getTotalCount()); + ret.setResultSize(vXTrxLogsV2.getResultSize()); + ret.setSortBy(vXTrxLogsV2.getSortBy()); + ret.setSortType(vXTrxLogsV2.getSortType()); + } + + return ret; + } + + public VXTrxLogV2List getReportLogsV2(SearchCriteria searchCriteria) { + VXTrxLogV2List ret; + PList<VXTrxLogV2> vXTrxLogsV2 = getVXTrxLogsV2(searchCriteria); + + if (vXTrxLogsV2 == null || CollectionUtils.isEmpty(vXTrxLogsV2.getList())) { + ret = new VXTrxLogV2List(Collections.emptyList()); + } else { + ret = new VXTrxLogV2List(validateXXTrxLogV2List(vXTrxLogsV2.getList())); + + ret.setStartIndex(vXTrxLogsV2.getStartIndex()); + ret.setPageSize(vXTrxLogsV2.getPageSize()); + ret.setTotalCount(vXTrxLogsV2.getTotalCount()); + ret.setResultSize(vXTrxLogsV2.getResultSize()); + ret.setSortBy(vXTrxLogsV2.getSortBy()); + ret.setSortType(vXTrxLogsV2.getSortType()); + } + return ret; + } + + public PList<VXTrxLogV2> getVXTrxLogsV2(SearchCriteria searchCriteria) { if (xaBizUtil.isAdmin() || xaBizUtil.isKeyAdmin() || xaBizUtil.isAuditAdmin() || xaBizUtil.isAuditKeyAdmin()) { if (searchCriteria == null) { searchCriteria = new SearchCriteria(); @@ -646,18 +688,7 @@ public VXTrxLogList getReportLogs(SearchCriteria searchCriteria) { searchCriteria.setGetCount(true); - PList<VXTrxLogV2> vXTrxLogsV2 = xTrxLogService.searchTrxLogs(searchCriteria); - List<VXTrxLog> vxTrxLogs = vXTrxLogsV2.getList().stream().map(VXTrxLogV2::toVXTrxLog).collect(Collectors.toList()); - VXTrxLogList ret = new VXTrxLogList(validateXXTrxLogList(vxTrxLogs)); - - ret.setStartIndex(vXTrxLogsV2.getStartIndex()); - ret.setPageSize(vXTrxLogsV2.getPageSize()); - ret.setTotalCount(vXTrxLogsV2.getTotalCount()); - ret.setResultSize(vXTrxLogsV2.getResultSize()); - ret.setSortBy(vXTrxLogsV2.getSortBy()); - ret.setSortType(vXTrxLogsV2.getSortType()); - - return ret; + return xTrxLogService.searchTrxLogs(searchCriteria); } else { throw restErrorUtil.create403RESTException("Permission Denied !"); } @@ -835,6 +866,84 @@ public List<VXTrxLog> validateXXTrxLogList(List<VXTrxLog> xTrxLogList) { return vXTrxLogs; } + public VXTrxLogV2List getTransactionReportV2(String transactionId) { + List<VXTrxLogV2> trxLogsV2 = xTrxLogService.findByTransactionId(transactionId); + + return new VXTrxLogV2List(validateXXTrxLogV2List(trxLogsV2)); + } + + public List<VXTrxLogV2> validateXXTrxLogV2List(List<VXTrxLogV2> xTrxLogV2List) { + List<VXTrxLogV2> vXTrxLogV2s = new ArrayList<>(); + + for (VXTrxLogV2 vXTrxLogV2 : xTrxLogV2List) { + ObjectChangeInfo objectChangeInfo = vXTrxLogV2.getChangeInfo(); + List<AttributeChangeInfo> attrChanges = (objectChangeInfo == null || objectChangeInfo.getAttributes() == null) ? Collections.emptyList() : objectChangeInfo.getAttributes(); + + for (AttributeChangeInfo attrChangeInfo : attrChanges) { + if (attrChangeInfo.getOldValue() == null || "null".equalsIgnoreCase(attrChangeInfo.getOldValue())) { + attrChangeInfo.setOldValue(""); + } + + if (attrChangeInfo.getNewValue() == null || "null".equalsIgnoreCase(attrChangeInfo.getNewValue())) { + attrChangeInfo.setNewValue(""); + } + + if ("Password".equalsIgnoreCase(attrChangeInfo.getAttributeName())) { + attrChangeInfo.setOldValue("*********"); + attrChangeInfo.setNewValue("***********"); + } + + if ("Connection Configurations".equalsIgnoreCase(attrChangeInfo.getAttributeName())) { + if (attrChangeInfo.getOldValue() != null && attrChangeInfo.getOldValue().contains("password")) { + String tempPreviousStr = attrChangeInfo.getOldValue(); + String[] tempPreviousArr = attrChangeInfo.getOldValue().split(","); + + for (String tempPrevious : tempPreviousArr) { + if (tempPrevious.contains("{\"password") && tempPrevious.contains("}")) { + attrChangeInfo.setOldValue(tempPreviousStr.replace(tempPrevious, "{\"password\":\"*****\"}")); + break; + } else if (tempPrevious.contains("{\"password")) { + attrChangeInfo.setOldValue(tempPreviousStr.replace(tempPrevious, "{\"password\":\"*****\"")); + break; + } else if (tempPrevious.contains("\"password") && tempPrevious.contains("}")) { + attrChangeInfo.setOldValue(tempPreviousStr.replace(tempPrevious, "\"password\":\"******\"}")); + break; + } else if (tempPrevious.contains("\"password")) { + attrChangeInfo.setOldValue(tempPreviousStr.replace(tempPrevious, "\"password\":\"******\"")); + break; + } + } + } + + if (attrChangeInfo.getNewValue() != null && attrChangeInfo.getNewValue().contains("password")) { + String tempNewStr = attrChangeInfo.getNewValue(); + String[] tempNewArr = attrChangeInfo.getNewValue().split(","); + + for (String tempNew : tempNewArr) { + if (tempNew.contains("{\"password") && tempNew.contains("}")) { + attrChangeInfo.setNewValue(tempNewStr.replace(tempNew, "{\"password\":\"*****\"}")); + break; + } else if (tempNew.contains("{\"password")) { + attrChangeInfo.setNewValue(tempNewStr.replace(tempNew, "{\"password\":\"*****\"")); + break; + } else if (tempNew.contains("\"password") && tempNew.contains("}")) { + attrChangeInfo.setNewValue(tempNewStr.replace(tempNew, "\"password\":\"******\"}")); + break; + } else if (tempNew.contains("\"password")) { + attrChangeInfo.setNewValue(tempNewStr.replace(tempNew, "\"password\":\"******\"")); + break; + } + } + } + } + } + + vXTrxLogV2s.add(vXTrxLogV2); + } + + return vXTrxLogV2s; + } + /* * (non-Javadoc) * 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 b0dbef3e8..668389b25 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 @@ -23,6 +23,7 @@ import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.db.BaseDao; import org.apache.ranger.entity.XXGdsDataset; +import org.apache.ranger.plugin.model.RangerGds.GdsShareStatus; import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,6 +89,22 @@ public List<XXGdsDataset> findByDataShareId(Long dataShareId) { return ret != null ? ret : Collections.emptyList(); } + public List<XXGdsDataset> findDatasetsWithDataShareInStatus(Long dataShareId, GdsShareStatus shareStatus) { + List<XXGdsDataset> ret = null; + + if (dataShareId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDataset.findDatasetsWithDataShareInStatus", tClass) + .setParameter("dataShareId", dataShareId) + .setParameter("status", shareStatus.ordinal()).getResultList(); + } catch (NoResultException e) { + LOG.debug("findDatasetsWithActiveDataShare({}): ", dataShareId, e); + } + } + + return ret != null ? ret : Collections.emptyList(); + } + public List<XXGdsDataset> findByProjectId(Long projectId) { List<XXGdsDataset> ret = null; diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetPolicyMapDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetPolicyMapDao.java index b1ff36ad0..0a98ee797 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetPolicyMapDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetPolicyMapDao.java @@ -82,4 +82,20 @@ public List<Long> getDatasetPolicyIds(Long datasetId) { return ret; } + + public Long getDatasetIdForPolicy(Long policyId) { + Long ret = null; + + if (policyId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsDatasetPolicyMap.getDatasetIdForPolicy", Long.class) + .setParameter("policyId", policyId) + .getSingleResult(); + } catch (NoResultException e) { + // ignore + } + } + + 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 a005519e7..1ed7259eb 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 @@ -23,6 +23,7 @@ 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; import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,6 +89,34 @@ public List<XXGdsProject> findByDatasetId(Long datasetId) { return ret != null ? ret : Collections.emptyList(); } + public List<XXGdsProject> findProjectsWithDatasetInStatus(Long datasetId, RangerGds.GdsShareStatus shareStatus) { + List<XXGdsProject> ret = null; + + try { + ret = getEntityManager().createNamedQuery("XXGdsProject.findProjectsWithDatasetInStatus", tClass) + .setParameter("datasetId", datasetId) + .setParameter("status", shareStatus.ordinal()).getResultList(); + } catch (NoResultException e) { + LOG.debug("findProjectsWithDatasetInStatus({}): ", datasetId, e); + } + + return ret != null ? ret : Collections.emptyList(); + } + + public List<XXGdsProject> findProjectsWithDataShareInStatus(Long dataShareId, RangerGds.GdsShareStatus shareStatus) { + List<XXGdsProject> ret = null; + + try { + ret = getEntityManager().createNamedQuery("XXGdsProject.findProjectsWithDataShareInStatus", tClass) + .setParameter("dataShareId", dataShareId) + .setParameter("status", shareStatus.ordinal()).getResultList(); + } catch (NoResultException e) { + LOG.debug("findProjectsWithDataShareInStatus({}): ", dataShareId, e); + } + + return ret != null ? ret : Collections.emptyList(); + } + public List<Long> findServiceIdsForProject(Long projectId) { List<Long> ret = null; diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectPolicyMapDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectPolicyMapDao.java index b3529e840..694e0cc8a 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectPolicyMapDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectPolicyMapDao.java @@ -82,4 +82,20 @@ public List<Long> getProjectPolicyIds(Long projectId) { return ret; } + + public Long getProjectIdForPolicy(Long policyId) { + Long ret = null; + + if (policyId != null) { + try { + ret = getEntityManager().createNamedQuery("XXGdsProjectPolicyMap.getProjectIdForPolicy", Long.class) + .setParameter("policyId", policyId) + .getSingleResult(); + } catch (NoResultException e) { + // ignore + } + } + + return ret; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/rest/AssetREST.java b/security-admin/src/main/java/org/apache/ranger/rest/AssetREST.java index d29e44eff..46ee557c1 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/AssetREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/AssetREST.java @@ -58,6 +58,7 @@ import org.apache.ranger.view.VXResourceList; import org.apache.ranger.view.VXResponse; import org.apache.ranger.view.VXTrxLogList; +import org.apache.ranger.view.VXTrxLogV2List; import org.apache.ranger.view.VXUgsyncAuditInfoList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -504,20 +505,21 @@ public VXPolicyExportAuditList searchXPolicyExportAudits(@Context HttpServletReq @Produces("application/json") @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_REPORT_LOGS + "\")") public VXTrxLogList getReportLogs(@Context HttpServletRequest request) { - SearchCriteria searchCriteria = searchUtil.extractCommonCriterias(request, xTrxLogService.getSortFields()); - - searchUtil.extractInt(request, searchCriteria, "objectClassType", "audit type."); - searchUtil.extractInt(request, searchCriteria, "objectId", "Object ID"); - searchUtil.extractString(request, searchCriteria, "attributeName", "Attribute Name", StringUtil.VALIDATION_TEXT); - searchUtil.extractString(request, searchCriteria, "action", "CRUD Action Type", StringUtil.VALIDATION_TEXT); - searchUtil.extractString(request, searchCriteria, "sessionId", "Session Id", StringUtil.VALIDATION_TEXT); - searchUtil.extractString(request, searchCriteria, "owner", "Owner", StringUtil.VALIDATION_TEXT); - searchUtil.extractDate(request, searchCriteria, "startDate", "Trasaction date since", "MM/dd/yyyy"); - searchUtil.extractDate(request, searchCriteria, "endDate", "Trasaction date till", "MM/dd/yyyy"); + SearchCriteria searchCriteria = extractSearchCriteriaFrom(request); return assetMgr.getReportLogs(searchCriteria); } + @GET + @Path("/v2/report") + @Produces("application/json") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_REPORT_LOGS + "\")") + public VXTrxLogV2List getReportLogsV2(@Context HttpServletRequest request) { + SearchCriteria searchCriteria = extractSearchCriteriaFrom(request); + + return assetMgr.getReportLogsV2(searchCriteria); + } + @GET @Path("/report/{transactionId}") @Produces("application/json") @@ -526,6 +528,14 @@ public VXTrxLogList getTransactionReport(@Context HttpServletRequest request, @P return assetMgr.getTransactionReport(transactionId); } + @GET + @Path("/v2/report/{transactionId}") + @Produces("application/json") + @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_TRANSACTION_REPORT + "\")") + public VXTrxLogV2List getTransactionReportV2(@Context HttpServletRequest request, @PathParam("transactionId") String transactionId) { + return assetMgr.getTransactionReportV2(transactionId); + } + @GET @Path("/accessAudit") @Produces("application/json") @@ -683,4 +693,19 @@ public VXUgsyncAuditInfoList getUgsyncAudits(@Context HttpServletRequest request public VXUgsyncAuditInfoList getUgsyncAuditsBySyncSource(@PathParam("syncSource") String syncSource) { return assetMgr.getUgsyncAuditsBySyncSource(syncSource); } + + private SearchCriteria extractSearchCriteriaFrom(HttpServletRequest request) { + SearchCriteria searchCriteria = searchUtil.extractCommonCriterias(request, xTrxLogService.getSortFields()); + + searchUtil.extractInt(request, searchCriteria, "objectClassType", "audit type."); + searchUtil.extractInt(request, searchCriteria, "objectId", "Object ID"); + searchUtil.extractString(request, searchCriteria, "attributeName", "Attribute Name", StringUtil.VALIDATION_TEXT); + searchUtil.extractString(request, searchCriteria, "action", "CRUD Action Type", StringUtil.VALIDATION_TEXT); + searchUtil.extractString(request, searchCriteria, "sessionId", "Session Id", StringUtil.VALIDATION_TEXT); + searchUtil.extractString(request, searchCriteria, "owner", "Owner", StringUtil.VALIDATION_TEXT); + searchUtil.extractDate(request, searchCriteria, "startDate", "Trasaction date since", "MM/dd/yyyy"); + searchUtil.extractDate(request, searchCriteria, "endDate", "Trasaction date till", "MM/dd/yyyy"); + + return searchCriteria; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerAuditedModelService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerAuditedModelService.java index edf514b1f..888b470ab 100755 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerAuditedModelService.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerAuditedModelService.java @@ -17,12 +17,24 @@ package org.apache.ranger.service; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.ranger.authorization.utils.JsonUtils; import org.apache.ranger.common.PropertiesUtil; import org.apache.ranger.common.view.VTrxLogAttr; import org.apache.ranger.entity.XXDBBase; +import org.apache.ranger.entity.XXGdsDataset; +import org.apache.ranger.entity.XXGdsProject; import org.apache.ranger.entity.XXTrxLogV2; import org.apache.ranger.plugin.model.RangerBaseModelObject; +import org.apache.ranger.plugin.model.RangerGds; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShare; +import org.apache.ranger.plugin.model.RangerGds.RangerDataShareInDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDataset; +import org.apache.ranger.plugin.model.RangerGds.RangerDatasetInProject; +import org.apache.ranger.plugin.model.RangerGds.RangerProject; +import org.apache.ranger.plugin.model.RangerGds.RangerSharedResource; +import org.apache.ranger.plugin.model.RangerPolicy; import org.apache.ranger.plugin.util.JsonUtilsV2; import org.apache.ranger.util.RangerEnumUtil; import org.apache.ranger.view.VXTrxLogV2.ObjectChangeInfo; @@ -51,6 +63,15 @@ public abstract class RangerAuditedModelService<T extends XXDBBase, V extends Ra @Autowired RangerDataHistService dataHistService; + @Autowired + RangerGdsDatasetService datasetService; + + @Autowired + RangerGdsDataShareService dataShareService; + + @Autowired + RangerGdsProjectService projectService; + @Autowired RangerEnumUtil xaEnumUtil; @@ -124,10 +145,10 @@ public void createTransactionLog(XXTrxLogV2 trxLog) { } public void createTransactionLog(V obj, V oldObj, int action) { - List<XXTrxLogV2> trxLogs = getTransactionLogs(obj, oldObj, action); + List<List<XXTrxLogV2>> trxLogs = getTransactionLogs(obj, oldObj, action); - if (trxLogs != null) { - bizUtil.createTrxLog(trxLogs); + for (List<XXTrxLogV2> trxLog : trxLogs) { + bizUtil.createTrxLog(trxLog); } } @@ -151,12 +172,12 @@ public String getTrxLogAttrValue(V obj, VTrxLogAttr trxLogAttr) { return trxLogAttr.getAttrValue(obj, xaEnumUtil); } - private List<XXTrxLogV2> getTransactionLogs(V obj, V oldObj, int action) { + private List<List<XXTrxLogV2>> getTransactionLogs(V obj, V oldObj, int action) { if (obj == null || (action == OPERATION_UPDATE_CONTEXT && oldObj == null)) { - return null; + return Collections.emptyList(); } - List<XXTrxLogV2> ret = new ArrayList<>(); + List<List<XXTrxLogV2>> ret = new ArrayList<>(); try { ObjectChangeInfo objChangeInfo = new ObjectChangeInfo(); @@ -165,9 +186,11 @@ private List<XXTrxLogV2> getTransactionLogs(V obj, V oldObj, int action) { processFieldToCreateTrxLog(trxLog, obj, oldObj, action, objChangeInfo); } - if (objChangeInfo.getAttributes() != null && !objChangeInfo.getAttributes().isEmpty()) { - ret.add(new XXTrxLogV2(classType, obj.getId(), getObjectName(obj), getParentObjectType(obj, oldObj), getParentObjectId(obj, oldObj), getParentObjectName(obj, oldObj), toActionString(action), JsonUtilsV2.objToJson(objChangeInfo))); + if (CollectionUtils.isNotEmpty(objChangeInfo.getAttributes())) { + addXXTrxLogV2(obj, oldObj, action, objChangeInfo, ret); } + + addTransactionLogsOnImpactedObjects(obj, oldObj, action, objChangeInfo, ret); } catch (Exception excp) { LOG.warn("failed to get transaction log for object: type={}, id={}", obj.getClass().getName(), obj.getId(), excp); } @@ -246,4 +269,117 @@ private String toActionString(int action) { return "unknown"; } + + protected void addXXTrxLogV2(V obj, V oldObj, int action, ObjectChangeInfo objChangeInfo, List<List<XXTrxLogV2>> ret) { + try { + if (obj != null) { + XXTrxLogV2 trxLog = new XXTrxLogV2(classType, obj.getId(), getObjectName(obj), getParentObjectType(obj, oldObj), getParentObjectId(obj, oldObj), getParentObjectName(obj, oldObj), toActionString(action), JsonUtilsV2.objToJson(objChangeInfo)); + + ret.add(Collections.singletonList(trxLog)); + } + } catch (Exception excp) { + LOG.warn("failed to get transaction log for object: type={}, id={}", obj.getClass().getName(), obj.getId(), excp); + } + } + + private void addTransactionLogsOnImpactedObjects(V obj, V oldObj, int action, ObjectChangeInfo objChangeInfo, List<List<XXTrxLogV2>> ret) { + V auditedObj = (action == OPERATION_DELETE_CONTEXT || action == OPERATION_IMPORT_DELETE_CONTEXT) ? oldObj : obj; + + if (auditedObj != null) { + ObjectChangeInfo changeSourceInfo = getChangeSourceInfo(auditedObj, action, objChangeInfo); + + if (auditedObj instanceof RangerSharedResource) { + Long dataShareId = ((RangerSharedResource) auditedObj).getDataShareId(); + RangerDataShare dataShare = dataShareService.read(dataShareId); + + dataShareService.addXXTrxLogV2(dataShare, dataShare, OPERATION_UPDATE_CONTEXT, changeSourceInfo, ret); + + List<XXGdsDataset> datasets = daoMgr.getXXGdsDataset().findDatasetsWithDataShareInStatus(dataShareId, RangerGds.GdsShareStatus.ACTIVE); + + if (CollectionUtils.isNotEmpty(datasets)) { + List<XXGdsProject> projects = daoMgr.getXXGdsProject().findProjectsWithDataShareInStatus(dataShareId, RangerGds.GdsShareStatus.ACTIVE); + + logImpactedDatasets(datasets, changeSourceInfo, ret); + logImpactedProjects(projects, changeSourceInfo, ret); + } + } else if (auditedObj instanceof RangerDataShare) { + Long dataShareId = auditedObj.getId(); + List<XXGdsDataset> datasets = daoMgr.getXXGdsDataset().findDatasetsWithDataShareInStatus(dataShareId, RangerGds.GdsShareStatus.ACTIVE); + + if (CollectionUtils.isNotEmpty(datasets)) { + List<XXGdsProject> projects = daoMgr.getXXGdsProject().findProjectsWithDataShareInStatus(dataShareId, RangerGds.GdsShareStatus.ACTIVE); + + logImpactedDatasets(datasets, changeSourceInfo, ret); + logImpactedProjects(projects, changeSourceInfo, ret); + } + } else if (auditedObj instanceof RangerDataShareInDataset) { + Long datasetId = ((RangerDataShareInDataset) auditedObj).getDatasetId(); + RangerDataset dataset = datasetService.read(datasetId); + + datasetService.addXXTrxLogV2(dataset, dataset, OPERATION_UPDATE_CONTEXT, changeSourceInfo, ret); + + List<XXGdsProject> projects = daoMgr.getXXGdsProject().findProjectsWithDatasetInStatus(datasetId, RangerGds.GdsShareStatus.ACTIVE); + + logImpactedProjects(projects, changeSourceInfo, ret); + } else if (auditedObj instanceof RangerDataset) { + Long datasetId = auditedObj.getId(); + + List<XXGdsProject> projects = daoMgr.getXXGdsProject().findProjectsWithDatasetInStatus(datasetId, RangerGds.GdsShareStatus.ACTIVE); + + logImpactedProjects(projects, changeSourceInfo, ret); + } else if (auditedObj instanceof RangerDatasetInProject) { + Long projectId = ((RangerDatasetInProject) auditedObj).getProjectId(); + RangerProject project = projectService.read(projectId); + + projectService.addXXTrxLogV2(project, project, OPERATION_UPDATE_CONTEXT, changeSourceInfo, ret); + } else if (auditedObj instanceof RangerPolicy) { + Long datasetId = daoMgr.getXXGdsDatasetPolicyMap().getDatasetIdForPolicy(auditedObj.getId()); + + if (datasetId != null) { + RangerDataset dataset = datasetService.read(datasetId); + + datasetService.addXXTrxLogV2(dataset, dataset, OPERATION_UPDATE_CONTEXT, changeSourceInfo, ret); + } else { + Long projectId = daoMgr.getXXGdsProjectPolicyMap().getProjectIdForPolicy(auditedObj.getId()); + + if (projectId != null) { + RangerProject project = projectService.read(projectId); + + projectService.addXXTrxLogV2(project, project, OPERATION_UPDATE_CONTEXT, changeSourceInfo, ret); + } + } + } + } + } + + private ObjectChangeInfo getChangeSourceInfo(V sourceObj, int action, ObjectChangeInfo objChangeInfo) { + ObjectChangeInfo ret = new ObjectChangeInfo(); + + ret.addAttribute("_objectId", null, String.valueOf(sourceObj.getId())); + ret.addAttribute("_objectClassType", null, String.valueOf(classType)); + ret.addAttribute("_objectClassName", null, sourceObj.getClass().getSimpleName()); + ret.addAttribute("_changeType", null, toActionString(action)); + + if (objChangeInfo.getAttributes() != null) { + ret.getAttributes().addAll(objChangeInfo.getAttributes()); + } + + return ret; + } + + private void logImpactedDatasets(List<XXGdsDataset> xxDatasets, ObjectChangeInfo changedObjInfo, List<List<XXTrxLogV2>> ret) { + for (XXGdsDataset xxDataset : xxDatasets) { + RangerDataset dataset = datasetService.getPopulatedViewObject(xxDataset); + + datasetService.addXXTrxLogV2(dataset, dataset, OPERATION_UPDATE_CONTEXT, changedObjInfo, ret); + } + } + + private void logImpactedProjects(List<XXGdsProject> xxProjects, ObjectChangeInfo changedObjInfo, List<List<XXTrxLogV2>> ret) { + for (XXGdsProject xxProject : xxProjects) { + RangerProject project = projectService.getPopulatedViewObject(xxProject); + + projectService.addXXTrxLogV2(project, project, OPERATION_UPDATE_CONTEXT, changedObjInfo, 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 3559877d5..1cc89ee4a 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 @@ -2211,6 +2211,14 @@ </query> </named-query> + <named-query name="XXGdsDataset.findDatasetsWithDataShareInStatus"> + <query>select obj from XXGdsDataset obj, XXGdsDataShareInDataset dsid + where dsid.dataShareId = :dataShareId + and dsid.datasetId = obj.id + and dsid.status = :status + </query> + </named-query> + <named-query name="XXGdsDataset.findByProjectId"> <query>select obj from XXGdsDataset obj, XXGdsDatasetInProject dip where dip.projectId = :projectId @@ -2244,6 +2252,22 @@ and dip.projectId = obj.id</query> </named-query> + <named-query name="XXGdsProject.findProjectsWithDatasetInStatus"> + <query>SELECT obj FROM XXGdsProject obj, XXGdsDatasetInProject dip + WHERE dip.datasetId = :datasetId + AND dip.projectId = obj.id + AND dip.status = :status</query> + </named-query> + + <named-query name="XXGdsProject.findProjectsWithDataShareInStatus"> + <query>SELECT DISTINCT obj FROM XXGdsProject obj, XXGdsDatasetInProject dip, XXGdsDataShareInDataset dshid + WHERE dshid.dataShareId = :dataShareId + AND dshid.status = :status + AND dip.datasetId = dshid.datasetId + AND dip.projectId = obj.id + AND dip.status = :status</query> + </named-query> + <named-query name="XXGdsProject.findServiceIds"> <query>SELECT DISTINCT(dsh.serviceId) FROM XXGdsDataShare dsh, XXGdsDataShareInDataset dshid, XXGdsDatasetInProject dip WHERE dip.projectId = :projectId @@ -2387,6 +2411,10 @@ <query>SELECT obj.policyId FROM XXGdsDatasetPolicyMap obj WHERE obj.datasetId = :datasetId</query> </named-query> + <named-query name="XXGdsDatasetPolicyMap.getDatasetIdForPolicy"> + <query>SELECT obj.datasetId FROM XXGdsDatasetPolicyMap obj WHERE obj.policyId = :policyId</query> + </named-query> + <named-query name="XXGdsProjectPolicyMap.getProjectPolicyMap"> <query>SELECT obj FROM XXGdsProjectPolicyMap obj WHERE obj.projectId = :projectId AND obj.policyId = :policyId</query> </named-query> @@ -2398,4 +2426,8 @@ <named-query name="XXGdsProjectPolicyMap.getProjectPolicyIds"> <query>SELECT obj.policyId FROM XXGdsProjectPolicyMap obj WHERE obj.projectId = :projectId</query> </named-query> + + <named-query name="XXGdsProjectPolicyMap.getProjectIdForPolicy"> + <query>SELECT obj.projectId FROM XXGdsProjectPolicyMap obj WHERE obj.policyId = :policyId</query> + </named-query> </entity-mappings> diff --git a/security-admin/src/test/java/org/apache/ranger/rest/TestAssetREST.java b/security-admin/src/test/java/org/apache/ranger/rest/TestAssetREST.java index 7bddf1874..7d87bb701 100644 --- a/security-admin/src/test/java/org/apache/ranger/rest/TestAssetREST.java +++ b/security-admin/src/test/java/org/apache/ranger/rest/TestAssetREST.java @@ -59,6 +59,8 @@ import org.apache.ranger.view.VXResponse; import org.apache.ranger.view.VXTrxLog; import org.apache.ranger.view.VXTrxLogList; +import org.apache.ranger.view.VXTrxLogV2; +import org.apache.ranger.view.VXTrxLogV2List; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Rule; @@ -510,6 +512,41 @@ public void testGetTransactionReport() { Mockito.verify(assetMgr).getTransactionReport(transactionId); } + @Test + public void testGetReportLogsV2() { + SearchCriteria searchCriteria = new SearchCriteria(); + List<SortField> sortFields = xTrxLogService.getSortFields(); + VXTrxLogV2List vXTrxLogV2List = new VXTrxLogV2List(new ArrayList<>()); + + Mockito.when(searchUtil.extractCommonCriterias(request, sortFields)).thenReturn(searchCriteria); + Mockito.when(searchUtil.extractString(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn("test"); + Mockito.when(searchUtil.extractInt(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString())).thenReturn(8); + Mockito.when(searchUtil.extractDate(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(new Date()); + Mockito.when(assetMgr.getReportLogsV2(searchCriteria)).thenReturn(vXTrxLogV2List); + + VXTrxLogV2List expectedVXTrxLogV2List = assetREST.getReportLogsV2(request); + + Assert.assertEquals(vXTrxLogV2List, expectedVXTrxLogV2List); + Mockito.verify(searchUtil, Mockito.times(4)).extractString(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + Mockito.verify(searchUtil, Mockito.times(2)).extractInt(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString()); + Mockito.verify(searchUtil, Mockito.times(2)).extractDate(Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + Mockito.verify(assetMgr).getReportLogsV2(searchCriteria); + Mockito.verify(searchUtil).extractCommonCriterias(request, sortFields); + } + + @Test + public void testGetTransactionReportV2() { + VXTrxLogV2List vXTrxLogV2List = new VXTrxLogV2List(new ArrayList<>()); + String transactionId = "123456"; + + Mockito.when(assetMgr.getTransactionReportV2(transactionId)).thenReturn(vXTrxLogV2List); + + VXTrxLogV2List expectedVXTrxLogList = assetREST.getTransactionReportV2(request, transactionId); + + Assert.assertEquals(vXTrxLogV2List, expectedVXTrxLogList); + Mockito.verify(assetMgr).getTransactionReportV2(transactionId); + } + @Test public void testGetAccessLogs() { SearchCriteria searchCriteria = new SearchCriteria();