Author: arp
Date: Fri Jun 27 08:32:51 2014
New Revision: 1605987

URL: http://svn.apache.org/r1605987
Log:
HADOOP-10565. Support IP ranges (CIDR) in proxyuser.hosts. (Contributed by 
Benoy Antony)

Added:
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/MachineList.java
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestMachineList.java
Modified:
    hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/site/apt/SecureMode.apt.vm
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java

Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1605987&r1=1605986&r2=1605987&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt 
(original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Fri Jun 
27 08:32:51 2014
@@ -480,6 +480,9 @@ Release 2.5.0 - UNRELEASED
     HADOOP-10754. Reenable several HA ZooKeeper-related tests on Windows.
     (cnauroth)
 
+    HADOOP-10565. Support IP ranges (CIDR) in proxyuser.hosts. (Benoy Antony
+    via Arpit Agarwal)
+
   OPTIMIZATIONS
 
   BUG FIXES 

Modified: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java?rev=1605987&r1=1605986&r2=1605987&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
 (original)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
 Fri Jun 27 08:32:51 2014
@@ -18,8 +18,6 @@
 
 package org.apache.hadoop.security.authorize;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -28,7 +26,7 @@ import java.util.regex.Pattern;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.util.StringUtils;
+import org.apache.hadoop.util.MachineList;
 
 import com.google.common.annotations.VisibleForTesting;
 
@@ -46,8 +44,8 @@ public class DefaultImpersonationProvide
   // acl and list of hosts per proxyuser
   private Map<String, AccessControlList> proxyUserAcl = 
     new HashMap<String, AccessControlList>();
-  private Map<String, Collection<String>> proxyHosts = 
-    new HashMap<String, Collection<String>>();
+  private static Map<String, MachineList> proxyHosts = 
+    new HashMap<String, MachineList>();
   private Configuration conf;
 
   @Override
@@ -70,7 +68,7 @@ public class DefaultImpersonationProvide
     allMatchKeys = conf.getValByRegex(CONF_HADOOP_PROXYUSER_RE_HOSTS);
     for(Entry<String, String> entry : allMatchKeys.entrySet()) {
       proxyHosts.put(entry.getKey(),
-          StringUtils.getTrimmedStringCollection(entry.getValue()));
+          new MachineList(entry.getValue()));
     }
   }
 
@@ -95,27 +93,10 @@ public class DefaultImpersonationProvide
           + " is not allowed to impersonate " + user.getUserName());
     }
 
-    boolean ipAuthorized = false;
-    Collection<String> ipList = proxyHosts.get(
+    MachineList MachineList = proxyHosts.get(
         getProxySuperuserIpConfKey(realUser.getShortUserName()));
 
-    if (isWildcardList(ipList)) {
-      ipAuthorized = true;
-    } else if (ipList != null && !ipList.isEmpty()) {
-      for (String allowedHost : ipList) {
-        InetAddress hostAddr;
-        try {
-          hostAddr = InetAddress.getByName(allowedHost);
-        } catch (UnknownHostException e) {
-          continue;
-        }
-        if (hostAddr.getHostAddress().equals(remoteAddress)) {
-          // Authorization is successful
-          ipAuthorized = true;
-        }
-      }
-    }
-    if(!ipAuthorized) {
+    if(!MachineList.includes(remoteAddress)) {
       throw new AuthorizationException("Unauthorized connection for 
super-user: "
           + realUser.getUserName() + " from IP " + remoteAddress);
     }
@@ -128,16 +109,6 @@ public class DefaultImpersonationProvide
     }
     return key;
   }
