diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index 98fc851ee0229..310d2ea6d39d6 100644 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -1,5 +1,12 @@ #!/bin/bash +if [[ "${USE_IPV6_TESTING:-}" == "true" ]]; then + # Ensure that `localhost` resolves to only `::1` + sudo bash -c 'echo "::1 localhost" | cat - /etc/hosts > temp_file && mv temp_file /etc/hosts' + sudo sed -i '/^127\.0\.0\.1/d' /etc/hosts + sudo resolvectl flush-caches || true +fi + # On some distros, this directory ends up not readable by the `elasticsearch` user that gets created during tests # This fixes that chmod 755 ~ diff --git a/.buildkite/pipelines/periodic.weekly.yml b/.buildkite/pipelines/periodic.weekly.yml new file mode 100644 index 0000000000000..4daf1031e1646 --- /dev/null +++ b/.buildkite/pipelines/periodic.weekly.yml @@ -0,0 +1,30 @@ +steps: + - group: ipv6-tests + steps: + - label: "{{matrix.GRADLE_TASK}} / ipv6-tests" + command: .ci/scripts/run-gradle.sh --continue -Djava.net.preferIPv6Addresses=true -Dbwc.checkout.align=true -Dorg.elasticsearch.build.cache.push=true -Dignore.tests.seed -Dscan.capture-file-fingerprints {{matrix.GRADLE_TASK}} + timeout_in_minutes: 300 + agents: + provider: aws + imagePrefix: elasticsearch-aws-ubuntu-2404-nvidia + instanceType: m7a.8xlarge + diskSizeGb: 150 + diskType: gp3 + diskName: /dev/sda1 + buildDirectory: /dev/shm/bk + ipv6Only: true + env: + GRADLE_TASK: "{{matrix.GRADLE_TASK}}" + JAVA_TOOL_OPTIONS: "-Djava.net.preferIPv6Addresses=true" + _JAVA_OPTIONS: "-Djava.net.preferIPv6Addresses=true" + USE_IPV6_TESTING: "true" + DISABLE_DOCKER_TESTS: "true" + matrix: + setup: + GRADLE_TASK: + - checkPart1 + - checkPart2 + - checkPart3 + - checkPart4 + - checkPart5 + - checkPart6 diff --git a/.buildkite/pipelines/pull-request/ipv6.yml b/.buildkite/pipelines/pull-request/ipv6.yml new file mode 100644 index 0000000000000..07a42443baa83 --- /dev/null +++ b/.buildkite/pipelines/pull-request/ipv6.yml @@ -0,0 +1,35 @@ +config: + allow-labels: test-ipv6 + skip-labels: + - ">test-mute" +steps: + - group: ipv6-tests + steps: + - label: "{{matrix.GRADLE_TASK}} / ipv6-tests" + key: "ipv6-tests" + command: .ci/scripts/run-gradle.sh --continue -Djava.net.preferIPv6Addresses=true -Dbwc.checkout.align=true -Dorg.elasticsearch.build.cache.push=true -Dignore.tests.seed -Dscan.capture-file-fingerprints {{matrix.GRADLE_TASK}} + timeout_in_minutes: 300 + agents: + provider: aws + imagePrefix: elasticsearch-aws-ubuntu-2404-nvidia + instanceType: m7a.8xlarge + diskSizeGb: 150 + diskType: gp3 + diskName: /dev/sda1 + buildDirectory: /dev/shm/bk + ipv6Only: true + env: + GRADLE_TASK: "{{matrix.GRADLE_TASK}}" + JAVA_TOOL_OPTIONS: "-Djava.net.preferIPv6Addresses=true" + _JAVA_OPTIONS: "-Djava.net.preferIPv6Addresses=true" + USE_IPV6_TESTING: "true" + DISABLE_DOCKER_TESTS: "true" + matrix: + setup: + GRADLE_TASK: + - checkPart1 + - checkPart2 + - checkPart3 + - checkPart4 + - checkPart5 + - checkPart6 diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java index 21829d95c870e..fa39bcbc8a3d7 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java @@ -1370,6 +1370,9 @@ private void createConfiguration() { baseConfig.put("path.repo", confPathRepo.toAbsolutePath().toString()); baseConfig.put("path.data", confPathData.toAbsolutePath().toString()); baseConfig.put("path.logs", confPathLogs.toAbsolutePath().toString()); + if (Boolean.getBoolean("java.net.preferIPv6Addresses")) { + baseConfig.put("network.host", "_local:ipv6_"); + } baseConfig.put("node.attr.testattr", "test"); baseConfig.put("node.portsfile", "true"); baseConfig.put("http.port", httpPort); diff --git a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/HttpClientTests.java b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/HttpClientTests.java index f4a3cfbde4f4c..abd8eb286edce 100644 --- a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/HttpClientTests.java +++ b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/HttpClientTests.java @@ -14,6 +14,7 @@ import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.ResourceNotFoundException; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.test.ESTestCase; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -117,7 +118,7 @@ public static void stopServer() { } private static String url(final String path) { - String hostname = server.getAddress().getHostString(); + String hostname = InetAddresses.toUriString(server.getAddress().getAddress()); int port = server.getAddress().getPort(); return "http://" + hostname + ":" + port + path; } diff --git a/modules/reindex/build.gradle b/modules/reindex/build.gradle index 86eabc6e773d9..803544b66a90e 100644 --- a/modules/reindex/build.gradle +++ b/modules/reindex/build.gradle @@ -31,7 +31,7 @@ testClusters.configureEach { module ':modules:lang-painless' module ':modules:rest-root' // Whitelist reindexing from the local node so we can test reindex-from-remote. - setting 'reindex.remote.whitelist', '127.0.0.1:*' + setting 'reindex.remote.whitelist', '127.0.0.1:*,[::1]:*' } dependencies { diff --git a/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexFromRemoteWithAuthTests.java b/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexFromRemoteWithAuthTests.java index eee6d67d4667e..9f4532616afe7 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexFromRemoteWithAuthTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/reindex/ReindexFromRemoteWithAuthTests.java @@ -74,7 +74,7 @@ protected boolean addMockHttpTransport() { protected Settings nodeSettings() { Settings.Builder settings = Settings.builder().put(super.nodeSettings()); // Whitelist reindexing from the http host we're going to use - settings.put(TransportReindexAction.REMOTE_CLUSTER_WHITELIST.getKey(), "127.0.0.1:*"); + settings.put(TransportReindexAction.REMOTE_CLUSTER_WHITELIST.getKey(), "127.0.0.1:*,::1:*"); settings.put(NetworkModule.HTTP_TYPE_KEY, Netty4Plugin.NETTY_HTTP_TRANSPORT_NAME); return settings.build(); } diff --git a/modules/reindex/src/test/java/org/elasticsearch/reindex/RetryTests.java b/modules/reindex/src/test/java/org/elasticsearch/reindex/RetryTests.java index fa0e1d22f4556..9825b2c31faff 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/reindex/RetryTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/reindex/RetryTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.client.internal.Client; import org.elasticsearch.common.BackoffPolicy; import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; @@ -91,7 +92,7 @@ protected boolean addMockHttpTransport() { final Settings nodeSettings() { return Settings.builder() // whitelist reindexing from the HTTP host we're going to use - .put(TransportReindexAction.REMOTE_CLUSTER_WHITELIST.getKey(), "127.0.0.1:*") + .put(TransportReindexAction.REMOTE_CLUSTER_WHITELIST.getKey(), "127.0.0.1:*,[::1]:*") .build(); } @@ -118,9 +119,10 @@ public void testReindexFromRemote() throws Exception { assertNotNull(masterNode); TransportAddress address = masterNode.getInfo(HttpInfo.class).getAddress().publishAddress(); + String host = InetAddresses.toUriString(address.address().getAddress()); RemoteInfo remote = new RemoteInfo( "http", - address.getAddress(), + host, address.getPort(), null, new BytesArray("{\"match_all\":{}}"), diff --git a/modules/reindex/src/yamlRestTest/java/org/elasticsearch/index/reindex/ReindexClientYamlTestSuiteIT.java b/modules/reindex/src/yamlRestTest/java/org/elasticsearch/index/reindex/ReindexClientYamlTestSuiteIT.java index 0378a63ed5481..10f227fffcbaf 100644 --- a/modules/reindex/src/yamlRestTest/java/org/elasticsearch/index/reindex/ReindexClientYamlTestSuiteIT.java +++ b/modules/reindex/src/yamlRestTest/java/org/elasticsearch/index/reindex/ReindexClientYamlTestSuiteIT.java @@ -33,7 +33,7 @@ public static Iterable parameters() throws Exception { .module("lang-painless") .module("parent-join") .module("rest-root") - .setting("reindex.remote.whitelist", "127.0.0.1:*") + .setting("reindex.remote.whitelist", "127.0.0.1:*,[::1]:*") .build(); @Override diff --git a/modules/repository-azure/src/internalClusterTest/java/org/elasticsearch/repositories/azure/AzureBlobStoreRepositoryTests.java b/modules/repository-azure/src/internalClusterTest/java/org/elasticsearch/repositories/azure/AzureBlobStoreRepositoryTests.java index 559184c678a10..496e817c0850a 100644 --- a/modules/repository-azure/src/internalClusterTest/java/org/elasticsearch/repositories/azure/AzureBlobStoreRepositoryTests.java +++ b/modules/repository-azure/src/internalClusterTest/java/org/elasticsearch/repositories/azure/AzureBlobStoreRepositoryTests.java @@ -146,7 +146,7 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { } // see com.azure.storage.blob.BlobUrlParts.parseIpUrl - final String endpoint = "ignored;DefaultEndpointsProtocol=http;BlobEndpoint=" + httpServerUrl() + "/" + accountName; + final String endpoint = "ignored;DefaultEndpointsProtocol=http;BlobEndpoint=" + httpServerUrlLocalhost() + "/" + accountName; // The first node configured sets these for all nodes MAX_CONNECTION_SETTING.compareAndSet(-1, randomIntBetween(10, 30)); diff --git a/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AbstractAzureServerTestCase.java b/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AbstractAzureServerTestCase.java index d718ee3cb801a..2cce924bedf1b 100644 --- a/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AbstractAzureServerTestCase.java +++ b/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AbstractAzureServerTestCase.java @@ -218,7 +218,9 @@ protected static Optional getRangeEnd(HttpExchange exchange) { protected String getEndpointForServer(HttpServer server, String accountName) { InetSocketAddress address = server.getAddress(); - return "http://" + InetAddresses.toUriString(address.getAddress()) + ":" + address.getPort() + "/" + accountName; + // Use "localhost" for loopback addresses to work around Azure SDK's inability to parse bracketed IPv6 addresses + String host = address.getAddress().isLoopbackAddress() ? "localhost" : InetAddresses.toUriString(address.getAddress()); + return "http://" + host + ":" + address.getPort() + "/" + accountName; } public static void readFromInputStream(InputStream inputStream, long bytesToRead) { diff --git a/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureBlobContainerRetriesTests.java b/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureBlobContainerRetriesTests.java index b6c2fe29636fe..d8edc390aac71 100644 --- a/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureBlobContainerRetriesTests.java +++ b/modules/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureBlobContainerRetriesTests.java @@ -797,7 +797,9 @@ private void warnIfUnsupportedSettingSet(String settingName, Object value) { private String getEndpointForServer(HttpServer server, String accountName) { InetSocketAddress address = server.getAddress(); - return "http://" + InetAddresses.toUriString(address.getAddress()) + ":" + address.getPort() + "/" + accountName; + // Use "localhost" for loopback addresses to work around Azure SDK's inability to parse bracketed IPv6 addresses + String host = address.getAddress().isLoopbackAddress() ? "localhost" : InetAddresses.toUriString(address.getAddress()); + return "http://" + host + ":" + address.getPort() + "/" + accountName; } @Override diff --git a/modules/repository-gcs/src/internalClusterTest/java/org/elasticsearch/repositories/gcs/GcsProxyIntegrationTests.java b/modules/repository-gcs/src/internalClusterTest/java/org/elasticsearch/repositories/gcs/GcsProxyIntegrationTests.java index d15284f143522..1a0545959363b 100644 --- a/modules/repository-gcs/src/internalClusterTest/java/org/elasticsearch/repositories/gcs/GcsProxyIntegrationTests.java +++ b/modules/repository-gcs/src/internalClusterTest/java/org/elasticsearch/repositories/gcs/GcsProxyIntegrationTests.java @@ -14,6 +14,7 @@ import com.sun.net.httpserver.HttpServer; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.MockSecureSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.core.SuppressForbidden; @@ -97,7 +98,8 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace("test").getKey(), TestUtils.createServiceAccount(random()) ); - String upstreamServerUrl = "http://" + upstreamServer.getAddress().getHostString() + ":" + upstreamServer.getAddress().getPort(); + String host = InetAddresses.toUriString(upstreamServer.getAddress().getAddress()); + String upstreamServerUrl = "http://" + host + ":" + upstreamServer.getAddress().getPort(); return Settings.builder() .put(super.nodeSettings(nodeOrdinal, otherSettings)) .put(ENDPOINT_SETTING.getConcreteSettingForNamespace("test").getKey(), upstreamServerUrl) diff --git a/modules/repository-gcs/src/test/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainerStatsTests.java b/modules/repository-gcs/src/test/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainerStatsTests.java index bb3cc42ea16c2..e3cd5a55c64a9 100644 --- a/modules/repository-gcs/src/test/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainerStatsTests.java +++ b/modules/repository-gcs/src/test/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageBlobContainerStatsTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.blobstore.support.BlobMetadata; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.util.BigArrays; @@ -279,7 +280,8 @@ private ContainerAndBlobStore createBlobContainer(final String repositoryName) t protected String getEndpointForServer(final HttpServer server) { final InetSocketAddress address = server.getAddress(); - return "http://" + address.getHostString() + ":" + address.getPort(); + String host = InetAddresses.toUriString(address.getAddress()); + return "http://" + host + ":" + address.getPort(); } private record ContainerAndBlobStore(GoogleCloudStorageBlobContainer blobContainer, GoogleCloudStorageBlobStore blobStore) diff --git a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ExplicitProtocolRestIT.java b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ExplicitProtocolRestIT.java index f6de488644f40..6f2e48d3e2d71 100644 --- a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ExplicitProtocolRestIT.java +++ b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ExplicitProtocolRestIT.java @@ -48,7 +48,7 @@ public class RepositoryS3ExplicitProtocolRestIT extends AbstractRepositoryS3Rest private static String getEndpoint() { final var s3FixtureAddress = s3Fixture.getAddress(); assertThat(s3FixtureAddress, startsWith("http://")); - return s3FixtureAddress.substring("http://".length()); + return "\"" + s3FixtureAddress.substring("http://".length()) + "\""; } public static ElasticsearchCluster cluster = ElasticsearchCluster.local() diff --git a/modules/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3BlobContainerRetriesTests.java b/modules/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3BlobContainerRetriesTests.java index dafdaa619f2ce..2bad0b68f5785 100644 --- a/modules/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3BlobContainerRetriesTests.java +++ b/modules/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3BlobContainerRetriesTests.java @@ -139,7 +139,7 @@ public void setUp() throws Exception { DEFAULT_REGION_UNAVAILABLE ) { private InetAddress[] resolveHost(String host) throws UnknownHostException { - assertEquals("127.0.0.1", host); + assertTrue(InetAddress.getByName(host).isLoopbackAddress()); if (shouldErrorOnDns && randomBoolean() && randomBoolean()) { throw new UnknownHostException(host); } @@ -204,7 +204,8 @@ protected BlobContainer createBlobContainer( final String clientName = randomAlphaOfLength(5).toLowerCase(Locale.ROOT); final InetSocketAddress address = httpServer.getAddress(); - final String endpoint = "http://" + InetAddresses.toUriString(address.getAddress()) + ":" + address.getPort(); + String host = InetAddresses.toUriString(address.getAddress()); + final String endpoint = "http://" + host + ":" + address.getPort(); logger.info("--> creating client with endpoint [{}]", endpoint); clientSettings.put(ENDPOINT_SETTING.getConcreteSettingForNamespace(clientName).getKey(), endpoint); diff --git a/modules/transport-netty4/src/internalClusterTest/java/org/elasticsearch/transport/netty4/Netty4TransportPublishAddressIT.java b/modules/transport-netty4/src/internalClusterTest/java/org/elasticsearch/transport/netty4/Netty4TransportPublishAddressIT.java index eaacb541ef977..b74714d164d97 100644 --- a/modules/transport-netty4/src/internalClusterTest/java/org/elasticsearch/transport/netty4/Netty4TransportPublishAddressIT.java +++ b/modules/transport-netty4/src/internalClusterTest/java/org/elasticsearch/transport/netty4/Netty4TransportPublishAddressIT.java @@ -64,11 +64,14 @@ public void testDifferentPorts() throws Exception { assertThat(boundTransportAddress.boundAddresses()[0].getPort(), equalTo(boundTransportAddress.publishAddress().getPort())); } else { assertThat(boundTransportAddress.boundAddresses().length, greaterThan(1)); + // Determine if the publish address is IPv4 or IPv6 + boolean publishIsV4 = boundTransportAddress.publishAddress().address().getAddress() instanceof Inet4Address; for (TransportAddress boundAddress : boundTransportAddress.boundAddresses()) { assertThat(boundAddress, instanceOf(TransportAddress.class)); TransportAddress inetBoundAddress = boundAddress; - if (inetBoundAddress.address().getAddress() instanceof Inet4Address) { - // IPv4 address is preferred publish address for _local_ + boolean boundIsV4 = inetBoundAddress.address().getAddress() instanceof Inet4Address; + if (boundIsV4 == publishIsV4) { + // The bound address matching the publish address type should have the same port assertThat(inetBoundAddress.getPort(), equalTo(boundTransportAddress.publishAddress().getPort())); } } diff --git a/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java b/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java index 5a0012bfaef4b..db311a29d964e 100644 --- a/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java +++ b/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java @@ -16,6 +16,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodeUtils; import org.elasticsearch.cluster.node.VersionInformation; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; @@ -92,7 +93,9 @@ public void testConnectException() throws UnknownHostException { null ); assertThat(e.getMessage(), containsString("connect_exception")); - assertThat(e.getMessage(), containsString("[127.0.0.1:9876]")); + + String loopback = InetAddresses.toUriString(InetAddress.getByName("localhost")); + assertThat(e.getMessage(), containsString("[" + loopback + ":9876]")); } public void testDefaultKeepAliveSettings() throws IOException { diff --git a/plugins/discovery-azure-classic/src/internalClusterTest/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java b/plugins/discovery-azure-classic/src/internalClusterTest/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java index 30759f27c5356..be3395900ef1e 100644 --- a/plugins/discovery-azure-classic/src/internalClusterTest/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java +++ b/plugins/discovery-azure-classic/src/internalClusterTest/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.common.io.FileSystemUtils; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.core.Booleans; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.discovery.DiscoveryModule; import org.elasticsearch.env.Environment; @@ -88,6 +89,17 @@ protected void before() { } }; + @ClassRule + public static final ExternalResource MUTE_IN_IPV6 = new ExternalResource() { + @Override + protected void before() { + assumeFalse( + "Tests not currently working correctly with IPv6", + Booleans.parseBoolean(System.getProperty("java.net.preferIPv6Addresses", "true")) + ); + } + }; + @BeforeClass public static void setupKeyStore() throws IOException { Path tempDir = createTempDir(); diff --git a/plugins/discovery-ec2/src/internalClusterTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2NetworkAddressesTestCase.java b/plugins/discovery-ec2/src/internalClusterTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2NetworkAddressesTestCase.java index b6a4845977b09..83b80b9c76102 100644 --- a/plugins/discovery-ec2/src/internalClusterTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2NetworkAddressesTestCase.java +++ b/plugins/discovery-ec2/src/internalClusterTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2NetworkAddressesTestCase.java @@ -33,10 +33,13 @@ protected boolean addMockHttpTransport() { void verifyPublishAddress(String publishAddressSetting, String expectedAddress) throws IOException { final var node = internalCluster().startNode(Settings.builder().put("http.publish_host", publishAddressSetting)); - assertEquals( - expectedAddress, - internalCluster().getInstance(HttpServerTransport.class, node).boundAddress().publishAddress().getAddress() - ); + String actualAddress = internalCluster().getInstance(HttpServerTransport.class, node).boundAddress().publishAddress().getAddress(); + + if (actualAddress.equals("::1") && expectedAddress.equals("127.0.0.1")) { + expectedAddress = "::1"; + } + + assertEquals(expectedAddress, actualAddress); internalCluster().stopNode(node); } } diff --git a/plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/EC2RetriesTests.java b/plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/EC2RetriesTests.java index cb3af9e3a4169..5c9ea1b3728e5 100644 --- a/plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/EC2RetriesTests.java +++ b/plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/EC2RetriesTests.java @@ -17,6 +17,7 @@ import org.apache.http.client.utils.URLEncodedUtils; import org.elasticsearch.TransportVersion; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.util.PageCacheRecycler; @@ -30,12 +31,12 @@ import org.hamcrest.Matchers; import java.io.IOException; +import java.net.InetAddress; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.Matchers.aMapWithSize; @@ -63,7 +64,11 @@ protected MockTransportService createTransportService() { public void testEC2DiscoveryRetriesOnRateLimiting() throws IOException { final String accessKey = "ec2_access"; - final List hosts = List.of("127.0.0.1:9300"); + final InetAddress loopbackAddress = InetAddress.getLoopbackAddress(); + // For the EC2 response, we use the plain IP address without port + final String loopbackAddressString = NetworkAddress.format(loopbackAddress); + // For the expected TransportAddress, use proper IPv6 formatting with brackets + final String expectedHost = NetworkAddress.format(loopbackAddress, 9300); final Map failedRequests = new ConcurrentHashMap<>(); // retry the same request 5 times at most final int maxRetries = randomIntBetween(1, 5); @@ -88,9 +93,7 @@ public void testEC2DiscoveryRetriesOnRateLimiting() throws IOException { for (NameValuePair parse : URLEncodedUtils.parse(request, UTF_8)) { if ("Action".equals(parse.getName())) { responseBody = generateDescribeInstancesResponse( - hosts.stream() - .map(address -> Instance.builder().publicIpAddress(address).build()) - .collect(Collectors.toList()) + List.of(Instance.builder().publicIpAddress(loopbackAddressString).build()) ); break; } @@ -111,7 +114,7 @@ public void testEC2DiscoveryRetriesOnRateLimiting() throws IOException { resolver.start(); final List addressList = seedHostsProvider.getSeedAddresses(resolver); assertThat(addressList, Matchers.hasSize(1)); - assertThat(addressList.get(0).toString(), is(hosts.get(0))); + assertThat(addressList.get(0).toString(), is(expectedHost)); assertThat(failedRequests, aMapWithSize(1)); assertThat(failedRequests.values().iterator().next(), is(maxRetries)); } diff --git a/rest-api-spec/build.gradle b/rest-api-spec/build.gradle index b4228a5bd30af..bc88059f4de8c 100644 --- a/rest-api-spec/build.gradle +++ b/rest-api-spec/build.gradle @@ -61,6 +61,24 @@ tasks.named("yamlRestCompatTestTransform").configure ({ task -> task.replaceValueInMatch("profile.shards.0.dfs.knn.0.collector.0.name", "TopScoreDocCollector", "dfs knn vector profiling with vector_operations_count") task.skipTest("cat.aliases/10_basic/Deprecated local parameter", "CAT APIs not covered by compatibility policy") task.skipTest("cat.shards/10_basic/Help", "sync_id is removed in 9.0") + if (System.getProperty("java.net.preferIPv6Addresses", "") == "true") { + task.skipTest("cat.allocation/10_basic/All Nodes", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.allocation/10_basic/Bytes", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.allocation/10_basic/Column headers", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.allocation/10_basic/Node ID", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.allocation/10_basic/One index", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.nodeattrs/10_basic/Test cat nodes attrs output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.nodes/10_basic/Test cat nodes output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.recovery/10_basic/Test cat recovery output for closed index", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.recovery/10_basic/Test cat recovery output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.segments/10_basic/Test cat segments output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.segments/10_basic/tsdb", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.shards/10_basic/Test cat shards output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.tasks/10_basic/Test cat tasks output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("cat.thread_pool/10_basic/Test cat thread_pool output", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("indices.recovery/10_basic/Indices recovery test for closed index", "IP/Host regexes in tests on old versions don't support IPV6") + task.skipTest("indices.recovery/10_basic/Indices recovery test", "IP/Host regexes in tests on old versions don't support IPV6") + } task.skipTest("search/330_fetch_fields/Test with subobjects: auto", "subobjects auto removed") task.skipTest("search/500_date_range/from, to, include_lower, include_upper deprecated", "deprecated parameters are removed in 9.0") task.skipTest("search.highlight/30_max_analyzed_offset/Plain highlighter with max_analyzed_offset < 0 should FAIL", "semantics of test has changed") diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.allocation/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.allocation/10_basic.yml index 6e7d14e4dc7aa..691db1232e4d0 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.allocation/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.allocation/10_basic.yml @@ -53,9 +53,9 @@ (\d+(\.\d+)?[kmgt]b \s+) #always should return value since we filter out non data nodes by default (\d+(\.\d+)?[kmgt]b \s+) #always should return value since we filter out non data nodes by default (\d+ \s+) #always should return value since we filter out non data nodes by default - [-\w.]+ \s+ - \d+(\.\d+){3} \s+ - [-\w.]+ \s+ + [-\w.%:]+ \s+ + [-\w.:]+ \s+ + [-\w.]+ \s+ [\w]+ \n )+ @@ -90,9 +90,9 @@ (\d+(\.\d+)?[kmgt]b \s+)? #no value from client nodes (\d+(\.\d+)?[kmgt]b \s+)? #no value from client nodes (\d+ \s+)? #no value from client nodes - [-\w.]+ \s+ - \d+(\.\d+){3} \s+ - [-\w.]+ \s+ + [-\w.%:]+ \s+ + [-\w.:]+ \s+ + [-\w.]+ \s+ [\w]+ \n ) @@ -131,9 +131,9 @@ (\d+(\.\d+)?[kmgt]b \s+)? #no value from client nodes (\d+(\.\d+)?[kmgt]b \s+)? #no value from client nodes (\d+ \s+)? #no value from client nodes - [-\w.]+ \s+ - \d+(\.\d+){3} \s+ - [-\w.]+ \s+ + [-\w.%:]+ \s+ + [-\w.:]+ \s+ + [-\w.]+ \s+ [\w]+ \n )+ @@ -183,9 +183,9 @@ (\d+(\.\d+)?[kmgt]b \s+) #always should return value since we filter out non data nodes by default (\d+(\.\d+)?[kmgt]b \s+) #always should return value since we filter out non data nodes by default (\d+ \s+) #always should return value since we filter out non data nodes by default - [-\w.]+ \s+ - \d+(\.\d+){3} \s+ - [-\w.]+ \s+ + [-\w.%:]+ \s+ + [-\w.:]+ \s+ + [-\w.]+ \s+ [\w]+ \n )+ @@ -250,9 +250,9 @@ (\d+ \s+) #always should return value since we filter out non data nodes by default (\d+ \s+) #always should return value since we filter out non data nodes by default (\d+ \s+) #always should return value since we filter out non data nodes by default - [-\w.]+ \s+ - \d+(\.\d+){3} \s+ - [-\w.]+ \s+ + [-\w.%:]+ \s+ + [-\w.:]+ \s+ + [-\w.]+ \s+ [\w]+ \n )+ diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodeattrs/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodeattrs/10_basic.yml index c205e29ff6fec..a90749b8230a4 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodeattrs/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodeattrs/10_basic.yml @@ -24,13 +24,13 @@ - match: $body: | /^# node\s+ host\s+ ip\s+ attr\s+ value\s* \n - (((\S+\s?){1,10})\s+(\S+)\s+(\d{1,3}\.){3}\d{1,3}\s+(\S+)\s+ (\S+)\s* \n)+ + (((\S+\s?){1,10})\s+(\S+)\s+[0-9a-f:.%]+\s+(\S+)\s+ (\S+)\s* \n)+ $/ # A specific planted attribute is present and looks good - match: $body: | /# node\s+ host\s+ ip\s+ attr\s+ value\s* \n - (\S+(\s\S+){0,7})\s+ (\S+)\s+ (\d{1,3}\.){3}\d{1,3}\s+testattr\s+ test \s* \n + (\S+(\s\S+){0,7})\s+ (\S+)\s+ [0-9a-f:.%]+\s+testattr\s+ test \s* \n / # Note for future editors: its quite possible to construct a regex with an # intense amount of backtracking if you use something like (\S\s?)+ to match @@ -43,13 +43,13 @@ - match: $body: | /^ node\s+ host\s+ ip\s+ attr\s+ value\s* \n - (((\S+\s?){1,10})\s+(\S+)\s+(\d{1,3}\.){3}\d{1,3}\s+(\S+)\s+ (\S+)\s* \n)+ + (((\S+\s?){1,10})\s+(\S+)\s+[0-9a-f:.%]+\s+(\S+)\s+ (\S+)\s* \n)+ $/ # A specific planted attribute is present and looks good - match: $body: | /# node\s+ host\s+ ip\s+ attr\s+ value\s* \n - (\S+(\s\S+){0,7})\s+ (\S+)\s+ (\d{1,3}\.){3}\d{1,3}\s+ testattr\s+ test \s* \n + (\S+(\s\S+){0,7})\s+ (\S+)\s+ [0-9a-f:.%]+\s+ testattr\s+ test \s* \n / - do: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodes/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodes/10_basic.yml index b9708e0a90448..114a7ca33de06 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodes/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodes/10_basic.yml @@ -6,7 +6,7 @@ - match: $body: | / #ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name - ^ ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/ + ^ ([0-9a-fA-F.:]+ \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/ - do: cat.nodes: @@ -15,7 +15,7 @@ - match: $body: | /^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ node\.role \s+ master \s+ name \n - ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/ + ([0-9a-fA-F.:]+ \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/ - do: cat.nodes: @@ -55,7 +55,7 @@ - match: $body: | - /^ http \n ((\d{1,3}\.){3}\d{1,3}:\d{1,5}\n)+ $/ + /^ http \n (\[?[0-9a-fA-F.:]+\]?:\d{1,5}\n)+ $/ --- "Test cat nodes output for all fields with available_processors": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.recovery/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.recovery/10_basic.yml index 55f7457b429ab..30bce8e09b875 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.recovery/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.recovery/10_basic.yml @@ -30,8 +30,8 @@ (?:\d+ms|\d+(?:\.\d+)?s) \s+ # time in ms or seconds (empty_store|existing_store|peer|snapshot|local_shards) \s+ # source type (init|index|verify_index|translog|finalize|done) \s+ # stage - [-\w./]+ \s+ # source_host - [-\w./]+ \s+ # target_host + [-\w.%:/]+ \s+ # source_host + [-\w.%:/]+ \s+ # target_host [-\w./]+ \s+ # repository [-\w./]+ \s+ # snapshot \d+ \s+ # files @@ -118,8 +118,8 @@ (?:\d+ms|\d+(?:\.\d+)?s) \s+ # time in ms or seconds existing_store \s+ # source type (always existing_store for closed indices) done \s+ # stage - [-\w./]+ \s+ # source_host - [-\w./]+ \s+ # target_host + [-\w.%:/]+ \s+ # source_host + [-\w.%:/]+ \s+ # target_host [-\w./]+ \s+ # repository [-\w./]+ \s+ # snapshot \d+ \s+ # files diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml index 33b4dd83ac01a..f68711e8d502c 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml @@ -48,7 +48,7 @@ cat.segments: {} - match: $body: | - /^(index1 \s+ \d \s+ (p|r) \s+ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} \s+ _\d (\s\d){3} \s+ + /^(index1 \s+ \d \s+ (p|r) \s+ [0-9a-fA-F.:]+ \s+ _\d (\s\d){3} \s+ (\d+|\d+[.]\d+)(kb|b) \s+ \d+ (\s+ (false|true)){2} \s+ \d+\.\d+(\.\d+)? \s+ (false|true) \s? \n?)$/ - do: @@ -207,7 +207,7 @@ tsdb: cat.segments: {} - match: $body: | - /^(tsdb \s+ 0 \s+ p \s+ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} \s+ _\d (\s\d){3} \s+ + /^(tsdb \s+ 0 \s+ p \s+ [0-9a-fA-F.:]+ \s+ _\d (\s\d){3} \s+ (\d+|\d+[.]\d+)(kb|b) \s+ \d+ (\s+ (false|true)){2} \s+ \d+\.\d+(\.\d+)? \s+ (false|true) \s? \n?)$/ --- diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.shards/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.shards/10_basic.yml index 45f381eab80b1..1eb3c5c1a2c69 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.shards/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.shards/10_basic.yml @@ -115,7 +115,7 @@ - match: $body: | - /^(index1 \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} \s+ .+|UNASSIGNED \s+) \n?){10}$/ + /^(index1 \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? [0-9a-f:.%]+ \s+ .+|UNASSIGNED \s+) \n?){10}$/ - do: indices.create: @@ -130,14 +130,14 @@ index: i* - match: $body: | - /^(index(1|2) \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} \s+ .+|UNASSIGNED \s+) \n?){15}$/ + /^(index(1|2) \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? [0-9a-f:.%]+ \s+ .+|UNASSIGNED \s+) \n?){15}$/ - do: cat.shards: index: index2 - match: $body: | - /^(index2 \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} \s+ .+|UNASSIGNED \s+) \n?){5}$/ + /^(index2 \s+ \d \s+ (p|r) \s+ ((STARTED|INITIALIZING|RELOCATING) \s+ (\d \s+ (\d+|\d+[.]\d+)(kb|b) \s+ (\d+|\d+[.]\d+)(kb|b) \s+)? [0-9a-f:.%]+ \s+ .+|UNASSIGNED \s+) \n?){5}$/ --- "Test cat shards using wildcards": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.tasks/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.tasks/10_basic.yml index 05c65eb64c31b..435c44419e394 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.tasks/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.tasks/10_basic.yml @@ -7,7 +7,7 @@ - match: $body: | / # action task_id parent_task_id type start_time timestamp running_time ip node - ^( \S+\s+ \S+\:\d+\s+ (?:\-|\S+\:\d+)\s+ \S+\s+ \d+\s+ \d\d\:\d\d\:\d\d\s+ \S+\s+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\s+ \S+\n)+$/ + ^( \S+\s+ \S+\:\d+\s+ (?:\-|\S+\:\d+)\s+ \S+\s+ \d+\s+ \d\d\:\d\d\:\d\d\s+ \S+\s+ [0-9a-f:.%]+\s+ \S+\n)+$/ - do: cat.tasks: @@ -16,7 +16,7 @@ - match: $body: | / # action task_id parent_task_id type start_time timestamp running_time ip node description - ^( \S+\s+ \S+\:\d+\s+ (?:\-|\S+\:\d+)\s+ \S+\s+ \d+\s+ \d\d\:\d\d\:\d\d\s+ \S+\s+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\s+ \S+\s+ .*\n)+$/ + ^( \S+\s+ \S+\:\d+\s+ (?:\-|\S+\:\d+)\s+ \S+\s+ \d+\s+ \d\d\:\d\d\:\d\d\s+ \S+\s+ [0-9a-f:.%]+\s+ \S+\s+ .*\n)+$/ --- "Test cat tasks output with X-Opaque-Id": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.thread_pool/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.thread_pool/10_basic.yml index 26e9de699f2e4..24fe4009c13c7 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.thread_pool/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.thread_pool/10_basic.yml @@ -25,7 +25,7 @@ - match: $body: | / #pid id host ip port - (\d+ \s+ \S+ \s+ \S+ \s+ (\d{1,3}\.){3}\d{1,3} \s+ (\d+|-) \n)+ $/ + (\d+ \s+ \S+ \s+ \S+ \s+ [0-9a-f:.%]+ \s+ (\d+|-) \n)+ $/ - do: cat.thread_pool: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.recovery/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.recovery/10_basic.yml index 0724f3831aeab..f0e9186731e35 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.recovery/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.recovery/10_basic.yml @@ -25,7 +25,7 @@ - match: { test_1.shards.0.stage: "DONE" } - match: { test_1.shards.0.primary: true } - match: { test_1.shards.0.start_time: /^2\d\d\d-.+/ } - - match: { test_1.shards.0.target.ip: /^\d+\.\d+\.\d+\.\d+$/ } + - match: { test_1.shards.0.target.ip: "/^[0-9a-f:.%]+$/" } - gte: { test_1.shards.0.index.files.total: 0 } - gte: { test_1.shards.0.index.files.reused: 0 } - gte: { test_1.shards.0.index.files.recovered: 0 } @@ -78,7 +78,7 @@ - match: { test_2.shards.0.stage: "DONE" } - match: { test_2.shards.0.primary: true } - match: { test_2.shards.0.start_time: /^2\d\d\d-.+/ } - - match: { test_2.shards.0.target.ip: /^\d+\.\d+\.\d+\.\d+$/ } + - match: { test_2.shards.0.target.ip: "/^[0-9a-f:.%]+$/" } - gte: { test_2.shards.0.index.files.total: 0 } - gte: { test_2.shards.0.index.files.reused: 0 } - gte: { test_2.shards.0.index.files.recovered: 0 } diff --git a/server/src/test/java/org/elasticsearch/discovery/SeedHostsResolverTests.java b/server/src/test/java/org/elasticsearch/discovery/SeedHostsResolverTests.java index f1900667e4e82..321f7f3445193 100644 --- a/server/src/test/java/org/elasticsearch/discovery/SeedHostsResolverTests.java +++ b/server/src/test/java/org/elasticsearch/discovery/SeedHostsResolverTests.java @@ -162,7 +162,7 @@ public BoundTransportAddress boundAddress() { ); closeables.push(transportService); recreateSeedHostsResolver(transportService); - List hosts = IntStream.range(9300, 9310).mapToObj(port -> NetworkAddress.format(loopbackAddress) + ":" + port).toList(); + List hosts = IntStream.range(9300, 9310).mapToObj(port -> NetworkAddress.format(loopbackAddress, port)).toList(); final List transportAddresses = seedHostsResolver.resolveHosts(hosts); assertThat(transportAddresses, hasSize(7)); final Set ports = new HashSet<>(); diff --git a/server/src/test/java/org/elasticsearch/http/HttpInfoTests.java b/server/src/test/java/org/elasticsearch/http/HttpInfoTests.java index d1ffdb03f2994..6a3d869048b99 100644 --- a/server/src/test/java/org/elasticsearch/http/HttpInfoTests.java +++ b/server/src/test/java/org/elasticsearch/http/HttpInfoTests.java @@ -34,7 +34,7 @@ public void testCorrectlyDisplayPublishedCname() throws Exception { ), 0L ), - "localhost/" + NetworkAddress.format(localhost) + ':' + port + "localhost/" + NetworkAddress.format(localhost, port) ); } @@ -49,7 +49,7 @@ public void testCorrectDisplayPublishedIp() throws Exception { ), 0L ), - NetworkAddress.format(localhost) + ':' + port + NetworkAddress.format(localhost, port) ); } diff --git a/server/src/test/java/org/elasticsearch/transport/TransportInfoTests.java b/server/src/test/java/org/elasticsearch/transport/TransportInfoTests.java index 9bc8140850ba2..7551efe37e9aa 100644 --- a/server/src/test/java/org/elasticsearch/transport/TransportInfoTests.java +++ b/server/src/test/java/org/elasticsearch/transport/TransportInfoTests.java @@ -36,13 +36,13 @@ private TransportInfo createTransportInfo(InetAddress address, int port) { public void testCorrectlyDisplayPublishedCname() throws Exception { InetAddress address = InetAddress.getByName("localhost"); int port = 9200; - assertPublishAddress(createTransportInfo(address, port), "localhost/" + NetworkAddress.format(address) + ':' + port); + assertPublishAddress(createTransportInfo(address, port), "localhost/" + NetworkAddress.format(address, port)); } public void testCorrectDisplayPublishedIp() throws Exception { InetAddress address = InetAddress.getByName(NetworkAddress.format(InetAddress.getByName("localhost"))); int port = 9200; - assertPublishAddress(createTransportInfo(address, port), NetworkAddress.format(address) + ':' + port); + assertPublishAddress(createTransportInfo(address, port), NetworkAddress.format(address, port)); } public void testCorrectDisplayPublishedIpv6() throws Exception { diff --git a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/MetricsApmIT.java b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/MetricsApmIT.java index 07141846dde4d..55f644a727427 100644 --- a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/MetricsApmIT.java +++ b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/MetricsApmIT.java @@ -51,7 +51,7 @@ public class MetricsApmIT extends ESRestTestCase { .module("apm") .setting("telemetry.metrics.enabled", "true") .setting("telemetry.agent.metrics_interval", "1s") - .setting("telemetry.agent.server_url", "http://127.0.0.1:" + mockApmServer.getPort()) + .setting("telemetry.agent.server_url", () -> "http://" + mockApmServer.getHttpAddress()) .build(); @Override diff --git a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/RecordingApmServer.java b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/RecordingApmServer.java index d20f2d08719e7..6d09d6422d9fb 100644 --- a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/RecordingApmServer.java +++ b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/RecordingApmServer.java @@ -110,6 +110,18 @@ public int getPort() { return server.getAddress().getPort(); } + /** + * Returns the HTTP address in the format "host:port", properly handling IPv6 addresses with brackets. + */ + public String getHttpAddress() { + String host = server.getAddress().getHostString(); + if (host.contains(":")) { + // IPv6 address needs brackets + host = "[" + host + "]"; + } + return host + ":" + getPort(); + } + public void addMessageConsumer(Consumer messageConsumer) { this.consumer = messageConsumer; } diff --git a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/TracesApmIT.java b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/TracesApmIT.java index d401fb1166149..7924db0219fa2 100644 --- a/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/TracesApmIT.java +++ b/test/external-modules/apm-integration/src/javaRestTest/java/org/elasticsearch/test/apmintegration/TracesApmIT.java @@ -53,7 +53,7 @@ public class TracesApmIT extends ESRestTestCase { .setting("telemetry.metrics.enabled", "false") .setting("telemetry.tracing.enabled", "true") .setting("telemetry.agent.metrics_interval", "1s") - .setting("telemetry.agent.server_url", () -> "http://127.0.0.1:" + mockApmServer.getPort()) + .setting("telemetry.agent.server_url", () -> "http://" + mockApmServer.getHttpAddress()) .build(); @ClassRule diff --git a/test/fixtures/aws-ec2-fixture/src/main/java/fixture/aws/ec2/AwsEc2HttpFixture.java b/test/fixtures/aws-ec2-fixture/src/main/java/fixture/aws/ec2/AwsEc2HttpFixture.java index ad4f48939009c..a14dd2e58ab59 100644 --- a/test/fixtures/aws-ec2-fixture/src/main/java/fixture/aws/ec2/AwsEc2HttpFixture.java +++ b/test/fixtures/aws-ec2-fixture/src/main/java/fixture/aws/ec2/AwsEc2HttpFixture.java @@ -10,6 +10,7 @@ import com.sun.net.httpserver.HttpServer; +import org.elasticsearch.common.network.InetAddresses; import org.junit.rules.ExternalResource; import java.net.InetAddress; @@ -33,7 +34,8 @@ public AwsEc2HttpFixture(BiPredicate authorizationPredicate, Sup } public String getAddress() { - return "http://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + String host = InetAddresses.toUriString(server.getAddress().getAddress()); + return "http://" + host + ":" + server.getAddress().getPort(); } public void stop(int delay) { diff --git a/test/fixtures/aws-sts-fixture/src/main/java/fixture/aws/sts/AwsStsHttpFixture.java b/test/fixtures/aws-sts-fixture/src/main/java/fixture/aws/sts/AwsStsHttpFixture.java index ee6857e04d9fb..f58aaeffd3a3f 100644 --- a/test/fixtures/aws-sts-fixture/src/main/java/fixture/aws/sts/AwsStsHttpFixture.java +++ b/test/fixtures/aws-sts-fixture/src/main/java/fixture/aws/sts/AwsStsHttpFixture.java @@ -11,6 +11,7 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.core.TimeValue; import org.junit.rules.ExternalResource; @@ -44,7 +45,8 @@ protected HttpHandler createHandler() { } public String getAddress() { - return "http://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + String host = InetAddresses.toUriString(server.getAddress().getAddress()); + return "http://" + host + ":" + server.getAddress().getPort(); } public void stop(int delay) { diff --git a/test/fixtures/azure-fixture/src/main/java/fixture/azure/AzureHttpFixture.java b/test/fixtures/azure-fixture/src/main/java/fixture/azure/AzureHttpFixture.java index ab4d54f4fc451..a6af6f0c9abc4 100644 --- a/test/fixtures/azure-fixture/src/main/java/fixture/azure/AzureHttpFixture.java +++ b/test/fixtures/azure-fixture/src/main/java/fixture/azure/AzureHttpFixture.java @@ -13,6 +13,7 @@ import com.sun.net.httpserver.HttpsServer; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.ssl.KeyStoreUtil; import org.elasticsearch.common.ssl.PemUtils; import org.elasticsearch.core.Nullable; @@ -149,20 +150,30 @@ private String scheme() { } public String getAddress() { - return scheme() + "://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort() + "/" + account; + InetSocketAddress addr = server.getAddress(); + // Use "localhost" for loopback addresses to work around Azure SDK's inability to parse bracketed IPv6 addresses + String host; + if (addr.getAddress().isLoopbackAddress()) { + host = "localhost"; + } else { + host = InetAddresses.toUriString(addr.getAddress()); + } + + return scheme() + "://" + host + ":" + addr.getPort() + "/" + account; } public String getOAuthTokenServiceAddress() { - return scheme() - + "://" - + oauthTokenServiceServer.getAddress().getHostString() - + ":" - + oauthTokenServiceServer.getAddress().getPort() - + "/"; + InetSocketAddress addr = oauthTokenServiceServer.getAddress(); + // Use "localhost" for loopback addresses to work around Azure SDK's inability to parse bracketed IPv6 addresses + String host = addr.getAddress().isLoopbackAddress() ? "localhost" : addr.getHostString(); + return scheme() + "://" + host + ":" + addr.getPort() + "/"; } public String getMetadataAddress() { - return "http://" + metadataServer.getAddress().getHostString() + ":" + metadataServer.getAddress().getPort() + "/"; + InetSocketAddress addr = metadataServer.getAddress(); + // Use "localhost" for loopback addresses to work around Azure SDK's inability to parse bracketed IPv6 addresses + String host = addr.getAddress().isLoopbackAddress() ? "localhost" : addr.getHostString(); + return "http://" + host + ":" + addr.getPort() + "/"; } public String getFederatedToken() { diff --git a/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java index 98c4c9ce6998a..3deabedff1df1 100644 --- a/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java +++ b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java @@ -10,6 +10,7 @@ import com.sun.net.httpserver.HttpServer; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.core.CheckedConsumer; import org.elasticsearch.core.Releasable; import org.elasticsearch.core.SuppressForbidden; @@ -39,7 +40,8 @@ public Ec2ImdsHttpFixture(Ec2ImdsServiceBuilder ec2ImdsServiceBuilder) { } public String getAddress() { - return "http://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + String host = InetAddresses.toUriString(server.getAddress().getAddress()); + return "http://" + host + ":" + server.getAddress().getPort(); } public void stop(int delay) { diff --git a/test/fixtures/gcs-fixture/src/main/java/fixture/gcs/GoogleCloudStorageHttpFixture.java b/test/fixtures/gcs-fixture/src/main/java/fixture/gcs/GoogleCloudStorageHttpFixture.java index 1853158e69b20..2a5d17b33eaa7 100644 --- a/test/fixtures/gcs-fixture/src/main/java/fixture/gcs/GoogleCloudStorageHttpFixture.java +++ b/test/fixtures/gcs-fixture/src/main/java/fixture/gcs/GoogleCloudStorageHttpFixture.java @@ -10,6 +10,7 @@ import com.sun.net.httpserver.HttpServer; +import org.elasticsearch.common.network.InetAddresses; import org.junit.rules.ExternalResource; import java.net.InetAddress; @@ -29,7 +30,8 @@ public GoogleCloudStorageHttpFixture(boolean enabled, final String bucket, final } public String getAddress() { - return "http://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + String host = InetAddresses.toUriString(server.getAddress().getAddress()); + return "http://" + host + ":" + server.getAddress().getPort(); } @Override diff --git a/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/EnterpriseGeoIpHttpFixture.java b/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/EnterpriseGeoIpHttpFixture.java index 3f3e0c0a25578..793b01f1a9622 100644 --- a/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/EnterpriseGeoIpHttpFixture.java +++ b/test/fixtures/geoip-fixture/src/main/java/fixture/geoip/EnterpriseGeoIpHttpFixture.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.hash.MessageDigests; +import org.elasticsearch.common.network.InetAddresses; import org.junit.rules.ExternalResource; import java.io.InputStream; @@ -44,7 +45,8 @@ public EnterpriseGeoIpHttpFixture(List maxmindDatabaseTypes, List) () -> { try { channelConnect(channel, socketAddress); @@ -66,9 +69,11 @@ default void tcpReadinessProbeFalse(ReadinessService readinessService) throws Ex @SuppressForbidden(reason = "Intentional socket open") default void tcpReadinessProbeFalse(Integer port) throws Exception { - InetSocketAddress socketAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), port); + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress socketAddress = new InetSocketAddress(loopback, port); + StandardProtocolFamily family = loopback instanceof Inet6Address ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; - try (SocketChannel channel = SocketChannel.open(StandardProtocolFamily.INET)) { + try (SocketChannel channel = SocketChannel.open(family)) { AccessController.doPrivileged((PrivilegedAction) () -> { expectThrows(ConnectException.class, () -> { var result = channelConnect(channel, socketAddress); diff --git a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java index c9095fd1e1549..180a60d2b8d9f 100644 --- a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java @@ -3226,6 +3226,9 @@ public void testChannelToString() { channel.sendResponse(ActionResponse.Empty.INSTANCE); }); serviceB.registerRequestHandler(ACTION, EsExecutors.DIRECT_EXECUTOR_SERVICE, EmptyRequest::new, (request, channel, task) -> { + String address = serviceB.getLocalNode().getAddress().toString(); + address = address.replace("::1", "0:0:0:0:0:0:0:1"); + assertThat( channel.toString(), allOf( @@ -3233,7 +3236,7 @@ public void testChannelToString() { containsString('{' + ACTION + '}'), containsString("TaskTransportChannel{task=" + task.getId() + '}'), containsString("localAddress="), - containsString(serviceB.getLocalNode().getAddress().toString()) + containsString(address) ) ); channel.sendResponse(ActionResponse.Empty.INSTANCE); diff --git a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java index 3adf1e5f897d2..5784df9c0518f 100644 --- a/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java +++ b/test/test-clusters/src/main/java/org/elasticsearch/test/cluster/local/DefaultSettingsProvider.java @@ -31,7 +31,12 @@ public Map get(LocalNodeSpec nodeSpec) { settings.put("node.portsfile", "true"); settings.put("http.port", "0"); settings.put("transport.port", "0"); - settings.put("network.host", "_local_"); + + if (Boolean.getBoolean("java.net.preferIPv6Addresses")) { + settings.put("network.host", "_local:ipv6_"); + } else { + settings.put("network.host", "_local_"); + } if (nodeSpec.getDistributionType() == DistributionType.INTEG_TEST) { settings.put("xpack.security.enabled", "false"); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/test/http/MockWebServer.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/test/http/MockWebServer.java index a1c3dd618d85a..6c625595e51dc 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/test/http/MockWebServer.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/test/http/MockWebServer.java @@ -119,7 +119,11 @@ public MockWebServer(SSLContext sslContext, TlsConfig tlsConfig) { * @throws IOException in case of a binding or other I/O errors */ public void start() throws IOException { - InetSocketAddress address = new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0); + start(InetAddress.getLoopbackAddress()); + } + + public void start(InetAddress bindAddress) throws IOException { + InetSocketAddress address = new InetSocketAddress(bindAddress.getHostAddress(), 0); if (sslContext != null) { HttpsServer httpsServer = MockHttpServer.createHttps(address, 0); httpsServer.setHttpsConfigurator(new CustomHttpsConfigurator(sslContext, tlsConfig)); @@ -255,6 +259,16 @@ private MockRequest createRequest(HttpExchange exchange) throws IOException { return request; } + public String getHttpAddress() { + String host = getHostName(); + if (host.contains(":")) { + // ixpv6 format + host = "[" + host + "]"; + } + + return host + ":" + getPort(); + } + /** * @return The hostname the server is bound to. */ diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/HttpClient5SslTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/HttpClient5SslTests.java index da99122f49ded..546cd873fcb0e 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/HttpClient5SslTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/HttpClient5SslTests.java @@ -28,6 +28,7 @@ import org.junit.Before; import java.io.IOException; +import java.net.InetAddress; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -341,7 +342,8 @@ private void startServer(String serverCert, boolean requireClientCert, List entityAsMap(String body) throws IOException { diff --git a/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java b/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java index 5250a1f764e5c..945f42913db39 100644 --- a/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java +++ b/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java @@ -133,7 +133,7 @@ private Settings.Builder baseSettings() { .put("xpack.monitoring.exporters._http.type", "http") .put("xpack.monitoring.exporters._http.ssl.truststore.password", "foobar") // ensure that ssl can be used by settings .put("xpack.monitoring.exporters._http.headers.ignored", "value") // ensure that headers can be used by settings - .put("xpack.monitoring.exporters._http.host", getFormattedAddress(webServer)) + .put("xpack.monitoring.exporters._http.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters._http.cluster_alerts.management.enabled", true) .putList("xpack.monitoring.exporters._http.cluster_alerts.management.blacklist", clusterAlertBlacklist) .put("xpack.monitoring.exporters._http.auth.username", userName); @@ -291,7 +291,7 @@ public void testHostChangeReChecksTemplate() throws Exception { final Settings newSettings = Settings.builder() .put(settings) - .putList("xpack.monitoring.exporters._http.host", getFormattedAddress(secondWebServer)) + .putList("xpack.monitoring.exporters._http.host", secondWebServer.getHttpAddress()) .build(); enqueueGetClusterVersionResponse(secondWebServer, Version.CURRENT); @@ -309,7 +309,7 @@ public void testHostChangeReChecksTemplate() throws Exception { public void testUnsupportedClusterVersion() throws Exception { final Settings settings = Settings.builder() .put("xpack.monitoring.exporters._http.type", "http") - .put("xpack.monitoring.exporters._http.host", getFormattedAddress(webServer)) + .put("xpack.monitoring.exporters._http.host", webServer.getHttpAddress()) .build(); // returning an unsupported cluster version @@ -347,7 +347,7 @@ public void testUnsupportedClusterVersion() throws Exception { public void testRemoteTemplatesNotPresent() throws Exception { final Settings settings = Settings.builder() .put("xpack.monitoring.exporters._http.type", "http") - .put("xpack.monitoring.exporters._http.host", getFormattedAddress(webServer)) + .put("xpack.monitoring.exporters._http.host", webServer.getHttpAddress()) .build(); // returning an unsupported cluster version @@ -890,10 +890,6 @@ private void assertBulkRequest(String requestBody, int numberOfActions) throws E } } - private String getFormattedAddress(MockWebServer server) { - return server.getHostName() + ":" + server.getPort(); - } - private MockWebServer createMockWebServer() throws IOException { MockWebServer server = new MockWebServer(); server.start(); diff --git a/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java b/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java index cfeb55feba2c6..c72d885c623ac 100644 --- a/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java +++ b/x-pack/plugin/monitoring/src/internalClusterTest/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java @@ -65,7 +65,7 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { } } - final String address = "https://" + webServer.getHostName() + ":" + webServer.getPort(); + final String address = "https://" + webServer.getHttpAddress(); final Settings.Builder builder = Settings.builder() .put(super.nodeSettings(nodeOrdinal, otherSettings)) .put("xpack.monitoring.exporters.plaintext.type", "http") @@ -137,7 +137,7 @@ public void testCanAddNewExporterWithSsl() { updateClusterSettings( Settings.builder() .put("xpack.monitoring.exporters._new.type", "http") - .put("xpack.monitoring.exporters._new.host", "https://" + webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters._new.host", "https://" + webServer.getHttpAddress()) .put("xpack.monitoring.exporters._new.ssl.truststore.path", truststore) .put("xpack.monitoring.exporters._new.ssl.truststore.password", "testnode") .put("xpack.monitoring.exporters._new.ssl.verification_mode", SslVerificationMode.CERTIFICATE.name()) @@ -164,7 +164,7 @@ private ActionFuture setVerificationMode(String n final String verificationModeName = randomBoolean() ? mode.name() : mode.name().toLowerCase(Locale.ROOT); final Settings settings = Settings.builder() .put("xpack.monitoring.exporters." + name + ".type", HttpExporter.TYPE) - .put("xpack.monitoring.exporters." + name + ".host", "https://" + webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters." + name + ".host", "https://" + webServer.getHttpAddress()) .put("xpack.monitoring.exporters." + name + ".ssl.verification_mode", verificationModeName) .build(); updateSettings.persistentSettings(settings); diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringMigrateAlertsActionTests.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringMigrateAlertsActionTests.java index fddcee25d636d..741acda551e8d 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringMigrateAlertsActionTests.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/action/TransportMonitoringMigrateAlertsActionTests.java @@ -298,7 +298,7 @@ public void testRemoteAlertsRemoval() throws Exception { .put("xpack.monitoring.elasticsearch.collection.enabled", false) .put("xpack.monitoring.exporters.remoteCluster.type", HttpExporter.TYPE) .put("xpack.monitoring.exporters.remoteCluster.enabled", true) - .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters.remoteCluster.cluster_alerts.management.enabled", true); // enable http exporter @@ -338,7 +338,7 @@ public void testDisabledRemoteAlertsRemoval() throws Exception { .put("xpack.monitoring.elasticsearch.collection.enabled", false) .put("xpack.monitoring.exporters.remoteCluster.type", HttpExporter.TYPE) .put("xpack.monitoring.exporters.remoteCluster.enabled", false) - .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters.remoteCluster.cluster_alerts.management.enabled", true); // configure disabled http exporter @@ -378,7 +378,7 @@ public void testRemoteAlertsRemovalWhenOriginalMonitoringClusterIsGone() throws .put("xpack.monitoring.elasticsearch.collection.enabled", false) .put("xpack.monitoring.exporters.remoteCluster.type", HttpExporter.TYPE) .put("xpack.monitoring.exporters.remoteCluster.enabled", false) - .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters.remoteCluster.cluster_alerts.management.enabled", true); // create a disabled http exporter @@ -413,7 +413,7 @@ public void testRemoteAlertsRemovalFailure() throws Exception { .put("xpack.monitoring.elasticsearch.collection.enabled", false) .put("xpack.monitoring.exporters.remoteCluster.type", HttpExporter.TYPE) .put("xpack.monitoring.exporters.remoteCluster.enabled", true) - .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters.remoteCluster.cluster_alerts.management.enabled", true); // enable http exporter @@ -457,7 +457,7 @@ public void testRemoteAlertsRemoteDisallowsWatcher() throws Exception { .put("xpack.monitoring.elasticsearch.collection.enabled", false) .put("xpack.monitoring.exporters.remoteCluster.type", HttpExporter.TYPE) .put("xpack.monitoring.exporters.remoteCluster.enabled", true) - .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters.remoteCluster.host", webServer.getHttpAddress()) .put("xpack.monitoring.exporters.remoteCluster.cluster_alerts.management.enabled", true); // enable http exporter diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java index d557fd7123332..72590559a8af3 100644 --- a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java @@ -104,7 +104,9 @@ protected void after() { } public String getBaseUrl() { - return "https://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + InetSocketAddress address = server.getAddress(); + // Use "localhost" for the hostname to match SSL certificate SANs (works for both IPv4 and IPv6) + return "https://localhost:" + address.getPort(); } private void registerGetAccessTokenHandler() { diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/audit/logfile/AuditTrailSettingsUpdateTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/audit/logfile/AuditTrailSettingsUpdateTests.java index 0e2e6c909fbd7..5394ea2915b4f 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/audit/logfile/AuditTrailSettingsUpdateTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/audit/logfile/AuditTrailSettingsUpdateTests.java @@ -8,6 +8,7 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; @@ -18,6 +19,7 @@ import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.junit.BeforeClass; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -111,6 +113,7 @@ public void testInvalidFilterSettings() throws Exception { } public void testDynamicHostSettings() { + final String expectedLoopbackAddress = NetworkAddress.format(InetAddress.getLoopbackAddress()); final Settings.Builder settingsBuilder = Settings.builder(); settingsBuilder.put(LoggingAuditTrail.EMIT_HOST_ADDRESS_SETTING.getKey(), true); settingsBuilder.put(LoggingAuditTrail.EMIT_HOST_NAME_SETTING.getKey(), true); @@ -123,14 +126,23 @@ public void testDynamicHostSettings() { .getAuditTrail(); assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.NODE_NAME_FIELD_NAME), startsWith("node_")); assertThat(loggingAuditTrail.entryCommonFields.commonFields.containsKey(LoggingAuditTrail.NODE_ID_FIELD_NAME), is(true)); - assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_ADDRESS_FIELD_NAME), is("127.0.0.1")); - assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_NAME_FIELD_NAME), is("127.0.0.1")); + assertThat( + loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_ADDRESS_FIELD_NAME), + is(expectedLoopbackAddress) + ); + assertThat( + loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_NAME_FIELD_NAME), + is(expectedLoopbackAddress) + ); settingsBuilder.put(LoggingAuditTrail.EMIT_HOST_ADDRESS_SETTING.getKey(), false); updateClusterSettings(settingsBuilder); assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.NODE_NAME_FIELD_NAME), startsWith("node_")); assertThat(loggingAuditTrail.entryCommonFields.commonFields.containsKey(LoggingAuditTrail.NODE_ID_FIELD_NAME), is(true)); assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_ADDRESS_FIELD_NAME), is(nullValue())); - assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_NAME_FIELD_NAME), is("127.0.0.1")); + assertThat( + loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.HOST_NAME_FIELD_NAME), + is(expectedLoopbackAddress) + ); settingsBuilder.put(LoggingAuditTrail.EMIT_HOST_NAME_SETTING.getKey(), false); updateClusterSettings(settingsBuilder); assertThat(loggingAuditTrail.entryCommonFields.commonFields.get(LoggingAuditTrail.NODE_NAME_FIELD_NAME), startsWith("node_")); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/logfile/LoggingAuditTrail.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/logfile/LoggingAuditTrail.java index 4de45cbc15c51..5feb69fc48793 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/logfile/LoggingAuditTrail.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/logfile/LoggingAuditTrail.java @@ -2018,7 +2018,8 @@ static class EntryCommonFields { commonFields.put(HOST_ADDRESS_FIELD_NAME, newLocalNode.getAddress().getAddress()); } if (EMIT_HOST_NAME_SETTING.get(settings)) { - commonFields.put(HOST_NAME_FIELD_NAME, newLocalNode.getAddress().address().getHostString()); + // Use getAddress() which uses NetworkAddress.format() for consistent IPv6 formatting + commonFields.put(HOST_NAME_FIELD_NAME, newLocalNode.getAddress().getAddress()); } if (EMIT_NODE_ID_SETTING.get(settings)) { commonFields.put(NODE_ID_FIELD_NAME, newLocalNode.getId()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/jwt/JwtIssuerHttpsServer.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/jwt/JwtIssuerHttpsServer.java index 4aac7f83c45f2..20bf0cc099bfa 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/jwt/JwtIssuerHttpsServer.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/jwt/JwtIssuerHttpsServer.java @@ -60,7 +60,11 @@ public class JwtIssuerHttpsServer implements Closeable { @SuppressForbidden(reason = "MockHttpServer.createHttps requires InetSocketAddress, PORT=0 resolves to an available ephemeral port.") public JwtIssuerHttpsServer(final byte[] encodedJwkSetPkcPublicBytes) throws Exception { this.httpsServer = MockHttpServer.createHttps(new InetSocketAddress(ADDRESS, PORT), BACKLOG); - this.url = "https://" + ADDRESS + ":" + this.httpsServer.getAddress().getPort() + PATH; // get ephemeral port + this.url = "https://" + + (ADDRESS.contains(":") && false == ADDRESS.startsWith("[") ? "[" + ADDRESS + "]" : ADDRESS) + + ":" + + this.httpsServer.getAddress().getPort() + + PATH; // get ephemeral port this.httpsServer.setHttpsConfigurator(new HttpsConfigurator(this.createSslContext())); this.httpsServer.createContext(PATH, new JwtIssuerHttpHandler(encodedJwkSetPkcPublicBytes)); LOGGER.trace("Starting [{}]", this.url); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java index b0607b54c8759..474718a60366b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapSessionFactoryTests.java @@ -13,7 +13,7 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.network.NetworkAddress; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -90,15 +90,9 @@ public void testBindWithReadTimeout() throws Exception { if (listenAddress == null) { listenAddress = InetAddress.getLoopbackAddress(); } - String ldapUrl = new LDAPURL( - protocol, - NetworkAddress.format(listenAddress), - ldapServer.getListenPort(protocol), - null, - null, - null, - null - ).toString(); + String host = InetAddresses.toUriString(listenAddress); + + String ldapUrl = new LDAPURL(protocol, host, ldapServer.getListenPort(protocol), null, null, null, null).toString(); String groupSearchBase = "o=sevenSeas"; String userTemplates = "cn={0},ou=people,o=sevenSeas"; @@ -293,15 +287,9 @@ public void testSslTrustIsReloaded() throws Exception { if (listenAddress == null) { listenAddress = InetAddress.getLoopbackAddress(); } - String ldapUrl = new LDAPURL( - "ldaps", - NetworkAddress.format(listenAddress), - ldapServer.getListenPort("ldaps"), - null, - null, - null, - null - ).toString(); + + String address = InetAddresses.toUriString(listenAddress); + String ldapUrl = new LDAPURL("ldaps", address, ldapServer.getListenPort("ldaps"), null, null, null, null).toString(); String groupSearchBase = "o=sevenSeas"; String userTemplates = "cn={0},ou=people,o=sevenSeas"; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/LdapTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/LdapTestCase.java index 18741b5a13a99..010fa9584c8f9 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/LdapTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/LdapTestCase.java @@ -20,6 +20,7 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; @@ -188,7 +189,8 @@ protected String[] ldapUrls() throws LDAPException { List urls = new ArrayList<>(numberOfLdapServers); for (int i = 0; i < numberOfLdapServers; i++) { InetAddress listenAddress = resolveListenAddress(ldapServers[i].getListenAddress()); - LDAPURL url = new LDAPURL("ldap", NetworkAddress.format(listenAddress), ldapServers[i].getListenPort(), null, null, null, null); + String hostName = InetAddresses.toUriString(listenAddress); + LDAPURL url = new LDAPURL("ldap", hostName, ldapServers[i].getListenPort(), null, null, null, null); urls.add(url.toString()); } return urls.toArray(Strings.EMPTY_ARRAY); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java index 742e4a09c51c8..35185d6ae8ed5 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.cluster.node.VersionInformation; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.OutputStreamStreamOutput; +import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.MockSecureSettings; @@ -175,13 +176,14 @@ protected Set> getSupportedSettings() { } public void testConnectException() throws UnknownHostException { + final InetAddress loopback = InetAddress.getLoopbackAddress(); final ConnectTransportException e = connectToNodeExpectFailure( serviceA, - DiscoveryNodeUtils.create("C", new TransportAddress(InetAddress.getByName("localhost"), 9876), emptyMap(), emptySet()), + DiscoveryNodeUtils.create("C", new TransportAddress(loopback, 9876), emptyMap(), emptySet()), null ); assertThat(e.getMessage(), containsString("connect_exception")); - assertThat(e.getMessage(), containsString("[127.0.0.1:9876]")); + assertThat(e.getMessage(), containsString("[" + NetworkAddress.format(loopback, 9876) + "]")); Throwable cause = ExceptionsHelper.unwrap(e, IOException.class); assertThat(cause, instanceOf(IOException.class)); } diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java index 31318a9261bce..af8ec98ba7ba3 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClientRequestTests.java @@ -70,7 +70,7 @@ public void testBinaryRequestDisabled() throws Exception { } private void assertBinaryRequest(boolean isBinary, XContentType xContentType) throws Exception { - String url = JdbcConfiguration.URL_PREFIX + webServer.getHostName() + ":" + webServer.getPort(); + String url = JdbcConfiguration.URL_PREFIX + webServer.getHttpAddress(); Properties props = new Properties(); props.setProperty(ConnectionConfiguration.BINARY_COMMUNICATION, Boolean.toString(isBinary)); @@ -186,6 +186,18 @@ int getPort() { return port; } + /** + * Returns the HTTP address in the format "host:port", properly handling IPv6 addresses with brackets. + */ + String getHttpAddress() { + String host = getHostName(); + if (host.contains(":")) { + // IPv6 address needs brackets + host = "[" + host + "]"; + } + return host + ":" + getPort(); + } + void enqueue(Response response) { responses.add(response); } diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/WebServerTestCase.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/WebServerTestCase.java index 1d940e059af4d..fc3716113ccca 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/WebServerTestCase.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/WebServerTestCase.java @@ -57,6 +57,12 @@ MainResponse createMainResponse(SqlVersion version) { } String webServerAddress() { - return webServer.getHostName() + ":" + webServer.getPort(); + String host = webServer.getHostName(); + if (host.contains(":") && false == host.startsWith("[")) { + // ipv6 format + host = "[" + host + "]"; + } + + return host + ":" + webServer.getPort(); } } diff --git a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java index 71c9fb5cee405..998658227e9f2 100644 --- a/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java +++ b/x-pack/plugin/sql/sql-client/src/test/java/org/elasticsearch/xpack/sql/client/HttpClientRequestTests.java @@ -93,7 +93,7 @@ public void testBinaryRequestForDriversDisabled() throws URISyntaxException { private void assertBinaryRequestForCLI(XContentType xContentType) throws URISyntaxException { boolean isBinary = XContentType.CBOR == xContentType; - String url = "http://" + webServer.getHostName() + ":" + webServer.getPort(); + String url = "http://" + webServer.getHttpAddress(); String query = randomAlphaOfLength(256); int fetchSize = randomIntBetween(1, 100); Properties props = new Properties(); @@ -151,7 +151,7 @@ private void assertBinaryRequestForCLI(XContentType xContentType) throws URISynt private void assertBinaryRequestForDrivers(XContentType xContentType) throws URISyntaxException { boolean isBinary = XContentType.CBOR == xContentType; - String url = "http://" + webServer.getHostName() + ":" + webServer.getPort(); + String url = "http://" + webServer.getHttpAddress(); String query = randomAlphaOfLength(256); Properties props = new Properties(); props.setProperty(ConnectionConfiguration.BINARY_COMMUNICATION, Boolean.toString(isBinary)); @@ -265,6 +265,18 @@ int getPort() { return port; } + /** + * Returns the HTTP address in the format "host:port", properly handling IPv6 addresses with brackets. + */ + String getHttpAddress() { + String host = getHostName(); + if (host.contains(":")) { + // IPv6 address needs brackets + host = "[" + host + "]"; + } + return host + ":" + getPort(); + } + void enqueue(Response response) { responses.add(response); } diff --git a/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java b/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java index 28824cd5f11a8..e4e063bd69033 100644 --- a/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java +++ b/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookIntegrationTests.java @@ -151,8 +151,8 @@ public void testWebhookWithTimebasedIndex() throws Exception { HttpServerTransport serverTransport = internalCluster().getDataNodeInstance(HttpServerTransport.class); TransportAddress publishAddress = serverTransport.boundAddress().publishAddress(); - String host = publishAddress.address().getHostString(); - HttpRequestTemplate.Builder builder = HttpRequestTemplate.builder(host, publishAddress.getPort()) + // Use "localhost" as the host since it resolves correctly for both IPv4 and IPv6 + HttpRequestTemplate.Builder builder = HttpRequestTemplate.builder("localhost", publishAddress.getPort()) .path(new TextTemplate("/%3Clogstash-%7Bnow%2Fd%7D%3E/_doc/1")) .body(new TextTemplate("{\"foo\":\"bar\"}")) .putHeader("Content-Type", new TextTemplate("application/json")) diff --git a/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java b/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java index 872f2b52ce123..f7bb1e2258aa1 100644 --- a/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java +++ b/x-pack/plugin/watcher/src/internalClusterTest/java/org/elasticsearch/xpack/watcher/test/integration/HttpSecretsIntegrationTests.java @@ -96,7 +96,7 @@ public void testHttpInput() throws Exception { watchBuilder().trigger(schedule(cron("0 0 0 1 * ? 2020"))) .input( httpInput( - HttpRequestTemplate.builder(webServer.getHostName(), webServer.getPort()) + HttpRequestTemplate.builder("localhost", webServer.getPort()) .path("/") .auth(new BasicAuth(USERNAME, PASSWORD.toCharArray())) ) @@ -184,7 +184,7 @@ public void testWebhookAction() throws Exception { .addAction( "_webhook", webhookAction( - HttpRequestTemplate.builder(webServer.getHostName(), webServer.getPort()) + HttpRequestTemplate.builder("localhost", webServer.getPort()) .path("/") .auth(new BasicAuth(USERNAME, PASSWORD.toCharArray())) ) diff --git a/x-pack/plugin/watcher/src/javaRestTest/java/org/elasticsearch/smoketest/SmokeTestWatcherTestSuiteIT.java b/x-pack/plugin/watcher/src/javaRestTest/java/org/elasticsearch/smoketest/SmokeTestWatcherTestSuiteIT.java index bd14330c9c480..8d4a4b0bf2c24 100644 --- a/x-pack/plugin/watcher/src/javaRestTest/java/org/elasticsearch/smoketest/SmokeTestWatcherTestSuiteIT.java +++ b/x-pack/plugin/watcher/src/javaRestTest/java/org/elasticsearch/smoketest/SmokeTestWatcherTestSuiteIT.java @@ -50,9 +50,18 @@ public void testMonitorClusterHealth() throws Exception { ObjectPath stats = ObjectPath.createFromResponse(statsResponse); String address = stats.evaluate("nodes." + masterNode + ".http.publish_address"); assertThat(address, is(notNullValue())); - String[] splitAddress = address.split(":", 2); - String host = splitAddress[0]; - int port = Integer.parseInt(splitAddress[1]); + String host; + int port; + // Handle IPv6 addresses in [host]:port format + if (address.startsWith("[")) { + int closingBracket = address.indexOf(']'); + host = address.substring(1, closingBracket); + port = Integer.parseInt(address.substring(closingBracket + 2)); + } else { + String[] splitAddress = address.split(":", 2); + host = splitAddress[0]; + port = Integer.parseInt(splitAddress[1]); + } // put watch try (XContentBuilder builder = jsonBuilder()) { diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java index 7e59d9aa29ddc..5a06c3bc2f1fa 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java @@ -578,7 +578,7 @@ public void testMaxHttpResponseSize() throws Exception { } public void testThatGetRedirectIsFollowed() throws Exception { - String redirectUrl = "http://" + webServer.getHostName() + ":" + webServer.getPort() + "/foo"; + String redirectUrl = "http://" + webServer.getHttpAddress() + "/foo"; webServer.enqueue(new MockResponse().setResponseCode(302).addHeader("Location", redirectUrl)); HttpMethod method = randomFrom(HttpMethod.GET, HttpMethod.HEAD); @@ -601,7 +601,7 @@ public void testThatGetRedirectIsFollowed() throws Exception { // not allowed by RFC, only allowed for GET or HEAD public void testThatPostRedirectIsNotFollowed() throws Exception { - String redirectUrl = "http://" + webServer.getHostName() + ":" + webServer.getPort() + "/foo"; + String redirectUrl = "http://" + webServer.getHttpAddress() + "/foo"; webServer.enqueue(new MockResponse().setResponseCode(302).addHeader("Location", redirectUrl)); webServer.enqueue(new MockResponse().setResponseCode(200).setBody("shouldNeverBeRead")); @@ -690,7 +690,7 @@ public void testThatWhiteListBlocksRedirects() throws Exception { public void testThatWhiteListingWorksForRedirects() throws Exception { int numberOfRedirects = randomIntBetween(1, 10); for (int i = 0; i < numberOfRedirects; i++) { - String redirectUrl = "http://" + webServer.getHostName() + ":" + webServer.getPort() + "/redirect" + i; + String redirectUrl = "http://" + webServer.getHttpAddress() + "/redirect" + i; webServer.enqueue(new MockResponse().setResponseCode(302).addHeader("Location", redirectUrl)); } webServer.enqueue(new MockResponse().setResponseCode(200).setBody("shouldBeRead")); @@ -846,6 +846,6 @@ public static ClusterService mockClusterService() { } private String getWebserverUri() { - return Strings.format("http://%s:%s", webServer.getHostName(), webServer.getPort()); + return Strings.format("http://%s", webServer.getHttpAddress()); } } diff --git a/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/10_webhook.yml b/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/10_webhook.yml index 21119e75ca14e..e9a902e5c5d9b 100644 --- a/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/10_webhook.yml +++ b/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/10_webhook.yml @@ -20,7 +20,7 @@ body: pipeline: description: _description - processors: [ grok: { field: host, patterns : ["%{IPORHOST:hostname}:%{NUMBER:port:int}"]} ] + processors: [ grok: { field: host, patterns : ["(?:\\[(?[^\\]]+)\\]|(?%{IPORHOST})):(?\\d+)"]} ] docs: [ { _index: index, _id: id, _source: { host: $host } } ] - set: { docs.0.doc._source.hostname: hostname } - set: { docs.0.doc._source.port: port } diff --git a/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/50_webhook_url_escaping.yml b/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/50_webhook_url_escaping.yml index c2da572490c68..9f5d71443be09 100644 --- a/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/50_webhook_url_escaping.yml +++ b/x-pack/plugin/watcher/src/yamlRestTest/resources/rest-api-spec/test/mustache/50_webhook_url_escaping.yml @@ -23,7 +23,7 @@ body: pipeline: description: _description - processors: [ grok: { field: host, patterns : ["%{IPORHOST:hostname}:%{NUMBER:port:int}"] } ] + processors: [ grok: { field: host, patterns : ["\\[?%{IPORHOST:hostname}\\]?:%{NUMBER:port:int}"] } ] docs: [ { _index: index, _id: id, _source: { host: $host } } ] - set: { docs.0.doc._source.hostname: hostname } - set: { docs.0.doc._source.port: port } diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java index 902791c6ec0c6..9d9844ddb04a0 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java @@ -17,6 +17,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.core.Booleans; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.core.TimeValue; @@ -55,7 +56,7 @@ public class SimpleKdcLdapServer { // KDC properties private String transport = ESTestCase.randomFrom("TCP", "UDP"); private int kdcPort = 0; - private String host; + private String host = NetworkAddress.format(InetAddress.getLoopbackAddress()); private String realm; private boolean krb5DebugBackupConfigValue; @@ -144,7 +145,9 @@ private void createLdapServiceAndStart() throws Exception { private void createLdapBackendConf() throws IOException { String backendConf = KdcConfigKey.KDC_IDENTITY_BACKEND.getPropertyKey() + " = org.apache.kerby.kerberos.kdc.identitybackend.LdapIdentityBackend\n" - + "host=127.0.0.1\n" + + "host=" + + host + + "\n" + "port=" + ldapPort + "\n" @@ -267,16 +270,14 @@ public Void run() throws Exception { private static int getServerPort(String transport) { if (transport != null && transport.trim().equalsIgnoreCase("TCP")) { - try ( - ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1, InetAddress.getByName("127.0.0.1")) - ) { + try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1, InetAddress.getLoopbackAddress())) { serverSocket.setReuseAddress(true); return serverSocket.getLocalPort(); } catch (Exception ex) { throw new RuntimeException("Failed to get a TCP server socket point"); } } else if (transport != null && transport.trim().equalsIgnoreCase("UDP")) { - try (DatagramSocket socket = new DatagramSocket(0, InetAddress.getByName("127.0.0.1"))) { + try (DatagramSocket socket = new DatagramSocket(0, InetAddress.getLoopbackAddress())) { socket.setReuseAddress(true); return socket.getLocalPort(); } catch (Exception ex) { diff --git a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java index c80c4fb7bb5d1..c4fcf0fea11c4 100644 --- a/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java +++ b/x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServerTests.java @@ -12,6 +12,7 @@ import com.unboundid.ldap.sdk.SearchScope; import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.core.Tuple; import org.elasticsearch.env.Environment; @@ -19,6 +20,7 @@ import org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils; import org.ietf.jgss.GSSException; +import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; import java.security.PrivilegedActionException; @@ -40,7 +42,7 @@ public void testPrincipalCreationAndSearchOnLdap() throws Exception { assertTrue(Files.exists(workDir.resolve("p1p2.keytab"))); try ( LDAPConnection ldapConn = LdapUtils.privilegedConnect( - () -> new LDAPConnection("localhost", simpleKdcLdapServer.getLdapListenPort()) + () -> new LDAPConnection(NetworkAddress.format(InetAddress.getLoopbackAddress()), simpleKdcLdapServer.getLdapListenPort()) ); ) { assertThat(ldapConn.isConnected(), is(true)); diff --git a/x-pack/qa/reindex-tests-with-security/src/yamlRestTest/java/org/elasticsearch/xpack/security/ReindexWithSecurityIT.java b/x-pack/qa/reindex-tests-with-security/src/yamlRestTest/java/org/elasticsearch/xpack/security/ReindexWithSecurityIT.java index 4f2949862b2fb..fcc8cc201a3f7 100644 --- a/x-pack/qa/reindex-tests-with-security/src/yamlRestTest/java/org/elasticsearch/xpack/security/ReindexWithSecurityIT.java +++ b/x-pack/qa/reindex-tests-with-security/src/yamlRestTest/java/org/elasticsearch/xpack/security/ReindexWithSecurityIT.java @@ -55,7 +55,7 @@ public static ElasticsearchCluster createCluster() { .configFile("http.key", Resource.fromClasspath("ssl/http.key")) .configFile("http.crt", Resource.fromClasspath("ssl/http.crt")) .configFile("ca.crt", Resource.fromClasspath("ssl/ca.crt")) - .setting("reindex.remote.whitelist", "127.0.0.1:*") + .setting("reindex.remote.whitelist", "127.0.0.1:*,[::1]:*") .setting("xpack.security.enabled", "true") .setting("xpack.ml.enabled", "false") .setting("xpack.license.self_generated.type", "trial") diff --git a/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/AbstractPasswordToolTestCase.java b/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/AbstractPasswordToolTestCase.java index 36c10fe189484..0e0903a03bbb2 100644 --- a/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/AbstractPasswordToolTestCase.java +++ b/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/AbstractPasswordToolTestCase.java @@ -11,9 +11,7 @@ import org.elasticsearch.cli.ProcessInfo; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.network.InetAddresses; -import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -32,7 +30,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -88,8 +85,12 @@ void writeConfigurationToDisk() throws Exception { Map firstNodeHttp = (Map) firstNode.get("http"); String nodePublishAddress = (String) firstNodeHttp.get("publish_address"); final int lastColonIndex = nodePublishAddress.lastIndexOf(':'); - InetAddress actualPublishAddress = InetAddresses.forString(nodePublishAddress.substring(0, lastColonIndex)); - InetAddress expectedPublishAddress = new NetworkService(Collections.emptyList()).resolvePublishHostAddresses(Strings.EMPTY_ARRAY); + String addressPart = nodePublishAddress.substring(0, lastColonIndex); + // Strip brackets from IPv6 addresses (e.g., "[::1]" -> "::1") + if (addressPart.startsWith("[") && addressPart.endsWith("]")) { + addressPart = addressPart.substring(1, addressPart.length() - 1); + } + InetAddress actualPublishAddress = InetAddresses.forString(addressPart); final int port = Integer.valueOf(nodePublishAddress.substring(lastColonIndex + 1)); List lines = Files.readAllLines(configPath.resolve("elasticsearch.yml")); @@ -97,8 +98,9 @@ void writeConfigurationToDisk() throws Exception { .filter(s -> s.startsWith("http.port") == false && s.startsWith("http.publish_port") == false) .collect(Collectors.toList()); lines.add(randomFrom("http.port", "http.publish_port") + ": " + port); - if (expectedPublishAddress.equals(actualPublishAddress) == false) { - lines.add("http.publish_address: " + InetAddresses.toAddrString(actualPublishAddress)); + + if (false == lines.stream().anyMatch(s -> s.startsWith("http.publish_host"))) { + lines.add("http.publish_host: " + InetAddresses.toAddrString(actualPublishAddress)); } Files.write(configPath.resolve("elasticsearch.yml"), lines, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING); } diff --git a/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolIT.java b/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolIT.java index ab849872cc6cb..6d3a6c31dbfed 100644 --- a/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolIT.java +++ b/x-pack/qa/security-setup-password-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authc/esnative/tool/ResetPasswordToolIT.java @@ -49,6 +49,7 @@ public void testResetBuiltinUser() throws Exception { status = resetPasswordTool.main(new String[] { "-i", "-b", "-u", user }, mockTerminal, getToolProcessInfo()); } logger.info("CLI TOOL OUTPUT:\n{}", mockTerminal.getOutput()); + logger.info("CLI TOOL ERROR OUTPUT:\n{}", mockTerminal.getErrorOutput()); assertEquals(0, status); final String basicHeader = "Basic " + Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.UTF_8)); try { @@ -119,6 +120,7 @@ public void testResetNativeUser() throws Exception { status = resetPasswordTool.main(new String[] { "-i", "-b", "-u", nativeUser }, mockTerminal, getToolProcessInfo()); } logger.info("CLI TOOL OUTPUT:\n{}", mockTerminal.getOutput()); + logger.info("CLI TOOL ERROR OUTPUT:\n{}", mockTerminal.getErrorOutput()); assertEquals(0, status); // and authenticate with the new password