Skip to content

Commit 9d15c1e

Browse files
authored
Merge branch 'main' into changelogs-08-26
2 parents 8cfb943 + b5b4424 commit 9d15c1e

21 files changed

Lines changed: 536 additions & 64 deletions

File tree

docs/changelog/157760.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
area: Audit
2+
issues: []
3+
pr: 157760
4+
summary: "Audit: reject oversized request bodies"
5+
type: enhancement

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ $$$xpack-sa-lf-events-emit-request$$$
6868
Be advised that sensitive data may be audited in plain text when including the request body in audit events, even though all the security APIs, such as those that change the user’s password, have the credentials filtered out when audited.
6969
::::
7070

71+
$$$xpack-sa-lf-events-max-request-body-size$$$
7172

73+
`xpack.security.audit.logfile.events.max_request_body_size` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on Elastic Cloud Hosted")
74+
: ([Dynamic](docs-content://deploy-manage/stack-settings.md#dynamic-cluster-setting)) Maximum rendered JSON body size (in characters) that may be included in audit events when [`xpack.security.audit.logfile.events.emit_request_body`](#xpack-sa-lf-events-emit-request) is `true`. The limit is applied to the JSON representation of the request body (after format conversion), so it correctly accounts for formats that expand when converted to JSON. Requests whose rendered body exceeds this limit are rejected with HTTP 413 (Request Entity Too Large), ensuring the audit log is always a complete record of accepted requests. The default value is `2147483647b` (`Integer.MAX_VALUE`). Set to `0` to disable the limit entirely. Lower this value on nodes with limited available memory as needed.
7275

7376
## Local Node Info Settings [node-audit-settings]
7477

modules/repository-s3/qa/deprecations/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3DeprecationsRestIT.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.elasticsearch.client.Request;
2020
import org.elasticsearch.common.ReferenceDocs;
21+
import org.elasticsearch.common.Strings;
2122
import org.elasticsearch.common.settings.Settings;
2223
import org.elasticsearch.test.cluster.ElasticsearchCluster;
2324
import org.elasticsearch.test.fixtures.testcontainers.TestContainersThreadFilter;
@@ -27,6 +28,9 @@
2728
import org.junit.rules.TestRule;
2829

2930
import java.io.IOException;
31+
import java.util.HashSet;
32+
import java.util.Map;
33+
import java.util.Set;
3034
import java.util.function.Supplier;
3135
import java.util.function.UnaryOperator;
3236

@@ -140,6 +144,47 @@ public void testUpgradeAssistantReportsInsecureCredentials() throws IOException
140144
}
141145
}
142146

