diff --git a/src/main/java/com/aws/greengrass/detector/config/Config.java b/src/main/java/com/aws/greengrass/detector/config/Config.java index c914a58..b77def7 100644 --- a/src/main/java/com/aws/greengrass/detector/config/Config.java +++ b/src/main/java/com/aws/greengrass/detector/config/Config.java @@ -14,19 +14,38 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +@SuppressWarnings("PMD.DataClass") public class Config { private final Logger logger = LogManager.getLogger(Config.class); static final String INCLUDE_IPV4_LOOPBACK_ADDRESSES_CONFIG_KEY = "includeIPv4LoopbackAddrs"; + static final String INCLUDE_IPV6_LOOPBACK_ADDRESSES_CONFIG_KEY = "includeIPv6LoopbackAddrs"; static final String INCLUDE_IPV4_LINK_LOCAL_ADDRESSES_CONFIG_KEY = "includeIPv4LinkLocalAddrs"; + static final String INCLUDE_IPV6_LINK_LOCAL_ADDRESSES_CONFIG_KEY = "includeIPv6LinkLocalAddrs"; + static final String INCLUDE_IPV4_ADDRESSES_CONFIG_KEY = "includeIPv4Addrs"; + static final String INCLUDE_IPV6_ADDRESSES_CONFIG_KEY = "includeIPv6Addrs"; static final String DEFAULT_PORT_CONFIG_KEY = "defaultPort"; static final boolean DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES = false; + static final boolean DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES = false; static final boolean DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES = false; + static final boolean DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES = false; + static final boolean DEFAULT_INCLUDE_IPV4_ADDRESSES = true; + static final boolean DEFAULT_INCLUDE_IPV6_ADDRESSES = false; static final int DEFAULT_PORT = 8883; - private AtomicInteger defaultPort = new AtomicInteger(DEFAULT_PORT); - private AtomicBoolean includeIPv4LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES); - private AtomicBoolean includeIPv4LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES); + private final AtomicInteger defaultPort = new AtomicInteger(DEFAULT_PORT); + private final AtomicBoolean includeIPv4LoopbackAddrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES); + private final AtomicBoolean includeIPv6LoopbackAddrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES); + private final AtomicBoolean includeIPv4LinkLocalAddrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES); + private final AtomicBoolean includeIPv6LinkLocalAddrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES); + private final AtomicBoolean includeIPv4Addrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_ADDRESSES); + private final AtomicBoolean includeIPv6Addrs + = new AtomicBoolean(DEFAULT_INCLUDE_IPV6_ADDRESSES); /** * Config constructor. @@ -37,29 +56,57 @@ public Config(Topics topics) { Topics configurationTopics = topics.lookupTopics(KernelConfigResolver.CONFIGURATION_CONFIG_KEY); configurationTopics.subscribe((whatHappened, node) -> { if (configurationTopics.isEmpty()) { - this.includeIPv4LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES); - this.includeIPv4LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES); - this.defaultPort = new AtomicInteger(DEFAULT_PORT); + this.includeIPv4LoopbackAddrs.set(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES); + this.includeIPv6LoopbackAddrs.set(DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES); + this.includeIPv4LinkLocalAddrs.set(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES); + this.includeIPv6LinkLocalAddrs.set(DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES); + this.includeIPv4Addrs.set(DEFAULT_INCLUDE_IPV4_ADDRESSES); + this.includeIPv6Addrs.set(DEFAULT_INCLUDE_IPV6_ADDRESSES); + this.defaultPort.set(DEFAULT_PORT); return; } - this.includeIPv4LoopbackAddrs = new AtomicBoolean( + this.includeIPv4LoopbackAddrs.set( Coerce.toBoolean( configurationTopics.findOrDefault( DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES, INCLUDE_IPV4_LOOPBACK_ADDRESSES_CONFIG_KEY))); - this.includeIPv4LinkLocalAddrs = new AtomicBoolean( + this.includeIPv6LoopbackAddrs.set( + Coerce.toBoolean( + configurationTopics.findOrDefault( + DEFAULT_INCLUDE_IPV6_LOOPBACK_ADDRESSES, + INCLUDE_IPV6_LOOPBACK_ADDRESSES_CONFIG_KEY))); + this.includeIPv4LinkLocalAddrs.set( Coerce.toBoolean( configurationTopics.findOrDefault( DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES, INCLUDE_IPV4_LINK_LOCAL_ADDRESSES_CONFIG_KEY))); - this.defaultPort = new AtomicInteger( + this.includeIPv6LinkLocalAddrs.set( + Coerce.toBoolean( + configurationTopics.findOrDefault( + DEFAULT_INCLUDE_IPV6_LINK_LOCAL_ADDRESSES, + INCLUDE_IPV6_LINK_LOCAL_ADDRESSES_CONFIG_KEY))); + this.includeIPv4Addrs.set( + Coerce.toBoolean( + configurationTopics.findOrDefault( + DEFAULT_INCLUDE_IPV4_ADDRESSES, + INCLUDE_IPV4_ADDRESSES_CONFIG_KEY))); + this.includeIPv6Addrs.set( + Coerce.toBoolean( + configurationTopics.findOrDefault( + DEFAULT_INCLUDE_IPV6_ADDRESSES, + INCLUDE_IPV6_ADDRESSES_CONFIG_KEY))); + this.defaultPort.set( Coerce.toInt( configurationTopics.findOrDefault(DEFAULT_PORT, DEFAULT_PORT_CONFIG_KEY))); logger.atInfo().kv("includeIPv4LoopbackAddrs", includeIPv4LoopbackAddrs.get()) .kv("includeIPv4LinkLocalAddrs", includeIPv4LinkLocalAddrs.get()) + .kv("includeIPv6LoopbackAddrs", includeIPv6LoopbackAddrs.get()) + .kv("includeIPv6LinkLocalAddrs", includeIPv6LinkLocalAddrs.get()) + .kv("includeIPv4Addrs", includeIPv4Addrs.get()) + .kv("includeIPv6Addrs", includeIPv6Addrs.get()) .kv("defaultPort", defaultPort.get()) .log("Configuration updated"); }); @@ -81,6 +128,38 @@ public boolean isIncludeIPv4LinkLocalAddrs() { return this.includeIPv4LinkLocalAddrs.get(); } + /** + * includeIPv6LoopbackAddrs getter. + * @return boolean includeIPv6LoopbackAddrs + */ + public boolean isIncludeIPv6LoopbackAddrs() { + return this.includeIPv6LoopbackAddrs.get(); + } + + /** + * includeIPv6LinkLocalAddrs getter. + * @return boolean includeIPv6LinkLocalAddrs + */ + public boolean isIncludeIPv6LinkLocalAddrs() { + return this.includeIPv6LinkLocalAddrs.get(); + } + + /** + * includeIPv4Addrs getter. + * @return boolean includeIPv4Addrs + */ + public boolean isIncludeIPv4Addrs() { + return this.includeIPv4Addrs.get(); + } + + /** + * includeIPv6Addrs getter. + * @return boolean includeIPv6Addrs + */ + public boolean isIncludeIPv6Addrs() { + return this.includeIPv6Addrs.get(); + } + /** * defaultPort getter. * @return integer defaultPort diff --git a/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java b/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java index 343dea6..75d640c 100644 --- a/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java +++ b/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java @@ -45,13 +45,25 @@ List getIpAddresses(Enumeration interfaces, Confi for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { InetAddress address = interfaceAddress.getAddress(); if (address instanceof Inet6Address) { - continue; - } - if (address.isLoopbackAddress() && !config.isIncludeIPv4LoopbackAddrs()) { - continue; - } - if (address.isLinkLocalAddress() && !config.isIncludeIPv4LinkLocalAddrs()) { - continue; + if (!config.isIncludeIPv6Addrs()) { + continue; + } + if (address.isLinkLocalAddress() && !config.isIncludeIPv6LinkLocalAddrs()) { + continue; + } + if (address.isLoopbackAddress() && !config.isIncludeIPv6LoopbackAddrs()) { + continue; + } + } else { + if (!config.isIncludeIPv4Addrs()) { + continue; + } + if (address.isLoopbackAddress() && !config.isIncludeIPv4LoopbackAddrs()) { + continue; + } + if (address.isLinkLocalAddress() && !config.isIncludeIPv4LinkLocalAddrs()) { + continue; + } } ipAddresses.add(address); } diff --git a/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java b/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java index b47caa1..2baeab5 100644 --- a/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java +++ b/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java @@ -41,6 +41,7 @@ public void GIVEN_validIps_WHEN_get_ipAddresses_THEN_ip_addresses_returned() thr Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses(); Mockito.doReturn(true).when(networkInterface1).isUp(); + Mockito.doReturn(true).when(config).isIncludeIPv4Addrs(); // include IPv4 Loopback addresses and Link-Local addresses Mockito.doReturn(true).when(config).isIncludeIPv4LoopbackAddrs(); Mockito.doReturn(true).when(config).isIncludeIPv4LinkLocalAddrs(); @@ -56,6 +57,70 @@ public void GIVEN_validIps_WHEN_get_ipAddresses_THEN_ip_addresses_returned() thr assertEquals(TestConstants.IPV4_LINK_LOCAL, ipAddresses.get(2).getHostAddress()); } + @Test + public void GIVEN_ipv6Enabled_WHEN_get_ipAddresses_THEN_ip_addresses_returned() throws SocketException { + NetworkInterface networkInterface1 = Mockito.mock(NetworkInterface.class); + Config config = Mockito.mock(Config.class); + + List networkInterfaces = new ArrayList<>(); + List interfaceAddresses = getAllAddresses(); + + Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses(); + Mockito.doReturn(true).when(networkInterface1).isUp(); + Mockito.doReturn(false).when(config).isIncludeIPv4Addrs(); + Mockito.doReturn(true).when(config).isIncludeIPv6Addrs(); + // include IPv6 Loopback addresses and Link-Local addresses + Mockito.doReturn(true).when(config).isIncludeIPv6LoopbackAddrs(); + Mockito.doReturn(true).when(config).isIncludeIPv6LinkLocalAddrs(); + + networkInterfaces.add(networkInterface1); + Enumeration enumeration = Collections.enumeration(networkInterfaces); + ipDetector = new IpDetector(); + List ipAddresses = ipDetector.getIpAddresses(enumeration, config); + + assertEquals(4, ipAddresses.size()); + assertEquals(TestConstants.IPV6_LOOPBACK, ipAddresses.get(0).getHostAddress()); + assertEquals(TestConstants.IPV6_LINK_LOCAL_1, ipAddresses.get(1).getHostAddress()); + assertEquals(TestConstants.IPV6_LINK_LOCAL_2, ipAddresses.get(2).getHostAddress()); + assertEquals(TestConstants.IPV6_1, ipAddresses.get(3).getHostAddress()); + + } + + + @Test + public void GIVEN_dualStack_WHEN_get_ipAddresses_THEN_ip_addresses_returned() throws SocketException { + NetworkInterface networkInterface1 = Mockito.mock(NetworkInterface.class); + Config config = Mockito.mock(Config.class); + + List networkInterfaces = new ArrayList<>(); + List interfaceAddresses = getAllAddresses(); + + Mockito.doReturn(interfaceAddresses).when(networkInterface1).getInterfaceAddresses(); + Mockito.doReturn(true).when(networkInterface1).isUp(); + Mockito.doReturn(true).when(config).isIncludeIPv4Addrs(); + Mockito.doReturn(true).when(config).isIncludeIPv6Addrs(); + // include IPv4 Loopback addresses and Link-Local addresses + Mockito.doReturn(true).when(config).isIncludeIPv4LoopbackAddrs(); + Mockito.doReturn(true).when(config).isIncludeIPv4LinkLocalAddrs(); + Mockito.lenient().doReturn(true).when(config).isIncludeIPv6LoopbackAddrs(); + Mockito.lenient().doReturn(true).when(config).isIncludeIPv6LinkLocalAddrs(); + + networkInterfaces.add(networkInterface1); + Enumeration enumeration = Collections.enumeration(networkInterfaces); + ipDetector = new IpDetector(); + List ipAddresses = ipDetector.getIpAddresses(enumeration, config); + + assertEquals(7, ipAddresses.size()); + assertEquals(TestConstants.IPV4_LOOPBACK, ipAddresses.get(0).getHostAddress()); + assertEquals(TestConstants.IP_1, ipAddresses.get(1).getHostAddress()); + assertEquals(TestConstants.IPV6_LOOPBACK, ipAddresses.get(2).getHostAddress()); + assertEquals(TestConstants.IPV6_LINK_LOCAL_1, ipAddresses.get(3).getHostAddress()); + assertEquals(TestConstants.IPV6_LINK_LOCAL_2, ipAddresses.get(4).getHostAddress()); + assertEquals(TestConstants.IPV4_LINK_LOCAL, ipAddresses.get(5).getHostAddress()); + assertEquals(TestConstants.IPV6_1, ipAddresses.get(6).getHostAddress()); + + } + @Test public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loopbackAddress_linkLocalAddress_filtered() throws SocketException { NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class); @@ -66,6 +131,7 @@ public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loo Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses(); Mockito.doReturn(true).when(networkInterface).isUp(); + Mockito.doReturn(true).when(config).isIncludeIPv4Addrs(); // Exclude IPv4 Loopback addresses and Link-Local addresses Mockito.doReturn(false).when(config).isIncludeIPv4LoopbackAddrs(); Mockito.doReturn(false).when(config).isIncludeIPv4LinkLocalAddrs(); @@ -79,6 +145,53 @@ public void GIVEN_loopbackAddress_linkLocalAddress_WHEN_get_ipAddresses_THEN_loo assertEquals(TestConstants.IP_1, ipAddresses.get(0).getHostAddress()); } + + @Test + public void GIVEN_ipv6_filter_WHEN_get_ipAddresses_THEN_loopbackAddress_linkLocalAddress_filtered() throws SocketException { + NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class); + Config config = Mockito.mock(Config.class); + + List networkInterfaces = new ArrayList<>(); + List interfaceAddresses = getAllAddresses(); + + Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses(); + Mockito.doReturn(true).when(networkInterface).isUp(); + Mockito.doReturn(false).when(config).isIncludeIPv4Addrs(); + Mockito.doReturn(true).when(config).isIncludeIPv6Addrs(); + // Exclude IPv4 Loopback addresses and Link-Local addresses + Mockito.lenient().doReturn(false).when(config).isIncludeIPv6LoopbackAddrs(); + Mockito.lenient().doReturn(false).when(config).isIncludeIPv6LinkLocalAddrs(); + + networkInterfaces.add(networkInterface); + Enumeration enumeration = Collections.enumeration(networkInterfaces); + ipDetector = new IpDetector(); + List ipAddresses = ipDetector.getIpAddresses(enumeration, config); + + assertEquals(1, ipAddresses.size()); + assertEquals(TestConstants.IPV6_1, ipAddresses.get(0).getHostAddress()); + } + + @Test + public void GIVEN_ipv4_ipv6_disabled_WHEN_get_ipAddresses_THEN_empty_returned() throws SocketException { + NetworkInterface networkInterface = Mockito.mock(NetworkInterface.class); + Config config = Mockito.mock(Config.class); + + List networkInterfaces = new ArrayList<>(); + List interfaceAddresses = getAllAddresses(); + + Mockito.doReturn(interfaceAddresses).when(networkInterface).getInterfaceAddresses(); + Mockito.doReturn(true).when(networkInterface).isUp(); + Mockito.doReturn(false).when(config).isIncludeIPv4Addrs(); + Mockito.doReturn(false).when(config).isIncludeIPv6Addrs(); + + networkInterfaces.add(networkInterface); + Enumeration enumeration = Collections.enumeration(networkInterfaces); + ipDetector = new IpDetector(); + List ipAddresses = ipDetector.getIpAddresses(enumeration, config); + + assertEquals(0, ipAddresses.size()); + } + @Test public void GIVEN_noIps_WHEN_get_ipAddresses_THEN_null_returned() throws SocketException { ipDetector = new IpDetector(); @@ -106,6 +219,7 @@ private List getAllAddresses() { InterfaceAddress interfaceAddress4 = Mockito.mock(InterfaceAddress.class); InterfaceAddress interfaceAddress5 = Mockito.mock(InterfaceAddress.class); InterfaceAddress interfaceAddress6 = Mockito.mock(InterfaceAddress.class); + InterfaceAddress interfaceAddress7 = Mockito.mock(InterfaceAddress.class); InetAddress inetAddress1 = Mockito.mock(Inet4Address.class); InetAddress inetAddress2 = Mockito.mock(Inet4Address.class); @@ -113,16 +227,21 @@ private List getAllAddresses() { InetAddress inetAddress4 = Mockito.mock(Inet6Address.class); InetAddress inetAddress5 = Mockito.mock(Inet6Address.class); InetAddress inetAddress6 = Mockito.mock(Inet4Address.class); + InetAddress inetAddress7 = Mockito.mock(Inet6Address.class); Mockito.lenient().doReturn(TestConstants.IPV4_LOOPBACK).when(inetAddress1).getHostAddress(); - Mockito.doReturn(TestConstants.IP_1).when(inetAddress2).getHostAddress(); - Mockito.lenient().doReturn(TestConstants.IP_2).when(inetAddress3).getHostAddress(); - Mockito.lenient().doReturn(TestConstants.IP_3).when(inetAddress4).getHostAddress(); - Mockito.lenient().doReturn(TestConstants.IP_4).when(inetAddress5).getHostAddress(); + Mockito.lenient().doReturn(TestConstants.IP_1).when(inetAddress2).getHostAddress(); + Mockito.lenient().doReturn(TestConstants.IPV6_LOOPBACK).when(inetAddress3).getHostAddress(); + Mockito.lenient().doReturn(TestConstants.IPV6_LINK_LOCAL_1).when(inetAddress4).getHostAddress(); + Mockito.lenient().doReturn(TestConstants.IPV6_LINK_LOCAL_2).when(inetAddress5).getHostAddress(); Mockito.lenient().doReturn(TestConstants.IPV4_LINK_LOCAL).when(inetAddress6).getHostAddress(); + Mockito.lenient().doReturn(TestConstants.IPV6_1).when(inetAddress7).getHostAddress(); - Mockito.doReturn(true).when(inetAddress1).isLoopbackAddress(); - Mockito.doReturn(true).when(inetAddress6).isLinkLocalAddress(); + Mockito.lenient().doReturn(true).when(inetAddress1).isLoopbackAddress(); + Mockito.lenient().doReturn(true).when(inetAddress3).isLoopbackAddress(); + Mockito.lenient().doReturn(true).when(inetAddress4).isLinkLocalAddress(); + Mockito.lenient().doReturn(true).when(inetAddress5).isLinkLocalAddress(); + Mockito.lenient().doReturn(true).when(inetAddress6).isLinkLocalAddress(); Mockito.doReturn(inetAddress1).when(interfaceAddress1).getAddress(); Mockito.doReturn(inetAddress2).when(interfaceAddress2).getAddress(); @@ -130,6 +249,7 @@ private List getAllAddresses() { Mockito.doReturn(inetAddress4).when(interfaceAddress4).getAddress(); Mockito.doReturn(inetAddress5).when(interfaceAddress5).getAddress(); Mockito.doReturn(inetAddress6).when(interfaceAddress6).getAddress(); + Mockito.doReturn(inetAddress7).when(interfaceAddress7).getAddress(); interfaceAddresses.add(interfaceAddress1); interfaceAddresses.add(interfaceAddress2); @@ -137,6 +257,7 @@ private List getAllAddresses() { interfaceAddresses.add(interfaceAddress4); interfaceAddresses.add(interfaceAddress5); interfaceAddresses.add(interfaceAddress6); + interfaceAddresses.add(interfaceAddress7); return interfaceAddresses; } diff --git a/src/test/java/com/aws/greengrass/detector/uploader/ConnectivityUpdaterTest.java b/src/test/java/com/aws/greengrass/detector/uploader/ConnectivityUpdaterTest.java index b1730db..1954d3e 100644 --- a/src/test/java/com/aws/greengrass/detector/uploader/ConnectivityUpdaterTest.java +++ b/src/test/java/com/aws/greengrass/detector/uploader/ConnectivityUpdaterTest.java @@ -170,7 +170,7 @@ private List getIps() { private List getNewIps() { List ips = new ArrayList<>(); ips.add(TestConstants.IPV4_LOOPBACK); - ips.add(TestConstants.IP_2); + ips.add(TestConstants.IPV6_LOOPBACK); return ips; } } diff --git a/src/test/java/com/aws/greengrass/utils/TestConstants.java b/src/test/java/com/aws/greengrass/utils/TestConstants.java index 6c2232b..36acfea 100644 --- a/src/test/java/com/aws/greengrass/utils/TestConstants.java +++ b/src/test/java/com/aws/greengrass/utils/TestConstants.java @@ -10,10 +10,11 @@ public final class TestConstants { public static final String IPV4_LOOPBACK = "127.0.0.1"; public static final String IP_1 = "0.61.124.18"; - public static final String IP_2 = "::1/128"; - public static final String IP_3 = "fe80::bd48:478f:3447:befd"; - public static final String IP_4 = "fe80::2711:7760:46f7:e23a"; + public static final String IPV6_LOOPBACK = "::1/128"; + public static final String IPV6_LINK_LOCAL_1 = "fe80::bd48:478f:3447:befd"; + public static final String IPV6_LINK_LOCAL_2 = "fe80::2711:7760:46f7:e23a"; public static final String IPV4_LINK_LOCAL = "169.254.0.0"; + public static final String IPV6_1 = "2001:db8:1234::1"; public static final int PORT_1 = 8883; public static final int PORT_2 = 8884;