From 40c6f1f6226255901d7e26b886f38da99b6dd49f Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Tue, 16 Dec 2025 12:17:48 +0000 Subject: [PATCH 1/3] Copy existing resolved index expressions when constructing a new `SearchRequest` from an existing one --- .../main/java/org/elasticsearch/action/search/SearchRequest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchRequest.java b/server/src/main/java/org/elasticsearch/action/search/SearchRequest.java index c889d344a06c8..a7c80af0bc92f 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchRequest.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchRequest.java @@ -251,6 +251,7 @@ private SearchRequest( this.waitForCheckpointsTimeout = searchRequest.waitForCheckpointsTimeout; this.forceSyntheticSource = searchRequest.forceSyntheticSource; this.projectRouting = searchRequest.projectRouting; + this.resolvedIndexExpressions = searchRequest.resolvedIndexExpressions; } /** From 78ede53913f67dff589614f81fdd4bd21644a38a Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Tue, 16 Dec 2025 17:09:57 +0000 Subject: [PATCH 2/3] Update docs/changelog/139596.yaml --- docs/changelog/139596.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/139596.yaml diff --git a/docs/changelog/139596.yaml b/docs/changelog/139596.yaml new file mode 100644 index 0000000000000..ffb62d3bfa805 --- /dev/null +++ b/docs/changelog/139596.yaml @@ -0,0 +1,6 @@ +pr: 139596 +summary: "CPS: Copy existing resolved index expressions when constructing a new `SearchRequest`\ + \ from an existing one" +area: CCS +type: bug +issues: [] From 2bb67b1a6bbcaa6c961e440e11aea2afb343211f Mon Sep 17 00:00:00 2001 From: Pawan Kartik Date: Wed, 17 Dec 2025 15:31:33 +0000 Subject: [PATCH 3/3] Address review comments --- ...sProjectIndexResolutionValidatorTests.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/src/test/java/org/elasticsearch/search/crossproject/CrossProjectIndexResolutionValidatorTests.java b/server/src/test/java/org/elasticsearch/search/crossproject/CrossProjectIndexResolutionValidatorTests.java index 706e07177a85d..0a78dd924dbd6 100644 --- a/server/src/test/java/org/elasticsearch/search/crossproject/CrossProjectIndexResolutionValidatorTests.java +++ b/server/src/test/java/org/elasticsearch/search/crossproject/CrossProjectIndexResolutionValidatorTests.java @@ -13,6 +13,7 @@ import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.ResolvedIndexExpression; import org.elasticsearch.action.ResolvedIndexExpressions; +import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.test.ESTestCase; @@ -1408,6 +1409,35 @@ public void testShouldReportFirstRemote404WhenNo403AndLocalProjectIsExcluded() { assertThat(e.getSuppressed(), emptyArray()); } + public void testResolvedIndexExpressionsAreCopiedOntoNewSearchRequest() { + ResolvedIndexExpressions expr = new ResolvedIndexExpressions( + List.of( + new ResolvedIndexExpression( + "logs", + new ResolvedIndexExpression.LocalExpressions( + Set.of("logs"), + ResolvedIndexExpression.LocalIndexResolutionResult.SUCCESS, + null + ), + Set.of("P1:logs") + ) + ) + ); + + String projectRouting = "_alias:_origin"; + SearchRequest original = new SearchRequest("logs"); + original.setResolvedIndexExpressions(expr); + original.setProjectRouting(projectRouting); + + /* + * When a new SearchRequest object is created from an existing one, we should copy over the previously + * resolved expressions since the new object will not go through the Security Action Filter. + */ + SearchRequest rewritten = new SearchRequest(original); + assertThat(rewritten.getResolvedIndexExpressions(), equalTo(expr)); + assertThat(rewritten.getProjectRouting(), equalTo(projectRouting)); + } + private IndicesOptions getStrictAllowNoIndices() { return getIndicesOptions(true, false); }