147+
private static final String PLACEHOLDER_CLIENT = "placeholder";
148+
private static final Map<String, String> DEPRECATED_CLIENT_SETTING_TEST_VALUES = Map.of(
149+
"protocol",
150+
"https",
151+
"use_throttle_retries",
152+
"true",
153+
"signer_override",
154+
"test_signer"
155+
);
156+
157+
public void testUpgradeAssistantReportsDeprecatedClientSettings() throws IOException {
158+
for (var deprecatedClientSetting : DEPRECATED_CLIENT_SETTING_TEST_VALUES.entrySet()) {
159+
final var settingKey = deprecatedClientSetting.getKey();
160+
final var repoName = registerRepository(b -> b.put(settingKey, deprecatedClientSetting.getValue()), Strings.format("""
161+
[s3.client.%s.%s] setting was deprecated in Elasticsearch and will be removed in a future release. \
162+
See the breaking changes documentation for the next major version.""", PLACEHOLDER_CLIENT, settingKey));
163+
try {
164+
assertDeprecationIssue(
165+
repoName,
166+
"S3 repository explicitly configures a deprecated client setting",
167+
ReferenceDocs.TROUBLESHOOT_REPOSITORY,
168+
S3Repository.deprecatedClientSettingDeprecationWarning(settingKey)
169+
);
170+
} finally {
171+
assertOK(client().performRequest(new Request("DELETE", "/_snapshot/" + repoName)));
172+
}
173+
}
174+
}
175+
176+
public void testAllDeprecatedClientSettingsAreCoveredByUpgradeAssistantTest() {
177+
final Set<String> deprecatedClientSettings = new HashSet<>();
178+
for (final var setting : S3RepositorySettings.DEPRECATED_CLIENT_SETTINGS) {
179+
deprecatedClientSettings.add(
180+
setting.getConcreteSettingForNamespace(PLACEHOLDER_CLIENT)
181+
.getKey()
182+
.substring(S3ClientSettings.REPOSITORY_CLIENT_SETTINGS_PREFIX.length())
183+
);
184+
}
185+
assertThat(DEPRECATED_CLIENT_SETTING_TEST_VALUES.keySet(), equalTo(deprecatedClientSettings));
186+
}
187+
143188
private static void assertDeprecationIssue(String repositoryName, String message, ReferenceDocs referenceDocs, String details)
144189
throws IOException {
145190
final var deprecations = assertOKAndCreateObjectPath(client().performRequest(new Request("GET", "/_migration/deprecations")));

modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3ClientSettings.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ final class S3ClientSettings {
5252

5353
/** Placeholder client name for normalizing client settings in the repository settings. */
5454
private static final String PLACEHOLDER_CLIENT = "placeholder";
55+
static final String REPOSITORY_CLIENT_SETTINGS_PREFIX = PREFIX + PLACEHOLDER_CLIENT + '.';
56+
57+
static Settings normalizeRepositorySettings(Settings repositorySettings) {
58+
return Settings.builder().put(repositorySettings).normalizePrefix(REPOSITORY_CLIENT_SETTINGS_PREFIX).build();
59+
}
5560

5661
/** The access key (ie login id) for connecting to s3. */
5762
static final Setting.AffixSetting<SecureString> ACCESS_KEY_SETTING = Setting.affixKeySetting(
@@ -349,10 +354,7 @@ private S3ClientSettings(
349354
*/
350355
S3ClientSettings refine(Settings repositorySettings) {
351356
// Normalize settings to placeholder client settings prefix so that we can use the affix settings directly
352-
final Settings normalizedSettings = Settings.builder()
353-
.put(repositorySettings)
354-
.normalizePrefix(PREFIX + PLACEHOLDER_CLIENT + '.')
355-
.build();
357+
final Settings normalizedSettings = normalizeRepositorySettings(repositorySettings);
356358
final HttpScheme newProtocol = getRepoSettingOrDefault(PROTOCOL_SETTING, normalizedSettings, protocol);
357359
final String newEndpoint = getRepoSettingOrDefault(ENDPOINT_SETTING, normalizedSettings, endpoint);
358360

@@ -399,6 +401,11 @@ S3ClientSettings refine(Settings repositorySettings) {
399401
tenaciousRetriesEnabled
400402
);
401403
final boolean newAlwaysSignRequests = getRepoSettingOrDefault(ALWAYS_SIGN_REQUESTS, normalizedSettings, alwaysSignRequests);
404+
405+
// Read unused settings too so repository registration emits deprecation warnings for explicit values.
406+
getRepoSettingOrDefault(UNUSED_USE_THROTTLE_RETRIES_SETTING, normalizedSettings, true);
407+
getRepoSettingOrDefault(UNUSED_SIGNER_OVERRIDE, normalizedSettings, "");
408+
402409
if (Objects.equals(protocol, newProtocol)
403410
&& Objects.equals(endpoint, newEndpoint)
404411
&& Objects.equals(proxyHost, newProxyHost)

modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3Repository.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,13 @@ class S3Repository extends MeteredBlobStoreRepository {
408408
UNSAFELY_INCOMPATIBLE_WITH_S3_CONDITIONAL_WRITES.getKey()
409409
);
410410

411+
static String deprecatedClientSettingDeprecationWarning(String settingKey) {
412+
return Strings.format(
413+
"This repository's settings include the deprecated S3 client setting [%s] which must be removed before upgrade.",
414+
settingKey
415+
);
416+
}
417+
411418
@Override
412419
public Collection<RepositoryDeprecationInfo> getDeprecationInfos() {
413420
final List<RepositoryDeprecationInfo> deprecationInfos = new ArrayList<>();
@@ -423,6 +430,24 @@ public Collection<RepositoryDeprecationInfo> getDeprecationInfos() {
423430
)
424431
);
425432
}
433+
for (String normalizedKey : S3ClientSettings.normalizeRepositorySettings(getMetadata().settings()).keySet()) {
434+
for (Setting.AffixSetting<?> setting : S3RepositorySettings.DEPRECATED_CLIENT_SETTINGS) {
435+
if (setting.match(normalizedKey)) {
436+
deprecationInfos.add(
437+
new RepositoryDeprecationInfo(
438+
RepositoryDeprecationInfo.Level.CRITICAL,
439+
"S3 repository explicitly configures a deprecated client setting",
440+
ReferenceDocs.TROUBLESHOOT_REPOSITORY,
441+
deprecatedClientSettingDeprecationWarning(
442+
normalizedKey.substring(S3ClientSettings.REPOSITORY_CLIENT_SETTINGS_PREFIX.length())
443+
),
444+
false
445+
)
446+
);
447+
break;
448+
}
449+
}
450+
}
426451
if (UNSAFELY_INCOMPATIBLE_WITH_S3_CONDITIONAL_WRITES.exists(getMetadata().settings())) {
427452
deprecationInfos.add(
428453
new RepositoryDeprecationInfo(

modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3RepositoryPlugin.java

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import org.elasticsearch.xcontent.NamedXContentRegistry;
3535

3636
import java.io.IOException;
37-
import java.util.Arrays;
3837
import java.util.Collection;
3938
import java.util.Collections;
4039
import java.util.List;
@@ -132,37 +131,7 @@ public Map<String, Repository.Factory> getRepositories(
132131

133132
@Override
134133
public List<Setting<?>> getSettings() {
135-
return Arrays.asList(
136-
// named s3 client configuration settings
137-
S3ClientSettings.ACCESS_KEY_SETTING,
138-
S3ClientSettings.SECRET_KEY_SETTING,
139-
S3ClientSettings.SESSION_TOKEN_SETTING,
140-
S3ClientSettings.ENDPOINT_SETTING,
141-
S3ClientSettings.PROTOCOL_SETTING,
142-
S3ClientSettings.PROXY_HOST_SETTING,
143-
S3ClientSettings.PROXY_PORT_SETTING,
144-
S3ClientSettings.PROXY_SCHEME_SETTING,
145-
S3ClientSettings.PROXY_USERNAME_SETTING,
146-
S3ClientSettings.PROXY_PASSWORD_SETTING,
147-
S3ClientSettings.READ_TIMEOUT_SETTING,
148-
S3ClientSettings.MAX_CONNECTIONS_SETTING,
149-
S3ClientSettings.MAX_RETRIES_SETTING,
150-
S3ClientSettings.API_CALL_TIMEOUT_SETTING,
151-
S3ClientSettings.UNUSED_USE_THROTTLE_RETRIES_SETTING,
152-
S3ClientSettings.USE_PATH_STYLE_ACCESS,
153-
S3ClientSettings.DISABLE_CHUNKED_ENCODING,
154-
S3ClientSettings.UNUSED_SIGNER_OVERRIDE,
155-
S3ClientSettings.ADD_PURPOSE_CUSTOM_QUERY_PARAMETER,
156-
S3ClientSettings.REGION,
157-
S3ClientSettings.CONNECTION_MAX_IDLE_TIME_SETTING,
158-
S3ClientSettings.MAX_COPY_SIZE_BEFORE_MULTIPART,
159-
S3Service.REPOSITORY_S3_CAS_TTL_SETTING,
160-
S3Service.REPOSITORY_S3_CAS_ANTI_CONTENTION_DELAY_SETTING,
161-
S3Repository.ACCESS_KEY_SETTING,
162-
S3Repository.SECRET_KEY_SETTING,
163-
S3ClientSettings.S3_TENACIOUS_RETRIES_ENABLED_SETTING,
164-
S3ClientSettings.ALWAYS_SIGN_REQUESTS
165-
);
134+
return S3RepositorySettings.SETTINGS;
166135
}
167136

168137
@Override
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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.repositories.s3;
11+
12+
import org.elasticsearch.common.settings.Setting;
13+
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
final class S3RepositorySettings {
18+
19+
static final List<Setting<?>> SETTINGS = List.of(
20+
// named s3 client configuration settings
21+
S3ClientSettings.ACCESS_KEY_SETTING,
22+
S3ClientSettings.SECRET_KEY_SETTING,
23+
S3ClientSettings.SESSION_TOKEN_SETTING,
24+
S3ClientSettings.ENDPOINT_SETTING,
25+
S3ClientSettings.PROTOCOL_SETTING,
26+
S3ClientSettings.PROXY_HOST_SETTING,
27+
S3ClientSettings.PROXY_PORT_SETTING,
28+
S3ClientSettings.PROXY_SCHEME_SETTING,
29+
S3ClientSettings.PROXY_USERNAME_SETTING,
30+
S3ClientSettings.PROXY_PASSWORD_SETTING,
31+
S3ClientSettings.READ_TIMEOUT_SETTING,
32+
S3ClientSettings.MAX_CONNECTIONS_SETTING,
33+
S3ClientSettings.MAX_RETRIES_SETTING,
34+
S3ClientSettings.API_CALL_TIMEOUT_SETTING,
35+
S3ClientSettings.UNUSED_USE_THROTTLE_RETRIES_SETTING,
36+
S3ClientSettings.USE_PATH_STYLE_ACCESS,
37+
S3ClientSettings.DISABLE_CHUNKED_ENCODING,
38+
S3ClientSettings.UNUSED_SIGNER_OVERRIDE,
39+
S3ClientSettings.ADD_PURPOSE_CUSTOM_QUERY_PARAMETER,
40+
S3ClientSettings.REGION,
41+
S3ClientSettings.CONNECTION_MAX_IDLE_TIME_SETTING,
42+
S3ClientSettings.MAX_COPY_SIZE_BEFORE_MULTIPART,
43+
S3Service.REPOSITORY_S3_CAS_TTL_SETTING,
44+
S3Service.REPOSITORY_S3_CAS_ANTI_CONTENTION_DELAY_SETTING,
45+
S3Repository.ACCESS_KEY_SETTING,
46+
S3Repository.SECRET_KEY_SETTING,
47+
S3ClientSettings.S3_TENACIOUS_RETRIES_ENABLED_SETTING,
48+
S3ClientSettings.ALWAYS_SIGN_REQUESTS
49+
);
50+
51+
static final List<Setting.AffixSetting<?>> DEPRECATED_CLIENT_SETTINGS = deprecatedClientSettings();
52+
53+
private S3RepositorySettings() {}
54+
55+
private static List<Setting.AffixSetting<?>> deprecatedClientSettings() {
56+
final List<Setting.AffixSetting<?>> deprecatedClientSettings = new ArrayList<>();
57+
for (Setting<?> setting : SETTINGS) {
58+
if (setting instanceof Setting.AffixSetting<?> affixSetting && setting.getProperties().contains(Setting.Property.Deprecated)) {
59+
deprecatedClientSettings.add(affixSetting);
60+
}
61+
}
62+
return List.copyOf(deprecatedClientSettings);
63+
}
64+
}

server/src/main/java/org/elasticsearch/escf/LuceneLongColumn.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.apache.lucene.document.column.LongColumn;
1515
import org.apache.lucene.document.column.LongTupleCursor;
1616
import org.apache.lucene.document.column.LongValuesCursor;
17+
import org.apache.lucene.index.DocValuesType;
1718
import org.apache.lucene.index.IndexableField;
1819
import org.apache.lucene.index.IndexableFieldType;
1920
import org.apache.lucene.util.BytesRef;
@@ -187,6 +188,23 @@ void setDocValue(long v) {
187188
fieldsData = v;
188189
}
189190

191+
@Override
192+
public Number numericValue() {
193+
final long raw = (Long) fieldsData;
194+
// For stored-only fields (no doc values), the indexing chain calls numericValue().floatValue()
195+
// or .doubleValue() to retrieve the actual value. Return the correctly-typed Number so that
196+
// the stored representation matches what StoredField would produce.
197+
if (fieldType().stored() && fieldType().docValuesType() == DocValuesType.NONE) {
198+
return switch (kind) {
199+
case LONG -> raw;
200+
case INT -> (int) raw;
201+
case FLOAT -> NumericUtils.sortableIntToFloat((int) raw);
202+
case DOUBLE -> NumericUtils.sortableLongToDouble(raw);
203+
};
204+
}
205+
return raw;
206+
}
207+
190208
@Override
191209
public BytesRef binaryValue() {
192210
// Consulted by the indexing chain only when fieldType.pointDimensionCount() > 0.

server/src/main/java/org/elasticsearch/escf/NumberColumnTransform.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,25 @@ public static EscfColumnData toHalfFloatPointBinaryColumn(EscfColumn source, Rec
5353
return builder.finish(source.docCount());
5454
}
5555

56+
/**
57+
* Converts a LONG {@link EscfColumn} whose values are
58+
* {@link HalfFloatPoint#halfFloatToSortableShort} encoded sortable shorts into a LONG
59+
* {@link EscfColumnData} containing {@link NumericUtils#floatToSortableInt} encoded sortable ints
60+
* (widened to long). Use the result with a {@link org.elasticsearch.escf.LuceneLongColumn} and
61+
* {@link org.apache.lucene.document.column.LongColumn.NumericKind#FLOAT} to emit the stored-fields
62+
* column for a {@code half_float} field.
63+
*/
64+
public static EscfColumnData toHalfFloatStoredLongColumn(EscfColumn source, Recycler<BytesRef> recycler) {
65+
assert source.kind() == EscfColumnKind.LONG : "expected LONG, got " + EscfColumnKind.name(source.kind());
66+
EscfColumnBuilder builder = newLongBuilder(recycler);
67+
LongTupleCursor cursor = source.longCursor();
68+
for (int doc = cursor.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = cursor.nextDoc()) {
69+
float f = HalfFloatPoint.sortableShortToHalfFloat((short) cursor.longValue());
70+
builder.setLong(doc, NumericUtils.floatToSortableInt(f));
71+
}
72+
return builder.finish(source.docCount());
73+
}
74+
5675
public static EscfColumnData toSortableLongColumn(
5776
EscfColumn source,
5877
NumberFieldMapper.NumberType type,

0 commit comments

Comments
 (0)