Skip to content

Commit

Permalink
Security Audit includes HTTP method for requests (#37322)
Browse files Browse the repository at this point in the history
Adds another field, named "request.method", to the structured logfile audit.
This field is present for all events associated with a REST request (not a
transport request) and the value is one of GET, POST, PUT, DELETE, OPTIONS,
HEAD, PATCH, TRACE and CONNECT.
  • Loading branch information
albertzaharovits committed Jan 13, 2019
1 parent 96cfa00 commit 6fd57d9
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 10 deletions.
3 changes: 3 additions & 0 deletions x-pack/docs/en/security/auditing/event-types.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ common ones):
This is URL encoded.
`url.query` :: The query part of the URL (after "?", if present) of the
REST request associated with this event. This is URL encoded.
`request.method` :: The HTTP method of the REST request associated with this
event. It is one of GET, POST, PUT, DELETE, OPTIONS,
HEAD, PATCH, TRACE and CONNECT.
`request.body` :: The full content of the REST request associated with this
event, if enabled. This contains the query body. The body
is escaped according to the JSON RFC 4627.
Expand Down
3 changes: 1 addition & 2 deletions x-pack/docs/en/security/auditing/output-logfile.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ For more information, see {ref}/logging.html#configuring-logging-levels[configur
[[audit-log-entry-format]]
=== Log entry format

The log entries in the `<clustername>_audit.log` file
have the following format:
The log entries in the `<clustername>_audit.log` file have the following format:

