From 4adc1d29a9ea694b20406a1a74cca587291fa3ea Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 2 May 2019 12:24:29 -0400 Subject: [PATCH 1/3] Simplify filtering addresses on interfaces This commit is a refactoring of how we filter addresses on interfaces. In particular, we refactor all of these methods into a common private method. We also change the order of logic to first check if an address matches our filter and then check if the interface is up. This is to possibly avoid problems we are seeing where devices are flapping up and down while we are checking for loopback addresses. We do not expect the loopback device to flap up and down so by reversing the logic here we avoid that problem on CI machines. Finally, we expand the error message when this does occur so that we know which device is flapping. --- .../common/network/NetworkUtils.java | 90 +++++++------------ 1 file changed, 34 insertions(+), 56 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/common/network/NetworkUtils.java b/server/src/main/java/org/elasticsearch/common/network/NetworkUtils.java index 7434fbc9d8bdf..4e8f871ed3044 100644 --- a/server/src/main/java/org/elasticsearch/common/network/NetworkUtils.java +++ b/server/src/main/java/org/elasticsearch/common/network/NetworkUtils.java @@ -22,6 +22,7 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.Constants; +import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -33,6 +34,7 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.function.Predicate; /** * Utilities for network interfaces / addresses binding and publishing. @@ -150,77 +152,53 @@ public static boolean defaultReuseAddress() { return Constants.WINDOWS ? false : true; } - /** Returns all interface-local scope (loopback) addresses for interfaces that are up. */ - static InetAddress[] getLoopbackAddresses() throws SocketException { - List list = new ArrayList<>(); - for (NetworkInterface intf : getInterfaces()) { - if (intf.isUp()) { - for (InetAddress address : Collections.list(intf.getInetAddresses())) { - if (address.isLoopbackAddress()) { - list.add(address); - } + private static InetAddress[] filterAllAddresses(final Predicate predicate, final String message) throws IOException { + final List interfaces = getInterfaces(); + final List list = new ArrayList<>(); + for (final NetworkInterface intf : interfaces) { + for (final InetAddress address : Collections.list(intf.getInetAddresses())) { + if (predicate.test(address) && isUp(intf)) { + list.add(address); } } } if (list.isEmpty()) { - throw new IllegalArgumentException("No up-and-running loopback addresses found, got " + getInterfaces()); + throw new IllegalArgumentException(message + ", got " + interfaces); + } + return list.toArray(new InetAddress[0]); + } + + private static boolean isUp(final NetworkInterface intf) throws IOException { + try { + return intf.isUp(); + } catch (final SocketException e) { + throw new IOException("failed to check if interface [" + intf.getName() + "] is up", e); } - return list.toArray(new InetAddress[list.size()]); + } + + /** Returns all interface-local scope (loopback) addresses for interfaces that are up. */ + static InetAddress[] getLoopbackAddresses() throws IOException { + return filterAllAddresses(InetAddress::isLoopbackAddress, "no up-and-running loopback addresses found"); } /** Returns all site-local scope (private) addresses for interfaces that are up. */ - static InetAddress[] getSiteLocalAddresses() throws SocketException { - List list = new ArrayList<>(); - for (NetworkInterface intf : getInterfaces()) { - if (intf.isUp()) { - for (InetAddress address : Collections.list(intf.getInetAddresses())) { - if (address.isSiteLocalAddress()) { - list.add(address); - } - } - } - } - if (list.isEmpty()) { - throw new IllegalArgumentException("No up-and-running site-local (private) addresses found, got " + getInterfaces()); - } - return list.toArray(new InetAddress[list.size()]); + static InetAddress[] getSiteLocalAddresses() throws IOException { + return filterAllAddresses(InetAddress::isSiteLocalAddress, "No up-and-running site-local (private) addresses found"); } /** Returns all global scope addresses for interfaces that are up. */ - static InetAddress[] getGlobalAddresses() throws SocketException { - List list = new ArrayList<>(); - for (NetworkInterface intf : getInterfaces()) { - if (intf.isUp()) { - for (InetAddress address : Collections.list(intf.getInetAddresses())) { - if (address.isLoopbackAddress() == false && - address.isSiteLocalAddress() == false && - address.isLinkLocalAddress() == false) { - list.add(address); - } - } - } - } - if (list.isEmpty()) { - throw new IllegalArgumentException("No up-and-running global-scope (public) addresses found, got " + getInterfaces()); - } - return list.toArray(new InetAddress[list.size()]); + static InetAddress[] getGlobalAddresses() throws IOException { + return filterAllAddresses( + address -> address.isLoopbackAddress() == false + && address.isSiteLocalAddress() == false + && address.isLinkLocalAddress() == false, + "no up-and-running global-scope (public) addresses found"); } /** Returns all addresses (any scope) for interfaces that are up. * This is only used to pick a publish address, when the user set network.host to a wildcard */ - static InetAddress[] getAllAddresses() throws SocketException { - List list = new ArrayList<>(); - for (NetworkInterface intf : getInterfaces()) { - if (intf.isUp()) { - for (InetAddress address : Collections.list(intf.getInetAddresses())) { - list.add(address); - } - } - } - if (list.isEmpty()) { - throw new IllegalArgumentException("No up-and-running addresses found, got " + getInterfaces()); - } - return list.toArray(new InetAddress[list.size()]); + static InetAddress[] getAllAddresses() throws IOException { + return filterAllAddresses(address -> true, "no up-and-running addresses found"); } /** Returns addresses for the given interface (it must be marked up) */ From b19730ea7ec6d22d4037f2f54d6505a8a7c98333 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 2 May 2019 12:32:46 -0400 Subject: [PATCH 2/3] Fix compilation --- .../org/elasticsearch/common/network/InetAddressHelper.java | 3 ++- .../org/elasticsearch/xpack/security/cli/CertGenUtils.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java index 3c852a3ae4017..f1be78f7e9b4a 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.common.network; +import java.io.IOException; import java.net.InetAddress; import java.net.SocketException; @@ -16,7 +17,7 @@ public class InetAddressHelper { private InetAddressHelper() {} - public static InetAddress[] getAllAddresses() throws SocketException { + public static InetAddress[] getAllAddresses() throws IOException { return NetworkUtils.getAllAddresses(); } diff --git a/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java index af6a71310569a..de91c58f033b9 100644 --- a/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java +++ b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java @@ -268,7 +268,7 @@ public static KeyPair generateKeyPair(int keysize) throws NoSuchAlgorithmExcepti /** * Converts the {@link InetAddress} objects into a {@link GeneralNames} object that is used to represent subject alternative names. */ - public static GeneralNames getSubjectAlternativeNames(boolean resolveName, Set addresses) throws SocketException { + public static GeneralNames getSubjectAlternativeNames(boolean resolveName, Set addresses) throws IOException { Set generalNameList = new HashSet<>(); for (InetAddress address : addresses) { if (address.isAnyLocalAddress()) { From 204ee3869baf1fb902e2d9ca7ba87a586cef4f5c Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 2 May 2019 12:34:00 -0400 Subject: [PATCH 3/3] Fix imports --- .../java/org/elasticsearch/common/network/InetAddressHelper.java | 1 - .../java/org/elasticsearch/xpack/security/cli/CertGenUtils.java | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java index f1be78f7e9b4a..1177b1d0318f2 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/common/network/InetAddressHelper.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.net.InetAddress; -import java.net.SocketException; /** * We use this class to access the package private method in NetworkUtils to resolve anyLocalAddress InetAddresses for certificate diff --git a/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java index de91c58f033b9..bc2b27df58047 100644 --- a/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java +++ b/x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java @@ -42,7 +42,6 @@ import java.io.IOException; import java.math.BigInteger; import java.net.InetAddress; -import java.net.SocketException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore;