ranger-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mad...@apache.org
Subject [2/2] incubator-ranger git commit: RANGER-256: sample condition evaluators to demonstrate dynamic conditions
Date Sat, 21 Feb 2015 17:23:01 GMT
RANGER-256: sample condition evaluators to demonstrate dynamic conditions


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/78889721
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/78889721
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/78889721

Branch: refs/heads/master
Commit: 788897211404666cbdbed19316cba65e3afacffa
Parents: c59617d
Author: Alok Lal <alal@hortonworks.com>
Authored: Sat Feb 21 09:22:51 2015 -0800
Committer: Madhan Neethiraj <madhan@apache.org>
Committed: Sat Feb 21 09:22:51 2015 -0800

----------------------------------------------------------------------
 .../conditionevaluator/RangerSimpleMatcher.java | 129 +++++++++++
 .../RangerTimeOfDayMatcher.java                 | 201 +++++++++++++++++
 .../RangerSimpleMatcherTest.java                | 122 +++++++++++
 .../RangerTimeOfDayMatcherTest.java             | 215 +++++++++++++++++++
 .../src/test/resources/log4j.properties         |  36 ++++
 5 files changed, 703 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/78889721/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java
b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java
new file mode 100644
index 0000000..e0bcefc
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcher.java
@@ -0,0 +1,129 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+
+public class RangerSimpleMatcher implements RangerConditionEvaluator {
+
+	private static final Log LOG = LogFactory.getLog(RangerSimpleMatcher.class);
+	private boolean _allowAny = false;
+	private String ConditionName = null;
+	private List<String> _values = new ArrayList<String>();
+	
+	@Override
+	public void init(RangerPolicyConditionDef conditionDef, RangerPolicyItemCondition condition)
{
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerSimpleMatcher.init(" + condition + ")");
+		}
+
+		if (condition == null) {
+			LOG.debug("init: null policy condition! Will match always!");
+			_allowAny = true;
+		} else if (conditionDef == null) {
+			LOG.debug("init: null policy condition definition! Will match always!");
+			_allowAny = true;
+		} else if (CollectionUtils.isEmpty(condition.getValues())) {
+			LOG.debug("init: empty conditions collection on policy condition!  Will match always!");
+			_allowAny = true;
+		} else if (StringUtils.isEmpty(conditionDef.getEvaluatorOptions())) {
+			LOG.debug("init: Evaluator options were empty.  Can't determine what value to use from
context.  Will match always.");
+			_allowAny = true;
+		} else {
+			ConditionName = conditionDef.getEvaluatorOptions();
+			for (String value : condition.getValues()) {
+				_values.add(value);
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerSimpleMatcher.init(" + condition + "): countries[" + _values +
"]");
+		}
+
+	}
+
+	@Override
+	public boolean isMatched(RangerAccessRequest request) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerSimpleMatcher.isMatched(" + request + ")");
+		}
+
+		boolean matched = true;
+		if (_allowAny) {
+			LOG.debug("isMatched: allowAny flag is true.  Matched!");
+		} else {
+			String requestValue = extractValue(request, ConditionName);
+			if (requestValue == null) {
+				LOG.debug("isMatched: couldn't get value from request.  Ok.  Implicitly matched!");
+			} else {
+				matched = false;
+				for (String policyValue : _values) {
+					if (FilenameUtils.wildcardMatch(requestValue, policyValue)) {
+						matched = true;
+						break;
+					}
+				}
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerSimpleMatcher.isMatched(" + request+ "): " + matched);
+		}
+
+		return matched;
+	}
+
+	String extractValue(final RangerAccessRequest request, String key) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerSimpleMatcher.extractValue(" + request+ ")");
+		}
+
+		String value = null;
+		if (request == null) {
+			LOG.debug("isMatched: Unexpected: null request.  Returning null!");
+		} else if (request.getContext() == null) {
+			LOG.debug("isMatched: Context map of request is null.  Ok. Returning null!");
+		} else if (CollectionUtils.isEmpty(request.getContext().entrySet())) {
+			LOG.debug("isMatched: Missing context on request.  Ok. Condition isn't applicable.  Returning
null!");
+		} else if (!request.getContext().containsKey(key)) {
+			if (LOG.isDebugEnabled()) {
+				LOG.debug("isMatched: Unexpected: Context did not have data for condition[" + key + "].
Returning null!");
+			}
+		} else {
+			value = (String)request.getContext().get(key);
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerSimpleMatcher.extractValue(" + request+ "): " + value);
+		}
+		return value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/78889721/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
new file mode 100644
index 0000000..e8bb8db
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcher.java
@@ -0,0 +1,201 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+
+public class RangerTimeOfDayMatcher implements RangerConditionEvaluator {
+
+	private static final Log LOG = LogFactory.getLog(RangerTimeOfDayMatcher.class);
+	boolean _allowAny = false;
+	List<int[]> _durations = new ArrayList<int[]>();
+	
+	@Override
+	public void init(RangerPolicyConditionDef conditionDef, RangerPolicyItemCondition condition)
{
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerTimeOfDayMatcher.init(" + condition + ")");
+		}
+
+		if (condition == null) {
+			LOG.debug("init: null policy condition! Will match always!");
+			_allowAny = true;
+		} else if (CollectionUtils.isEmpty(condition.getValues())) {
+			LOG.debug("init: empty conditions collection on policy condition!  Will match always!");
+			_allowAny = true;
+		} else {
+			for (String value : condition.getValues()) {
+				if (StringUtils.isEmpty(value)) {
+					LOG.warn("init: Unexpected: one of the value in condition is null or empty!");
+				} else {
+					int[] aDuration = extractDuration(value);
+					if (aDuration != null) {
+						_durations.add(aDuration);
+					}
+				}
+			}
+		}
+		
+		if (_durations.isEmpty()) {
+			LOG.debug("No valid durations found.  Will always match!");
+			_allowAny = true;
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerTimeOfDayMatcher.init(" + condition + "): countries[" + _durations
+ "]");
+		}
+	}
+
+	// match "9am-5pm", "9 Am - 5 PM", "9 am.- 5 P.M", "9:30 AM - 4:00p.m." etc. spaces around
- and after digits are allowed and dots in am/pm string in mixed cases is allowed
+	static final Pattern _Pattern = Pattern.compile(" *(\\d{1,2})(:(\\d{1,2}))? *([aApP])\\.?[mM]\\.?
*- *(\\d{1,2})(:(\\d{1,2}))? *([aApP])\\.?[mM]\\.? *");
+
+	int[] extractDuration(String value) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerTimeOfDayMatcher.extractDuration(" + value + ")");
+		}
+		
+		int[] result = null;
+		if (value == null) {
+			LOG.warn("extractDuration: null input value!");
+		} else {
+			Matcher m = _Pattern.matcher(value);
+			if (!m.matches()) {
+				LOG.warn("extractDuration: input[" + value + "] did not match pattern!");
+			} else {
+				int startHour = Integer.parseInt(m.group(1));
+				int startMin = 0;
+				if (m.group(3) != null) {
+					startMin = Integer.parseInt(m.group(3));
+				}
+				String startType = m.group(4).toUpperCase();
+				
+				int endHour = Integer.parseInt(m.group(5));
+				int endMinute = 0;
+				if (m.group(7) != null) {
+					endMinute = Integer.parseInt(m.group(7));
+				}
+				String endType = m.group(8).toUpperCase();
+				if (startType.equals("P") && endType.equals("A")) {
+					LOG.warn("extractDuration: Invalid duration:" + value);
+				} else {
+					if (startType.equals("P")) {
+						startHour += 12;
+					}
+					if (endType.equals("P")) {
+						endHour += 12;
+					}
+					result = new int[] { (startHour*60)+startMin, (endHour*60)+endMinute };
+				}
+			}
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerTimeOfDayMatcher.extractDuration(" + value + "): duration[" +
result + "]");
+		}
+		return result;
+	}
+
+	@Override
+	public boolean isMatched(RangerAccessRequest request) {
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerTimeOfDayMatcher.isMatched(" + request + ")");
+		}
+
+		boolean matched = true;
+		if (_allowAny) {
+			LOG.debug("isMatched: allowAny flag is true.  Matched!");
+		} else if (request == null) {
+			LOG.warn("isMatched: Unexpected: Request is null!  Implicitly matched!");
+		} else if (request.getAccessTime() == null) {
+			LOG.warn("isMatched: Unexpected: Accesstime on the request is null!  Implicitly matched!");
+		} else {
+			Date date = request.getAccessTime();
+			Calendar calendar = GregorianCalendar.getInstance();
+			calendar.setTime(date);
+			int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
+			int minutes = calendar.get(Calendar.MINUTE);
+			if (durationMatched(_durations, hourOfDay, minutes)) {
+				if (LOG.isDebugEnabled()) {
+					LOG.debug("isMatched: None of the durations contains this hour of day[" + hourOfDay
+ "]");
+				}
+			} else {
+				matched = false;
+			}
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerTimeOfDayMatcher.isMatched(" + request+ "): " + matched);
+		}
+
+		return matched;
+	}
+
+	boolean durationMatched(List<int[]> durations, int hourOfDay, int minutes) {
+		for (int[] aDuration : durations) {
+			int start = aDuration[0];
+			int end = aDuration[1];
+			int minutesOfDay = hourOfDay*60 + minutes;
+			if (start <= minutesOfDay && minutesOfDay <= end) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	String extractValue(final RangerAccessRequest request, String key) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerSimpleMatcher.extractValue(" + request+ ")");
+		}
+
+		String value = null;
+		if (request == null) {
+			LOG.debug("isMatched: Unexpected: null request.  Returning null!");
+		} else if (request.getContext() == null) {
+			LOG.debug("isMatched: Context map of request is null.  Ok. Returning null!");
+		} else if (CollectionUtils.isEmpty(request.getContext().entrySet())) {
+			LOG.debug("isMatched: Missing context on request.  Ok. Condition isn't applicable.  Returning
null!");
+		} else if (!request.getContext().containsKey(key)) {
+			if (LOG.isDebugEnabled()) {
+				LOG.debug("isMatched: Unexpected: Context did not have data for condition[" + key + "].
Returning null!");
+			}
+		} else {
+			value = (String)request.getContext().get(key);
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerSimpleMatcher.extractValue(" + request+ "): " + value);
+		}
+		return value;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/78889721/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcherTest.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcherTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcherTest.java
new file mode 100644
index 0000000..4bd2a43
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerSimpleMatcherTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.junit.Test;
+
+public class RangerSimpleMatcherTest {
+
+	final String _conditionOption = "key1";
+	@Test
+	public void testIsMatched_happyPath() {
+		// this documents some unexpected behavior of the ip matcher
+		RangerSimpleMatcher ipMatcher = createMatcher(new String[]{"US", "C*"} );
+		assertTrue(ipMatcher.isMatched(createRequest("US")));
+		assertTrue(ipMatcher.isMatched(createRequest("CA")));
+		assertTrue(ipMatcher.isMatched(createRequest("C---")));
+		assertFalse(ipMatcher.isMatched(createRequest(" US ")));
+		assertFalse(ipMatcher.isMatched(createRequest("Us")));
+		assertFalse(ipMatcher.isMatched(createRequest("ca")));
+	}
+	
+	@Test
+	public void test_firewallings() {
+		
+		// create a request for some policyValue, say, country and use it to match against matcher
initialized with all sorts of bad data
+		RangerAccessRequest request = createRequest("AB");
+
+		RangerSimpleMatcher matcher = new RangerSimpleMatcher();
+		// Matcher initialized with null policy should behave sensibly!  It matches everything!
+		matcher.init(null, null);
+		assertTrue(matcher.isMatched(request));
+		
+		RangerPolicyItemCondition policyItemCondition = mock(RangerPolicyItemCondition.class);
+		matcher.init(null, policyItemCondition);
+		assertTrue(matcher.isMatched(request));
+		
+		RangerPolicyConditionDef conditionDef = mock(RangerPolicyConditionDef.class);
+		matcher.init(conditionDef, null);
+		assertTrue(matcher.isMatched(request));
+		
+		// so should a policy item condition with initialized with null list of values 
+		when(policyItemCondition.getValues()).thenReturn(null);
+		matcher.init(conditionDef, policyItemCondition);
+		assertTrue(matcher.isMatched(request));
+
+		// not null item condition with empty condition list
+		List<String> values = new ArrayList<String>();
+		when(policyItemCondition.getValues()).thenReturn(values);
+		matcher.init(conditionDef, policyItemCondition);
+		assertTrue(matcher.isMatched(request));
+
+		// values as sensible items in it, however, the conditionDef has null evaluator option,
so that too suppresses any check
+		values.add("AB");
+		when(policyItemCondition.getValues()).thenReturn(values);
+		when(conditionDef.getEvaluatorOptions()).thenReturn(null);
+		matcher.init(conditionDef, policyItemCondition);
+		assertTrue(matcher.isMatched(request));
+
+		// If evaluator option on the condition def is non-null then it starts to evaluate for
real
+		when(conditionDef.getEvaluatorOptions()).thenReturn(_conditionOption);
+		matcher.init(conditionDef, policyItemCondition);
+		assertTrue(matcher.isMatched(request));
+	}
+	
+	RangerSimpleMatcher createMatcher(String[] ipArray) {
+		RangerSimpleMatcher matcher = new RangerSimpleMatcher();
+
+		if (ipArray == null) {
+			matcher.init(null, null);
+		} else {
+			RangerPolicyItemCondition condition = mock(RangerPolicyItemCondition.class);
+			List<String> addresses = Arrays.asList(ipArray);
+			when(condition.getValues()).thenReturn(addresses);
+			
+			RangerPolicyConditionDef conditionDef = mock(RangerPolicyConditionDef.class);
+			when(conditionDef.getEvaluatorOptions()).thenReturn(_conditionOption);
+			matcher.init(conditionDef, condition);
+		}
+		
+		return matcher;
+	}
+	
+	RangerAccessRequest createRequest(String value) {
+		Map<String, Object> context = new HashMap<String, Object>();
+		context.put(_conditionOption, value);
+		RangerAccessRequest request = mock(RangerAccessRequest.class);
+		when(request.getContext()).thenReturn(context);
+		return request;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/78889721/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcherTest.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcherTest.java
b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcherTest.java
new file mode 100644
index 0000000..21e4769
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerTimeOfDayMatcherTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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 static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class RangerTimeOfDayMatcherTest {
+
+	final Pattern p = RangerTimeOfDayMatcher._Pattern;
+
+	@Test
+	public void test_patterMatching_happyPath() {
+		// sensible values and some goofy ones work
+		String[] durations = new String[] { 
+				"9am-5pm", " 9Am -5 Pm", " 9Am -5 Pm", "9 AM -5 p.m.", "9a.M - 5Pm.",
+				"9:30am-5:30pm", " 9:00Am -5:59 Pm",
+				"   9   am   -  4 pm  "
+		};
+		check(durations, true);
+	}
+	
+	@Test
+	public void test_patterMatching_unexpectedMatches() {
+		// even semantically illegal durations work -- parsing is just for format not for semantics!
+		String[] durations = new String[] {
+				"9pm-5AM",   // illegal duration where start > end is allows parsed as right!
+				"00PM-44PM",  // any two digits are allowed!
+				"9:0am-5:7pm", // Minute part can be one digit
+		};
+		check(durations, true);
+	}
+	
+	@Test
+	public void test_patterMatching_misMatches() {
+		// clearly invalid values don't match.
+		String[] durations = new String[] {
+				"9am", "-", "", "9-5", "9-10am", "9pm-6",
+				"009AM-5AM", // only 2 digits allowed
+				"9am-5p m", // space betweem am or pm are not allowed
+				"9:am-5:30pm", // if there is a : then minutes part must follow!
+				"9:00am-5:300pm", // Minutes part is limited to 2 digits
+				"9: 00am-5 :300pm", // No space allowed around the :
+				};
+		check(durations, false);
+	}	
+
+	void check(String[] durations, boolean match) {
+		for (String aDuration : durations) {
+			Matcher matcher = p.matcher(aDuration);
+			if (match) {
+				assertTrue(aDuration, matcher.matches());
+			} else {
+				assertFalse(aDuration, matcher.matches());
+			}
+		}
+	}
+
+	@Test
+	public void test_patterMatching_happyPath_groups() {
+		// groups returned by matcher are right
+		String[][] input = new String[][] {
+				{ "9am-5pm", "9", null, "a", "5", null, "p"},
+				{ "9Am -5 pM", "9", null, "A", "5", null, "p"},
+				{ "9 AM -5 p.m.", "9", null, "A", "5", null, "p" },
+				{ "9:30AM - 5:15pm", "9", "30", "A", "5", "15", "p" },
+				{ "9:30 AM - 5:15 p.m.", "9", "30", "A", "5", "15", "p" },
+		};
+		checkGroups(input);
+	}
+	
+	void checkGroups(String[][] input) {
+		for (String[] data : input) {
+			Matcher m = p.matcher(data[0]);
+			assertTrue(data[0], m.matches());
+			assertEquals(8, m.groupCount());
+			assertEquals(data[1], m.group(1));
+			assertEquals(data[2], m.group(3));
+			assertEquals(data[3], m.group(4));
+			assertEquals(data[4], m.group(5));
+			assertEquals(data[5], m.group(7));
+			assertEquals(data[6], m.group(8));
+		}
+	}
+
+	@Test
+	public void test_ExtractDuration_happyPath() {
+		RangerTimeOfDayMatcher matcher = new RangerTimeOfDayMatcher();
+		Object[][] input = new Object[][] {
+				{ "9am-5pm", true, 9*60, (12+5)*60 },
+				{ "1 PM - 10P.M.", true, (12+1)*60, (12+10)*60 },
+				{ "1PM - 9AM", false, null, null }, // illegal duration should come back as null
+				{ "1PM", false, null, null }, // illegal patterns should come back as null, too
+		};
+		for (Object[] data: input) {
+			int[] duration = matcher.extractDuration((String)data[0]);
+			boolean expectedToMatch = (boolean)data[1];
+			if (expectedToMatch) {
+				int start = (Integer)data[2];
+				int end = (Integer)data[3];
+				assertArrayEquals(new int[] { start, end }, duration);
+			} else {
+				assertNull(duration);
+			}
+		}
+	}
+	
+	@Test
+	public void test_durationsMatched() {
+		List<int[]> durations = Lists.newArrayList(
+				new int[]{2*60, 7*60},   // 2am-7am
+				new int[]{9*60, 17*60}); // 9am-5pm
+		RangerTimeOfDayMatcher matcher = new RangerTimeOfDayMatcher();
+		Object[][] input = new Object[][] {
+				{ 1, false },
+				{ 2, true },
+				{ 3, true },
+				{ 7, true },
+				{ 8, false },
+				{9, true },
+				{10, true },
+				{16, true}, 
+				{17, true}, 
+				{18, false },
+				{23, false },
+		};
+		for (Object[] data : input) {
+			int hour = (int)data[0];
+			boolean matchExpected = (boolean)data[1];
+			boolean result = matcher.durationMatched(durations, hour, 0);
+			if (matchExpected) {
+				assertTrue("" + hour, result);
+			} else {
+				assertFalse("" + hour, result);
+			}
+		}
+	}
+	
+	@Test
+	public void test_end2end_happyPath() {
+		RangerPolicyItemCondition itemCondition = mock(RangerPolicyItemCondition.class);
+		when(itemCondition.getValues()).thenReturn(Arrays.asList("2:45a.m. -7:00 AM", "  9:15AM-
5:30P.M. "));
+
+		RangerTimeOfDayMatcher matcher = new RangerTimeOfDayMatcher();
+		matcher.init(null, itemCondition);
+		
+		Object[][] input = new Object[][] {
+				{ 1, 0, false },
+				{ 2, 44, false },
+				{ 2, 45, true },
+				{ 3, 0, true },
+				{ 7, 0, true },
+				{ 7, 01, false },
+				{ 8, 0, false },
+				{ 9, 15, true },
+				{10, 0, true },
+				{17, 0, true}, 
+				{17, 30, true}, 
+				{17, 31, false}, 
+				{18, 0, false },
+				{23, 0, false },
+		};
+		
+		RangerAccessRequest request = mock(RangerAccessRequest.class);
+		for (Object[] data : input) {
+			int hour = (int)data[0];
+			int minute = (int)data[1];
+			Calendar c = new GregorianCalendar(2015, Calendar.APRIL, 1, hour, minute);
+			Date aDate = c.getTime();
+			when(request.getAccessTime()).thenReturn(aDate);
+			boolean matchExpected = (boolean)data[2];
+			if (matchExpected) {
+				assertTrue("" + hour, matcher.isMatched(request));
+			} else {
+				assertFalse("" + hour, matcher.isMatched(request));
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/78889721/agents-common/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/agents-common/src/test/resources/log4j.properties b/agents-common/src/test/resources/log4j.properties
new file mode 100644
index 0000000..12e172b
--- /dev/null
+++ b/agents-common/src/test/resources/log4j.properties
@@ -0,0 +1,36 @@
+# 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.
+
+##-- To prevent junits from cluttering the build run by default all test runs send output
to null appender 
+log4j.appender.devnull=org.apache.log4j.varia.NullAppender
+log4j.rootLogger=FATAL, devnull
+
+##-- uncomment the following line during during development/debugging so see debug messages
during test run to be emitted to console
+# ranger.root.logger=WARN,console
+
+# Define the root logger to the system property "hbase.root.logger".
+log4j.rootLogger=${ranger.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2}: %m%n


Mime
View raw message