diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityTestCase.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityTestCase.java index 2c61707f57a5a..52ae569df1230 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityTestCase.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/AbstractRemoteClusterSecurityTestCase.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.remotecluster; +import io.netty.handler.codec.http.HttpMethod; + import org.apache.http.HttpHost; import org.apache.http.client.methods.HttpPost; import org.elasticsearch.client.Request; @@ -25,6 +27,7 @@ import org.elasticsearch.test.cluster.util.resource.Resource; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ObjectPath; +import org.elasticsearch.xpack.security.SecurityFeatures; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -33,8 +36,11 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.equalTo; @@ -78,6 +84,7 @@ public abstract class AbstractRemoteClusterSecurityTestCase extends ESRestTestCa .configFile("remote-cluster-client.key", Resource.fromClasspath("ssl/remote-cluster-client.key")) .configFile("remote-cluster-client.crt", Resource.fromClasspath("ssl/remote-cluster-client.crt")) .configFile("remote-cluster-client-ca.crt", Resource.fromClasspath("ssl/remote-cluster-client-ca.crt")) + .configFile("signing.crt", Resource.fromClasspath("signing/signing.crt")) .module("reindex") // Needed for the role metadata migration .user(USER, PASS.toString()); @@ -197,8 +204,10 @@ protected void configureRemoteCluster( boolean isProxyMode, boolean skipUnavailable ) throws Exception { + putFulfillingClusterSettings(); + // For configurable remote cluster security, this method assumes the cross cluster access API key is already configured in keystore - putRemoteClusterSettings(clusterAlias, targetFulfillingCluster, basicSecurity, isProxyMode, skipUnavailable); + putQueryClusterSettings(clusterAlias, targetFulfillingCluster, basicSecurity, isProxyMode, skipUnavailable); // Ensure remote cluster is connected checkRemoteConnection(clusterAlias, targetFulfillingCluster, basicSecurity, isProxyMode); @@ -234,7 +243,18 @@ protected void reloadSecureSettings() throws IOException { } } - protected void putRemoteClusterSettings( + protected void putFulfillingClusterSettings() throws IOException { + if (getFulfillingClusterNodeFeatures().contains(SecurityFeatures.CERTIFICATE_IDENTITY_FIELD_FEATURE.id())) { + final var request = newXContentRequest(HttpMethod.PUT, "/_cluster/settings", (builder, params) -> { + builder.startObject("persistent"); + Settings.builder().put("cluster.remote.signing.certificate_authorities", "signing.crt").build().toXContent(builder, params); + return builder.endObject(); + }); + assertOK(performRequestAgainstFulfillingCluster(request)); + } + } + + protected void putQueryClusterSettings( String clusterAlias, ElasticsearchCluster targetFulfillingCluster, boolean basicSecurity, @@ -303,6 +323,22 @@ protected static String randomEncodedApiKey() { .encodeToString((UUIDs.base64UUID() + ":" + UUIDs.randomBase64UUIDSecureString()).getBytes(StandardCharsets.UTF_8)); } + protected Set getFulfillingClusterNodeFeatures() throws IOException { + final Request request = new Request("GET", "_cluster/state"); + request.addParameter("filter_path", "nodes_features"); + final Response response = performRequestAgainstFulfillingCluster(request); + + var responseData = responseAsMap(response); + if (responseData.get("nodes_features") instanceof List nodesFeatures) { + return nodesFeatures.stream().map(Map.class::cast).flatMap(nodeFeatureMap -> { + @SuppressWarnings("unchecked") + List features = (List) nodeFeatureMap.get("features"); + return features.stream(); + }).collect(Collectors.toSet()); + } + return Set.of(); + } + protected record TestClusterConfigProviders(LocalClusterConfigProvider server, LocalClusterConfigProvider client) {} protected static TestClusterConfigProviders EMPTY_CONFIG_PROVIDERS = new TestClusterConfigProviders(cluster -> {}, cluster -> {}); diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityBWCToRCS2ClusterRestIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityBWCToRCS2ClusterRestIT.java index c62a18602ae2d..05d0218b65292 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityBWCToRCS2ClusterRestIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityBWCToRCS2ClusterRestIT.java @@ -40,8 +40,6 @@ public class RemoteClusterSecurityBWCToRCS2ClusterRestIT extends AbstractRemoteC .setting("xpack.ml.enabled", "false") .setting("remote_cluster_server.enabled", "true") .setting("remote_cluster.port", "0") - .setting("cluster.remote.signing.certificate_authorities", "signing.crt") - .configFile("signing.crt", Resource.fromClasspath("signing/signing.crt")) .setting("xpack.security.remote_cluster_server.ssl.enabled", "true") .setting("xpack.security.remote_cluster_server.ssl.key", "remote-cluster.key") .setting("xpack.security.remote_cluster_server.ssl.certificate", "remote-cluster.crt") diff --git a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityReloadCredentialsRestIT.java b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityReloadCredentialsRestIT.java index fb941e9e815cf..8eb19e435bb45 100644 --- a/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityReloadCredentialsRestIT.java +++ b/x-pack/plugin/security/qa/multi-cluster/src/javaRestTest/java/org/elasticsearch/xpack/remotecluster/RemoteClusterSecurityReloadCredentialsRestIT.java @@ -197,7 +197,7 @@ private void configureRcs2() throws Exception { final boolean configureSettingsFirst = randomBoolean(); // it's valid to first configure remote cluster, then credentials if (configureSettingsFirst) { - putRemoteClusterSettings("my_remote_cluster", fulfillingCluster, false, isProxyMode, randomBoolean()); + putQueryClusterSettings("my_remote_cluster", fulfillingCluster, false, isProxyMode, randomBoolean()); } configureRemoteClusterCredentials("my_remote_cluster", remoteClusterCredentials, keystoreSettings);