-
-  /**
-   * Return true if the configuration specifies the special configuration value
-   * "*", indicating that any group or host list is allowed to use this 
configuration.
-   */
-  private boolean isWildcardList(Collection<String> list) {
-    return (list != null) &&
-    (list.size() == 1) &&
-    (list.contains("*"));
-  }
   
   /**
    * Returns configuration key for effective usergroups allowed for a superuser
@@ -180,6 +151,12 @@ public class DefaultImpersonationProvide
 
   @VisibleForTesting
   public Map<String, Collection<String>> getProxyHosts() {
-    return proxyHosts;
+    Map<String, Collection<String>> tmpProxyHosts = 
+        new HashMap<String, Collection<String>>();
+    for (Map.Entry<String, MachineList> proxyHostEntry :proxyHosts.entrySet()) 
{
+      tmpProxyHosts.put(proxyHostEntry.getKey(), 
+          proxyHostEntry.getValue().getCollection());
+    }
+    return tmpProxyHosts;
   }
 }

Added: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/MachineList.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/MachineList.java?rev=1605987&view=auto
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/MachineList.java
 (added)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/MachineList.java
 Fri Jun 27 08:32:51 2014
@@ -0,0 +1,203 @@
+/**
+ * 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.hadoop.util;
+
+import java.net.InetAddress;
+
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.net.util.SubnetUtils;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.net.InetAddresses;
+
+/**
+ * Container class which holds a list of ip/host addresses and 
+ * answers membership queries.
+ * .
+ * Accepts list of ip addresses, ip addreses in CIDR format and/or 
+ * host addresses.
+ */
+
+public class MachineList {
+  
+  public static final Log LOG = LogFactory.getLog(MachineList.class);
+
+  /**
+   * InetAddressFactory is used to obtain InetAddress from host.
+   * This class makes it easy to simulate host to ip mappings during testing.
+   *
+   */
+  public static class InetAddressFactory {
+
+    static final InetAddressFactory S_INSTANCE = new InetAddressFactory();
+
+    public InetAddress getByName (String host) throws UnknownHostException {
+      return InetAddress.getByName(host);
+    }
+  }
+
+  private final boolean all;
+  private final Set<String> ipAddresses;
+  private final List<SubnetUtils.SubnetInfo> cidrAddresses;
+  private final Set<String> hostNames;
+  private final InetAddressFactory addressFactory;
+
+  /**
+   * 
+   * @param hostEntries comma separated ip/cidr/host addresses
+   */
+  public MachineList(String hostEntries) {
+    this(StringUtils.getTrimmedStringCollection(hostEntries),
+        InetAddressFactory.S_INSTANCE);
+  }
+
+  /**
+   * Accepts a collection of ip/cidr/host addresses
+   * 
+   * @param hostEntries
+   * @param addressFactory addressFactory to convert host to InetAddress
+   */
+  public MachineList(Collection<String> hostEntries, InetAddressFactory 
addressFactory) {
+    this.addressFactory = addressFactory;
+    if (hostEntries != null) {
+      if ((hostEntries.size() == 1) && (hostEntries.contains("*"))) {
+        all = true; 
+        ipAddresses = null; 
+        hostNames = null; 
+        cidrAddresses = null; 
+      } else {
+        all = false;
+        Set<String> ips = new HashSet<String>();
+        List<SubnetUtils.SubnetInfo> cidrs = new 
LinkedList<SubnetUtils.SubnetInfo>();
+        Set<String> hosts = new HashSet<String>();
+        for (String hostEntry : hostEntries) {
+          //ip address range
+          if (hostEntry.indexOf("/") > -1) {
+            try {
+              SubnetUtils subnet = new SubnetUtils(hostEntry);
+              subnet.setInclusiveHostCount(true);
+              cidrs.add(subnet.getInfo());
+            } catch (IllegalArgumentException e) {
+              LOG.warn("Invalid CIDR syntax : " + hostEntry);
+              throw e;
+            }
+          } else if (InetAddresses.isInetAddress(hostEntry)) { //ip address
+            ips.add(hostEntry);
+          } else { //hostname
+            hosts.add(hostEntry);
+          }
+        }
+        ipAddresses = (ips.size() > 0) ? ips : null;
+        cidrAddresses = (cidrs.size() > 0) ? cidrs : null;
+        hostNames = (hosts.size() > 0) ? hosts : null;
+      }
+    } else {
+      all = false; 
+      ipAddresses = null;
+      hostNames = null; 
+      cidrAddresses = null; 
+    }
+  }
+  /**
+   * Accepts an ip address and return true if ipAddress is in the list
+   * @param ipAddress
+   * @return true if ipAddress is part of the list
+   */
+  public boolean includes(String ipAddress) {
+    
+    if (all) {
+      return true;
+    }
+    
+    //check in the set of ipAddresses
+    if ((ipAddresses != null) && ipAddresses.contains(ipAddress)) {
+      return true;
+    }
+    
+    //iterate through the ip ranges for inclusion
+    if (cidrAddresses != null) {
+      for(SubnetUtils.SubnetInfo cidrAddress : cidrAddresses) {
+        if(cidrAddress.isInRange(ipAddress)) {
+          return true;
+        }
+      }
+    }
+    
+    //check if the ipAddress matches one of hostnames
+    if (hostNames != null) {
+      //convert given ipAddress to hostname and look for a match
+      InetAddress hostAddr;
+      try {
+        hostAddr = addressFactory.getByName(ipAddress);
+        if ((hostAddr != null) && 
hostNames.contains(hostAddr.getCanonicalHostName())) {
+          return true;
+        }
+      } catch (UnknownHostException e) {
+        //ignore the exception and proceed to resolve the list of hosts
+      }
+
+      //loop through host addresses and convert them to ip and look for a match
+      for (String host : hostNames) {
+        try {
+          hostAddr = addressFactory.getByName(host);
+        } catch (UnknownHostException e) {
+          continue;
+        }
+        if (hostAddr.getHostAddress().equals(ipAddress)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * returns the contents of the MachineList as a Collection<String>
+   * This can be used for testing 
+   * @return contents of the MachineList
+   */
+  @VisibleForTesting
+  public Collection<String> getCollection() {
+    Collection<String> list = new ArrayList<String>();
+    if (all) {
+      list.add("*"); 
+    } else {
+      if (ipAddresses != null) {
+        list.addAll(ipAddresses);
+      }
+      if (hostNames != null) {
+        list.addAll(hostNames);
+      }
+      if (cidrAddresses != null) {
+        for(SubnetUtils.SubnetInfo cidrAddress : cidrAddresses) {
+          list.add(cidrAddress.getCidrSignature());
+        }
+      }
+    }
+    return list;
+  }
+}

Modified: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/site/apt/SecureMode.apt.vm
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/site/apt/SecureMode.apt.vm?rev=1605987&r1=1605986&r2=1605987&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/site/apt/SecureMode.apt.vm
 (original)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/site/apt/SecureMode.apt.vm
 Fri Jun 27 08:32:51 2014
@@ -236,6 +236,25 @@ KVNO Timestamp         Principal
   </property>
 ----
 
+  The <<<hadoop.proxyuser.${superuser}.hosts>>> accepts list of ip addresses,
+  ip address ranges in CIDR format and/or host names.
+  
+  For example, by specifying as below in core-site.xml,
+  user named <<<oozie>>> accessing from hosts in the range 
+  10.222.0.0-15 and 10.113.221.221
+  can impersonate any user belonging to any group.
+  
+  ----
+  <property>
+    <name>hadoop.proxyuser.oozie.hosts</name>
+    <value>10.222.0.0/16,10.113.221.221</value>
+  </property>
+  <property>
+    <name>hadoop.proxyuser.oozie.groups</name>
+    <value>*</value>
+  </property>
+----
+
 ** Secure DataNode
 
   Because the data transfer protocol of DataNode

Modified: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java?rev=1605987&r1=1605986&r2=1605987&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
 (original)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
 Fri Jun 27 08:32:51 2014
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.fail;
 
 import java.io.IOException;
+import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -50,6 +51,7 @@ public class TestProxyUsers {
   private static final String[] SUDO_GROUP_NAMES =
     new String[] { "sudo_proxied_user" };
   private static final String PROXY_IP = "1.2.3.4";
+  private static final String PROXY_IP_RANGE = "10.222.0.0/16,10.113.221.221";
 
   /**
    * Test the netgroups (groups in ACL rules that start with @)
@@ -294,6 +296,29 @@ public class TestProxyUsers {
     assertNotAuthorized(proxyUserUgi, "1.2.3.4");
     assertNotAuthorized(proxyUserUgi, "1.2.3.5");
   }
+  
+  @Test
+  public void testIPRange() {
+    Configuration conf = new Configuration();
+    conf.set(
+        
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+        "*");
+    conf.set(
+        
DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
+        PROXY_IP_RANGE);
+    ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
+
+    // First try proxying a group that's allowed
+    UserGroupInformation realUserUgi = UserGroupInformation
+        .createRemoteUser(REAL_USER_NAME);
+    UserGroupInformation proxyUserUgi = 
UserGroupInformation.createProxyUserForTesting(
+        PROXY_USER_NAME, realUserUgi, GROUP_NAMES);
+
+    // From good IP
+    assertAuthorized(proxyUserUgi, "10.222.0.0");
+    // From bad IP
+    assertNotAuthorized(proxyUserUgi, "10.221.0.0");
+  }
 
   @Test
   public void testWithDuplicateProxyGroups() throws Exception {
@@ -431,4 +456,71 @@ public class TestProxyUsers {
       return null;
     }
   }
+  
+  public static void loadTest(String ipString, int testRange) {
+    Configuration conf = new Configuration();
+    conf.set(
+        
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+        StringUtils.join(",", Arrays.asList(GROUP_NAMES)));
+
+    conf.set(
+        
DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
+        ipString
+        );
+    ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
+
+
+    // First try proxying a group that's allowed
+    UserGroupInformation realUserUgi = UserGroupInformation
+        .createRemoteUser(REAL_USER_NAME);
+    UserGroupInformation proxyUserUgi = 
UserGroupInformation.createProxyUserForTesting(
+        PROXY_USER_NAME, realUserUgi, GROUP_NAMES);
+
+    long startTime = System.nanoTime();
+    SecureRandom sr = new SecureRandom();
+    for (int i=1; i < 1000000; i++){
+      try {
+        ProxyUsers.authorize(proxyUserUgi,  "1.2.3."+ sr.nextInt(testRange));
+       } catch (AuthorizationException e) {
+      }
+    }
+    long stopTime = System.nanoTime();
+    long elapsedTime = stopTime - startTime;
+    System.out.println(elapsedTime/1000000 + " ms");
+  }
+  
+  /**
+   * invokes the load Test
+   * A few sample invocations  are as below
+   * TestProxyUsers ip 128 256
+   * TestProxyUsers range 1.2.3.0/25 256
+   * TestProxyUsers ip 4 8
+   * TestProxyUsers range 1.2.3.0/30 8
+   * @param args
+   */
+  public static void main (String[] args){
+    String ipValues = null;
+
+    if (args.length != 3 || (!args[0].equals("ip") && 
!args[0].equals("range"))) {
+      System.out.println("Invalid invocation. The right syntax is ip/range 
<numberofIps/cidr> <testRange>");
+    }
+    else {
+      if (args[0].equals("ip")){
+        int numberOfIps =  Integer.parseInt(args[1]);
+        StringBuilder sb = new StringBuilder();
+        for (int i=0; i < numberOfIps; i++){
+          sb.append("1.2.3."+ i + ",");
+        }
+        ipValues = sb.toString();
+      }
+      else if (args[0].equals("range")){
+        ipValues = args[1];
+      }
+
+      int testRange = Integer.parseInt(args[2]);
+
+      loadTest(ipValues, testRange);
+    }
+  }
+
 }

Added: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestMachineList.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestMachineList.java?rev=1605987&view=auto
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestMachineList.java
 (added)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestMachineList.java
 Fri Jun 27 08:32:51 2014
@@ -0,0 +1,291 @@
+/**
+ * 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.hadoop.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Collection;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestMachineList {
+  private static String IP_LIST = 
"10.119.103.110,10.119.103.112,10.119.103.114";
+  private static String IP_LIST_SPACES = 
+    " 10.119.103.110 , 10.119.103.112,10.119.103.114 ,10.119.103.110, ";
+  private static String CIDR_LIST = "10.222.0.0/16,10.241.23.0/24";
+  private static String CIDR_LIST1 = "10.222.0.0/16";
+  private static String CIDR_LIST2 = "10.241.23.0/24";
+  private static String INVALID_CIDR = "10.241/24";
+  private static String IP_CIDR_LIST =
+    
"10.222.0.0/16,10.119.103.110,10.119.103.112,10.119.103.114,10.241.23.0/24";
+  private static String HOST_LIST = "host1,host4";
+  private static String HOSTNAME_IP_CIDR_LIST =
+    
"host1,10.222.0.0/16,10.119.103.110,10.119.103.112,10.119.103.114,10.241.23.0/24,host4,";
+
+  @Test
+  public void testWildCard() {
+    //create MachineList with a list of of IPs
+    MachineList ml = new MachineList("*");
+
+    //test for inclusion with any IP
+    assertTrue(ml.includes("10.119.103.112"));
+    assertTrue(ml.includes("1.2.3.4"));
+  }
+
+  @Test
+  public void testIPList() {
+    //create MachineList with a list of of IPs
+    MachineList ml = new MachineList(IP_LIST);
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("10.119.103.112"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+  }
+
+  @Test
+  public void testIPListSpaces() {
+    //create MachineList with a ip string which has duplicate ip and spaces
+    MachineList ml = new MachineList(IP_LIST_SPACES);
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("10.119.103.112"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+  }
+
+  @Test
+  public void testStaticIPHostNameList()throws UnknownHostException {
+    //create MachineList with a list of of Hostnames
+    InetAddress addressHost1 = InetAddress.getByName("1.2.3.1");
+    InetAddress addressHost4 = InetAddress.getByName("1.2.3.4");
+
+    MachineList.InetAddressFactory addressFactory = 
+      Mockito.mock(MachineList.InetAddressFactory.class);
+    Mockito.when(addressFactory.getByName("host1")).thenReturn(addressHost1);
+    Mockito.when(addressFactory.getByName("host4")).thenReturn(addressHost4);
+
+    MachineList ml = new MachineList(
+        StringUtils.getTrimmedStringCollection(HOST_LIST), addressFactory);
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("1.2.3.4"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("1.2.3.5"));
+  }
+
+  @Test
+  public void testHostNames() throws UnknownHostException {
+    //create MachineList with a list of of Hostnames
+    InetAddress addressHost1 = InetAddress.getByName("1.2.3.1");
+    InetAddress addressHost4 = InetAddress.getByName("1.2.3.4");
+    InetAddress addressMockHost4 = Mockito.mock(InetAddress.class);
+    
Mockito.when(addressMockHost4.getCanonicalHostName()).thenReturn("differentName");
+
+    InetAddress addressMockHost5 = Mockito.mock(InetAddress.class);
+    Mockito.when(addressMockHost5.getCanonicalHostName()).thenReturn("host5");
+
+    MachineList.InetAddressFactory addressFactory = 
+      Mockito.mock(MachineList.InetAddressFactory.class);
+    
Mockito.when(addressFactory.getByName("1.2.3.4")).thenReturn(addressMockHost4);
+    
Mockito.when(addressFactory.getByName("1.2.3.5")).thenReturn(addressMockHost5);
+    Mockito.when(addressFactory.getByName("host1")).thenReturn(addressHost1);
+    Mockito.when(addressFactory.getByName("host4")).thenReturn(addressHost4);
+
+    MachineList ml = new MachineList(
+        StringUtils.getTrimmedStringCollection(HOST_LIST), addressFactory );
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("1.2.3.4"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("1.2.3.5"));
+  }
+
+  @Test
+  public void testHostNamesReverserIpMatch() throws UnknownHostException {
+    //create MachineList with a list of of Hostnames
+    InetAddress addressHost1 = InetAddress.getByName("1.2.3.1");
+    InetAddress addressHost4 = InetAddress.getByName("1.2.3.4");
+    InetAddress addressMockHost4 =  Mockito.mock(InetAddress.class);
+    Mockito.when(addressMockHost4.getCanonicalHostName()).thenReturn("host4");
+
+    InetAddress addressMockHost5 =  Mockito.mock(InetAddress.class);
+    Mockito.when(addressMockHost5.getCanonicalHostName()).thenReturn("host5");
+
+    MachineList.InetAddressFactory addressFactory = 
+      Mockito.mock(MachineList.InetAddressFactory.class);
+    
Mockito.when(addressFactory.getByName("1.2.3.4")).thenReturn(addressMockHost4);
+    
Mockito.when(addressFactory.getByName("1.2.3.5")).thenReturn(addressMockHost5);
+    Mockito.when(addressFactory.getByName("host1")).thenReturn(addressHost1);
+    Mockito.when(addressFactory.getByName("host4")).thenReturn(addressHost4);
+
+    MachineList ml = new MachineList(
+        StringUtils.getTrimmedStringCollection(HOST_LIST), addressFactory );
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("1.2.3.4"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("1.2.3.5"));
+  }
+
+  @Test
+  public void testCIDRs() {
+    //create MachineList with a list of of ip ranges specified in CIDR format
+    MachineList ml = new MachineList(CIDR_LIST);
+
+    //test for inclusion/exclusion 
+    assertFalse(ml.includes("10.221.255.255"));
+    assertTrue(ml.includes("10.222.0.0")); 
+    assertTrue(ml.includes("10.222.0.1"));
+    assertTrue(ml.includes("10.222.0.255"));
+    assertTrue(ml.includes("10.222.255.0"));
+    assertTrue(ml.includes("10.222.255.254"));
+    assertTrue(ml.includes("10.222.255.255"));
+    assertFalse(ml.includes("10.223.0.0"));
+
+    assertTrue(ml.includes("10.241.23.0"));
+    assertTrue(ml.includes("10.241.23.1"));
+    assertTrue(ml.includes("10.241.23.254"));
+    assertTrue(ml.includes("10.241.23.255"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+
+  }
+
+  @Test
+  public void testCIDRWith16bitmask() {
+    //create MachineList with a list of of ip ranges specified in CIDR format
+    MachineList ml = new MachineList(CIDR_LIST1);
+
+    //test for inclusion/exclusion 
+    assertFalse(ml.includes("10.221.255.255"));
+    assertTrue(ml.includes("10.222.0.0")); 
+    assertTrue(ml.includes("10.222.0.1"));
+    assertTrue(ml.includes("10.222.0.255"));
+    assertTrue(ml.includes("10.222.255.0"));
+    assertTrue(ml.includes("10.222.255.254"));
+    assertTrue(ml.includes("10.222.255.255"));
+    assertFalse(ml.includes("10.223.0.0"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+  }
+
+  @Test
+  public void testCIDRWith8BitMask() {
+    //create MachineList with a list of of ip ranges specified in CIDR format
+    MachineList ml = new MachineList(CIDR_LIST2);
+
+    //test for inclusion/exclusion  
+    assertFalse(ml.includes("10.241.22.255"));
+    assertTrue(ml.includes("10.241.23.0")); 
+    assertTrue(ml.includes("10.241.23.1"));
+    assertTrue(ml.includes("10.241.23.254"));
+    assertTrue(ml.includes("10.241.23.255")); 
+    assertFalse(ml.includes("10.241.24.0"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+  }
+
+  //test invalid cidr
+  @Test
+  public void testInvalidCIDR() {
+    //create MachineList with an Invalid CIDR
+    try {
+    new MachineList(INVALID_CIDR);
+    fail("Expected IllegalArgumentException");
+    } catch (IllegalArgumentException e) {
+      //expected Exception
+    } catch (Throwable t) {
+      fail ("Expected only IllegalArgumentException");
+    }
+  }
+  //
+  @Test
+  public void testIPandCIDRs() {
+    //create MachineList with a list of of ip ranges and ip addresses
+    MachineList ml = new MachineList(IP_CIDR_LIST);
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("10.119.103.112"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+
+    //CIDR Ranges
+    assertFalse(ml.includes("10.221.255.255"));
+    assertTrue(ml.includes("10.222.0.0")); 
+    assertTrue(ml.includes("10.222.255.255"));
+    assertFalse(ml.includes("10.223.0.0"));
+
+    assertFalse(ml.includes("10.241.22.255"));
+    assertTrue(ml.includes("10.241.23.0")); 
+    assertTrue(ml.includes("10.241.23.255")); 
+    assertFalse(ml.includes("10.241.24.0"));
+  }
+
+  @Test
+  public void testHostNameIPandCIDRs() {
+    //create MachineList with a mix of ip addresses , hostnames and ip ranges
+    MachineList ml = new MachineList(HOSTNAME_IP_CIDR_LIST);
+
+    //test for inclusion with an known IP
+    assertTrue(ml.includes("10.119.103.112"));
+
+    //test for exclusion with an unknown IP
+    assertFalse(ml.includes("10.119.103.111"));
+
+    //CIDR Ranges
+    assertFalse(ml.includes("10.221.255.255"));
+    assertTrue(ml.includes("10.222.0.0")); 
+    assertTrue(ml.includes("10.222.255.255"));
+    assertFalse(ml.includes("10.223.0.0"));
+
+    assertFalse(ml.includes("10.241.22.255"));
+    assertTrue(ml.includes("10.241.23.0")); 
+    assertTrue(ml.includes("10.241.23.255")); 
+    assertFalse(ml.includes("10.241.24.0"));
+  }
+
+  @Test
+  public void testGetCollection() {
+    //create MachineList with a mix of ip addresses , hostnames and ip ranges
+    MachineList ml = new MachineList(HOSTNAME_IP_CIDR_LIST);
+
+    Collection<String> col = ml.getCollection();
+    //test getCollectionton to return the full collection
+    assertEquals(7,ml.getCollection().size());
+
+    for (String 
item:StringUtils.getTrimmedStringCollection(HOSTNAME_IP_CIDR_LIST)) {
+      assertTrue(col.contains(item));
+    }
+  }
+}


Reply via email to