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: [] 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; } /** 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); }