/*
* 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.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class RangerIpMatcherTest {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testUnexpected() {
// this documents some unexpected behavior of the ip matcher
RangerIpMatcher ipMatcher = createMatcher(new String[]{"1.2.3.*"} );
// NOTE: absurd and downright illegal ipv4 address would match too!
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.123567")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3..123567")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.boo")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.")));
// wildcard match happens only at the end
ipMatcher = createMatcher(new String[]{"1.*.3.4"} );
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.3.3.4")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.1.3.4")));
// it becomes a literal match!
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.*.3.4")));
// same is true of ipv6
ipMatcher = createMatcher(new String[]{"99:a9:b9:c9:*"} );
// NOTE: absurd and downright illegal ipv4 address would match too!
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9:*")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9:1.3.4")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9: <:-) ")));
}
@Test
public void test_isWildcardMatched() {
List<String> ips = Arrays.asList("1.2.3.", "1.3.", "2.", "a0:b0:c0:", "a0:b1:", "a2:");
RangerIpMatcher matcher = new RangerIpMatcher();
Assert.assertTrue(matcher.isWildcardMatched(ips, "1.2.3.4"));
Assert.assertTrue(matcher.isWildcardMatched(ips, "1.3.3.4"));
Assert.assertTrue(matcher.isWildcardMatched(ips, "2.3.3.4"));
Assert.assertTrue(matcher.isWildcardMatched(ips, "A0:B0:C0:D0:E0:F0"));
Assert.assertTrue(matcher.isWildcardMatched(ips, "A0:B1:C0:D0:E0:F0"));
Assert.assertTrue(matcher.isWildcardMatched(ips, "A2:B0:C1:D2:E3:F4"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "1.2.33.4"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "1.33.3.4"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "22.3.3.4"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "A0:B0:00:D0:E0:F0"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "A0:B2:C0:D0:E0:F0"));
Assert.assertFalse(matcher.isWildcardMatched(ips, "22:B0:C1:D2:E3:F4"));
}
@Test
public void test_isExactlyMatched() {
List<String> ips = Arrays.asList("1.2.3.1", "1.2.3.11", "1.2.3.111", "a0:b0:c0:d0:e0:f0", "a0:b0:c0:d0:e0:f1", "a0:b0:c0:d0:e0:f2");
RangerIpMatcher matcher = new RangerIpMatcher();
Assert.assertTrue(matcher.isExactlyMatched(ips, "1.2.3.1"));
Assert.assertTrue(matcher.isExactlyMatched(ips, "1.2.3.111"));
Assert.assertTrue(matcher.isExactlyMatched(ips, "A0:B0:C0:D0:E0:F1"));
Assert.assertTrue(matcher.isExactlyMatched(ips, "a0:b0:c0:d0:e0:f1"));
Assert.assertFalse(matcher.isExactlyMatched(ips, "1.2.3.2"));
Assert.assertFalse(matcher.isExactlyMatched(ips, "a0:b0:c0:d0:e0:f3"));
}
@Test
public void test_extractIp() {
RangerIpMatcher matcher = new RangerIpMatcher();
Assert.assertNull(matcher.extractIp(null));
RangerAccessRequest request = mock(RangerAccessRequest.class);
when(request.getClientIPAddress()).thenReturn(null);
Assert.assertNull(matcher.extractIp(request));
when(request.getClientIPAddress()).thenReturn("anIp"); // note ip address is merely a string. It can be any string.
Assert.assertEquals("anIp", matcher.extractIp(request));
}
@Test
public void test_digestIp() {
// comlete wildcards get reduced to empty string.
RangerIpMatcher matcher = new RangerIpMatcher();
Assert.assertEquals("", matcher.digestPolicyIp("*"));
Assert.assertEquals("", matcher.digestPolicyIp("*.*"));
Assert.assertEquals("", matcher.digestPolicyIp("*.*.*"));
Assert.assertEquals("", matcher.digestPolicyIp("*.*.*.*"));
Assert.assertEquals("", matcher.digestPolicyIp("*:*:*:*"));
Assert.assertEquals("", matcher.digestPolicyIp("*:*:*:*:*:*"));
// wildcard parts get dropped; retails trailing ./: to avoid doing partial number match
Assert.assertEquals("10.", matcher.digestPolicyIp("10.*"));
Assert.assertEquals("10.", matcher.digestPolicyIp("10.*.*"));
Assert.assertEquals("10.", matcher.digestPolicyIp("10.*.*.*"));
Assert.assertEquals("10.20.", matcher.digestPolicyIp("10.20.*"));
Assert.assertEquals("10.20.", matcher.digestPolicyIp("10.20.*.*"));
Assert.assertEquals("10.20.30.", matcher.digestPolicyIp("10.20.30.*"));
// ipv6 digested values are also lower cased to ensure sensible comparison later
Assert.assertEquals("a0:", matcher.digestPolicyIp("A0:*"));
Assert.assertEquals("a0:", matcher.digestPolicyIp("a0:*:*"));
Assert.assertEquals("a0:", matcher.digestPolicyIp("A0:*:*:*"));
Assert.assertEquals("a0:b0:c0:", matcher.digestPolicyIp("A0:B0:C0:*"));
}
@Test
public void test_integration() {
RangerIpMatcher ipMatcher = createMatcher(null);
// Matcher initialized with null policy should behave sensibly! It matches everything!
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.4")));
// empty ip-address list is same as null, i.e. matchs anything!
ipMatcher = createMatcher(new String[]{});
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.4")));
// wildcard address will match anything -- ipv4 and ipv6 addresses
ipMatcher = createMatcher(new String[]{"*"});
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.4")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1:2:3:4:5:6")));
// partial wildcard matches work as expected.
ipMatcher = createMatcher(new String[]{"1.2.3.*"} );
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.4")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.123")));
// NOTE: absurd ipv4 address but it should match too!
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.123567")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3..123567")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("1.2.3.boo")));
// mismatches caught correctly
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.2.31.123567")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.2.33.123567")));
// no address has special meaning
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.2.0.0")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.2.255.255")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("1.2.254.254")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("0.0.0.0")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("255.255.255.255")));
// wild card can be more than one octets
ipMatcher = createMatcher(new String[]{"11.22.*.*"} );
Assert.assertTrue(ipMatcher.isMatched(createRequest("11.22.33.4")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("11.22.33.44")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("11.22.253.190")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("11.22.253.190")));
// mismatches
Assert.assertFalse(ipMatcher.isMatched(createRequest("11.222.253.190")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("11.21.253.190")));
// one need't provide all the octets; missing ones are treaetd as wild cards
ipMatcher = createMatcher(new String[]{"193.214.*"} ); // note just 3 octets in pattern
Assert.assertTrue(ipMatcher.isMatched(createRequest("193.214.3.4")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("193.21.253.190")));
// can't match ipv6 address using a ipv4 policy
Assert.assertFalse(ipMatcher.isMatched(createRequest("193:214:3:4")));
// same holds for ipv6 addresses
ipMatcher = createMatcher(new String[]{"193:214:*"} );
Assert.assertTrue(ipMatcher.isMatched(createRequest("193:214:3:4:5:6")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("193:214:13:94:a90:b4f")));
// mismatches work as expected
Assert.assertFalse(ipMatcher.isMatched(createRequest("193:215:13:94:a90:b4f")));
// can't match ipv4 address against ipv6 policy
Assert.assertFalse(ipMatcher.isMatched(createRequest("193.214.3.4")));
// direct match works as expected
ipMatcher = createMatcher(new String[]{"99:a9:b9:c9:d9:e9"} );
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9:d9:e9")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("99:a9:b9:c9:d0:e9")));
// Matcher can support multiple patterns of different domains - a mix of ipv4 and ipv6 addresses
ipMatcher = createMatcher(new String[]{"10.20.30.*", "99:a9:b9:c9:d9:*"} );
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9:d9:e9")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("99:a9:b9:c9:d9:e9")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("99:a9:b9:c9:dd:e9")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("89:a9:b9:c9:d9:e9")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("10.20.30.10")));
Assert.assertTrue(ipMatcher.isMatched(createRequest("10.20.30.20")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("10.20.3.10")));
Assert.assertFalse(ipMatcher.isMatched(createRequest("10.20.33.10")));
}
RangerIpMatcher createMatcher(String[] ipArray) {
RangerIpMatcher matcher = new RangerIpMatcher();
if (ipArray == null) {
matcher.setConditionDef(null);
matcher.setPolicyItemCondition(null);
} else {
RangerPolicyItemCondition condition = mock(RangerPolicyItemCondition.class);
List<String> addresses = Arrays.asList(ipArray);
when(condition.getValues()).thenReturn(addresses);
matcher.setConditionDef(null);
matcher.setPolicyItemCondition(condition);
}
matcher.init();
return matcher;
}
RangerAccessRequest createRequest(String requestIp) {
RangerAccessRequest request = mock(RangerAccessRequest.class);
when(request.getClientIPAddress()).thenReturn(requestIp);
return request;
}
}