Skip to content

Commit 65c628c

Browse files
committed
Handle streaming request body in audit log (elastic#127798)
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.
1 parent f4ec27e commit 65c628c

File tree

3 files changed

+31
-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

+31
-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: 23 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;
@@ -105,6 +109,25 @@ public void testFilteringOfRequestBodies() throws Exception {
105109
});
106110
}
107111

112+
public void testAuditAuthenticationSuccessForStreamingRequest() throws Exception {
113+
final Request request = new Request("POST", "/testindex/_bulk");
114+
request.setEntity(new StringEntity("""
115+
{"index":{}}
116+
{}
117+
""", ContentType.create("application/x-ndjson", StandardCharsets.UTF_8)));
118+
executeAndVerifyAudit(
119+
request,
120+
AuditLevel.AUTHENTICATION_SUCCESS,
121+
event -> assertThat(
122+
event,
123+
allOf(
124+
hasEntry(LoggingAuditTrail.AUTHENTICATION_TYPE_FIELD_NAME, "REALM"),
125+
hasEntry(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME, "Request body had not been received at the time of the audit event")
126+
)
127+
)
128+
);
129+
}
130+
108131
private void executeAndVerifyAudit(Request request, AuditLevel eventType, CheckedConsumer<Map<String, Object>, Exception> assertions)
109132
throws Exception {
110133
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
var content = request.content();
3134
try {
3235
return XContentHelper.convertToJson(content, false, false, request.getXContentType());

0 commit comments

Comments
 (0)