diff --git a/pom.xml b/pom.xml
index 8a3b7f0..f69885a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,13 +45,13 @@
com.aws.greengrass
nucleus
- 2.2.0-SNAPSHOT
+ 2.12.0-SNAPSHOT
provided
com.aws.greengrass
nucleus
- 2.2.0-SNAPSHOT
+ 2.12.0-SNAPSHOT
test-jar
test
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..9075856 100644
--- a/src/main/java/com/aws/greengrass/detector/config/Config.java
+++ b/src/main/java/com/aws/greengrass/detector/config/Config.java
@@ -6,11 +6,15 @@
package com.aws.greengrass.detector.config;
import com.aws.greengrass.componentmanager.KernelConfigResolver;
+import com.aws.greengrass.config.Topic;
import com.aws.greengrass.config.Topics;
import com.aws.greengrass.logging.api.Logger;
import com.aws.greengrass.logging.impl.LogManager;
import com.aws.greengrass.util.Coerce;
+import lombok.Getter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -19,6 +23,7 @@ public class Config {
static final String INCLUDE_IPV4_LOOPBACK_ADDRESSES_CONFIG_KEY = "includeIPv4LoopbackAddrs";
static final String INCLUDE_IPV4_LINK_LOCAL_ADDRESSES_CONFIG_KEY = "includeIPv4LinkLocalAddrs";
+ static final String EXCLUDED_IP_ADDRESSES_CONFIG_KEY = "excludedIPAddresses";
static final String DEFAULT_PORT_CONFIG_KEY = "defaultPort";
static final boolean DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES = false;
static final boolean DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES = false;
@@ -27,6 +32,8 @@ public class Config {
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);
+ @Getter
+ private final List excludedIPAddresses = new ArrayList<>();
/**
* Config constructor.
@@ -39,6 +46,7 @@ public Config(Topics topics) {
if (configurationTopics.isEmpty()) {
this.includeIPv4LoopbackAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES);
this.includeIPv4LinkLocalAddrs = new AtomicBoolean(DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES);
+ this.excludedIPAddresses.clear();
this.defaultPort = new AtomicInteger(DEFAULT_PORT);
return;
}
@@ -57,9 +65,20 @@ public Config(Topics topics) {
Coerce.toInt(
configurationTopics.findOrDefault(DEFAULT_PORT,
DEFAULT_PORT_CONFIG_KEY)));
+ Topic excludedIPTopic = configurationTopics.find(EXCLUDED_IP_ADDRESSES_CONFIG_KEY);
+ if (excludedIPTopic != null) {
+ if (excludedIPTopic.getOnce() instanceof List) {
+ this.excludedIPAddresses.clear();
+ this.excludedIPAddresses.addAll(Coerce.toStringList(excludedIPTopic.getOnce()));
+ } else {
+ logger.atWarn().kv("value", excludedIPTopic.getOnce()).log("Invalid config value for"
+ + " excludedIPAddresses. The config must be input as a list");
+ }
+ }
logger.atInfo().kv("includeIPv4LoopbackAddrs", includeIPv4LoopbackAddrs.get())
.kv("includeIPv4LinkLocalAddrs", includeIPv4LinkLocalAddrs.get())
+ .kv("excludedIPAddresses", excludedIPAddresses)
.kv("defaultPort", defaultPort.get())
.log("Configuration updated");
});
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..5acae14 100644
--- a/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java
+++ b/src/main/java/com/aws/greengrass/detector/detector/IpDetector.java
@@ -44,6 +44,9 @@ List getIpAddresses(Enumeration interfaces, Confi
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
InetAddress address = interfaceAddress.getAddress();
+ if (config.getExcludedIPAddresses().contains(address.getHostAddress())) {
+ continue;
+ }
if (address instanceof Inet6Address) {
continue;
}
diff --git a/src/test/java/com/aws/greengrass/detector/config/ConfigTest.java b/src/test/java/com/aws/greengrass/detector/config/ConfigTest.java
index 50f6cfd..3b421f3 100644
--- a/src/test/java/com/aws/greengrass/detector/config/ConfigTest.java
+++ b/src/test/java/com/aws/greengrass/detector/config/ConfigTest.java
@@ -7,14 +7,20 @@
import com.aws.greengrass.config.ChildChanged;
+import com.aws.greengrass.config.Topic;
import com.aws.greengrass.config.Topics;
import com.aws.greengrass.util.Coerce;
+import com.aws.greengrass.utils.TestConstants;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
+import java.util.Collections;
+import java.util.List;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -30,8 +36,11 @@ class ConfigTest {
public void GIVEN_config_topics_WHEN_initialize_THEN_configuration_created() {
Topics topics = Mockito.mock(Topics.class);
Topics configTopics = Mockito.mock(Topics.class);
+ Topic excludedIpTopic = Mockito.mock(Topic.class);
String mockIncludeIPv4LoopbackAddrsConfig = "true";
String mockIncludeIPv4LinkLocalAddrsConfig = "true";
+ String mockExcludeIPsConfig = String.format("[%s]", TestConstants.IP_1);
+ List mockList = Collections.singletonList(TestConstants.IP_1);
int mockPortValue = 9000;
// stub subscribe() to call just the callback method without adding watcher
@@ -49,6 +58,8 @@ public void GIVEN_config_topics_WHEN_initialize_THEN_configuration_created() {
Mockito.doReturn(mockPortValue)
.when(configTopics).findOrDefault(anyInt(), eq(Config.DEFAULT_PORT_CONFIG_KEY));
+ Mockito.doReturn(excludedIpTopic).when(configTopics).find(Config.EXCLUDED_IP_ADDRESSES_CONFIG_KEY);
+ Mockito.doReturn(mockList).when(excludedIpTopic).getOnce();
Mockito.doReturn(configTopics).when(topics).lookupTopics(anyString());
config = new Config(topics);
@@ -56,6 +67,7 @@ public void GIVEN_config_topics_WHEN_initialize_THEN_configuration_created() {
assertEquals(mockPortValue, config.getDefaultPort());
assertEquals(Coerce.toBoolean(mockIncludeIPv4LoopbackAddrsConfig), config.isIncludeIPv4LoopbackAddrs());
assertEquals(Coerce.toBoolean(mockIncludeIPv4LinkLocalAddrsConfig), config.isIncludeIPv4LinkLocalAddrs());
+ assertEquals(Coerce.toStringList(mockExcludeIPsConfig), config.getExcludedIPAddresses());
}
@Test
@@ -78,5 +90,29 @@ public void GIVEN_empty_config_topics_WHEN_initialize_THEN_default_configuration
assertEquals(Config.DEFAULT_INCLUDE_IPV4_LOOPBACK_ADDRESSES, config.isIncludeIPv4LoopbackAddrs());
assertEquals(Config.DEFAULT_INCLUDE_IPV4_LINK_LOCAL_ADDRESSES, config.isIncludeIPv4LinkLocalAddrs());
assertEquals(Config.DEFAULT_PORT, config.getDefaultPort());
+ assertTrue(config.getExcludedIPAddresses().isEmpty());
+ }
+
+ @Test
+ public void GIVEN_invalid_excluded_ips_list_WHEN_initialize_THEN_default_configuration_created() {
+ Topics topics = Mockito.mock(Topics.class);
+ Topics configTopics = Mockito.mock(Topics.class);
+
+ // stub subscribe() to call just the callback method without adding watcher
+ doAnswer((Answer) invocation -> {
+ ChildChanged childChanged = invocation.getArgument(0);
+ childChanged.childChanged(null, null);
+ return null;
+ }).when(configTopics).subscribe(any());
+
+ Mockito.doReturn(false).when(configTopics).isEmpty();
+ Mockito.doReturn(configTopics).when(topics).lookupTopics(anyString());
+ Topic excludedIpTopic = Mockito.mock(Topic.class);
+ Mockito.doReturn(excludedIpTopic).when(configTopics).find(Config.EXCLUDED_IP_ADDRESSES_CONFIG_KEY);
+ Mockito.doReturn("bad-config").when(excludedIpTopic).getOnce();
+ config = new Config(topics);
+
+ assertNotNull(config);
+ assertTrue(config.getExcludedIPAddresses().isEmpty());
}
}
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..38acc52 100644
--- a/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java
+++ b/src/test/java/com/aws/greengrass/detector/detector/IpDetectorTest.java
@@ -22,8 +22,10 @@
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
+import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith({MockitoExtension.class})
@@ -98,6 +100,34 @@ public void GIVEN_network_down_WHEN_get_ipAddresses_THEN_null_returned() throws
assertTrue(ipAddresses.isEmpty());
}
+ @Test
+ public void GIVEN_excludeIPAddresses_WHEN_get_ipAddresses_THEN_excludeIPs_filtered() throws SocketException {
+ // exclude IP_1 (0.61.124.18)
+ 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();
+ // Exclude IPv4 Loopback addresses and Link-Local addresses
+ Mockito.doReturn(true).when(config).isIncludeIPv4LoopbackAddrs();
+ Mockito.doReturn(true).when(config).isIncludeIPv4LinkLocalAddrs();
+ Mockito.doReturn(Collections.singletonList(TestConstants.IP_1)).when(config).getExcludedIPAddresses();
+
+ networkInterfaces.add(networkInterface);
+ Enumeration enumeration = Collections.enumeration(networkInterfaces);
+ ipDetector = new IpDetector();
+ List ipAddresses = ipDetector.getIpAddresses(enumeration, config);
+
+ assertEquals(2, ipAddresses.size());
+ assertFalse(ipAddresses.stream().map(InetAddress::getHostAddress)
+ .collect(Collectors.joining()).contains(TestConstants.IP_1));
+ assertEquals(TestConstants.IPV4_LOOPBACK, ipAddresses.get(0).getHostAddress());
+ assertEquals(TestConstants.IPV4_LINK_LOCAL, ipAddresses.get(1).getHostAddress());
+ }
+
private List getAllAddresses() {
List interfaceAddresses = new ArrayList<>();
InterfaceAddress interfaceAddress1 = Mockito.mock(InterfaceAddress.class);