diff --git a/build.gradle b/build.gradle index f70e9a503b..2bb0dd51db 100644 --- a/build.gradle +++ b/build.gradle @@ -589,6 +589,7 @@ dependencies { implementation 'com.nimbusds:nimbus-jose-jwt:9.48' implementation 'com.rfksystems:blake2b:2.0.0' implementation 'com.password4j:password4j:1.8.2' + implementation "com.github.seancfoley:ipaddress:5.5.1" // Action privileges: check tables and compact collections implementation 'com.selectivem.collections:special-collections-complete:1.4.0' diff --git a/src/main/java/org/opensearch/security/auth/AuthFailureListener.java b/src/main/java/org/opensearch/security/auth/AuthFailureListener.java index cbc76cc2e0..9f23391275 100644 --- a/src/main/java/org/opensearch/security/auth/AuthFailureListener.java +++ b/src/main/java/org/opensearch/security/auth/AuthFailureListener.java @@ -19,11 +19,12 @@ import java.net.InetAddress; -import org.opensearch.security.support.WildcardMatcher; +import org.opensearch.security.support.HostAndCidrMatcher; import org.opensearch.security.user.AuthCredentials; public interface AuthFailureListener { void onAuthFailure(InetAddress remoteAddress, AuthCredentials authCredentials, Object request); - WildcardMatcher getIgnoreHostsMatcher(); + HostAndCidrMatcher getIgnoreHostsMatcher(); + } diff --git a/src/main/java/org/opensearch/security/auth/BackendRegistry.java b/src/main/java/org/opensearch/security/auth/BackendRegistry.java index b527b8fca2..83c42321f1 100644 --- a/src/main/java/org/opensearch/security/auth/BackendRegistry.java +++ b/src/main/java/org/opensearch/security/auth/BackendRegistry.java @@ -28,7 +28,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -66,7 +65,7 @@ import org.opensearch.security.http.XFFResolver; import org.opensearch.security.securityconf.DynamicConfigModel; import org.opensearch.security.support.ConfigConstants; -import org.opensearch.security.support.WildcardMatcher; +import org.opensearch.security.support.HostAndCidrMatcher; import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.user.User; import org.opensearch.threadpool.ThreadPool; @@ -80,7 +79,7 @@ public class BackendRegistry { - protected final Logger log = LogManager.getLogger(this.getClass()); + protected static final Logger log = LogManager.getLogger(BackendRegistry.class); private SortedSet restAuthDomains; private Set restAuthorizers; @@ -696,8 +695,7 @@ private boolean isBlocked(InetAddress address) { } for (ClientBlockRegistry clientBlockRegistry : ipClientBlockRegistries) { - WildcardMatcher ignoreHostsMatcher = ((AuthFailureListener) clientBlockRegistry).getIgnoreHostsMatcher(); - if (matchesHostPatterns(ignoreHostsMatcher, address, hostResolverMode)) { + if (matchesIgnoreHostPatterns(clientBlockRegistry, address, hostResolverMode)) { return false; } if (clientBlockRegistry.isBlocked(address)) { @@ -708,21 +706,17 @@ private boolean isBlocked(InetAddress address) { return false; } - public static boolean matchesHostPatterns(WildcardMatcher hostMatcher, InetAddress address, String hostResolverMode) { - if (hostMatcher == null) { + private static boolean matchesIgnoreHostPatterns( + ClientBlockRegistry clientBlockRegistry, + InetAddress address, + String hostResolverMode + ) { + HostAndCidrMatcher ignoreHostsMatcher = ((AuthFailureListener) clientBlockRegistry).getIgnoreHostsMatcher(); + if (ignoreHostsMatcher == null || address == null) { return false; } - if (address != null) { - List valuesToCheck = new ArrayList<>(List.of(address.getHostAddress())); - if (hostResolverMode != null - && (hostResolverMode.equalsIgnoreCase("ip-hostname") || hostResolverMode.equalsIgnoreCase("ip-hostname-lookup"))) { - final String hostName = address.getHostName(); - valuesToCheck.add(hostName); - } + return ignoreHostsMatcher.matches(address, hostResolverMode); - return valuesToCheck.stream().anyMatch(hostMatcher); - } - return false; } private boolean isBlocked(String authBackend, String userName) { diff --git a/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java b/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java index a0028fc1d6..a266109c66 100644 --- a/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java +++ b/src/main/java/org/opensearch/security/auth/limiting/AbstractRateLimiter.java @@ -26,7 +26,7 @@ import org.opensearch.security.auth.AuthFailureListener; import org.opensearch.security.auth.blocking.ClientBlockRegistry; import org.opensearch.security.auth.blocking.HeapBasedClientBlockRegistry; -import org.opensearch.security.support.WildcardMatcher; +import org.opensearch.security.support.HostAndCidrMatcher; import org.opensearch.security.user.AuthCredentials; import org.opensearch.security.util.ratetracking.RateTracker; @@ -34,7 +34,7 @@ public abstract class AbstractRateLimiter implements AuthFailureLi protected final ClientBlockRegistry clientBlockRegistry; protected final RateTracker rateTracker; protected final List ignoreHosts; - private WildcardMatcher ignoreHostMatcher; + private HostAndCidrMatcher ignoreHostMatcher; public AbstractRateLimiter(Settings settings, Path configPath, Class clientIdType) { this.ignoreHosts = settings.getAsList("ignore_hosts", Collections.emptyList()); @@ -54,13 +54,13 @@ public AbstractRateLimiter(Settings settings, Path configPath, Class map(final User user, final TransportAddress caller) { } if (caller.address() != null - && (hostResolverMode.equalsIgnoreCase("ip-hostname") || hostResolverMode.equalsIgnoreCase("ip-hostname-lookup"))) { + && (hostResolverMode.equalsIgnoreCase(HostResolverMode.IP_HOSTNAME.getValue()) + || hostResolverMode.equalsIgnoreCase(HostResolverMode.IP_HOSTNAME_LOOKUP.getValue()))) { final String hostName = caller.address().getHostString(); for (String p : WildcardMatcher.getAllMatchingPatterns(hostMatchers, hostName)) { @@ -338,7 +340,7 @@ private Set map(final User user, final TransportAddress caller) { } } - if (caller.address() != null && hostResolverMode.equalsIgnoreCase("ip-hostname-lookup")) { + if (caller.address() != null && hostResolverMode.equalsIgnoreCase(HostResolverMode.IP_HOSTNAME_LOOKUP.getValue())) { final String resolvedHostName = caller.address().getHostName(); diff --git a/src/main/java/org/opensearch/security/support/HostAndCidrMatcher.java b/src/main/java/org/opensearch/security/support/HostAndCidrMatcher.java new file mode 100644 index 0000000000..caffa6b871 --- /dev/null +++ b/src/main/java/org/opensearch/security/support/HostAndCidrMatcher.java @@ -0,0 +1,106 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.support; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import inet.ipaddr.IPAddressString; + +/** + * A utility class that performs matching of IP addresses against hostname patterns and CIDR ranges. + * This matcher supports both wildcard hostname patterns (e.g., *.example.com) and CIDR notation (e.g., 192.168.1.0/24). + */ +public class HostAndCidrMatcher { + protected final Logger log = LogManager.getLogger(HostAndCidrMatcher.class); + private final WildcardMatcher hostMatcher; + private final List cidrMatchers; + + /** + * Constructs a new matcher with the specified host patterns. + * + * @param hostPatterns A list of patterns that can include both hostname wildcards + * (e.g., *.example.com) and CIDR ranges (e.g., 192.168.1.0/24). + * Must not be null. + * @throws IllegalArgumentException if hostPatterns is null + */ + public HostAndCidrMatcher(List hostPatterns) { + if (hostPatterns == null) { + throw new IllegalArgumentException("Host patterns cannot be null"); + } + + this.hostMatcher = WildcardMatcher.from(hostPatterns); + this.cidrMatchers = hostPatterns.stream().map(IPAddressString::new).filter(IPAddressString::isIPAddress).toList(); + } + + /** + * Checks if the provided IP address matches any of the configured CIDR ranges. + * + * @param address The IP address to check. Can be either IPv4 or IPv6. + * @return true if the address matches any configured CIDR range, false otherwise + * or if the address is null + */ + public boolean matchesCidr(InetAddress address) { + if (address == null || cidrMatchers == null) { + return false; + } + + IPAddressString addressString = new IPAddressString(address.getHostAddress()); + return cidrMatchers.stream().anyMatch(cidrAddress -> cidrAddress.contains(addressString)); + } + + /** + * Checks if the provided IP address matches any of the configured hostname patterns. + * This method can perform DNS lookups depending on the hostResolverMode. + * + * @param address The IP address to check + * @param hostResolverMode The resolution mode. Must be one of {@link HostResolverMode} to enable hostname matching + * @return true if the address matches any configured hostname pattern, false otherwise, + * if the address is null, or if the resolver mode is invalid + * @implNote This method may perform DNS lookups which could impact performance + */ + public boolean matchesHostname(InetAddress address, String hostResolverMode) { + if (address == null || hostMatcher == null) { + return false; + } + + List valuesToCheck = new ArrayList<>(List.of(address.getHostAddress())); + if (hostResolverMode != null + && (hostResolverMode.equalsIgnoreCase(HostResolverMode.IP_HOSTNAME.getValue()) + || hostResolverMode.equalsIgnoreCase(HostResolverMode.IP_HOSTNAME_LOOKUP.getValue()))) { + try { + final String hostName = address.getHostName(); // potential blocking call + valuesToCheck.add(hostName); + } catch (Exception e) { + log.warn("Failed to resolve hostname for {}: {}", address.getHostAddress(), e.getMessage()); + return false; + } + } + return valuesToCheck.stream().anyMatch(hostMatcher); + } + + /** + * Checks if the provided IP address matches either hostname patterns or CIDR ranges. + * + * @param address The IP address to check + * @param hostResolverMode The resolution mode for hostname matching + * @return true if the address matches either hostname patterns or CIDR ranges, + * false otherwise + */ + public boolean matches(InetAddress address, String hostResolverMode) { + return matchesHostname(address, hostResolverMode) || matchesCidr(address); + } +} diff --git a/src/main/java/org/opensearch/security/support/HostResolverMode.java b/src/main/java/org/opensearch/security/support/HostResolverMode.java new file mode 100644 index 0000000000..00ce6e9117 --- /dev/null +++ b/src/main/java/org/opensearch/security/support/HostResolverMode.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.support; + +public enum HostResolverMode { + IP_HOSTNAME("ip-hostname"), + IP_HOSTNAME_LOOKUP("ip-hostname-lookup"); + + private final String value; + + HostResolverMode(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/test/java/org/opensearch/security/UtilTests.java b/src/test/java/org/opensearch/security/UtilTests.java index fcfd26576f..15361b027c 100644 --- a/src/test/java/org/opensearch/security/UtilTests.java +++ b/src/test/java/org/opensearch/security/UtilTests.java @@ -26,15 +26,11 @@ package org.opensearch.security; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.List; import java.util.Map; import org.junit.Test; import org.opensearch.common.settings.Settings; -import org.opensearch.security.auth.BackendRegistry; import org.opensearch.security.hasher.PasswordHasher; import org.opensearch.security.hasher.PasswordHasherFactory; import org.opensearch.security.support.ConfigConstants; @@ -226,88 +222,4 @@ public void testNoEnvReplace() { ); } } - - @Test - public void testHostMatching() throws UnknownHostException { - assertThat(BackendRegistry.matchesHostPatterns(null, null, "ip-only"), is(false)); - assertThat(BackendRegistry.matchesHostPatterns(null, null, null), is(false)); - assertThat(BackendRegistry.matchesHostPatterns(WildcardMatcher.from(List.of("127.0.0.1")), null, "ip-only"), is(false)); - assertThat(BackendRegistry.matchesHostPatterns(null, InetAddress.getByName("127.0.0.1"), "ip-only"), is(false)); - assertThat( - BackendRegistry.matchesHostPatterns(WildcardMatcher.from(List.of("127.0.0.1")), InetAddress.getByName("127.0.0.1"), "ip-only"), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns(WildcardMatcher.from(List.of("127.0.0.*")), InetAddress.getByName("127.0.0.1"), "ip-only"), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("127.0.0.1")), - InetAddress.getByName("localhost"), - "ip-hostname" - ), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns(WildcardMatcher.from(List.of("127.0.0.1")), InetAddress.getByName("localhost"), "ip-only"), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("127.0.0.1")), - InetAddress.getByName("localhost"), - "ip-hostname" - ), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("127.0.0.1")), - InetAddress.getByName("example.org"), - "ip-hostname" - ), - is(false) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("example.org")), - InetAddress.getByName("example.org"), - "ip-hostname" - ), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("example.org")), - InetAddress.getByName("example.org"), - "ip-only" - ), - is(false) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("*example.org")), - InetAddress.getByName("example.org"), - "ip-hostname" - ), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("example.*")), - InetAddress.getByName("example.org"), - "ip-hostname" - ), - is(true) - ); - assertThat( - BackendRegistry.matchesHostPatterns( - WildcardMatcher.from(List.of("opensearch.org")), - InetAddress.getByName("example.org"), - "ip-hostname" - ), - is(false) - ); - } } diff --git a/src/test/java/org/opensearch/security/support/HostAndCidrMatcherTest.java b/src/test/java/org/opensearch/security/support/HostAndCidrMatcherTest.java new file mode 100644 index 0000000000..d351c532b0 --- /dev/null +++ b/src/test/java/org/opensearch/security/support/HostAndCidrMatcherTest.java @@ -0,0 +1,218 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.support; + +import java.net.InetAddress; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class HostAndCidrMatcherTest { + + private static final String OPENSEARCH_DOMAIN = "*.opensearch.org"; + private static final String OPENSEARCH_WWW = "www.opensearch.org"; + private static final String EXAMPLE_DOMAIN = "*.example.com"; + private static final String EXAMPLE_WWW = "www.example.com"; + + // CIDR ranges + private static final String PRIVATE_CLASS_A_CIDR = "10.0.0.0/8"; + private static final String PRIVATE_CLASS_B_CIDR = "172.16.0.0/12"; + private static final String PRIVATE_CLASS_C_CIDR = "192.168.1.0/24"; + private static final String IPV6_DOCUMENTATION_CIDR = "2001:db8::/32"; + + // IP addresses within the CIDR ranges + private static final String PRIVATE_CLASS_A_IP = "10.10.10.10"; + private static final String PRIVATE_CLASS_B_IP = "172.16.1.1"; + private static final String PRIVATE_CLASS_C_IP = "192.168.1.100"; + private static final String IPV6_DOCUMENTATION_IP = "2001:db8:1:2::"; + + private HostAndCidrMatcher matcher; + + @Test(expected = IllegalArgumentException.class) + public void constructorShouldThrowExceptionForNullInput() { + new HostAndCidrMatcher(null); + } + + @Test + public void shouldReturnFalseForEmptyResolverMode() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(OPENSEARCH_DOMAIN)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matchesHostname(address, ""), is(false)); + } + + @Test + public void shouldReturnFalseForInvalidResolverMode() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(OPENSEARCH_DOMAIN)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matchesHostname(address, "invalid-mode"), is(false)); + } + + @Test + public void shouldReturnFalseForNullResolverMode() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(OPENSEARCH_DOMAIN)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matchesHostname(address, null), is(false)); + } + + @Test + public void shouldReturnFalseForWrongCaseResolverMode() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(OPENSEARCH_DOMAIN)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matchesHostname(address, "IP_HOSTNAME"), is(false)); + } + + @Test + public void shouldReturnTrueForExactMatch() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList("127.0.0.1")); + InetAddress address = InetAddress.getByName("127.0.0.1"); + assertThat(matcher.matchesHostname(address, "ip-only"), is(true)); + } + + @Test + public void shouldReturnTrueForIpPatternMatch() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList("127.0.0.*")); + InetAddress address = InetAddress.getByName("127.0.0.1"); + assertThat(matcher.matchesHostname(address, "ip-only"), is(true)); + } + + @Test + public void shouldReturnFalseForHostMatchWithIpResolve() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList("127.0.0.1")); + InetAddress address = InetAddress.getByName("localhost"); + assertThat(matcher.matchesHostname(address, "ip-only"), is(true)); + } + + @Test + public void shouldReturnTrueForHostMatchWithIpResolve() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList("127.0.0.1")); + InetAddress address = InetAddress.getByName("localhost"); + assertThat(matcher.matchesHostname(address, "ip-hostname"), is(true)); + } + + @Test + public void shouldMatchIpv4WithinCidrRange() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(PRIVATE_CLASS_C_CIDR, PRIVATE_CLASS_A_CIDR)); + InetAddress address = InetAddress.getByName(PRIVATE_CLASS_C_IP); + assertThat(matcher.matchesCidr(address), is(true)); + } + + @Test + public void shouldNotMatchIpv4OutsideCidrRange() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(PRIVATE_CLASS_C_CIDR, PRIVATE_CLASS_A_CIDR)); + InetAddress address = InetAddress.getByName("192.168.2.100"); + assertThat(matcher.matchesCidr(address), is(false)); + } + + @Test + public void shouldMatchIpv6WithinCidrRange() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(IPV6_DOCUMENTATION_CIDR)); + InetAddress address = InetAddress.getByName(IPV6_DOCUMENTATION_IP); + assertThat(matcher.matchesCidr(address), is(true)); + } + + @Test + public void shouldHandleNullAddressInCidrMatching() { + matcher = new HostAndCidrMatcher(Arrays.asList(PRIVATE_CLASS_C_CIDR)); + assertThat(matcher.matchesCidr(null), is(false)); + } + + @Test + public void shouldMatchValidHostnamePattern() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN, OPENSEARCH_WWW)); + InetAddress address = InetAddress.getByName(EXAMPLE_WWW); + assertThat(matcher.matchesHostname(address, "ip-hostname"), is(true)); + } + + @Test + public void shouldHandleNullAddressInHostnameMatching() { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN)); + assertThat(matcher.matchesHostname(null, "ip-hostname"), is(false)); + } + + @Test + public void shouldMatchWhenIpMatchesCidrOnly() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN, PRIVATE_CLASS_C_CIDR)); + InetAddress address = InetAddress.getByName(PRIVATE_CLASS_C_IP); + assertThat(matcher.matches(address, "ip-hostname"), is(true)); + } + + @Test + public void shouldMatchWhenHostnameMatchesOnly() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN, PRIVATE_CLASS_C_CIDR)); + InetAddress address = InetAddress.getByName(EXAMPLE_WWW); + assertThat(matcher.matches(address, "ip-hostname"), is(true)); + } + + @Test + public void shouldNotMatchWhenNeitherMatches() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN, PRIVATE_CLASS_C_CIDR)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matches(address, "ip-hostname"), is(false)); + } + + @Test + public void shouldHandleEmptyPatternList() throws Exception { + matcher = new HostAndCidrMatcher(Collections.emptyList()); + InetAddress address = InetAddress.getByName(PRIVATE_CLASS_C_IP); + assertThat(matcher.matches(address, "ip-hostname"), is(false)); + } + + @Test + public void shouldHandleInvalidCidrNotation() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList("invalid/cidr/notation")); + InetAddress address = InetAddress.getByName(PRIVATE_CLASS_C_IP); + assertThat(matcher.matchesCidr(address), is(false)); + } + + @Test + public void shouldMatchIpHostnameLookupMode() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(OPENSEARCH_DOMAIN)); + InetAddress address = InetAddress.getByName(OPENSEARCH_WWW); + assertThat(matcher.matchesHostname(address, "ip-hostname-lookup"), is(true)); + } + + @Test + public void shouldHandleMultipleCidrRanges() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(PRIVATE_CLASS_C_CIDR, PRIVATE_CLASS_A_CIDR, PRIVATE_CLASS_B_CIDR)); + InetAddress address1 = InetAddress.getByName(PRIVATE_CLASS_C_IP); + InetAddress address2 = InetAddress.getByName(PRIVATE_CLASS_A_IP); + InetAddress address3 = InetAddress.getByName(PRIVATE_CLASS_B_IP); + + assertThat(matcher.matchesCidr(address1), is(true)); + assertThat(matcher.matchesCidr(address2), is(true)); + assertThat(matcher.matchesCidr(address3), is(true)); + } + + @Test + public void shouldHandleMultipleHostnamePatterns() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(EXAMPLE_DOMAIN, OPENSEARCH_DOMAIN)); + InetAddress address1 = InetAddress.getByName(EXAMPLE_WWW); + InetAddress address2 = InetAddress.getByName(OPENSEARCH_WWW); + + assertThat(matcher.matchesHostname(address1, "ip-hostname"), is(true)); + assertThat(matcher.matchesHostname(address2, "ip-hostname"), is(true)); + } + + @Test + public void shouldHandleMixedIpv4AndIpv6Patterns() throws Exception { + matcher = new HostAndCidrMatcher(Arrays.asList(PRIVATE_CLASS_C_CIDR, IPV6_DOCUMENTATION_CIDR, EXAMPLE_DOMAIN)); + InetAddress ipv4Address = InetAddress.getByName(PRIVATE_CLASS_C_IP); + InetAddress ipv6Address = InetAddress.getByName(IPV6_DOCUMENTATION_IP); + + assertThat(matcher.matchesCidr(ipv4Address), is(true)); + assertThat(matcher.matchesCidr(ipv6Address), is(true)); + } +} diff --git a/src/test/java/org/opensearch/security/support/HostResolverModeTest.java b/src/test/java/org/opensearch/security/support/HostResolverModeTest.java new file mode 100644 index 0000000000..bee18e5242 --- /dev/null +++ b/src/test/java/org/opensearch/security/support/HostResolverModeTest.java @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +package org.opensearch.security.support; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class HostResolverModeTest { + + @Test + public void testIpHostnameValue() { + assertThat(HostResolverMode.IP_HOSTNAME.getValue(), is("ip-hostname")); + } + + @Test + public void testIpHostnameLookupValue() { + assertThat(HostResolverMode.IP_HOSTNAME_LOOKUP.getValue(), is("ip-hostname-lookup")); + } + + @Test + public void testEnumCount() { + assertThat(HostResolverMode.values().length, is(2)); + } +}