|
@@ -7,13 +7,11 @@
|
|
|
|
|
|
package org.elasticsearch.xpack.remotecluster;
|
|
|
|
|
|
-import org.apache.http.client.methods.HttpPost;
|
|
|
import org.elasticsearch.action.search.SearchResponse;
|
|
|
import org.elasticsearch.client.Request;
|
|
|
import org.elasticsearch.client.RequestOptions;
|
|
|
import org.elasticsearch.client.Response;
|
|
|
import org.elasticsearch.client.ResponseException;
|
|
|
-import org.elasticsearch.common.settings.SecureString;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
import org.elasticsearch.core.Strings;
|
|
|
import org.elasticsearch.search.SearchHit;
|
|
@@ -43,31 +41,36 @@ import static org.hamcrest.Matchers.empty;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.not;
|
|
|
import static org.hamcrest.Matchers.notNullValue;
|
|
|
+import static org.hamcrest.Matchers.nullValue;
|
|
|
|
|
|
public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTestCase {
|
|
|
|
|
|
private static final AtomicReference<Map<String, Object>> API_KEY_MAP_REF = new AtomicReference<>();
|
|
|
private static final AtomicReference<Map<String, Object>> REST_API_KEY_MAP_REF = new AtomicReference<>();
|
|
|
private static final AtomicBoolean SSL_ENABLED_REF = new AtomicBoolean();
|
|
|
+ private static final AtomicBoolean NODE1_RCS_SERVER_ENABLED = new AtomicBoolean();
|
|
|
+ private static final AtomicBoolean NODE2_RCS_SERVER_ENABLED = new AtomicBoolean();
|
|
|
|
|
|
static {
|
|
|
fulfillingCluster = ElasticsearchCluster.local()
|
|
|
.name("fulfilling-cluster")
|
|
|
.nodes(3)
|
|
|
.apply(commonClusterConfig)
|
|
|
- .setting("remote_cluster_server.enabled", "true")
|
|
|
.setting("remote_cluster.port", "0")
|
|
|
- .setting("xpack.security.remote_cluster_server.ssl.enabled", String.valueOf(SSL_ENABLED_REF.get()))
|
|
|
+ .setting("xpack.security.remote_cluster_server.ssl.enabled", () -> String.valueOf(SSL_ENABLED_REF.get()))
|
|
|
.setting("xpack.security.remote_cluster_server.ssl.key", "remote-cluster.key")
|
|
|
.setting("xpack.security.remote_cluster_server.ssl.certificate", "remote-cluster.crt")
|
|
|
.setting("xpack.security.authc.token.enabled", "true")
|
|
|
.keystore("xpack.security.remote_cluster_server.ssl.secure_key_passphrase", "remote-cluster-password")
|
|
|
+ .node(0, spec -> spec.setting("remote_cluster_server.enabled", "true"))
|
|
|
+ .node(1, spec -> spec.setting("remote_cluster_server.enabled", () -> String.valueOf(NODE1_RCS_SERVER_ENABLED.get())))
|
|
|
+ .node(2, spec -> spec.setting("remote_cluster_server.enabled", () -> String.valueOf(NODE2_RCS_SERVER_ENABLED.get())))
|
|
|
.build();
|
|
|
|
|
|
queryCluster = ElasticsearchCluster.local()
|
|
|
.name("query-cluster")
|
|
|
.apply(commonClusterConfig)
|
|
|
- .setting("xpack.security.remote_cluster_client.ssl.enabled", String.valueOf(SSL_ENABLED_REF.get()))
|
|
|
+ .setting("xpack.security.remote_cluster_client.ssl.enabled", () -> String.valueOf(SSL_ENABLED_REF.get()))
|
|
|
.setting("xpack.security.remote_cluster_client.ssl.certificate_authorities", "remote-cluster-ca.crt")
|
|
|
.setting("xpack.security.authc.token.enabled", "true")
|
|
|
.keystore("cluster.remote.my_remote_cluster.credentials", () -> {
|
|
@@ -114,9 +117,11 @@ public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTe
|
|
|
// Use a RuleChain to ensure that fulfilling cluster is started before query cluster
|
|
|
// `SSL_ENABLED_REF` is used to control the SSL-enabled setting on the test clusters
|
|
|
// We set it here, since randomization methods are not available in the static initialize context above
|
|
|
- public static TestRule clusterRule = RuleChain.outerRule(new RunnableTestRuleAdapter(() -> SSL_ENABLED_REF.set(usually())))
|
|
|
- .around(fulfillingCluster)
|
|
|
- .around(queryCluster);
|
|
|
+ public static TestRule clusterRule = RuleChain.outerRule(new RunnableTestRuleAdapter(() -> {
|
|
|
+ SSL_ENABLED_REF.set(usually());
|
|
|
+ NODE1_RCS_SERVER_ENABLED.set(randomBoolean());
|
|
|
+ NODE2_RCS_SERVER_ENABLED.set(randomBoolean());
|
|
|
+ })).around(fulfillingCluster).around(queryCluster);
|
|
|
|
|
|
public void testCrossClusterSearch() throws Exception {
|
|
|
configureRemoteCluster();
|
|
@@ -151,7 +156,8 @@ public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTe
|
|
|
{ "index": { "_index": "shared-metrics" } }
|
|
|
{ "name": "metric3" }
|
|
|
{ "index": { "_index": "shared-metrics" } }
|
|
|
- { "name": "metric4" }\n"""));
|
|
|
+ { "name": "metric4" }
|
|
|
+ """));
|
|
|
assertOK(performRequestAgainstFulfillingCluster(bulkRequest));
|
|
|
}
|
|
|
|
|
@@ -353,24 +359,34 @@ public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTe
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
public void testNodesInfo() throws IOException {
|
|
|
- final Request request = new Request("GET", "/_nodes/transport,remote_cluster_server");
|
|
|
+ final Request request = new Request("GET", "/_nodes/settings,transport,remote_cluster_server");
|
|
|
final Response response = performRequestAgainstFulfillingCluster(request);
|
|
|
assertOK(response);
|
|
|
final Map<String, Object> responseMap = responseAsMap(response);
|
|
|
|
|
|
assertThat(ObjectPath.eval("_nodes.total", responseMap), equalTo(3));
|
|
|
final Map<String, Object> nodes = ObjectPath.eval("nodes", responseMap);
|
|
|
- nodes.forEach((k, v) -> {
|
|
|
- final Map<String, Object> node = (Map<String, Object>) v;
|
|
|
+ int numberOfRemoteClusterServerNodes = 0;
|
|
|
+ for (Map.Entry<String, Object> entry : nodes.entrySet()) {
|
|
|
+ final Map<String, Object> node = (Map<String, Object>) entry.getValue();
|
|
|
// remote cluster is not reported in transport profiles
|
|
|
assertThat(ObjectPath.eval("transport.profiles", node), anEmptyMap());
|
|
|
|
|
|
- final List<String> boundAddresses = ObjectPath.eval("remote_cluster_server.bound_address", node);
|
|
|
- assertThat(boundAddresses, notNullValue());
|
|
|
- assertThat(boundAddresses, not(empty()));
|
|
|
- final String publishAddress = ObjectPath.eval("remote_cluster_server.publish_address", node);
|
|
|
- assertThat(publishAddress, notNullValue());
|
|
|
- });
|
|
|
+ if (Boolean.parseBoolean(ObjectPath.eval("settings.remote_cluster_server.enabled", node))) {
|
|
|
+ numberOfRemoteClusterServerNodes += 1;
|
|
|
+ final List<String> boundAddresses = ObjectPath.eval("remote_cluster_server.bound_address", node);
|
|
|
+ assertThat(boundAddresses, notNullValue());
|
|
|
+ assertThat(boundAddresses, not(empty()));
|
|
|
+ final String publishAddress = ObjectPath.eval("remote_cluster_server.publish_address", node);
|
|
|
+ assertThat(publishAddress, notNullValue());
|
|
|
+ } else {
|
|
|
+ assertThat(ObjectPath.eval("remote_cluster_server", node), nullValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ assertThat(
|
|
|
+ numberOfRemoteClusterServerNodes,
|
|
|
+ equalTo(1 + (NODE1_RCS_SERVER_ENABLED.get() ? 1 : 0) + (NODE2_RCS_SERVER_ENABLED.get() ? 1 : 0))
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
private Response performRequestWithRemoteSearchUser(final Request request) throws IOException {
|
|
@@ -393,22 +409,4 @@ public class RemoteClusterSecurityRestIT extends AbstractRemoteClusterSecurityTe
|
|
|
);
|
|
|
return client().performRequest(request);
|
|
|
}
|
|
|
-
|
|
|
- private String headerFromRandomAuthMethod(final String username, final SecureString password) throws IOException {
|
|
|
- final boolean useBearerTokenAuth = randomBoolean();
|
|
|
- if (useBearerTokenAuth) {
|
|
|
- final Request request = new Request(HttpPost.METHOD_NAME, "/_security/oauth2/token");
|
|
|
- request.setJsonEntity(String.format(Locale.ROOT, """
|
|
|
- {
|
|
|
- "grant_type":"password",
|
|
|
- "username":"%s",
|
|
|
- "password":"%s"
|
|
|
- }
|
|
|
- """, username, password));
|
|
|
- final Map<String, Object> responseBody = entityAsMap(adminClient().performRequest(request));
|
|
|
- return "Bearer " + responseBody.get("access_token");
|
|
|
- } else {
|
|
|
- return basicAuthHeaderValue(username, password);
|
|
|
- }
|
|
|
- }
|
|
|
}
|