Skip to content

Commit b7edc9b

Browse files
authored
Handle streaming request body in audit log (#127843)
* Handle streaming request body in audit log The audit event for a successfully-authenticated REST request occurs when we start to process the request. For APIs that accept a streaming request body this means we have received the request headers, but not its body, at the time of the audit event. Today such requests will fail with a `ClassCastException` if the `emit_request_body` flag is set. This change fixes the handling of streaming requests in the audit log to now report that the request body was not available when writing the audit entry. Backport of #127798 to `8.17` * Enable incremental bulks in AuditIT
1 parent 05af256 commit b7edc9b

File tree

3 files changed

+32
-0
lines changed
  • docs/changelog
  • x-pack/plugin/security
    • qa/audit/src/javaRestTest/java/org/elasticsearch/xpack/security/audit
    • src/main/java/org/elasticsearch/xpack/security/audit

3 files changed

+32
-0
lines changed

docs/changelog/127798.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 127798
2+
summary: Handle streaming request body in audit log
3+
area: Audit
4+
type: bug
5+
issues: []

x-pack/plugin/security/qa/audit/src/javaRestTest/java/org/elasticsearch/xpack/security/audit/AuditIT.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
package org.elasticsearch.xpack.security.audit;
99

10+
import org.apache.http.entity.ContentType;
11+
import org.apache.http.entity.StringEntity;
1012
import org.elasticsearch.client.Request;
1113
import org.elasticsearch.client.RequestOptions;
1214
import org.elasticsearch.client.Response;
@@ -29,6 +31,7 @@
2931
import org.junit.ClassRule;
3032

3133
import java.io.IOException;
34+
import java.nio.charset.StandardCharsets;
3235
import java.time.Instant;
3336
import java.time.ZonedDateTime;
3437
import java.time.format.DateTimeFormatter;
@@ -39,6 +42,7 @@
3942
import java.util.concurrent.TimeUnit;
4043
import java.util.function.Predicate;
4144

45+
import static org.hamcrest.Matchers.allOf;
4246
import static org.hamcrest.Matchers.containsString;
4347
import static org.hamcrest.Matchers.hasEntry;
4448
import static org.hamcrest.Matchers.hasKey;
@@ -59,6 +63,7 @@ public class AuditIT extends ESRestTestCase {
5963
.setting("xpack.security.audit.enabled", "true")
6064
.setting("xpack.security.audit.logfile.events.include", "[ \"_all\" ]")
6165
.setting("xpack.security.audit.logfile.events.emit_request_body", "true")
66+
.setting("rest.incremental_bulk", "true")
6267
.user("admin_user", "admin-password")
6368
.user(API_USER, "api-password", "superuser", false)
6469
.build();
@@ -105,6 +110,25 @@ public void testFilteringOfRequestBodies() throws Exception {
105110
});
106111
}
107112

113+
public void testAuditAuthenticationSuccessForStreamingRequest() throws Exception {
114+
final Request request = new Request("POST", "/testindex/_bulk");
115+
request.setEntity(new StringEntity("""
116+
{"index":{}}
117+
{}
118+
""", ContentType.create("application/x-ndjson", StandardCharsets.UTF_8)));
119+
executeAndVerifyAudit(
120+
request,
121+
AuditLevel.AUTHENTICATION_SUCCESS,
122+
event -> assertThat(
123+
event,
124+
allOf(
125+
hasEntry(LoggingAuditTrail.AUTHENTICATION_TYPE_FIELD_NAME, "REALM"),
126+
hasEntry(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME, "Request body had not been received at the time of the audit event")
127+
)
128+
)
129+
);
130+
}
131+
108132
private void executeAndVerifyAudit(Request request, AuditLevel eventType, CheckedConsumer<Map<String, Object>, Exception> assertions)
109133
throws Exception {
110134
Instant start = Instant.now();

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/AuditUtil.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public class AuditUtil {
2727

2828
public static String restRequestContent(RestRequest request) {
2929
if (request.hasContent()) {
30+
if (request.isStreamedContent()) {
31+
return "Request body had not been received at the time of the audit event";
32+
}
3033
try {
3134
return XContentHelper.convertToJson(request.content(), false, false, request.getXContentType());
3235
} catch (IOException ioe) {

0 commit comments

Comments
 (0)