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);
+        }
+    }
+}

Reply via email to