- Each log entry is a one line JSON document and each one is printed on a separate line.
- The fields of a log entry are ordered. However, if a field does not have a value it
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugin/core/src/main/config/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ appender.audit_rolling.layout.pattern = {\
%varsNotEmpty{, "realm":"%enc{%map{realm}}{JSON}"}\
%varsNotEmpty{, "url.path":"%enc{%map{url.path}}{JSON}"}\
%varsNotEmpty{, "url.query":"%enc{%map{url.query}}{JSON}"}\
%varsNotEmpty{, "request.method":"%enc{%map{request.method}}{JSON}"}\
%varsNotEmpty{, "request.body":"%enc{%map{request.body}}{JSON}"}\
%varsNotEmpty{, "request.id":"%enc{%map{request.id}}{JSON}"}\
%varsNotEmpty{, "action":"%enc{%map{action}}{JSON}"}\
Expand Down Expand Up @@ -51,6 +52,7 @@ appender.audit_rolling.layout.pattern = {\
# "realm" name of a realm that has generated an "authentication_failed" or an "authentication_successful"; the subject is not yet authenticated
# "url.path" the URI component between the port and the query string; it is percent (URL) encoded
# "url.query" the URI component after the path and before the fragment; it is percent (URL) encoded
# "request.method" the method of the HTTP request, i.e. one of GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH, TRACE, CONNECT
# "request.body" the content of the request body entity, JSON escaped
# "request.id" a synthentic identifier for the incoming request, this is unique per incoming request, and consistent across all audit events generated by that request
# "action" an action is the most granular operation that is authorized and this identifies it in a namespaced way (internal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
public static final String REALM_FIELD_NAME = "realm";
public static final String URL_PATH_FIELD_NAME = "url.path";
public static final String URL_QUERY_FIELD_NAME = "url.query";
public static final String REQUEST_METHOD_FIELD_NAME = "request.method";
public static final String REQUEST_BODY_FIELD_NAME = "request.body";
public static final String REQUEST_ID_FIELD_NAME = "request.id";
public static final String ACTION_FIELD_NAME = "action";
Expand Down Expand Up @@ -211,7 +212,7 @@ public void authenticationSuccess(String requestId, String realm, User user, Res
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "authentication_success")
.with(REALM_FIELD_NAME, realm)
.withRestUri(request)
.withRestUriAndMethod(request)
.withRequestId(requestId)
.withPrincipal(user)
.withRestOrigin(request)
Expand Down Expand Up @@ -276,7 +277,7 @@ public void anonymousAccessDenied(String requestId, RestRequest request) {
final StringMapMessage logEntry = new LogEntryBuilder()
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
.withRestUri(request)
.withRestUriAndMethod(request)
.withRestOrigin(request)
.withRequestBody(request)
.withRequestId(requestId)
Expand Down Expand Up @@ -316,7 +317,7 @@ public void authenticationFailed(String requestId, RestRequest request) {
final StringMapMessage logEntry = new LogEntryBuilder()
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
.withRestUri(request)
.withRestUriAndMethod(request)
.withRestOrigin(request)
.withRequestBody(request)
.withRequestId(requestId)
Expand Down Expand Up @@ -357,7 +358,7 @@ public void authenticationFailed(String requestId, AuthenticationToken token, Re
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
.with(PRINCIPAL_FIELD_NAME, token.principal())
.withRestUri(request)
.withRestUriAndMethod(request)
.withRestOrigin(request)
.withRequestBody(request)
.withRequestId(requestId)
Expand Down Expand Up @@ -401,7 +402,7 @@ public void authenticationFailed(String requestId, String realm, AuthenticationT
.with(EVENT_ACTION_FIELD_NAME, "realm_authentication_failed")
.with(REALM_FIELD_NAME, realm)
.with(PRINCIPAL_FIELD_NAME, token.principal())
.withRestUri(request)
.withRestUriAndMethod(request)
.withRestOrigin(request)
.withRequestBody(request)
.withRequestId(requestId)
Expand Down Expand Up @@ -468,7 +469,7 @@ public void tamperedRequest(String requestId, RestRequest request) {
final StringMapMessage logEntry = new LogEntryBuilder()
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "tampered_request")
.withRestUri(request)
.withRestUriAndMethod(request)
.withRestOrigin(request)
.withRequestBody(request)
.withRequestId(requestId)
Expand Down Expand Up @@ -617,7 +618,7 @@ public void runAsDenied(String requestId, Authentication authentication, RestReq
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
.with(EVENT_ACTION_FIELD_NAME, "run_as_denied")
.with(PRINCIPAL_ROLES_FIELD_NAME, roleNames)
.withRestUri(request)
.withRestUriAndMethod(request)
.withRunAsSubject(authentication)
.withRestOrigin(request)
.withRequestBody(request)
Expand All @@ -637,7 +638,7 @@ private class LogEntryBuilder {
logEntry = new StringMapMessage(LoggingAuditTrail.this.entryCommonFields.commonFields);
}

LogEntryBuilder withRestUri(RestRequest request) {
LogEntryBuilder withRestUriAndMethod(RestRequest request) {
final int queryStringIndex = request.uri().indexOf('?');
int queryStringLength = request.uri().indexOf('#');
if (queryStringLength < 0) {
Expand All @@ -651,6 +652,7 @@ LogEntryBuilder withRestUri(RestRequest request) {
if (queryStringIndex > -1) {
logEntry.with(URL_QUERY_FIELD_NAME, request.uri().substring(queryStringIndex + 1, queryStringLength));
}
logEntry.with(REQUEST_METHOD_FIELD_NAME, request.method().toString());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ public void testAnonymousAccessDeniedRest() throws Exception {
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
.put(LoggingAuditTrail.ORIGIN_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -346,6 +347,7 @@ public void testAuthenticationFailedRest() throws Exception {
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, mockToken.principal())
.put(LoggingAuditTrail.ORIGIN_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -386,6 +388,7 @@ public void testAuthenticationFailedRestNoToken() throws Exception {
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, null)
.put(LoggingAuditTrail.ORIGIN_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -468,6 +471,7 @@ public void testAuthenticationFailedRealmRest() throws Exception {
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, mockToken.principal())
.put(LoggingAuditTrail.ACTION_FIELD_NAME, null)
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -627,6 +631,7 @@ public void testTamperedRequestRest() throws Exception {
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "tampered_request")
.put(LoggingAuditTrail.ORIGIN_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -891,6 +896,7 @@ public void testAuthenticationSuccessRest() throws Exception {
.put(LoggingAuditTrail.REALM_FIELD_NAME, realm)
.put(LoggingAuditTrail.ORIGIN_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
.put(LoggingAuditTrail.REQUEST_METHOD_FIELD_NAME, request.method().toString())
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
Expand Down Expand Up @@ -1080,6 +1086,7 @@ private Tuple<RestContent, RestRequest> prepareRestContent(String uri, InetSocke
}
builder.withRemoteAddress(remoteAddress);
builder.withParams(params);
builder.withMethod(randomFrom(RestRequest.Method.values()));
return new Tuple<>(content, builder.build());
}

Expand Down

0 comments on commit 6fd57d9

Please sign in to comment.