Skip to content

Commit 811dabe

Browse files
committed
Merge branch 'main' into allow-opt-out-ilm
2 parents 605795f + fa252fa commit 811dabe

File tree

192 files changed

+3926
-1628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+3926
-1628
lines changed

docs/changelog/136828.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 136828
2+
summary: Can match phase coordinator duration APM metric
3+
area: Search
4+
type: enhancement
5+
issues: []

docs/changelog/136996.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 136996
2+
summary: Add periodic PKC JWK set reloading capability to JWT realm
3+
area: Security
4+
type: enhancement
5+
issues: []

docs/reference/elasticsearch/configuration-reference/security-settings.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,19 @@ $$$jwt-claim-pattern-principal$$$
15231523
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) Specifies the time-to-live for the period of time to cache JWT entries. JWTs can only be cached if client authentication is successful (or disabled). Uses the standard {{es}} [time units](/reference/elasticsearch/rest-apis/api-conventions.md#time-units). If clients use a different JWT for every request, set to `0` to disable the JWT cache. Defaults to `20m`.
15241524

15251525
`pkc_jwkset_path` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
1526-
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) The file name or URL to a JSON Web Key Set (JWKS) with the public key material that the JWT Realm uses for verifying token signatures. A value is considered a file name if it does not begin with `https`. The file name is resolved relative to the {{es}} configuration directory. If a URL is provided, then it must begin with `https://` (`http://` is not supported). {{es}} automatically caches the JWK set and will attempt to refresh the JWK set upon signature verification failure, as this might indicate that the JWT Provider has rotated the signing keys.
1526+
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) The file name or URL to a JSON Web Key Set (JWKS) with the public key material that the JWT Realm uses for verifying token signatures. A value is considered a file name if it does not begin with `https`. The file name is resolved relative to the {{es}} configuration directory. If a URL is provided, then it must begin with `https://` (`http://` is not supported). {{es}} automatically caches the JWK set and will attempt to refresh the JWK set upon signature verification failure, as this might indicate that the JWT Provider has rotated the signing keys. Background JWKS reloading can also be configured with the setting `pkc_jwkset_reload.enabled`. This ensures that rotated keys are automatically discovered and used to verify JWT signatures.
1527+
1528+
`pkc_jwkset_reload.enabled` {applies_to}`stack: ga 9.3` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
1529+
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) Indicates whether JWKS background reloading is enabled. Defaults to `false`.
1530+
1531+
`pkc_jwkset_reload.file_interval` {applies_to}`stack: ga 9.3` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
1532+
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) Specifies the reload interval for file-based JWKS. Defaults to `5m`.
1533+
1534+
`pkc_jwkset_reload.url_interval_min` {applies_to}`stack: ga 9.3` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
1535+
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) Specifies the minimum reload interval for URL-based JWKS. The `Expires` and `Cache-Control` HTTP response headers inform the reload interval. This configuration setting is the lower bound of what is considered, and it is also the default interval in the absence of useful response headers. Defaults to `1h`.
1536+
1537+
`pkc_jwkset_reload.url_interval_max` {applies_to}`stack: ga 9.3` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
1538+
: ([Static](docs-content://deploy-manage/stack-settings.md#static-cluster-setting)) Specifies the maximum reload interval for URL-based JWKS. This configuration setting is the upper bound of what is considered from header responses (`5d`).
15271539

15281540
`hmac_jwkset` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
15291541
: ([Secure](docs-content://deploy-manage/security/secure-settings.md)) Contents of a JSON Web Key Set (JWKS), including the secret key that the JWT realm uses to verify token signatures. This format supports multiple keys and optional attributes, and is preferred over the `hmac_key` setting. Cannot be used in conjunction with the `hmac_key` setting. Refer to [Configure {{es}} to use a JWT realm](docs-content://deploy-manage/users-roles/cluster-or-deployment-auth/jwt.md).

muted-tests.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,12 @@ tests:
507507
- class: org.elasticsearch.xpack.ilm.TimeSeriesDataStreamsIT
508508
method: testSearchableSnapshotAction
509509
issue: https://github.com/elastic/elasticsearch/issues/137167
510+
- class: org.elasticsearch.xpack.security.CoreWithSecurityClientYamlTestSuiteIT
511+
method: test {yaml=indices.validate_query/20_query_string/validate_query with query_string parameters}
512+
issue: https://github.com/elastic/elasticsearch/issues/137391
513+
- class: org.elasticsearch.xpack.downsample.ILMDownsampleDisruptionIT
514+
method: testILMDownsampleRollingRestart
515+
issue: https://github.com/elastic/elasticsearch/issues/136585
510516

511517
# Examples:
512518
#
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
"Test get sample with multiple reroutes":
3+
- requires:
4+
cluster_features: [ "random_sampling" ]
5+
reason: requires feature 'random_sampling' to get random samples
6+
7+
- do:
8+
ingest.put_pipeline:
9+
id: pipeline1
10+
body: >
11+
{
12+
"processors" : [
13+
{
14+
"set" : {
15+
"field": "message",
16+
"value": "set by pipeline1"
17+
}
18+
},
19+
{
20+
"reroute" : {
21+
"destination": "foo.bar"
22+
}
23+
}
24+
]
25+
}
26+
- match: { acknowledged: true }
27+
28+
- do:
29+
ingest.put_pipeline:
30+
id: pipeline2
31+
body: >
32+
{
33+
"processors" : [
34+
{
35+
"set" : {
36+
"field": "message",
37+
"value": "set by pipeline2"
38+
}
39+
},
40+
{
41+
"reroute" : {
42+
"destination": "foo.bar.baz"
43+
}
44+
}
45+
]
46+
}
47+
- match: { acknowledged: true }
48+
49+
- do:
50+
indices.put_index_template:
51+
name: my-template1
52+
body:
53+
index_patterns: [foo]
54+
template:
55+
settings:
56+
default_pipeline: pipeline1
57+
index.number_of_shards: 1
58+
index.number_of_replicas: 0
59+
mappings:
60+
dynamic: strict
61+
properties:
62+
message:
63+
type: text
64+
data_stream: {}
65+
- match: { acknowledged: true }
66+
67+
- do:
68+
indices.put_index_template:
69+
name: my-template2
70+
body:
71+
index_patterns: [foo.bar]
72+
template:
73+
settings:
74+
default_pipeline: pipeline2
75+
index.number_of_shards: 1
76+
index.number_of_replicas: 0
77+
mappings:
78+
dynamic: strict
79+
properties:
80+
message:
81+
type: text
82+
data_stream: {}
83+
- match: { acknowledged: true }
84+
85+
- do:
86+
indices.put_index_template:
87+
name: my-template3
88+
body:
89+
index_patterns: [foo.bar.baz]
90+
template:
91+
settings:
92+
index.number_of_shards: 1
93+
index.number_of_replicas: 0
94+
mappings:
95+
dynamic: strict
96+
properties:
97+
message:
98+
type: text
99+
data_stream: {}
100+
- match: { acknowledged: true }
101+
102+
- do:
103+
indices.create_data_stream:
104+
name: foo
105+
- is_true: acknowledged
106+
107+
- do:
108+
indices.create_data_stream:
109+
name: foo.bar
110+
- is_true: acknowledged
111+
112+
- do:
113+
indices.create_data_stream:
114+
name: foo.bar.baz
115+
- is_true: acknowledged
116+
117+
- do:
118+
indices.rollover:
119+
alias: foo.bar.baz
120+
wait_for_active_shards: 1
121+
- match: { rolled_over: true }
122+
123+
- do:
124+
indices.put_sample_configuration:
125+
index: foo
126+
body:
127+
rate: 1.0
128+
max_samples: 100
129+
130+
- do:
131+
indices.put_sample_configuration:
132+
index: foo.bar
133+
body:
134+
rate: 1.0
135+
max_samples: 100
136+
137+
- do:
138+
indices.put_sample_configuration:
139+
index: foo.bar.baz
140+
body:
141+
rate: 1.0
142+
max_samples: 100
143+
144+
- do:
145+
bulk:
146+
refresh: true
147+
body:
148+
- '{ "create":{"_index": "foo" } }'
149+
- '{"@timestamp": 123456, "message": "This is the original message"}'
150+
- '{ "create":{"_index": "foo" } }'
151+
- '{"@timestamp": 123456, "message": "This is the original message"}'
152+
- match: { errors: false }
153+
154+
- do:
155+
indices.get_sample:
156+
index: foo
157+
- length: { sample: 2 }
158+
- match: { sample.0.index: "foo" }
159+
- match: { sample.0.source.message: "This is the original message" }
160+
- match: { sample.1.source.message: "This is the original message" }
161+
162+
- do:
163+
indices.get_sample:
164+
index: foo.bar
165+
- length: { sample: 2 }
166+
- match: { sample.0.index: "foo.bar" }
167+
- match: { sample.0.source.message: "This is the original message" }
168+
- match: { sample.1.source.message: "This is the original message" }
169+
170+
- do:
171+
indices.get_sample:
172+
index: foo.bar.baz
173+
- length: { sample: 2 }
174+
- match: { sample.0.index: "foo.bar.baz" }
175+
- match: { sample.0.source.message: "This is the original message" }
176+
- match: { sample.1.source.message: "This is the original message" }
177+
178+
---
179+
teardown:
180+
- requires:
181+
cluster_features: [ "random_sampling" ]
182+
reason: requires feature 'random_sampling' to get random samples
183+
184+
- do:
185+
indices.delete_data_stream:
186+
name: foo*

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.core.Nullable;
2020
import org.elasticsearch.index.query.CoordinatorRewriteContext;
2121
import org.elasticsearch.index.query.CoordinatorRewriteContextProvider;
22+
import org.elasticsearch.rest.action.search.SearchResponseMetrics;
2223
import org.elasticsearch.search.CanMatchShardResponse;
2324
import org.elasticsearch.search.SearchService;
2425
import org.elasticsearch.search.SearchShardTarget;
@@ -58,6 +59,8 @@
5859
*/
5960
final class CanMatchPreFilterSearchPhase {
6061

62+
private static final String PHASE_NAME = "can_match";
63+
6164
private final Logger logger;
6265
private final SearchRequest request;
6366
private final List<SearchShardIterator> shardsIts;
@@ -136,20 +139,35 @@ public static SubscribableListener<List<SearchShardIterator>> execute(
136139
TransportSearchAction.SearchTimeProvider timeProvider,
137140
SearchTask task,
138141
boolean requireAtLeastOneMatch,
139-
CoordinatorRewriteContextProvider coordinatorRewriteContextProvider
142+
CoordinatorRewriteContextProvider coordinatorRewriteContextProvider,
143+
SearchResponseMetrics searchResponseMetrics
140144
) {
141145
if (shardsIts.isEmpty()) {
142146
return SubscribableListener.newSucceeded(List.of());
143147
}
144148
final SubscribableListener<List<SearchShardIterator>> listener = new SubscribableListener<>();
149+
long phaseStartTimeInNanos = System.nanoTime();
150+
151+
listener.addListener(new ActionListener<>() {
152+
@Override
153+
public void onResponse(List<SearchShardIterator> shardsIts) {
154+
searchResponseMetrics.recordSearchPhaseDuration(PHASE_NAME, System.nanoTime() - phaseStartTimeInNanos);
155+
}
156+
157+
@Override
158+
public void onFailure(Exception e) {
159+
// do not record duration of failed phases
160+
}
161+
});
162+
145163
// Note that the search is failed when this task is rejected by the executor
146164
executor.execute(new AbstractRunnable() {
147165
@Override
148166
public void onFailure(Exception e) {
149167
if (logger.isDebugEnabled()) {
150168
logger.debug(() -> format("Failed to execute [%s] while running [can_match] phase", request), e);
151169
}
152-
listener.onFailure(new SearchPhaseExecutionException("can_match", "start", e, ShardSearchFailure.EMPTY_ARRAY));
170+
listener.onFailure(new SearchPhaseExecutionException(PHASE_NAME, "start", e, ShardSearchFailure.EMPTY_ARRAY));
153171
}
154172

155173
@Override
@@ -249,7 +267,7 @@ private synchronized void consumeResult(int shardIndex, boolean canMatch, MinAnd
249267

250268
private void checkNoMissingShards(List<SearchShardIterator> shards) {
251269
assert assertSearchCoordinationThread();
252-
SearchPhase.doCheckNoMissingShards("can_match", request, shards);
270+
SearchPhase.doCheckNoMissingShards(PHASE_NAME, request, shards);
253271
}
254272

255273
private Map<SendingTarget, List<SearchShardIterator>> groupByNode(List<SearchShardIterator> shards) {
@@ -386,7 +404,7 @@ public void onFailure(Exception e) {
386404
if (logger.isDebugEnabled()) {
387405
logger.debug(() -> format("Failed to execute [%s] while running [can_match] phase", request), e);
388406
}
389-
listener.onFailure(new SearchPhaseExecutionException("can_match", "round", e, ShardSearchFailure.EMPTY_ARRAY));
407+
listener.onFailure(new SearchPhaseExecutionException(PHASE_NAME, "round", e, ShardSearchFailure.EMPTY_ARRAY));
390408
}
391409
}
392410

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ public boolean allowsRemoteIndices() {
163163
return true;
164164
}
165165

166+
@Override
167+
public boolean allowsCrossProject() {
168+
return true;
169+
}
170+
166171
/**
167172
* Creates a new sub-search request starting from the original search request that is provided.
168173
* For internal use only, allows to fork a search request into multiple search requests that will be executed independently.

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,13 +609,18 @@ public Clusters(StreamInput in) throws IOException {
609609
}
610610

611611
public Clusters(Map<String, Cluster> clusterInfoMap) {
612+
this(clusterInfoMap, true);
613+
}
614+
615+
public Clusters(Map<String, Cluster> clusterInfoMap, boolean ccsMinimizeRoundtrips) {
612616
assert clusterInfoMap.size() > 0 : "this constructor should not be called with an empty Cluster info map";
613617
this.total = clusterInfoMap.size();
614-
this.clusterInfo = clusterInfoMap;
618+
this.clusterInfo = ConcurrentCollections.newConcurrentMap();
619+
this.clusterInfo.putAll(clusterInfoMap);
615620
this.successful = getClusterStateCount(Cluster.Status.SUCCESSFUL);
616621
this.skipped = getClusterStateCount(Cluster.Status.SKIPPED);
617622
// should only be called if "details" section of fromXContent is present (for ccsMinimizeRoundtrips)
618-
this.ccsMinimizeRoundtrips = true;
623+
this.ccsMinimizeRoundtrips = ccsMinimizeRoundtrips;
619624
}
620625

621626
@Override

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.action.ActionRequestValidationException;
1313
import org.elasticsearch.action.IndicesRequest;
1414
import org.elasticsearch.action.LegacyActionRequest;
15+
import org.elasticsearch.action.ResolvedIndexExpressions;
1516
import org.elasticsearch.action.support.IndicesOptions;
1617
import org.elasticsearch.common.io.stream.StreamInput;
1718
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -43,6 +44,8 @@ public final class SearchShardsRequest extends LegacyActionRequest implements In
4344

4445
private final String clusterAlias;
4546

47+
private ResolvedIndexExpressions resolvedIndexExpressions;
48+
4649
public SearchShardsRequest(
4750
String[] indices,
4851
IndicesOptions indicesOptions,
@@ -179,4 +182,14 @@ public int hashCode() {
179182
result = 31 * result + Arrays.hashCode(indices);
180183
return result;
181184
}
185+
186+
@Override
187+
public void setResolvedIndexExpressions(ResolvedIndexExpressions expressions) {
188+
this.resolvedIndexExpressions = expressions;
189+
}
190+
191+
@Override
192+
public ResolvedIndexExpressions getResolvedIndexExpressions() {
193+
return resolvedIndexExpressions;
194+
}
182195
}

0 commit comments

Comments
 (0)