From b4d8e1b1318f0972b45b320b33b0541709011374 Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Thu, 16 Oct 2025 16:07:47 +0100 Subject: [PATCH 1/4] Disable cross-cluster functionality for `_fleet/_fleet_msearch` --- .../FleetSearchRemoteIndicesDisallowedIT.java | 38 +++++++++++++++++++ .../rest/RestFleetMultiSearchAction.java | 14 +++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java b/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java index 26700e53df8da..5084a839aa79e 100644 --- a/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java +++ b/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java @@ -41,5 +41,43 @@ public void testEndpointsShouldRejectRemoteIndices() { Matchers.containsString("Fleet search API does not support remote indices. Found: [" + remoteIndex + "]") ); } + + { + Request request = new Request("POST", "/" + remoteIndex + "/_fleet/_fleet_msearch"); + request.setJsonEntity("{}\n{}\n"); + ResponseException responseException = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request)); + assertThat( + responseException.getMessage(), + Matchers.containsString("Fleet search API does not support remote indices. Found: [" + remoteIndex + "]") + ); + } + + { + // This is fine, there are no remote indices. + Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); + request.setJsonEntity("{\"index\": \"bar*\"}\n{}\n"); + try { + getRestClient().performRequest(request); + } catch (Exception r) { + throw new AssertionError(r); + } + } + + { + // This is not valid. We shouldn't be passing multiple indices. + Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); + request.setJsonEntity("{\"index\": \"bar*,baz\"}\n{}\n"); + + ResponseException responseException = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request)); + assertThat(responseException.getMessage(), Matchers.containsString("Fleet search API only supports searching a single index.")); + } + + { + // This is not valid. We shouldn't be passing remote indices. + Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); + request.setJsonEntity("{\"index\": \"bar*\"}\n{}\n{\"index\": \"remote:index\"}\n{}\n"); + ResponseException responseException = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request)); + assertThat(responseException.getMessage(), Matchers.containsString("Fleet search API does not support remote indices. Found:")); + } } } diff --git a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java index 480230b44edc0..4444144c308f5 100644 --- a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java +++ b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java @@ -22,6 +22,7 @@ import org.elasticsearch.rest.action.RestRefCountedChunkedToXContentListener; import org.elasticsearch.rest.action.search.RestMultiSearchAction; import org.elasticsearch.rest.action.search.RestSearchAction; +import org.elasticsearch.transport.RemoteClusterService; import org.elasticsearch.usage.SearchUsageHolder; import java.io.IOException; @@ -106,12 +107,17 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli "Fleet search API param wait_for_checkpoints is only supported with an index to search specified. " + "No index specified." ); - } else if (indices.length > 1) { - throw new IllegalArgumentException( - "Fleet search API only supports searching a single index. Found: [" + Arrays.toString(indices) + "]." - ); } } + if (indices.length > 1) { + throw new IllegalArgumentException( + "Fleet search API only supports searching a single index. Found: [" + Arrays.toString(indices) + "]." + ); + } + + if (RemoteClusterService.isRemoteIndexName(indices[0])) { + throw new IllegalArgumentException("Fleet search API does not support remote indices. Found: [" + indices[0] + "]."); + } long[] checkpoints = searchRequest.getWaitForCheckpoints().get("*"); if (checkpoints != null) { searchRequest.setWaitForCheckpoints(Collections.singletonMap(indices[0], checkpoints)); From dcdb29ea5ea37701bba548c691695132556e3ed8 Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Thu, 16 Oct 2025 16:28:40 +0100 Subject: [PATCH 2/4] Update docs/changelog/136703.yaml --- docs/changelog/136703.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/changelog/136703.yaml diff --git a/docs/changelog/136703.yaml b/docs/changelog/136703.yaml new file mode 100644 index 0000000000000..527c0f7ff9d37 --- /dev/null +++ b/docs/changelog/136703.yaml @@ -0,0 +1,12 @@ +pr: 136703 +summary: Disable cross-cluster functionality for `_fleet/_fleet_msearch` +area: CCS +type: breaking +issues: [] +breaking: + title: Disable cross-cluster functionality for `_fleet/_fleet_msearch` + area: CCS + details: Please describe the details of this change for the release notes. You can + use asciidoc. + impact: Please describe the impact of this change to users + notable: false From 3d2f7aab922c424a634d2a32e17a09b70a6bb41f Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Thu, 16 Oct 2025 22:03:36 +0100 Subject: [PATCH 3/4] Undo behaviour tweak and add tests --- .../FleetSearchRemoteIndicesDisallowedIT.java | 23 +++++++++++++++---- .../rest/RestFleetMultiSearchAction.java | 11 ++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java b/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java index 5084a839aa79e..0299dea5451bc 100644 --- a/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java +++ b/x-pack/plugin/fleet/src/internalClusterTest/java/org/elasticsearch/xpack/fleet/action/FleetSearchRemoteIndicesDisallowedIT.java @@ -52,22 +52,35 @@ public void testEndpointsShouldRejectRemoteIndices() { ); } + { + /* + * It is possible, however, to sneak in multiple indices and a remote index if checkpoints are not specified. + * Unfortunately, that's the current behaviour and the Fleet team does not want us to touch it. + */ + Request request = new Request("POST", "/foo,bar:baz/_fleet/_fleet_msearch"); + request.setJsonEntity("{}\n{}\n"); + try { + getRestClient().performRequest(request); + } catch (Exception e) { + throw new AssertionError(e); + } + } + { // This is fine, there are no remote indices. Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); request.setJsonEntity("{\"index\": \"bar*\"}\n{}\n"); try { getRestClient().performRequest(request); - } catch (Exception r) { - throw new AssertionError(r); + } catch (Exception e) { + throw new AssertionError(e); } } { // This is not valid. We shouldn't be passing multiple indices. Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); - request.setJsonEntity("{\"index\": \"bar*,baz\"}\n{}\n"); - + request.setJsonEntity("{\"index\": \"bar,baz\", \"wait_for_checkpoints\": 1 }\n{}\n"); ResponseException responseException = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request)); assertThat(responseException.getMessage(), Matchers.containsString("Fleet search API only supports searching a single index.")); } @@ -75,7 +88,7 @@ public void testEndpointsShouldRejectRemoteIndices() { { // This is not valid. We shouldn't be passing remote indices. Request request = new Request("POST", "/foo/_fleet/_fleet_msearch"); - request.setJsonEntity("{\"index\": \"bar*\"}\n{}\n{\"index\": \"remote:index\"}\n{}\n"); + request.setJsonEntity("{\"index\": \"bar:baz\", \"wait_for_checkpoints\": 1 }\n{}\n"); ResponseException responseException = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request)); assertThat(responseException.getMessage(), Matchers.containsString("Fleet search API does not support remote indices. Found:")); } diff --git a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java index 4444144c308f5..1550a9a942b1f 100644 --- a/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java +++ b/x-pack/plugin/fleet/src/main/java/org/elasticsearch/xpack/fleet/rest/RestFleetMultiSearchAction.java @@ -107,15 +107,14 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli "Fleet search API param wait_for_checkpoints is only supported with an index to search specified. " + "No index specified." ); + } else if (indices.length > 1) { + throw new IllegalArgumentException( + "Fleet search API only supports searching a single index. Found: [" + Arrays.toString(indices) + "]." + ); } } - if (indices.length > 1) { - throw new IllegalArgumentException( - "Fleet search API only supports searching a single index. Found: [" + Arrays.toString(indices) + "]." - ); - } - if (RemoteClusterService.isRemoteIndexName(indices[0])) { + if (indices.length == 1 && RemoteClusterService.isRemoteIndexName(indices[0])) { throw new IllegalArgumentException("Fleet search API does not support remote indices. Found: [" + indices[0] + "]."); } long[] checkpoints = searchRequest.getWaitForCheckpoints().get("*"); From fc30371aa56dbba5fe5518bd0bb83438c24340fe Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Thu, 16 Oct 2025 22:09:05 +0100 Subject: [PATCH 4/4] Update changelog --- docs/changelog/136703.yaml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/changelog/136703.yaml b/docs/changelog/136703.yaml index 527c0f7ff9d37..8aaa19ae1f48a 100644 --- a/docs/changelog/136703.yaml +++ b/docs/changelog/136703.yaml @@ -1,12 +1,18 @@ pr: 136703 summary: Disable cross-cluster functionality for `_fleet/_fleet_msearch` -area: CCS +area: Search type: breaking issues: [] breaking: title: Disable cross-cluster functionality for `_fleet/_fleet_msearch` - area: CCS - details: Please describe the details of this change for the release notes. You can - use asciidoc. - impact: Please describe the impact of this change to users + area: Search + details: |- + This endpoint is largely used for local searches only and is not compatible with true cross-cluster searches where + arbitrary number of indices and remotes can be specified. Although it is meant to accept an index parameter that + denotes a single searchable target, such a limitation can be bypassed through various means. + + Keeping in view this endpoint's stated intent and future scope, cross-cluster functionality is being explicitly disabled. + impact: |- + This endpoint will no longer accept remote indices. Should one be provided, a top-level error is returned with + an appropriate explanation. notable: false