Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -143,10 +142,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<String> INVALID_IPS = new HashSet<>(Arrays.asList(
"0.0.0.0", "127.0.0.1"));

private HddsServerUtil() {
}

Expand All @@ -164,8 +159,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 returns all IP addresses that are valid to
* add to a certificate's SAN extension, as determined by
* {@link #isValidInetForCsr(InetAddress)}.
*
* @return List<InetAddress>
* @throws IOException if no network interface are found or if an error
Expand All @@ -174,7 +170,6 @@ public static void addPBProtocol(Configuration conf, Class<?> protocol,
public static List<InetAddress> getValidInetsForCurrentHost()
throws IOException {
List<InetAddress> hostIps = new ArrayList<>();
InetAddressValidator ipValidator = InetAddressValidator.getInstance();

Enumeration<NetworkInterface> enumNI =
NetworkInterface.getNetworkInterfaces();
Expand All @@ -189,13 +184,11 @@ public static List<InetAddress> getValidInetsForCurrentHost()
while (enumAdds.hasMoreElements()) {
InetAddress addr = enumAdds.nextElement();

String hostAddress = addr.getHostAddress();
if (!INVALID_IPS.contains(hostAddress) && ipValidator.isValid(hostAddress)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is ipValidator.isValid being removed? Is InetAddress obtained via NetworkInterface guaranteed to be valid?

&& !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());
}
}
}
Expand All @@ -204,6 +197,24 @@ public static List<InetAddress> 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()
&& !isScopedOrMaskingIPv6Address(addr);
}

/**
* Determines if the supplied address is an IPv6 address, with a defined scope-id and/or with a defined prefix length.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
Loading