This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.6
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.6 by this push:
new 29b949f18 RANGER-4970: add custom condition to support validity
schedule
29b949f18 is described below
commit 29b949f18be929e327b1b8c26f2a9ace2f2eed27
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Mon Oct 28 16:42:16 2024 -0700
RANGER-4970: add custom condition to support validity schedule
(cherry picked from commit ad1fdce46890d9f26d8f3767bd03576e66005510)
---
.../RangerValidityScheduleConditionEvaluator.java | 91 +++++++++++
...stRangerValidityScheduleConditionEvaluator.java | 166 +++++++++++++++++++++
2 files changed, 257 insertions(+)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerValidityScheduleConditionEvaluator.java
b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerValidityScheduleConditionEvaluator.java
new file mode 100644
index 000000000..2c4a756a3
--- /dev/null
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerValidityScheduleConditionEvaluator.java
@@ -0,0 +1,91 @@
+/*
+ * 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.plugin.conditionevaluator;
+
+import org.apache.ranger.authorization.utils.JsonUtils;
+import org.apache.ranger.plugin.model.RangerValiditySchedule;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import
org.apache.ranger.plugin.policyevaluator.RangerValidityScheduleEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+public class RangerValidityScheduleConditionEvaluator extends
RangerAbstractConditionEvaluator {
+ private static final Logger LOG =
LoggerFactory.getLogger(RangerValidityScheduleConditionEvaluator.class);
+
+ private List<RangerValidityScheduleEvaluator> evaluators =
Collections.emptyList();
+
+ @Override
+ public void init() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> RangerValidityScheduleConditionEvaluator.init({})",
condition);
+ }
+
+ super.init();
+
+ if (condition != null && condition.getValues() != null &&
!condition.getValues().isEmpty()) {
+ evaluators = new ArrayList<>(condition.getValues().size());
+
+ for (String scheduleStr : condition.getValues()) {
+ try {
+ RangerValiditySchedule schedule =
JsonUtils.jsonToObject(scheduleStr, RangerValiditySchedule.class);
+
+ if (schedule != null) {
+ evaluators.add(new
RangerValidityScheduleEvaluator(schedule));
+ }
+ } catch (Exception excp) {
+
LOG.error("RangerValidityScheduleConditionEvaluator.init({}): failed to
initialize schedule {}", condition, scheduleStr, excp);
+ }
+
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== RangerValidityScheduleConditionEvaluator.init({}):
evaluator={}", condition, evaluators);
+ }
+ }
+
+ @Override
+ public boolean isMatched(RangerAccessRequest request) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==>
RangerValidityScheduleConditionEvaluator.isMatched({})", request);
+ }
+
+ final boolean ret;
+
+ if (evaluators.isEmpty() || request.getAccessTime() == null) {
+ ret = true;
+ } else {
+ final long accessTime = request.getAccessTime().getTime();
+
+ ret = evaluators.stream().filter(evaluator ->
evaluator.isApplicable(accessTime)).findFirst().orElse(null) != null;
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<==
RangerValidityScheduleConditionEvaluator.isMatched({}): condition={}, ret={}",
request, condition, ret);
+ }
+
+ return ret;
+ }
+}
diff --git
a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/TestRangerValidityScheduleConditionEvaluator.java
b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/TestRangerValidityScheduleConditionEvaluator.java
new file mode 100644
index 000000000..4377c2645
--- /dev/null
+++
b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/TestRangerValidityScheduleConditionEvaluator.java
@@ -0,0 +1,166 @@
+/*
+ * 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.plugin.conditionevaluator;
+
+
+import org.apache.ranger.authorization.utils.JsonUtils;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import
org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import
org.apache.ranger.plugin.policyevaluator.RangerValidityScheduleEvaluator;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+public class TestRangerValidityScheduleConditionEvaluator {
+ private static final String SERVICE_DEF_RESOURCE_PATH
= "/admin/service-defs/test-hive-servicedef.json";
+ private static final RangerPolicyConditionDef
VALIDITY_SCHEDULE_CONDITION_DEF = new RangerPolicyConditionDef(1L,
"__validitySchedule", RangerValidityScheduleEvaluator.class.getName(), null);
+ private static final RangerServiceDef TEST_SERVICE_DEF
= initServiceDef();
+
+
+ @Test
+ public void testBothStartAndEndTime() {
+ RangerValidityScheduleConditionEvaluator evaluator = getEvaluator("{
\"startTime\": \"2024/01/12 00:00:00\", \"endTime\": \"2024/01/13 00:00:00\"
}");
+ RangerAccessRequest request =
mock(RangerAccessRequest.class);
+
+ // should match only for anytime on 2024/01/12
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 11, 9, 0,
0));
+ assertFalse(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 12, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 13, 9, 0,
0));
+ assertFalse(evaluator.isMatched(request));
+ }
+
+ @Test
+ public void testOnlyStartTime() {
+ RangerValidityScheduleConditionEvaluator evaluator = getEvaluator("{
\"startTime\": \"2024/01/12 00:00:00\" }");
+ RangerAccessRequest request =
mock(RangerAccessRequest.class);
+
+ // should match only for anytime on or after 2024/01/12
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 11, 9, 0,
0));
+ assertFalse(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 12, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 13, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+ }
+
+ @Test
+ public void testOnlyEndTime() {
+ RangerValidityScheduleConditionEvaluator evaluator = getEvaluator("{
\"endTime\": \"2024/01/13 00:00:00\" }");
+ RangerAccessRequest request =
mock(RangerAccessRequest.class);
+
+ // should match only for anytime before 2024/01/13
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 11, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 12, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 13, 9, 0,
0));
+ assertFalse(evaluator.isMatched(request));
+ }
+
+ @Test
+ public void testMultipleSchedules() {
+ RangerValidityScheduleConditionEvaluator evaluator = getEvaluator("{
\"endTime\": \"2024/01/01 00:00:00\" }", "{ \"startTime\": \"2024/04/01
00:00:00\" }", "{ \"startTime\": \"2024/02/01 00:00:00\", \"endTime\":
\"2024/02/15 00:00:00\" }");
+ RangerAccessRequest request =
mock(RangerAccessRequest.class);
+
+ // match following time periods:
+ // - anytime before 2024/01/01
+ // - anytime on or after 2024/04/01
+ // - anytime between 2024/02/01 - 2024/02/15
+ when(request.getAccessTime()).thenReturn(getDate(2023, 12, 31, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 4, 1, 9, 0, 0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 2, 1, 9, 0, 0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 2, 14, 9, 0,
0));
+ assertTrue(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 1, 1, 9, 0, 0));
+ assertFalse(evaluator.isMatched(request));
+
+ when(request.getAccessTime()).thenReturn(getDate(2024, 3, 31, 9, 0,
0));
+ assertFalse(evaluator.isMatched(request));
+ }
+
+ private RangerValidityScheduleConditionEvaluator
getEvaluator(String...schedules) {
+ RangerValidityScheduleConditionEvaluator evaluator = new
RangerValidityScheduleConditionEvaluator();
+
+ evaluator.setServiceDef(TEST_SERVICE_DEF);
+ evaluator.setConditionDef(VALIDITY_SCHEDULE_CONDITION_DEF);
+ evaluator.setPolicyItemCondition(new
RangerPolicyItemCondition(VALIDITY_SCHEDULE_CONDITION_DEF.getName(),
Arrays.asList(schedules)));
+
+ evaluator.init();
+
+ return evaluator;
+ }
+
+ private static Date getDate(int year, int month, int day, int hour, int
min, int sec) {
+ Calendar cal = Calendar.getInstance();
+
+ cal.set(year, month - 1, day, hour, min, sec);
+
+ return cal.getTime();
+ }
+
+ private static RangerServiceDef initServiceDef() throws RuntimeException {
+ try (InputStream inStr =
TestRangerValidityScheduleConditionEvaluator.class.getResourceAsStream(SERVICE_DEF_RESOURCE_PATH))
{
+ RangerServiceDef serviceDef = inStr != null ?
JsonUtils.jsonToObject(new InputStreamReader(inStr), RangerServiceDef.class) :
null;
+
+ if (serviceDef == null) {
+ throw new RuntimeException("failed to load servicedef from " +
SERVICE_DEF_RESOURCE_PATH);
+ }
+
+ Long maxId =
serviceDef.getPolicyConditions().stream().map(RangerPolicyConditionDef::getItemId).filter(Objects::nonNull).max(Long::compareTo).orElse(0L);
+
+ VALIDITY_SCHEDULE_CONDITION_DEF.setItemId(maxId + 1L);
+
+
serviceDef.getPolicyConditions().add(VALIDITY_SCHEDULE_CONDITION_DEF);
+
+ return serviceDef;
+ } catch (IOException excp) {
+ throw new RuntimeException(excp);
+ }
+ }
+}