Skip to content

Commit 24cd7d9

Browse files
authored
Guard against project_routing in non-CPS env for PIT and Field Caps (#138867)
In CPS we support project_routing either as query parameter or in the body of the request. With this change we throw a bad request error if project_routing is set in non-CPS env.
1 parent b8d824a commit 24cd7d9

File tree

5 files changed

+82
-1
lines changed

5 files changed

+82
-1
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.http;
11+
12+
import org.apache.http.HttpStatus;
13+
import org.elasticsearch.client.Request;
14+
import org.elasticsearch.client.ResponseException;
15+
16+
import static org.hamcrest.Matchers.containsString;
17+
import static org.hamcrest.Matchers.equalTo;
18+
19+
public class FieldCapabilitiesIT extends HttpSmokeTestCase {
20+
21+
public void testProjectRoutingInNonCrossProjectEnv() {
22+
// With project_routing as query param in non-CPS env
23+
{
24+
Request request = new Request("POST", "_field_caps?fields=*&project_routing=_alias:_origin");
25+
ResponseException error = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request));
26+
assertThat(error.getMessage(), containsString("request [_field_caps] contains unrecognized parameter: [project_routing]"));
27+
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
28+
}
29+
// With project_routing in body in non-CPS env
30+
{
31+
Request request = new Request("POST", "_field_caps?fields=*");
32+
request.setJsonEntity("""
33+
{
34+
"project_routing": "_alias:_origin"
35+
}
36+
""");
37+
ResponseException error = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request));
38+
assertThat(error.getMessage(), containsString("Unknown key for a VALUE_STRING in [project_routing]"));
39+
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
40+
}
41+
}
42+
}

qa/smoke-test-http/src/internalClusterTest/java/org/elasticsearch/http/PointInTimeIT.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,28 @@ public void testMissingRequiredParameters() {
4444
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
4545
}
4646
}
47+
48+
public void testProjectRoutingInNonCrossProjectEnv() {
49+
// With project_routing as query param in non-CPS env
50+
{
51+
Request request = new Request("POST", "_pit?project_routing=_alias:_origin");
52+
request.addParameter("keep_alive", "1m");
53+
ResponseException error = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request));
54+
assertThat(error.getMessage(), containsString("request [_pit] contains unrecognized parameter: [project_routing]"));
55+
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
56+
}
57+
// With project_routing in body in non-CPS env
58+
{
59+
Request request = new Request("POST", "logs-*/_pit");
60+
request.addParameter("keep_alive", "1m");
61+
request.setJsonEntity("""
62+
{
63+
"project_routing": "_alias:_origin"
64+
}
65+
""");
66+
ResponseException error = expectThrows(ResponseException.class, () -> getRestClient().performRequest(request));
67+
assertThat(error.getMessage(), containsString("Unknown key for a VALUE_STRING in [project_routing]"));
68+
assertThat(error.getResponse().getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_BAD_REQUEST));
69+
}
70+
}
4771
}

server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesRequest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,13 @@ public ActionRequestValidationException validate() {
355355
if (fields == null || fields.length == 0) {
356356
validationException = ValidateActions.addValidationError("no fields specified", validationException);
357357
}
358+
if (projectRouting != null && indicesOptions.resolveCrossProjectIndexExpression() == false) {
359+
validationException = ValidateActions.addValidationError(
360+
"Unknown key for a VALUE_STRING in [project_routing]",
361+
validationException
362+
);
363+
364+
}
358365
return validationException;
359366
}
360367

server/src/main/java/org/elasticsearch/action/search/OpenPointInTimeRequest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.action.IndicesRequest;
1515
import org.elasticsearch.action.LegacyActionRequest;
1616
import org.elasticsearch.action.ResolvedIndexExpressions;
17+
import org.elasticsearch.action.ValidateActions;
1718
import org.elasticsearch.action.support.IndicesOptions;
1819
import org.elasticsearch.common.io.stream.StreamInput;
1920
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -104,6 +105,13 @@ public ActionRequestValidationException validate() {
104105
if (keepAlive == null) {
105106
validationException = addValidationError("[keep_alive] is not specified", validationException);
106107
}
108+
if (projectRouting != null && indicesOptions.resolveCrossProjectIndexExpression() == false) {
109+
validationException = ValidateActions.addValidationError(
110+
"Unknown key for a VALUE_STRING in [project_routing]",
111+
validationException
112+
);
113+
114+
}
107115
return validationException;
108116
}
109117

server/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
6161
final FieldCapabilitiesRequest fieldRequest = new FieldCapabilitiesRequest();
6262

6363
final boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
64-
if (crossProjectModeDecider.crossProjectEnabled()) {
64+
if (crossProjectEnabled) {
6565
fieldRequest.projectRouting(request.param("project_routing", null));
6666
// Setting includeResolvedTo to always include index resolution data structure in the linked project responses,
6767
// in order to allow the coordinating node to call CrossProjectIndexResolutionValidator#validate

0 commit comments

Comments
 (0)