From 3d3bb4dc41a4bf134e00a33bb7591daa890bd7bd Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:05:55 -0700 Subject: [PATCH 1/3] HDDS-9894. IP address checks neglect disabling some IPv6 addresses that are disabled for IPv4 --- .../hadoop/hdds/utils/HddsServerUtil.java | 37 +++++++++++++------ .../hadoop/hdds/scm/TestHddsServerUtils.java | 26 +++++++++++++ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java index e9050346931..a29167a435e 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java @@ -143,10 +143,6 @@ public final class HddsServerUtil { public static final String OZONE_RATIS_SNAPSHOT_COMPLETE_FLAG_NAME = "OZONE_RATIS_SNAPSHOT_COMPLETE"; - // List of ip's not recommended to be added to CSR. - private static final Set INVALID_IPS = new HashSet<>(Arrays.asList( - "0.0.0.0", "127.0.0.1")); - private HddsServerUtil() { } @@ -164,8 +160,9 @@ public static void addPBProtocol(Configuration conf, Class protocol, } /** - * Iterates through network interfaces and return all valid ip's not - * listed in {@link #INVALID_IPS}. + * Iterates through network interfaces and return all ip's that are valid to + * add to a certificate's SAN extension, as determined by + * {@link #isValidInetForCsr(InetAddress)}. * * @return List * @throws IOException if no network interface are found or if an error @@ -174,7 +171,6 @@ public static void addPBProtocol(Configuration conf, Class protocol, public static List getValidInetsForCurrentHost() throws IOException { List hostIps = new ArrayList<>(); - InetAddressValidator ipValidator = InetAddressValidator.getInstance(); Enumeration enumNI = NetworkInterface.getNetworkInterfaces(); @@ -189,13 +185,11 @@ public static List getValidInetsForCurrentHost() while (enumAdds.hasMoreElements()) { InetAddress addr = enumAdds.nextElement(); - String hostAddress = addr.getHostAddress(); - if (!INVALID_IPS.contains(hostAddress) && ipValidator.isValid(hostAddress) - && !isScopedOrMaskingIPv6Address(addr)) { - LOG.info("Adding ip:{},host:{}", hostAddress, addr.getHostName()); + if (isValidInetForCsr(addr)) { + LOG.info("Adding ip:{},host:{}", addr.getHostAddress(), addr.getHostName()); hostIps.add(addr); } else { - LOG.info("ip:{} not returned.", hostAddress); + LOG.info("ip:{} not returned.", addr.getHostAddress()); } } } @@ -204,6 +198,25 @@ public static List getValidInetsForCurrentHost() return hostIps; } + /** + * Determines whether the supplied address is valid to add to a certificate's + * SAN extension. Wildcard/unspecified (0.0.0.0, ::) and loopback + * (127.0.0.0/8, ::1) addresses are excluded for both IPv4 and IPv6, along + * with scoped or masked IPv6 addresses (see + * {@link #isScopedOrMaskingIPv6Address(InetAddress)}). Using the + * {@link InetAddress} predicates rather than a fixed set of address strings + * ensures the IPv6 forms are excluded, not just their IPv4 equivalents. + * + * @param addr the InetAddress to check + * @return true if the address should be added to the CSR + */ + public static boolean isValidInetForCsr(InetAddress addr) { + return !addr.isAnyLocalAddress() + && !addr.isLoopbackAddress() + && InetAddressValidator.getInstance().isValid(addr.getHostAddress()) + && !isScopedOrMaskingIPv6Address(addr); + } + /** * Determines if the supplied address is an IPv6 address, with a defined scope-id and/or with a defined prefix length. *

diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestHddsServerUtils.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestHddsServerUtils.java index 3d6e94e0a87..b19b59320c7 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestHddsServerUtils.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/TestHddsServerUtils.java @@ -24,12 +24,15 @@ import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_NAMES; import static org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_STALENODE_INTERVAL; import static org.apache.hadoop.ozone.OzoneConsts.OZONE_SCM_DATANODE_ID_FILE_DEFAULT; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; +import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.apache.hadoop.hdds.HddsConfigKeys; @@ -190,6 +193,29 @@ public void testNoScmDbDirConfigured() { () -> ServerUtils.getScmDbDir(new OzoneConfiguration())); } + /** + * Wildcard and loopback addresses must be excluded from a certificate's SAN + * extension for both IPv4 and IPv6. See HDDS-9894. + */ + @Test + public void testInvalidInetsExcludedFromCsr() throws UnknownHostException { + // IPv4 wildcard and loopback + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("0.0.0.0"))).isFalse(); + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("127.0.0.1"))).isFalse(); + // IPv6 equivalents: unspecified (::) and loopback (::1) + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("::"))).isFalse(); + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("::1"))).isFalse(); + } + + /** + * Regular routable addresses stay eligible for the SAN extension. + */ + @Test + public void testValidInetsIncludedInCsr() throws UnknownHostException { + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("1.2.3.4"))).isTrue(); + assertThat(HddsServerUtil.isValidInetForCsr(InetAddress.getByName("2001:db8::1"))).isTrue(); + } + @Test public void testGetStaleNodeInterval() { final OzoneConfiguration conf = new OzoneConfiguration(); From 43d1ecbf87bc1eb80cf0657ef44f91a5d9284e58 Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:09:37 -0700 Subject: [PATCH 2/3] Remove dead check --- .../main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java index a29167a435e..4ec7645c647 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java @@ -86,7 +86,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.commons.validator.routines.InetAddressValidator; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hdds.HddsConfigKeys; import org.apache.hadoop.hdds.HddsUtils; @@ -213,7 +212,6 @@ public static List getValidInetsForCurrentHost() public static boolean isValidInetForCsr(InetAddress addr) { return !addr.isAnyLocalAddress() && !addr.isLoopbackAddress() - && InetAddressValidator.getInstance().isValid(addr.getHostAddress()) && !isScopedOrMaskingIPv6Address(addr); } From d7c24037a3e66ad9ed8eb26558028e927f1f27db Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Wed, 8 Jul 2026 15:15:20 -0700 Subject: [PATCH 3/3] Address Copilot comment Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java index 4ec7645c647..49a71025c76 100644 --- a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java +++ b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/utils/HddsServerUtil.java @@ -159,7 +159,7 @@ public static void addPBProtocol(Configuration conf, Class protocol, } /** - * Iterates through network interfaces and return all ip's that are valid to + * Iterates through network interfaces and returns all IP addresses that are valid to * add to a certificate's SAN extension, as determined by * {@link #isValidInetForCsr(InetAddress)}. *