This is an automated email from the ASF dual-hosted git repository.
pradeepagrawal8184 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new 63e5bd704 RANGER-5804: Support Ranger Admin for displaying audit
metrics from OpenSearch (#1251)
63e5bd704 is described below
commit 63e5bd7040954455f89c5f6f4615a92d18093510
Author: Rakesh Gupta <[email protected]>
AuthorDate: Wed Sep 30 13:00:12 2026 +0530
RANGER-5804: Support Ranger Admin for displaying audit metrics from
OpenSearch (#1251)
* RANGER-5804: Support Ranger Admin for displaying audit metrics from
OpenSearch
* RANGER-5804: Support Ranger Admin for displaying audit metrics from
OpenSearch - fix review comment
---
.../audit/metrics/AccessAuditsMetricsService.java | 39 ++
.../metrics/AccessAuditsMetricsServiceFactory.java | 48 ++
.../ranger/audit/metrics/AuditMetricsHelper.java | 248 ++++++++++
.../opensearch/OpenSearchAccessAuditsService.java | 52 ++-
.../opensearch/OpenSearchAuditMetricsHelper.java | 518 +++++++++++++++++++++
.../org/apache/ranger/rest/AuditMetricsREST.java | 25 +-
.../ranger/solr/SolrAccessAuditsService.java | 3 +-
.../apache/ranger/solr/SolrAuditMetricsHelper.java | 185 +-------
.../AccessAuditsMetricsServiceFactoryTest.java | 69 +++
.../OpenSearchAuditMetricsHelperTest.java | 238 ++++++++++
.../apache/ranger/rest/TestAuditMetricsREST.java | 60 +--
.../ranger/solr/SolrAccessAuditsServiceTest.java | 4 +-
.../ranger/solr/SolrAuditMetricsHelperTest.java | 15 +-
13 files changed, 1305 insertions(+), 199 deletions(-)
diff --git
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
new file mode 100644
index 000000000..63a07d428
--- /dev/null
+++
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.ranger.audit.metrics;
+
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+import java.util.List;
+
+public interface AccessAuditsMetricsService {
+ RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone);
+
+ RangerAuditMetrics getAuditMetrics(Long serviceId, String timezone);
+
+ List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter filter,
String timezone);
+
+ List<RangerAuditMetricsByDays> getAuditMetricsByDays(int olderThanInDays,
SearchFilter filter, String timezone);
+
+ List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter, String timezone);
+}
diff --git
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
new file mode 100644
index 000000000..d1f1f1c07
--- /dev/null
+++
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.ranger.audit.metrics;
+
+import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.opensearch.OpenSearchAccessAuditsService;
+import org.apache.ranger.solr.SolrAccessAuditsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AccessAuditsMetricsServiceFactory {
+ @Autowired
+ RangerBizUtil rangerBizUtil;
+
+ @Autowired
+ SolrAccessAuditsService solrAccessAuditsService;
+
+ @Autowired
+ OpenSearchAccessAuditsService openSearchAccessAuditsService;
+
+ public AccessAuditsMetricsService getAccessAuditsMetricsService() {
+ AccessAuditsMetricsService ret = solrAccessAuditsService;
+
+ if
(RangerBizUtil.AUDIT_STORE_OPENSEARCH.equalsIgnoreCase(rangerBizUtil.getAuditDBType()))
{
+ ret = openSearchAccessAuditsService;
+ }
+
+ return ret;
+ }
+}
diff --git
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
new file mode 100644
index 000000000..ba1a515b1
--- /dev/null
+++
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
@@ -0,0 +1,248 @@
+/*
+ * 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.ranger.audit.metrics;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeParseException;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class AuditMetricsHelper {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(AuditMetricsHelper.class);
+
+ public static final long MISSING_REPO_TYPE_SENTINEL = -1L;
+
+ private final Map<String, Long> repoTypeByServiceType = new
ConcurrentHashMap<>();
+
+ @Autowired
+ RangerDaoManager daoManager;
+
+ public SearchFilter buildSearchFilter(String serviceType, String
serviceName, String appId, String clusterName, String clientIP) {
+ SearchFilter filter = new SearchFilter();
+
+ filter.setParam(SearchFilter.SERVICE_TYPE, serviceType);
+ filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+ filter.setParam(SearchFilter.PLUGIN_APP_ID, appId);
+ filter.setParam(SearchFilter.CLUSTER_NAME, clusterName);
+ filter.setParam(SearchFilter.CLIENT_IP, clientIP);
+
+ return filter;
+ }
+
+ public FilterParams getFilterParams(SearchFilter filter) {
+ FilterParams params = new FilterParams();
+
+ if (filter != null) {
+ params.serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+ params.serviceName = filter.getParam(SearchFilter.SERVICE_NAME);
+ params.appId = filter.getParam(SearchFilter.PLUGIN_APP_ID);
+ params.clusterName = filter.getParam(SearchFilter.CLUSTER_NAME);
+ params.clientIP = filter.getParam(SearchFilter.CLIENT_IP);
+ }
+
+ return params;
+ }
+
+ public RangerAuditMetrics buildAuditMetrics(String serviceType, String
serviceName, String appId, String clusterName, String clientIP, long count) {
+ RangerAuditMetrics metric = new RangerAuditMetrics();
+
+ metric.setServiceName(serviceName);
+ metric.setServiceType(resolveServiceType(serviceType, serviceName));
+ metric.setAppId(appId);
+ metric.setClusterName(clusterName);
+ metric.setClientIP(clientIP);
+ metric.setNumberOfAudits(count);
+
+ Long serviceId = resolveServiceId(serviceName);
+
+ if (serviceId != null) {
+ metric.setId(serviceId);
+ }
+
+ return metric;
+ }
+
+ public RangerAuditMetricsByDays buildAuditMetricsByDays(FilterParams
params, Long auditDate, long count) {
+ return new RangerAuditMetricsByDays(params.serviceType,
params.serviceName, params.appId, params.clusterName, params.clientIP,
auditDate, count);
+ }
+
+ public RangerAuditMetricsByHours buildAuditMetricsByHours(FilterParams
params, int hour, long count) {
+ return new RangerAuditMetricsByHours(params.serviceType,
params.serviceName, params.appId, params.clusterName, params.clientIP, hour,
count);
+ }
+
+ public Long resolveServiceId(String serviceName) {
+ Long ret = null;
+
+ if (StringUtils.isNotBlank(serviceName) && daoManager != null &&
daoManager.getXXService() != null) {
+ XXService service =
daoManager.getXXService().findByName(serviceName);
+
+ if (service != null) {
+ ret = service.getId();
+ }
+ }
+
+ return ret;
+ }
+
+ public String resolveServiceType(XXService service) {
+ String ret = null;
+
+ if (service != null && daoManager != null &&
daoManager.getXXServiceDef() != null) {
+ XXServiceDef serviceDef =
daoManager.getXXServiceDef().getById(service.getType());
+
+ if (serviceDef != null) {
+ ret = serviceDef.getName();
+ }
+ }
+
+ return ret;
+ }
+
+ public String resolveServiceType(String serviceType, String serviceName) {
+ String ret = serviceType;
+
+ if (StringUtils.isBlank(ret)) {
+ if (StringUtils.isNotBlank(serviceName) && daoManager != null &&
daoManager.getXXService() != null) {
+ XXService service =
daoManager.getXXService().findByName(serviceName);
+ ret = resolveServiceType(service);
+ } else {
+ ret = null;
+ }
+ }
+
+ return ret;
+ }
+
+ public long resolveRepoType(String serviceType) {
+ long ret = MISSING_REPO_TYPE_SENTINEL;
+
+ if (StringUtils.isBlank(serviceType)) {
+ return ret;
+ }
+
+ String cacheKey = serviceType.trim().toLowerCase();
+ Long cached = repoTypeByServiceType.get(cacheKey);
+
+ if (cached != null) {
+ ret = cached;
+ return ret;
+ }
+
+ if (daoManager != null && daoManager.getXXServiceDef() != null) {
+ XXServiceDef serviceDef =
daoManager.getXXServiceDef().findByName(serviceType);
+
+ if (serviceDef != null && serviceDef.getId() != null) {
+ ret = serviceDef.getId();
+ }
+ }
+
+ repoTypeByServiceType.put(cacheKey, ret);
+
+ return ret;
+ }
+
+ public ZoneId parseZoneId(String timezone) {
+ ZoneId ret = null;
+
+ if (StringUtils.isNotBlank(timezone)) {
+ try {
+ ret = ZoneId.of(timezone.trim());
+ } catch (DateTimeException e) {
+ LOGGER.warn("Invalid timezone value: {}", timezone, e);
+ }
+ }
+
+ return ret;
+ }
+
+ public ZoneId resolveZoneId(String timezone) {
+ ZoneId ret = parseZoneId(timezone);
+
+ if (ret == null) {
+ ret = ZoneOffset.UTC;
+ }
+
+ return ret;
+ }
+
+ public Long parseAuditDate(Object value) {
+ Long ret = null;
+
+ if (value instanceof Date) {
+ ret = ((Date) value).getTime();
+ } else if (value instanceof Number) {
+ ret = ((Number) value).longValue();
+ } else if (value instanceof String) {
+ try {
+ ret = Instant.parse((String) value).toEpochMilli();
+ } catch (DateTimeParseException e) {
+ LOGGER.warn("Unable to parse audit metric date value: {}",
value, e);
+ }
+ }
+
+ return ret;
+ }
+
+ public static class FilterParams {
+ private String serviceType;
+ private String serviceName;
+ private String appId;
+ private String clusterName;
+ private String clientIP;
+
+ public String getServiceType() {
+ return serviceType;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public String getClientIP() {
+ return clientIP;
+ }
+ }
+}
diff --git
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
index 340ac34df..aa2f979f3 100644
---
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
+++
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
@@ -19,6 +19,8 @@
package org.apache.ranger.opensearch;
+import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
import org.apache.ranger.audit.provider.MiscUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.PropertiesUtil;
@@ -28,7 +30,11 @@
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.opensearch.OpenSearchUtil.OpenSearchSearchResult;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
import org.apache.ranger.plugin.util.JsonUtilsV2;
+import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.view.VXAccessAudit;
import org.apache.ranger.view.VXAccessAuditList;
import org.apache.ranger.view.VXLong;
@@ -47,7 +53,7 @@
@Service
@Scope("singleton")
-public class OpenSearchAccessAuditsService extends
org.apache.ranger.AccessAuditsService {
+public class OpenSearchAccessAuditsService extends AccessAuditsService
implements AccessAuditsMetricsService {
private static final Logger LOG =
LoggerFactory.getLogger(OpenSearchAccessAuditsService.class);
@Autowired
@@ -56,6 +62,9 @@ public class OpenSearchAccessAuditsService extends
org.apache.ranger.AccessAudit
@Autowired
OpenSearchUtil openSearchUtil;
+ @Autowired
+ OpenSearchAuditMetricsHelper auditMetricsHelper;
+
public VXAccessAuditList searchXAccessAudits(SearchCriteria
searchCriteria) {
RestClient client = openSearchMgr.getClient();
final boolean hiveQueryVisibility =
PropertiesUtil.getBooleanProperty("ranger.audit.hive.query.visibility", true);
@@ -132,6 +141,47 @@ public VXLong getXAccessAuditSearchCount(SearchCriteria
searchCriteria) {
return vXLong;
}
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone) {
+ return auditMetricsHelper.getLatestAuditMetrics(serviceType,
serviceName, timezone);
+ }
+
+ public RangerAuditMetrics getAuditMetrics(Long serviceId, String timezone)
{
+ if (serviceId == null) {
+ throw restErrorUtil.createRESTException("AuditMetrics id is
required");
+ }
+
+ if (daoManager == null || daoManager.getXXService() == null) {
+ throw restErrorUtil.createRESTException("Service lookup is not
available");
+ }
+
+ XXService service = daoManager.getXXService().getById(serviceId);
+
+ if (service == null) {
+ throw restErrorUtil.createRESTException("AuditMetrics with Id: " +
serviceId + " does not exist");
+ }
+
+ String serviceName = service.getName();
+ String serviceType = auditMetricsHelper.resolveServiceType(service);
+
+ RangerAuditMetrics metric =
auditMetricsHelper.getLatestAuditMetrics(serviceType, serviceName, timezone);
+
+ metric.setId(serviceId);
+
+ return metric;
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter, String timezone) {
+ return auditMetricsHelper.getLatestAuditMetricsList(filter, timezone);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter, String timezone) {
+ return auditMetricsHelper.getAuditMetricsByDays(olderThanInDays,
filter, timezone);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter, String timezone) {
+ return auditMetricsHelper.getAuditMetricsByHours(filter, timezone);
+ }
+
private VXAccessAudit populateViewBean(Map<String, Object> source) {
VXAccessAudit accessAudit = new VXAccessAudit();
Object value;
diff --git
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
new file mode 100644
index 000000000..2ff9c62ab
--- /dev/null
+++
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
@@ -0,0 +1,518 @@
+/*
+ * 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.ranger.opensearch;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.entity.ContentType;
+import org.apache.http.nio.entity.NStringEntity;
+import org.apache.http.util.EntityUtils;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper.FilterParams;
+import org.apache.ranger.common.MessageEnums;
+import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class OpenSearchAuditMetricsHelper {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(OpenSearchAuditMetricsHelper.class);
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private static final String FACET_REPO = "per_repo";
+ private static final String FACET_AGENT = "per_agent";
+ private static final String FACET_CLIIP = "per_cliip";
+ private static final String FACET_CLUSTER = "per_cluster";
+ private static final int AGG_SIZE = 10000;
+ private static final String MISSING_BUCKET = "";
+
+ @Autowired
+ OpenSearchMgr openSearchMgr;
+
+ @Autowired
+ RESTErrorUtil restErrorUtil;
+
+ @Autowired
+ AuditMetricsHelper auditMetricsHelper;
+
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone) {
+ SearchFilter filter =
auditMetricsHelper.buildSearchFilter(serviceType, serviceName, null, null,
null);
+ List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+ applyLatestRangeFilter(filters, timezone);
+
+ Map<String, Object> queryBody = buildMetricsQueryBody(filters, null);
+ JsonNode response = runMetricsSearch(queryBody, "latest
audit metrics");
+ long count =
response.at("/hits/total/value").asLong(0L);
+
+ return auditMetricsHelper.buildAuditMetrics(serviceType, serviceName,
null, null, null, count);
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter, String timezone) {
+ List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+ applyLatestRangeFilter(filters, timezone);
+
+ Map<String, Object> aggregations = buildAuditMetricsListAggregation();
+ Map<String, Object> queryBody = buildMetricsQueryBody(filters,
aggregations);
+ JsonNode response = runMetricsSearch(queryBody, "audit
metrics list");
+
+ return extractAuditMetricsList(response, filter);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter, String timezone) {
+ List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+ applyDaysRangeFilter(filters, olderThanInDays, timezone);
+
+ Map<String, Object> aggregations = buildDayAggregation(timezone);
+ Map<String, Object> queryBody = buildMetricsQueryBody(filters,
aggregations);
+ JsonNode response = runMetricsSearch(queryBody, "audit
metrics by days");
+
+ return extractAuditMetricsByDays(response, filter, timezone);
+ }
+
+ public String resolveServiceType(XXService service) {
+ return auditMetricsHelper.resolveServiceType(service);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter, String timezone) {
+ List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+ applyTodayRangeFilter(filters, timezone);
+
+ Map<String, Object> aggregations = buildHourAggregation(timezone);
+ Map<String, Object> queryBody = buildMetricsQueryBody(filters,
aggregations);
+ JsonNode response = runMetricsSearch(queryBody, "audit
metrics by hours");
+
+ return extractAuditMetricsByHours(response, filter, timezone);
+ }
+
+ private Map<String, Object> buildMetricsQueryBody(List<Map<String,
Object>> filters, Map<String, Object> aggregations) {
+ Map<String, Object> queryBody = new LinkedHashMap<>();
+
+ queryBody.put("size", 0);
+
+ Map<String, Object> boolQuery = new LinkedHashMap<>();
+
+ boolQuery.put("filter", filters.isEmpty() ?
List.of(Map.of("match_all", Map.of())) : filters);
+ queryBody.put("query", Map.of("bool", boolQuery));
+
+ if (aggregations != null) {
+ queryBody.put("aggs", aggregations);
+ }
+
+ return queryBody;
+ }
+
+ private List<Map<String, Object>> buildMetricsFilters(SearchFilter filter)
{
+ List<Map<String, Object>> filters = new ArrayList<>();
+
+ if (filter == null) {
+ return filters;
+ }
+
+ addMatchFilter(filters, "repo",
filter.getParam(SearchFilter.SERVICE_NAME));
+ addMatchFilter(filters, "cluster",
filter.getParam(SearchFilter.CLUSTER_NAME));
+ addMatchFilter(filters, "cliIP",
filter.getParam(SearchFilter.CLIENT_IP));
+ addMatchFilter(filters, "agent",
filter.getParam(SearchFilter.PLUGIN_APP_ID));
+
+ String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+
+ if (StringUtils.isNotBlank(serviceType)) {
+ long repoType = auditMetricsHelper.resolveRepoType(serviceType);
+
+ if (repoType == AuditMetricsHelper.MISSING_REPO_TYPE_SENTINEL) {
+ filters.add(Map.of("term", Map.of("repoType", -1)));
+ } else {
+ filters.add(Map.of("term", Map.of("repoType", repoType)));
+ }
+ }
+
+ return filters;
+ }
+
+ private void addMatchFilter(List<Map<String, Object>> filters, String
field, String value) {
+ if (filters == null || StringUtils.isBlank(value)) {
+ return;
+ }
+
+ filters.add(Map.of("match_phrase", Map.of(field,
value.trim().toLowerCase())));
+ }
+
+ private void applyLatestRangeFilter(List<Map<String, Object>> filters,
String timezone) {
+ applyRangeFilter(filters, "now-1d", "now", timezone);
+ }
+
+ private void applyTodayRangeFilter(List<Map<String, Object>> filters,
String timezone) {
+ applyRangeFilter(filters, "now/d", "now", timezone);
+ }
+
+ private void applyDaysRangeFilter(List<Map<String, Object>> filters, int
olderThanInDays, String timezone) {
+ int daysBack = olderThanInDays - 1;
+
+ applyRangeFilter(filters, "now-" + daysBack + "d/d", "now", timezone);
+ }
+
+ private void applyRangeFilter(List<Map<String, Object>> filters, String
from, String to, String timezone) {
+ if (filters == null) {
+ return;
+ }
+
+ Map<String, Object> rangeParams = new LinkedHashMap<>();
+
+ rangeParams.put("from", from);
+ rangeParams.put("to", to);
+
+ ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+ if (zoneId != null) {
+ rangeParams.put("time_zone", zoneId.getId());
+ }
+
+ filters.add(Map.of("range", Map.of("evtTime", rangeParams)));
+ }
+
+ private Map<String, Object> buildAuditMetricsListAggregation() {
+ Map<String, Object> perClusterTerms = new LinkedHashMap<>();
+
+ perClusterTerms.put("field", "cluster");
+ perClusterTerms.put("size", AGG_SIZE);
+ perClusterTerms.put("missing", MISSING_BUCKET);
+
+ Map<String, Object> perCluster = new LinkedHashMap<>();
+
+ perCluster.put("terms", perClusterTerms);
+
+ Map<String, Object> perCliIpAggs = new LinkedHashMap<>();
+
+ perCliIpAggs.put(FACET_CLUSTER, perCluster);
+
+ Map<String, Object> perCliIpTerms = new LinkedHashMap<>();
+
+ perCliIpTerms.put("field", "cliIP");
+ perCliIpTerms.put("size", AGG_SIZE);
+ perCliIpTerms.put("missing", MISSING_BUCKET);
+
+ Map<String, Object> perCliIp = new LinkedHashMap<>();
+
+ perCliIp.put("terms", perCliIpTerms);
+ perCliIp.put("aggs", perCliIpAggs);
+
+ Map<String, Object> perAgentAggs = new LinkedHashMap<>();
+
+ perAgentAggs.put(FACET_CLIIP, perCliIp);
+
+ Map<String, Object> perAgentTerms = new LinkedHashMap<>();
+
+ perAgentTerms.put("field", "agent");
+ perAgentTerms.put("size", AGG_SIZE);
+ perAgentTerms.put("missing", MISSING_BUCKET);
+
+ Map<String, Object> perAgent = new LinkedHashMap<>();
+
+ perAgent.put("terms", perAgentTerms);
+ perAgent.put("aggs", perAgentAggs);
+
+ Map<String, Object> perRepoAggs = new LinkedHashMap<>();
+
+ perRepoAggs.put(FACET_AGENT, perAgent);
+
+ Map<String, Object> perRepoTerms = new LinkedHashMap<>();
+
+ perRepoTerms.put("field", "repo");
+ perRepoTerms.put("size", AGG_SIZE);
+ perRepoTerms.put("order", Map.of("_count", "desc"));
+
+ Map<String, Object> perRepo = new LinkedHashMap<>();
+
+ perRepo.put("terms", perRepoTerms);
+ perRepo.put("aggs", perRepoAggs);
+
+ Map<String, Object> aggregations = new LinkedHashMap<>();
+
+ aggregations.put(FACET_REPO, perRepo);
+
+ return aggregations;
+ }
+
+ private Map<String, Object> buildDayAggregation(String timezone) {
+ Map<String, Object> dateHistogram = new LinkedHashMap<>();
+
+ dateHistogram.put("field", "evtTime");
+ dateHistogram.put("calendar_interval", "1d");
+
+ ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+ if (zoneId != null) {
+ dateHistogram.put("time_zone", zoneId.getId());
+ }
+
+ return Map.of("per_day", Map.of("date_histogram", dateHistogram));
+ }
+
+ private Map<String, Object> buildHourAggregation(String timezone) {
+ Map<String, Object> dateHistogram = new LinkedHashMap<>();
+
+ dateHistogram.put("field", "evtTime");
+ dateHistogram.put("fixed_interval", "1h");
+
+ ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+ if (zoneId != null) {
+ dateHistogram.put("time_zone", zoneId.getId());
+ }
+
+ return Map.of("per_hour", Map.of("date_histogram", dateHistogram));
+ }
+
+ private JsonNode runMetricsSearch(Map<String, Object> queryBody, String
context) {
+ RestClient client = openSearchMgr.getClient();
+
+ if (client == null) {
+ LOGGER.warn("OpenSearch client is null, so not running the
query.");
+
+ throw restErrorUtil.createRESTException("Error connecting to
search engine", MessageEnums.ERROR_SYSTEM);
+ }
+
+ JsonNode result;
+
+ try {
+ String body = MAPPER.writeValueAsString(queryBody);
+ Request request = new Request("POST", "/" +
openSearchMgr.getIndex() + "/_search");
+
+ request.setEntity(new NStringEntity(body,
ContentType.APPLICATION_JSON));
+
+ Response response = client.performRequest(request);
+
+ result = parseMetricsSearchResponse(response, context);
+ } catch (IOException e) {
+ LOGGER.warn("OpenSearch query failed for {}: {}", context,
e.getMessage());
+
+ throw restErrorUtil.createRESTException("Error querying search
engine", MessageEnums.ERROR_SYSTEM);
+ }
+
+ return result;
+ }
+
+ private JsonNode parseMetricsSearchResponse(Response response, String
context) throws IOException {
+ int statusCode = response.getStatusLine().getStatusCode();
+
+ if (statusCode < 200 || statusCode >= 300) {
+ LOGGER.warn("OpenSearch query failed for {} with status {}",
context, statusCode);
+
+ throw restErrorUtil.createRESTException("Error querying search
engine", MessageEnums.ERROR_SYSTEM);
+ }
+
+ String json = EntityUtils.toString(response.getEntity());
+
+ return MAPPER.readTree(json);
+ }
+
+ private List<RangerAuditMetrics> extractAuditMetricsList(JsonNode
response, SearchFilter filter) {
+ JsonNode buckets = response.at("/aggregations/per_repo/buckets");
+
+ if (!buckets.isArray()) {
+ return Collections.emptyList();
+ }
+
+ String serviceTypeFilter = filter != null ?
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
+ List<RangerAuditMetrics> metrics = new ArrayList<>();
+
+ for (JsonNode repoBucket : buckets) {
+ processRepoBucket(repoBucket, metrics, serviceTypeFilter);
+ }
+
+ return metrics;
+ }
+
+ private void processRepoBucket(JsonNode repoBucket,
List<RangerAuditMetrics> metrics, String serviceTypeFilter) {
+ String serviceName = bucketKeyToString(repoBucket);
+
+ if (serviceName == null) {
+ return;
+ }
+
+ JsonNode agentBuckets = getSubBuckets(repoBucket, FACET_AGENT);
+
+ if (agentBuckets == null) {
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, null, null, null, bucketDocCount(repoBucket)));
+ } else {
+ processAgentBuckets(agentBuckets, metrics, serviceTypeFilter,
serviceName);
+ }
+ }
+
+ private void processAgentBuckets(JsonNode agentBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName)
{
+ for (JsonNode agentBucket : agentBuckets) {
+ String appId = bucketKeyToString(agentBucket);
+ JsonNode cliIpBuckets = getSubBuckets(agentBucket, FACET_CLIIP);
+
+ if (cliIpBuckets == null) {
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, null, null, bucketDocCount(agentBucket)));
+ } else {
+ processCliIpBuckets(cliIpBuckets, metrics, serviceTypeFilter,
serviceName, appId);
+ }
+ }
+ }
+
+ private void processCliIpBuckets(JsonNode cliIpBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName,
String appId) {
+ for (JsonNode cliIpBucket : cliIpBuckets) {
+ String clientIP = bucketKeyToString(cliIpBucket);
+ JsonNode clusterBuckets = getSubBuckets(cliIpBucket,
FACET_CLUSTER);
+
+ if (clusterBuckets == null) {
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, null, clientIP, bucketDocCount(cliIpBucket)));
+ } else {
+ processClusterBuckets(clusterBuckets, metrics,
serviceTypeFilter, serviceName, appId, clientIP);
+ }
+ }
+ }
+
+ private void processClusterBuckets(JsonNode clusterBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName,
String appId, String clientIP) {
+ for (JsonNode clusterBucket : clusterBuckets) {
+ String clusterName = bucketKeyToString(clusterBucket);
+
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, clusterName, clientIP, bucketDocCount(clusterBucket)));
+ }
+ }
+
+ private JsonNode getSubBuckets(JsonNode parentBucket, String aggName) {
+ JsonNode buckets = parentBucket.path(aggName).path("buckets");
+
+ if (!buckets.isArray() || buckets.isEmpty()) {
+ return null;
+ }
+
+ return buckets;
+ }
+
+ private String bucketKeyToString(JsonNode bucket) {
+ String ret = null;
+
+ if (bucket != null && bucket.has("key")) {
+ ret = bucket.get("key").asText(null);
+
+ if (StringUtils.isBlank(ret)) {
+ ret = null;
+ }
+ }
+
+ return ret;
+ }
+
+ private long bucketDocCount(JsonNode bucket) {
+ long ret = 0L;
+
+ if (bucket != null && bucket.has("doc_count")) {
+ ret = bucket.get("doc_count").asLong();
+ }
+
+ return ret;
+ }
+
+ private List<RangerAuditMetricsByDays> extractAuditMetricsByDays(JsonNode
response, SearchFilter filter, String timezone) {
+ List<RangerAuditMetricsByDays> metrics = new ArrayList<>();
+ JsonNode buckets =
response.at("/aggregations/per_day/buckets");
+
+ if (!buckets.isArray()) {
+ return Collections.emptyList();
+ }
+
+ FilterParams params = auditMetricsHelper.getFilterParams(filter);
+
+ for (JsonNode bucket : buckets) {
+ Long auditDate = parseBucketTime(bucket, timezone);
+
+ if (auditDate == null) {
+ continue;
+ }
+
+ metrics.add(auditMetricsHelper.buildAuditMetricsByDays(params,
auditDate, bucket.get("doc_count").asLong()));
+ }
+
+ return metrics;
+ }
+
+ private List<RangerAuditMetricsByHours>
extractAuditMetricsByHours(JsonNode response, SearchFilter filter, String
timezone) {
+ List<RangerAuditMetricsByHours> metrics = new ArrayList<>();
+ JsonNode buckets =
response.at("/aggregations/per_hour/buckets");
+
+ if (!buckets.isArray()) {
+ return Collections.emptyList();
+ }
+
+ FilterParams params = auditMetricsHelper.getFilterParams(filter);
+ ZoneId zoneId = auditMetricsHelper.resolveZoneId(timezone);
+
+ for (JsonNode bucket : buckets) {
+ Long auditDate = parseBucketTime(bucket, timezone);
+
+ if (auditDate == null) {
+ continue;
+ }
+
+ ZonedDateTime dateTime =
ZonedDateTime.ofInstant(Instant.ofEpochMilli(auditDate), zoneId);
+ int hour = dateTime.getHour();
+
+ metrics.add(auditMetricsHelper.buildAuditMetricsByHours(params,
hour, bucket.get("doc_count").asLong()));
+ }
+
+ return metrics;
+ }
+
+ private Long parseBucketTime(JsonNode bucket, String timezone) {
+ Long result = null;
+
+ if (bucket != null) {
+ String keyAsString = bucket.get("key_as_string").asText(null);
+
+ if (keyAsString == null) {
+ keyAsString = bucket.get("key").asText(null);
+ }
+
+ if (keyAsString != null) {
+ result = auditMetricsHelper.parseAuditDate(keyAsString);
+ }
+ }
+
+ return result;
+ }
+}
diff --git
a/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
b/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
index 8a992b88a..44c916d6d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
@@ -20,6 +20,8 @@
package org.apache.ranger.rest;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsServiceFactory;
import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RESTErrorUtil;
@@ -29,7 +31,6 @@
import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
import org.apache.ranger.plugin.util.SearchFilter;
import org.apache.ranger.security.context.RangerAPIList;
-import org.apache.ranger.solr.SolrAccessAuditsService;
import org.apache.ranger.view.RangerAuditMetricsList;
import org.apache.ranger.view.RangerAuditMetricsListByDays;
import org.apache.ranger.view.RangerAuditMetricsListByHours;
@@ -73,7 +74,7 @@ public class AuditMetricsREST {
RangerSearchUtil searchUtil;
@Autowired
- SolrAccessAuditsService solrAccessAuditsService;
+ AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
@GET
@Path("/metrics/servicetype/{servicetype}/servicename/{servicename}")
@@ -84,7 +85,9 @@ public RangerAuditMetrics
getLatestAuditMetrics(@PathParam("servicetype") String
LOG.debug("==> AuditMetricsREST.getLatestAuditMetrics(serviceType={}
serviceName={})", serviceType, serviceName);
RangerAuditMetrics ret;
try {
- ret = solrAccessAuditsService.getLatestAuditMetrics(serviceType,
serviceName, timezone);
+ AccessAuditsMetricsService accessAuditsMetricsService =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ ret =
accessAuditsMetricsService.getLatestAuditMetrics(serviceType, serviceName,
timezone);
} catch (WebApplicationException excp) {
throw excp;
} catch (Throwable excp) {
@@ -104,7 +107,9 @@ public RangerAuditMetrics getAuditMetrics(@PathParam("id")
Long id, @QueryParam(
LOG.debug("==> AuditMetricsREST.getAuditMetrics(id={})", id);
RangerAuditMetrics ret;
try {
- ret = solrAccessAuditsService.getAuditMetrics(id, timezone);
+ AccessAuditsMetricsService accessAuditsMetricsService =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ ret = accessAuditsMetricsService.getAuditMetrics(id, timezone);
} catch (WebApplicationException excp) {
throw excp;
} catch (Throwable excp) {
@@ -128,7 +133,9 @@ public RangerAuditMetricsList
getAllLatestRangerAuditMetrics(@Context HttpServle
SearchFilter filter = searchUtil.getSearchFilter(request,
Collections.emptyList());
try {
- rangerAuditMetrics =
solrAccessAuditsService.getLatestAuditMetricsList(filter, timezone);
+ AccessAuditsMetricsService accessAuditsMetricsService =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ rangerAuditMetrics =
accessAuditsMetricsService.getLatestAuditMetricsList(filter, timezone);
} catch (WebApplicationException excp) {
throw excp;
} catch (Throwable excp) {
@@ -156,7 +163,9 @@ public RangerAuditMetricsListByHours
getDailyAuditMetrics(@Context HttpServletRe
SearchFilter filter = searchUtil.getSearchFilter(request,
Collections.emptyList());
try {
- rangerAuditMetricsByHours =
solrAccessAuditsService.getAuditMetricsByHours(filter, timezone);
+ AccessAuditsMetricsService accessAuditsMetricsService =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ rangerAuditMetricsByHours =
accessAuditsMetricsService.getAuditMetricsByHours(filter, timezone);
} catch (WebApplicationException excp) {
throw excp;
} catch (Throwable excp) {
@@ -191,7 +200,9 @@ public RangerAuditMetricsListByDays
getDaysAuditMetrics(@Context HttpServletRequ
List<RangerAuditMetricsByDays> rangerAuditMetricsByDays;
SearchFilter filter =
searchUtil.getSearchFilter(request, Collections.emptyList());
try {
- rangerAuditMetricsByDays =
solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, filter,
timezone);
+ AccessAuditsMetricsService accessAuditsMetricsService =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ rangerAuditMetricsByDays =
accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, filter,
timezone);
} catch (WebApplicationException excp) {
throw excp;
} catch (Throwable excp) {
diff --git
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
index 4e6a8510e..701b86a0f 100644
---
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
+++
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
@@ -20,6 +20,7 @@
package org.apache.ranger.solr;
import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
import org.apache.ranger.audit.provider.MiscUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.PropertiesUtil;
@@ -51,7 +52,7 @@
@Service
@Scope("singleton")
-public class SolrAccessAuditsService extends AccessAuditsService {
+public class SolrAccessAuditsService extends AccessAuditsService implements
AccessAuditsMetricsService {
private static final Logger LOGGER =
LoggerFactory.getLogger(SolrAccessAuditsService.class);
@Autowired
diff --git
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
index f926b6d26..f73319ee5 100644
---
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
+++
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
@@ -20,11 +20,11 @@
package org.apache.ranger.solr;
import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper.FilterParams;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RESTErrorUtil;
-import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.entity.XXService;
-import org.apache.ranger.entity.XXServiceDef;
import org.apache.ranger.plugin.model.RangerAuditMetrics;
import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
@@ -39,23 +39,17 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-import java.time.DateTimeException;
import java.time.Instant;
import java.time.ZoneId;
-import java.time.ZoneOffset;
import java.time.ZonedDateTime;
-import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
@Component
public class SolrAuditMetricsHelper {
private static final Logger LOGGER =
LoggerFactory.getLogger(SolrAuditMetricsHelper.class);
- private static final long MISSING_REPO_TYPE_SENTINEL = -1L;
private static final String FACET_REPO = "per_repo";
private static final String FACET_AGENT = "per_agent";
@@ -64,8 +58,6 @@ public class SolrAuditMetricsHelper {
private static final String BUCKET_VAL = "val";
private static final String FACETS_KEY = "facets";
- private final Map<String, Long> repoTypeByServiceType = new
ConcurrentHashMap<>();
-
@Autowired
SolrMgr solrMgr;
@@ -76,10 +68,10 @@ public class SolrAuditMetricsHelper {
RESTErrorUtil restErrorUtil;
@Autowired
- RangerDaoManager daoManager;
+ AuditMetricsHelper auditMetricsHelper;
public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone) {
- SearchFilter filter = buildSearchFilter(serviceType, serviceName,
null, null, null);
+ SearchFilter filter =
auditMetricsHelper.buildSearchFilter(serviceType, serviceName, null, null,
null);
SolrQuery query = buildMetricsQuery();
applyAuditMetricsFilters(query, filter);
@@ -88,7 +80,7 @@ public RangerAuditMetrics getLatestAuditMetrics(String
serviceType, String servi
QueryResponse response = runMetricsQuery(query, "latest audit
metrics");
long count = response.getResults() != null ?
response.getResults().getNumFound() : 0L;
- return buildAuditMetrics(serviceType, serviceName, null, null, null,
count);
+ return auditMetricsHelper.buildAuditMetrics(serviceType, serviceName,
null, null, null, count);
}
public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter, String timezone) {
@@ -124,16 +116,7 @@ public List<RangerAuditMetricsByHours>
getAuditMetricsByHours(SearchFilter filte
}
public String resolveServiceType(XXService service) {
- String ret = null;
-
- if (service != null && daoManager != null &&
daoManager.getXXServiceDef() != null) {
- XXServiceDef serviceDef =
daoManager.getXXServiceDef().getById(service.getType());
- if (serviceDef != null) {
- ret = serviceDef.getName();
- }
- }
-
- return ret;
+ return auditMetricsHelper.resolveServiceType(service);
}
private SolrQuery buildMetricsQuery() {
@@ -167,7 +150,6 @@ private QueryResponse runMetricsQuery(SolrQuery query,
String context) {
}
private String buildAuditAccessMetricsFacet(int olderThanInDays) {
- // If olderThanInDays is 7, we go back 6 days from today to include
today
int daysBack = olderThanInDays - 1;
return
String.format("{per_day:{type:range,field:evtTime,start:\"NOW-%dDAYS/DAY\",end:\"NOW\",gap:\"+1DAY\",mincount:1}}",
daysBack);
@@ -201,16 +183,6 @@ private void addTodayMetricsRangeFilter(SolrQuery query) {
query.addFilterQuery("evtTime:[NOW/DAY TO NOW]");
}
- private SearchFilter buildSearchFilter(String serviceType, String
serviceName, String appId, String clusterName, String clientIP) {
- SearchFilter filter = new SearchFilter();
- filter.setParam(SearchFilter.SERVICE_TYPE, serviceType);
- filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
- filter.setParam(SearchFilter.PLUGIN_APP_ID, appId);
- filter.setParam(SearchFilter.CLUSTER_NAME, clusterName);
- filter.setParam(SearchFilter.CLIENT_IP, clientIP);
- return filter;
- }
-
private void applyAuditMetricsFilters(SolrQuery query, SearchFilter
filter) {
if (query == null || filter == null) {
return;
@@ -221,8 +193,8 @@ private void applyAuditMetricsFilters(SolrQuery query,
SearchFilter filter) {
String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
if (StringUtils.isNotBlank(serviceType)) {
- long repoType = resolveRepoType(serviceType);
- if (repoType == MISSING_REPO_TYPE_SENTINEL) {
+ long repoType = auditMetricsHelper.resolveRepoType(serviceType);
+ if (repoType == AuditMetricsHelper.MISSING_REPO_TYPE_SENTINEL) {
query.addFilterQuery("repoType:-1");
} else {
query.addFilterQuery("repoType:" + repoType);
@@ -249,35 +221,13 @@ private void applyTimezone(SolrQuery query, String
timezone) {
}
String tz = timezone.trim();
- try {
- ZoneId.of(tz);
- query.set("TZ", tz);
- } catch (DateTimeException e) {
- query.set("TZ", "UTC");
- }
- }
+ ZoneId zoneId = auditMetricsHelper.parseZoneId(tz);
- private long resolveRepoType(String serviceType) {
- if (StringUtils.isBlank(serviceType)) {
- return MISSING_REPO_TYPE_SENTINEL;
- }
-
- String cacheKey = serviceType.trim().toLowerCase();
- Long cached = repoTypeByServiceType.get(cacheKey);
- if (cached != null) {
- return cached;
- }
-
- long resolved = MISSING_REPO_TYPE_SENTINEL;
- if (daoManager != null && daoManager.getXXServiceDef() != null) {
- XXServiceDef serviceDef =
daoManager.getXXServiceDef().findByName(serviceType);
- if (serviceDef != null && serviceDef.getId() != null) {
- resolved = serviceDef.getId();
- }
+ if (zoneId != null) {
+ query.set("TZ", zoneId.getId());
+ } else {
+ query.set("TZ", "UTC");
}
-
- repoTypeByServiceType.put(cacheKey, resolved);
- return resolved;
}
private List<RangerAuditMetrics> extractAuditMetricsList(QueryResponse
response, SearchFilter filter) {
@@ -312,7 +262,7 @@ private void processRepoBuckets(List<?> repoBuckets,
List<RangerAuditMetrics> me
List<?> agentBuckets = extractBuckets(getBucketValue(repoBucket,
FACET_AGENT));
if (agentBuckets == null || agentBuckets.isEmpty()) {
- metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName,
null, null, null, bucketCount(repoBucket)));
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, null, null, null, bucketCount(repoBucket)));
} else {
processAgentBuckets(agentBuckets, metrics, serviceTypeFilter,
serviceName);
}
@@ -326,7 +276,7 @@ private void processAgentBuckets(List<?> agentBuckets,
List<RangerAuditMetrics>
List<?> cliIpBuckets = extractBuckets(getBucketValue(agentBucket,
FACET_CLIIP));
if (cliIpBuckets == null || cliIpBuckets.isEmpty()) {
- metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName,
appId, null, null, bucketCount(agentBucket)));
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, null, null, bucketCount(agentBucket)));
} else {
processCliIpBuckets(cliIpBuckets, metrics, serviceTypeFilter,
serviceName, appId);
}
@@ -339,7 +289,7 @@ private void processCliIpBuckets(List<?> cliIpBuckets,
List<RangerAuditMetrics>
List<?> clusterBuckets =
extractBuckets(getBucketValue(cliIpBucket, FACET_CLUSTER));
if (clusterBuckets == null || clusterBuckets.isEmpty()) {
- metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName,
appId, null, clientIP, bucketCount(cliIpBucket)));
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, null, clientIP, bucketCount(cliIpBucket)));
} else {
processClusterBuckets(clusterBuckets, metrics,
serviceTypeFilter, serviceName, appId, clientIP);
}
@@ -349,7 +299,7 @@ private void processCliIpBuckets(List<?> cliIpBuckets,
List<RangerAuditMetrics>
private void processClusterBuckets(List<?> clusterBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName,
String appId, String clientIP) {
for (Object clusterBucket : clusterBuckets) {
String clusterName =
bucketValToString(getBucketValue(clusterBucket, BUCKET_VAL));
- metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName,
appId, clusterName, clientIP, bucketCount(clusterBucket)));
+
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter,
serviceName, appId, clusterName, clientIP, bucketCount(clusterBucket)));
}
}
@@ -371,51 +321,6 @@ private String bucketValToString(Object value) {
return ret;
}
- private RangerAuditMetrics buildAuditMetrics(String serviceType, String
serviceName, String appId, String clusterName, String clientIP, long count) {
- RangerAuditMetrics metric = new RangerAuditMetrics();
- metric.setServiceName(serviceName);
- metric.setServiceType(resolveServiceType(serviceType, serviceName));
- metric.setAppId(appId);
- metric.setClusterName(clusterName);
- metric.setClientIP(clientIP);
- metric.setNumberOfAudits(count);
-
- Long serviceId = resolveServiceId(serviceName);
- if (serviceId != null) {
- metric.setId(serviceId);
- }
-
- return metric;
- }
-
- private Long resolveServiceId(String serviceName) {
- Long ret = null;
-
- if (StringUtils.isNotBlank(serviceName) && daoManager != null &&
daoManager.getXXService() != null) {
- XXService service =
daoManager.getXXService().findByName(serviceName);
- if (service != null) {
- ret = service.getId();
- }
- }
-
- return ret;
- }
-
- private String resolveServiceType(String serviceType, String serviceName) {
- String ret = serviceType;
-
- if (StringUtils.isBlank(ret)) {
- if (StringUtils.isNotBlank(serviceName) && daoManager != null &&
daoManager.getXXService() != null) {
- XXService service =
daoManager.getXXService().findByName(serviceName);
- ret = resolveServiceType(service);
- } else {
- ret = null;
- }
- }
-
- return ret;
- }
-
private List<RangerAuditMetricsByDays>
extractAuditMetricsByDays(QueryResponse response, SearchFilter filter) {
NamedList<Object> responseList = response.getResponse();
if (responseList == null) {
@@ -436,15 +341,11 @@ private List<RangerAuditMetricsByDays>
extractAuditMetricsByDays(QueryResponse r
}
List<RangerAuditMetricsByDays> metrics = new ArrayList<>();
- String serviceType = filter != null ?
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
- String serviceName = filter != null ?
filter.getParam(SearchFilter.SERVICE_NAME) : null;
- String appId = filter != null ?
filter.getParam(SearchFilter.PLUGIN_APP_ID) : null;
- String clusterName = filter != null ?
filter.getParam(SearchFilter.CLUSTER_NAME) : null;
- String clientIP = filter != null ?
filter.getParam(SearchFilter.CLIENT_IP) : null;
+ FilterParams params = auditMetricsHelper.getFilterParams(filter);
for (Object bucketObj : buckets) {
Object dateValue = getBucketValue(bucketObj, BUCKET_VAL);
- Long auditDate = parseAuditDate(dateValue);
+ Long auditDate = auditMetricsHelper.parseAuditDate(dateValue);
if (auditDate == null) {
continue;
}
@@ -452,8 +353,7 @@ private List<RangerAuditMetricsByDays>
extractAuditMetricsByDays(QueryResponse r
Object countObj = getBucketValue(bucketObj, "count");
long count = countObj instanceof Number ? ((Number)
countObj).longValue() : 0L;
- RangerAuditMetricsByDays metric = new
RangerAuditMetricsByDays(serviceType, serviceName, appId, clusterName,
clientIP, auditDate, count);
- metrics.add(metric);
+ metrics.add(auditMetricsHelper.buildAuditMetricsByDays(params,
auditDate, count));
}
return metrics;
@@ -479,15 +379,12 @@ private List<RangerAuditMetricsByHours>
extractAuditMetricsByHours(QueryResponse
}
List<RangerAuditMetricsByHours> metrics = new ArrayList<>();
- String serviceType = filter != null ?
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
- String serviceName = filter != null ?
filter.getParam(SearchFilter.SERVICE_NAME) : null;
- String appId = filter != null ?
filter.getParam(SearchFilter.PLUGIN_APP_ID) : null;
- String clusterName = filter != null ?
filter.getParam(SearchFilter.CLUSTER_NAME) : null;
- String clientIP = filter != null ?
filter.getParam(SearchFilter.CLIENT_IP) : null;
+ FilterParams params = auditMetricsHelper.getFilterParams(filter);
+ ZoneId zoneId = auditMetricsHelper.resolveZoneId(timezone);
for (Object bucketObj : buckets) {
Object dateValue = getBucketValue(bucketObj, BUCKET_VAL);
- Long auditDate = parseAuditDate(dateValue);
+ Long auditDate = auditMetricsHelper.parseAuditDate(dateValue);
if (auditDate == null) {
continue;
}
@@ -495,31 +392,15 @@ private List<RangerAuditMetricsByHours>
extractAuditMetricsByHours(QueryResponse
Object countObj = getBucketValue(bucketObj, "count");
long count = countObj instanceof Number ? ((Number)
countObj).longValue() : 0L;
- ZoneId zoneId = resolveZoneId(timezone);
ZonedDateTime dateTime =
ZonedDateTime.ofInstant(Instant.ofEpochMilli(auditDate), zoneId);
int hour = dateTime.getHour();
- RangerAuditMetricsByHours metric = new
RangerAuditMetricsByHours(serviceType, serviceName, appId, clusterName,
clientIP, hour, count);
- metrics.add(metric);
+ metrics.add(auditMetricsHelper.buildAuditMetricsByHours(params,
hour, count));
}
return metrics;
}
- private ZoneId resolveZoneId(String timezone) {
- ZoneId ret = ZoneOffset.UTC;
-
- if (StringUtils.isNotBlank(timezone)) {
- try {
- ret = ZoneId.of(timezone.trim());
- } catch (DateTimeException e) {
- LOGGER.warn("Invalid timezone '{}', using UTC", timezone, e);
- }
- }
-
- return ret;
- }
-
private List<?> extractBuckets(Object perDayObj) {
List<?> ret = Collections.emptyList();
@@ -549,22 +430,4 @@ private Object getBucketValue(Object bucketObj, String
key) {
return ret;
}
-
- private Long parseAuditDate(Object value) {
- Long ret = null;
-
- if (value instanceof Date) {
- ret = ((Date) value).getTime();
- } else if (value instanceof Number) {
- ret = ((Number) value).longValue();
- } else if (value instanceof String) {
- try {
- ret = Instant.parse((String) value).toEpochMilli();
- } catch (DateTimeParseException e) {
- LOGGER.warn("Unable to parse audit metric date value: {}",
value, e);
- }
- }
-
- return ret;
- }
}
diff --git
a/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
b/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
new file mode 100644
index 000000000..a4ded6739
--- /dev/null
+++
b/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ranger.audit.metrics;
+
+import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.opensearch.OpenSearchAccessAuditsService;
+import org.apache.ranger.solr.SolrAccessAuditsService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class AccessAuditsMetricsServiceFactoryTest {
+ @Mock
+ RangerBizUtil rangerBizUtil;
+
+ @Mock
+ SolrAccessAuditsService solrAccessAuditsService;
+
+ @Mock
+ OpenSearchAccessAuditsService openSearchAccessAuditsService;
+
+ @InjectMocks
+ AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
+
+ @BeforeEach
+ void setUp() {
+
when(rangerBizUtil.getAuditDBType()).thenReturn(RangerBizUtil.AUDIT_STORE_SOLR);
+ }
+
+ @Test
+ void getAccessAuditsMetricsService_returnsSolrByDefault() {
+ AccessAuditsMetricsService service =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ assertSame(solrAccessAuditsService, service);
+ }
+
+ @Test
+ void getAccessAuditsMetricsService_returnsOpenSearchWhenConfigured() {
+
when(rangerBizUtil.getAuditDBType()).thenReturn(RangerBizUtil.AUDIT_STORE_OPENSEARCH);
+
+ AccessAuditsMetricsService service =
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+ assertSame(openSearchAccessAuditsService, service);
+ }
+}
diff --git
a/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
b/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
new file mode 100644
index 000000000..ae8a355b9
--- /dev/null
+++
b/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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.ranger.opensearch;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.StatusLine;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXServiceDao;
+import org.apache.ranger.db.XXServiceDefDao;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class OpenSearchAuditMetricsHelperTest {
+ @Test
+ void getLatestAuditMetrics_returnsCount() throws Exception {
+ OpenSearchAuditMetricsHelper helper =
createHelperWithServiceId("dev_hdfs", 1L);
+ stubOpenSearchResponse(helper,
"{\"hits\":{\"total\":{\"value\":42}}}", 200);
+
+ RangerAuditMetrics metrics = helper.getLatestAuditMetrics("hdfs",
"dev_hdfs", null);
+
+ assertEquals("dev_hdfs", metrics.getServiceName());
+ assertEquals("hdfs", metrics.getServiceType());
+ assertEquals(42L, metrics.getNumberOfAudits());
+ }
+
+ @Test
+ void getLatestAuditMetrics_whenClientNull_throws() {
+ OpenSearchAuditMetricsHelper helper = new
OpenSearchAuditMetricsHelper();
+ helper.openSearchMgr = mock(OpenSearchMgr.class);
+ helper.restErrorUtil = new RESTErrorUtil();
+ helper.auditMetricsHelper = new AuditMetricsHelper();
+
+ when(helper.openSearchMgr.getClient()).thenReturn(null);
+
+ assertThrows(WebApplicationException.class, () ->
helper.getLatestAuditMetrics("hdfs", "dev_hdfs", null));
+ }
+
+ @Test
+ void getLatestAuditMetrics_whenHttpError_throws() throws Exception {
+ OpenSearchAuditMetricsHelper helper = createHelper();
+ stubOpenSearchErrorResponse(helper, 400);
+
+ assertThrows(WebApplicationException.class, () ->
helper.getLatestAuditMetrics("hdfs", "dev_hdfs", null));
+ }
+
+ @Test
+ void getLatestAuditMetricsList_includesAgentCliIpAndCluster() throws
Exception {
+ OpenSearchAuditMetricsHelper helper = createHelperWithDao("dev_hdfs",
1L, "hdfs", 10L);
+ stubOpenSearchResponse(helper, buildNestedMetricsResponse("dev_hdfs",
"hdfs", "172.18.0.16", "ABC cluster", 7L), 200);
+
+ List<RangerAuditMetrics> metrics =
helper.getLatestAuditMetricsList(new SearchFilter(), null);
+
+ assertEquals(1, metrics.size());
+ RangerAuditMetrics metric = metrics.get(0);
+ assertEquals("dev_hdfs", metric.getServiceName());
+ assertEquals("hdfs", metric.getAppId());
+ assertEquals("172.18.0.16", metric.getClientIP());
+ assertEquals("ABC cluster", metric.getClusterName());
+ assertEquals(7L, metric.getNumberOfAudits());
+ assertEquals(1L, metric.getId());
+ }
+
+ @Test
+ void getLatestAuditMetricsList_missingAgent_omitsAppId() throws Exception {
+ OpenSearchAuditMetricsHelper helper = createHelperWithDao("dev_hdfs",
1L, "hdfs", 10L);
+ stubOpenSearchResponse(helper, buildNestedMetricsResponse("dev_hdfs",
"", "172.18.0.16", "ABC cluster", 5L), 200);
+
+ List<RangerAuditMetrics> metrics =
helper.getLatestAuditMetricsList(new SearchFilter(), null);
+
+ assertEquals(1, metrics.size());
+ assertNull(metrics.get(0).getAppId());
+ assertEquals("172.18.0.16", metrics.get(0).getClientIP());
+ assertEquals("ABC cluster", metrics.get(0).getClusterName());
+ assertEquals(5L, metrics.get(0).getNumberOfAudits());
+ }
+
+ @Test
+ void getAuditMetricsByDays_returnsDailyBuckets() throws Exception {
+ OpenSearchAuditMetricsHelper helper = createHelper();
+ stubOpenSearchResponse(helper,
+
"{\"aggregations\":{\"per_day\":{\"buckets\":[{\"key_as_string\":\"2026-08-11T00:00:00.000Z\",\"doc_count\":25}]}}}",
+ 200);
+
+ SearchFilter filter = new SearchFilter();
+ filter.setParam(SearchFilter.SERVICE_NAME, "dev_hdfs");
+ filter.setParam(SearchFilter.SERVICE_TYPE, "hdfs");
+
+ List<RangerAuditMetricsByDays> metrics =
helper.getAuditMetricsByDays(7, filter, "UTC");
+
+ assertEquals(1, metrics.size());
+ assertEquals(25L, metrics.get(0).getNumberOfAudits());
+ assertEquals("dev_hdfs", metrics.get(0).getServiceName());
+ assertEquals("hdfs", metrics.get(0).getServiceType());
+ }
+
+ @Test
+ void getAuditMetricsByHours_returnsHourlyBuckets() throws Exception {
+ OpenSearchAuditMetricsHelper helper = createHelper();
+ stubOpenSearchResponse(helper,
+
"{\"aggregations\":{\"per_hour\":{\"buckets\":[{\"key_as_string\":\"2026-08-11T12:00:00.000Z\",\"doc_count\":15}]}}}",
+ 200);
+
+ List<RangerAuditMetricsByHours> metrics =
helper.getAuditMetricsByHours(new SearchFilter(), "UTC");
+
+ assertEquals(1, metrics.size());
+ assertEquals(12, metrics.get(0).getHours());
+ assertEquals(15L, metrics.get(0).getNumberOfAudits());
+ }
+
+ private OpenSearchAuditMetricsHelper createHelper() {
+ OpenSearchAuditMetricsHelper helper = new
OpenSearchAuditMetricsHelper();
+ helper.openSearchMgr = mock(OpenSearchMgr.class);
+ helper.restErrorUtil = new RESTErrorUtil();
+ helper.auditMetricsHelper = new AuditMetricsHelper();
+
+ return helper;
+ }
+
+ private OpenSearchAuditMetricsHelper createHelperWithServiceId(String
serviceName, Long serviceId) throws Exception {
+ RangerDaoManager daoManager = mock(RangerDaoManager.class);
+ XXServiceDao svcDao = mock(XXServiceDao.class);
+ XXService xxService = mock(XXService.class);
+
+ when(daoManager.getXXService()).thenReturn(svcDao);
+ when(svcDao.findByName(serviceName)).thenReturn(xxService);
+ when(xxService.getId()).thenReturn(serviceId);
+
+ return injectDaoManager(createHelper(), daoManager);
+ }
+
+ private OpenSearchAuditMetricsHelper createHelperWithDao(String
serviceName, Long serviceId, String serviceType, Long serviceDefId) throws
Exception {
+ RangerDaoManager daoManager = mock(RangerDaoManager.class);
+ XXServiceDao svcDao = mock(XXServiceDao.class);
+ XXServiceDefDao sdDao = mock(XXServiceDefDao.class);
+ XXService xxService = mock(XXService.class);
+ XXServiceDef sd = mock(XXServiceDef.class);
+
+ when(daoManager.getXXService()).thenReturn(svcDao);
+ when(daoManager.getXXServiceDef()).thenReturn(sdDao);
+ when(svcDao.findByName(serviceName)).thenReturn(xxService);
+ when(xxService.getId()).thenReturn(serviceId);
+ when(xxService.getType()).thenReturn(serviceDefId);
+ when(sdDao.getById(serviceDefId)).thenReturn(sd);
+ when(sd.getName()).thenReturn(serviceType);
+
+ return injectDaoManager(createHelper(), daoManager);
+ }
+
+ private OpenSearchAuditMetricsHelper
injectDaoManager(OpenSearchAuditMetricsHelper helper, RangerDaoManager
daoManager) throws Exception {
+ java.lang.reflect.Field daoField =
AuditMetricsHelper.class.getDeclaredField("daoManager");
+
+ daoField.setAccessible(true);
+ daoField.set(helper.auditMetricsHelper, daoManager);
+
+ return helper;
+ }
+
+ private void stubOpenSearchResponse(OpenSearchAuditMetricsHelper helper,
String json, int statusCode) throws Exception {
+ RestClient client = mock(RestClient.class);
+ Response response = mock(Response.class);
+ StatusLine statusLine = mock(StatusLine.class);
+ HttpEntity entity = mock(HttpEntity.class);
+
+ when(helper.openSearchMgr.getClient()).thenReturn(client);
+ when(helper.openSearchMgr.getIndex()).thenReturn("ranger_audits");
+ when(client.performRequest(any(Request.class))).thenReturn(response);
+ when(response.getStatusLine()).thenReturn(statusLine);
+ when(statusLine.getStatusCode()).thenReturn(statusCode);
+ when(response.getEntity()).thenReturn(entity);
+ when(entity.getContent()).thenReturn(new
ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ private void stubOpenSearchErrorResponse(OpenSearchAuditMetricsHelper
helper, int statusCode) throws Exception {
+ RestClient client = mock(RestClient.class);
+ Response response = mock(Response.class);
+ StatusLine statusLine = mock(StatusLine.class);
+
+ when(helper.openSearchMgr.getClient()).thenReturn(client);
+ when(helper.openSearchMgr.getIndex()).thenReturn("ranger_audits");
+ when(client.performRequest(any(Request.class))).thenReturn(response);
+ when(response.getStatusLine()).thenReturn(statusLine);
+ when(statusLine.getStatusCode()).thenReturn(statusCode);
+ }
+
+ private String buildNestedMetricsResponse(String serviceName, String
appId, String clientIP, String clusterName, long count) {
+ return "{"
+ + "\"aggregations\":{"
+ + "\"per_repo\":{\"buckets\":[{\"key\":\"" + serviceName +
"\",\"doc_count\":" + count + ","
+ + "\"per_agent\":{\"buckets\":[{\"key\":\"" + appId +
"\",\"doc_count\":" + count + ","
+ + "\"per_cliip\":{\"buckets\":[{\"key\":\"" + clientIP +
"\",\"doc_count\":" + count + ","
+ + "\"per_cluster\":{\"buckets\":[{\"key\":\"" + clusterName +
"\",\"doc_count\":" + count + "}]"
+ + "}}]}}]}}]}"
+ + "}}";
+ }
+}
diff --git
a/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
b/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
index bf31dfcb3..724b2a400 100644
---
a/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
+++
b/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
@@ -19,6 +19,8 @@
package org.apache.ranger.rest;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsServiceFactory;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerSearchUtil;
@@ -26,7 +28,6 @@
import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.solr.SolrAccessAuditsService;
import org.apache.ranger.view.RangerAuditMetricsList;
import org.apache.ranger.view.RangerAuditMetricsListByDays;
import org.apache.ranger.view.RangerAuditMetricsListByHours;
@@ -53,6 +54,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -72,7 +74,10 @@ class TestAuditMetricsREST {
RangerSearchUtil searchUtil;
@Mock
- SolrAccessAuditsService solrAccessAuditsService;
+ AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
+
+ @Mock
+ AccessAuditsMetricsService accessAuditsMetricsService;
@Mock
HttpServletRequest httpServletRequest;
@@ -91,6 +96,7 @@ void setUp() {
testAuditMetricsByHours = createTestAuditMetricsByHours();
testAuditMetricsByDays = createTestAuditMetricsByDays();
testSearchFilter = new SearchFilter();
+
lenient().when(accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService()).thenReturn(accessAuditsMetricsService);
}
@Test
@@ -98,7 +104,7 @@ void testGetLatestAuditMetrics_Success() {
String serviceType = "hive";
String serviceName = "test-service";
String timezone = "Asia/Kolkata";
- when(solrAccessAuditsService.getLatestAuditMetrics(serviceType,
serviceName, timezone)).thenReturn(testAuditMetrics);
+ when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType,
serviceName, timezone)).thenReturn(testAuditMetrics);
RangerAuditMetrics result =
auditMetricsREST.getLatestAuditMetrics(serviceType, serviceName, timezone);
@@ -106,7 +112,7 @@ void testGetLatestAuditMetrics_Success() {
assertEquals(testAuditMetrics.getId(), result.getId());
assertEquals(testAuditMetrics.getServiceType(),
result.getServiceType());
assertEquals(testAuditMetrics.getNumberOfAudits(),
result.getNumberOfAudits());
- verify(solrAccessAuditsService,
times(1)).getLatestAuditMetrics(serviceType, serviceName, timezone);
+ verify(accessAuditsMetricsService,
times(1)).getLatestAuditMetrics(serviceType, serviceName, timezone);
}
@Test
@@ -114,7 +120,7 @@ void testGetLatestAuditMetrics_WebApplicationException() {
String serviceType = "hive";
String serviceName = "test-service";
WebApplicationException webException = new WebApplicationException();
- when(solrAccessAuditsService.getLatestAuditMetrics(serviceType,
serviceName, null)).thenThrow(webException);
+ when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType,
serviceName, null)).thenThrow(webException);
WebApplicationException exception =
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getLatestAuditMetrics(serviceType,
serviceName, null));
@@ -127,7 +133,7 @@ void testGetLatestAuditMetrics_WebApplicationException() {
void testGetLatestAuditMetrics_GeneralException() {
String serviceType = "hive";
String serviceName = "test-service";
- when(solrAccessAuditsService.getLatestAuditMetrics(serviceType,
serviceName, null))
+ when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType,
serviceName, null))
.thenThrow(new RuntimeException("General exception"));
when(restErrorUtil.createRESTException(anyString())).thenReturn(new
WebApplicationException());
@@ -141,21 +147,21 @@ void testGetLatestAuditMetrics_GeneralException() {
void testGetAuditMetrics_Success() {
Long id = 1L;
String timezone = "UTC";
- when(solrAccessAuditsService.getAuditMetrics(id,
timezone)).thenReturn(testAuditMetrics);
+ when(accessAuditsMetricsService.getAuditMetrics(id,
timezone)).thenReturn(testAuditMetrics);
RangerAuditMetrics result = auditMetricsREST.getAuditMetrics(id,
timezone);
assertNotNull(result);
assertEquals(testAuditMetrics.getId(), result.getId());
assertEquals(testAuditMetrics.getServiceName(),
result.getServiceName());
- verify(solrAccessAuditsService, times(1)).getAuditMetrics(id,
timezone);
+ verify(accessAuditsMetricsService, times(1)).getAuditMetrics(id,
timezone);
}
@Test
void testGetAuditMetrics_WebApplicationException() {
Long id = 1L;
WebApplicationException webException = new WebApplicationException();
- when(solrAccessAuditsService.getAuditMetrics(id,
null)).thenThrow(webException);
+ when(accessAuditsMetricsService.getAuditMetrics(id,
null)).thenThrow(webException);
WebApplicationException exception =
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getAuditMetrics(id, null));
@@ -167,7 +173,7 @@ void testGetAuditMetrics_WebApplicationException() {
@Test
void testGetAuditMetrics_GeneralException() {
Long id = 1L;
- when(solrAccessAuditsService.getAuditMetrics(id, null)).thenThrow(new
RuntimeException("General exception"));
+ when(accessAuditsMetricsService.getAuditMetrics(id,
null)).thenThrow(new RuntimeException("General exception"));
when(restErrorUtil.createRESTException(anyString())).thenReturn(new
WebApplicationException());
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getAuditMetrics(id, null));
@@ -180,21 +186,21 @@ void testGetAllLatestRangerAuditMetrics_Success() {
List<RangerAuditMetrics> metricsList =
Collections.singletonList(testAuditMetrics);
String timezone = "Asia/Kolkata";
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter,
timezone)).thenReturn(metricsList);
+
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter,
timezone)).thenReturn(metricsList);
RangerAuditMetricsList result =
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, timezone);
assertNotNull(result);
assertEquals(1, result.getListSize());
assertEquals(testAuditMetrics,
result.getRangerAuditMetricsList().get(0));
- verify(solrAccessAuditsService,
times(1)).getLatestAuditMetricsList(testSearchFilter, timezone);
+ verify(accessAuditsMetricsService,
times(1)).getLatestAuditMetricsList(testSearchFilter, timezone);
}
@Test
void testGetAllLatestRangerAuditMetrics_WebApplicationException() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
WebApplicationException webException = new WebApplicationException();
-
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter,
null)).thenThrow(webException);
+
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter,
null)).thenThrow(webException);
WebApplicationException exception =
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, null));
@@ -206,7 +212,7 @@ void
testGetAllLatestRangerAuditMetrics_WebApplicationException() {
@Test
void testGetAllLatestRangerAuditMetrics_EmptyList() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter,
null)).thenReturn(Collections.emptyList());
+
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter,
null)).thenReturn(Collections.emptyList());
RangerAuditMetricsList result =
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, null);
@@ -217,7 +223,7 @@ void testGetAllLatestRangerAuditMetrics_EmptyList() {
@Test
void testGetAllLatestRangerAuditMetrics_GeneralException() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter, null))
+
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter,
null))
.thenThrow(new RuntimeException("General exception"));
when(restErrorUtil.createRESTException(anyString())).thenReturn(new
WebApplicationException());
@@ -232,20 +238,20 @@ void testGetDailyAuditMetrics_Success() {
List<RangerAuditMetricsByHours> metricsList =
Collections.singletonList(testAuditMetricsByHours);
String timezone = "Asia/Kolkata";
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter,
timezone)).thenReturn(metricsList);
+
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter,
timezone)).thenReturn(metricsList);
RangerAuditMetricsListByHours result =
auditMetricsREST.getDailyAuditMetrics(httpServletRequest, timezone);
assertNotNull(result);
assertEquals(1, result.getListSize());
- verify(solrAccessAuditsService,
times(1)).getAuditMetricsByHours(testSearchFilter, timezone);
+ verify(accessAuditsMetricsService,
times(1)).getAuditMetricsByHours(testSearchFilter, timezone);
}
@Test
void testGetDailyAuditMetrics_WebApplicationException() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
WebApplicationException webException = new WebApplicationException();
- when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter,
null)).thenThrow(webException);
+
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter,
null)).thenThrow(webException);
WebApplicationException exception =
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getDailyAuditMetrics(httpServletRequest,
null));
@@ -257,7 +263,7 @@ void testGetDailyAuditMetrics_WebApplicationException() {
@Test
void testGetDailyAuditMetrics_GeneralException() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter,
null))
+
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter, null))
.thenThrow(new RuntimeException("Daily metrics failed"));
when(restErrorUtil.createRESTException(anyString())).thenReturn(new
WebApplicationException());
@@ -270,7 +276,7 @@ void testGetDailyAuditMetrics_GeneralException() {
@Test
void testGetDailyAuditMetrics_EmptyList() {
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter,
null)).thenReturn(Collections.emptyList());
+
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter,
null)).thenReturn(Collections.emptyList());
RangerAuditMetricsListByHours result =
auditMetricsREST.getDailyAuditMetrics(httpServletRequest, null);
@@ -284,13 +290,13 @@ void testGetDaysAuditMetrics_Success() {
String timezone = "Asia/Kolkata";
List<RangerAuditMetricsByDays> metricsList =
Collections.singletonList(testAuditMetricsByDays);
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, timezone)).thenReturn(metricsList);
+ when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, timezone)).thenReturn(metricsList);
RangerAuditMetricsListByDays result =
auditMetricsREST.getDaysAuditMetrics(httpServletRequest, olderThanInDays,
timezone);
assertNotNull(result);
assertEquals(1, result.getListSize());
- verify(solrAccessAuditsService,
times(1)).getAuditMetricsByDays(olderThanInDays, testSearchFilter, timezone);
+ verify(accessAuditsMetricsService,
times(1)).getAuditMetricsByDays(olderThanInDays, testSearchFilter, timezone);
}
@Test
@@ -298,7 +304,7 @@ void testGetDaysAuditMetrics_WebApplicationException() {
Integer olderThanInDays = 7;
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
WebApplicationException webException = new WebApplicationException();
- when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null)).thenThrow(webException);
+ when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null)).thenThrow(webException);
WebApplicationException exception =
assertThrows(WebApplicationException.class, () ->
auditMetricsREST.getDaysAuditMetrics(httpServletRequest,
olderThanInDays, null));
@@ -311,7 +317,7 @@ void testGetDaysAuditMetrics_WebApplicationException() {
void testGetDaysAuditMetrics_GeneralException() {
Integer olderThanInDays = 7;
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null))
+ when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null))
.thenThrow(new RuntimeException("Days metrics failed"));
when(restErrorUtil.createRESTException(anyString())).thenReturn(new
WebApplicationException());
@@ -325,7 +331,7 @@ void testGetDaysAuditMetrics_GeneralException() {
void testGetDaysAuditMetrics_EmptyList() {
Integer olderThanInDays = 7;
when(searchUtil.getSearchFilter(eq(httpServletRequest),
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
- when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null))
+ when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays,
testSearchFilter, null))
.thenReturn(Collections.emptyList());
RangerAuditMetricsListByDays result =
auditMetricsREST.getDaysAuditMetrics(httpServletRequest, olderThanInDays, null);
@@ -345,7 +351,7 @@ void testGetDaysAuditMetrics_invalidOlderThanInDays_zero() {
verify(restErrorUtil, times(1)).createRESTException(
contains("olderThanInDays must be between 1 and"),
eq(MessageEnums.INVALID_INPUT_DATA));
- verify(solrAccessAuditsService,
never()).getAuditMetricsByDays(anyInt(), any(), any());
+ verify(accessAuditsMetricsService,
never()).getAuditMetricsByDays(anyInt(), any(), any());
}
@Test
@@ -359,7 +365,7 @@ void
testGetDaysAuditMetrics_invalidOlderThanInDays_exceedsMax() {
verify(restErrorUtil, times(1)).createRESTException(
contains("olderThanInDays must be between 1 and"),
eq(MessageEnums.INVALID_INPUT_DATA));
- verify(solrAccessAuditsService,
never()).getAuditMetricsByDays(anyInt(), any(), any());
+ verify(accessAuditsMetricsService,
never()).getAuditMetricsByDays(anyInt(), any(), any());
}
private RangerAuditMetrics createTestAuditMetrics() {
diff --git
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
index a8f340540..4cd9f6e57 100644
---
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
+++
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
@@ -17,6 +17,7 @@
package org.apache.ranger.solr;
import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.SearchCriteria;
@@ -241,7 +242,7 @@ public void getAuditMetrics_success_setsServiceId() throws
Throwable {
when(sdDao.getById(1L)).thenReturn(sd);
when(sd.getName()).thenReturn("hdfs");
injectField(service, AccessAuditsService.class, "daoManager",
daoManager);
- service.auditMetricsHelper.daoManager = daoManager;
+ injectField(service.auditMetricsHelper.auditMetricsHelper,
AuditMetricsHelper.class, "daoManager", daoManager);
RangerAuditMetrics metrics = service.getAuditMetrics(5L, null);
@@ -253,6 +254,7 @@ public void getAuditMetrics_success_setsServiceId() throws
Throwable {
private SolrAccessAuditsService createServiceWithHelper() {
SolrAccessAuditsService service = new SolrAccessAuditsService();
service.auditMetricsHelper = new SolrAuditMetricsHelper();
+ service.auditMetricsHelper.auditMetricsHelper = new
AuditMetricsHelper();
service.auditMetricsHelper.solrMgr = mock(SolrMgr.class);
service.auditMetricsHelper.solrUtil = mock(SolrUtil.class);
service.auditMetricsHelper.restErrorUtil = new RESTErrorUtil();
diff --git
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
index 8ab339633..870267b6a 100644
---
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
+++
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.ranger.solr;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.db.XXServiceDao;
@@ -230,7 +231,19 @@ private SolrAuditMetricsHelper
createHelper(RangerDaoManager daoManager) {
helper.solrMgr = mock(SolrMgr.class);
helper.solrUtil = mock(SolrUtil.class);
helper.restErrorUtil = new RESTErrorUtil();
- helper.daoManager = daoManager;
+ helper.auditMetricsHelper = new AuditMetricsHelper();
+
+ if (daoManager != null) {
+ try {
+ java.lang.reflect.Field daoField =
AuditMetricsHelper.class.getDeclaredField("daoManager");
+
+ daoField.setAccessible(true);
+ daoField.set(helper.auditMetricsHelper, daoManager);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
return helper;
}