[Fix] removed null hosts in the audit logs

Some request are created locally by elasticsearch and therefore are not associated with a remote address (we only associate the remote address with a request that arrives remotely from via the transport layer). An example of such request is the periodic nodes info that is collected by elasticsearch. Also, requests that originate from the REST layer also create transport requests locally.

  This commit takes this behaviour into account and makes sure that we'll always log the host in the audit logs. We do that in the following way:

   - `host` is replaced by two attributes: `origin_type` and `origin_address`. `origin_type` can be either `rest`, `remote_node` or `local_node`. `origin_address` holds the host address of the origin
   - when no remote address is associated with the request, it's safe to assume it was created locally. We'll then output `origin_type=[local_node] origin_address=[<the localhost address>]`
   - when a rest request gets in, we'll copy and place its remote address in the context of the request (the context of the rest request is copied to the context of the transport request)
   - . in the audit logs, we'll inspect the transport request and look for a `rest_host` in its context. if we find it, we'll log the log entry under `origin_type=[rest], origin_address=[<the remote rest address>]` attributes. This way, the origin of the request won't get "lost" and we'll still differentiate between transport hosts and rest hosts.
   - if the request is holds a remote address, it can only come from the transport layer, so we'll output "origin_type=[transport] origin_address=[<remote address]"

 While at it, also changed the format of the log entries:

  - lowercased the whole message (e.g. `ANONYMOUS_ACCESS` to `[anonymous_access]` (for consistency sake)
  - introduced layer categorization for every entry to indicate whether its `[transport]`, `[rest]` or `[ip_filter]` related. I reckon this will make it easier to parse the logs if one wishes to do so.

Fixes elastic/elasticsearch#550

Original commit: elastic/x-pack-elasticsearch@b84f0c5548
This commit is contained in:
uboness 2015-01-17 04:47:25 +01:00
parent 98c3531bf9
commit d7d96d866e
4 changed files with 190 additions and 60 deletions

View File

@ -10,19 +10,24 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.audit.AuditTrail;
import org.elasticsearch.shield.authc.AuthenticationToken;
import org.elasticsearch.shield.authz.Privilege;
import org.elasticsearch.shield.rest.RemoteHostHeader;
import org.elasticsearch.shield.transport.filter.ShieldIpFilterRule;
import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.transport.TransportRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
/**
@ -63,15 +68,15 @@ public class LoggingAuditTrail implements AuditTrail {
String indices = indices(message);
if (indices != null) {
if (logger.isDebugEnabled()) {
logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), action, indices, message.getClass().getSimpleName());
logger.debug("{}[transport] [anonymous_access]\t{}, action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message), action, indices, message.getClass().getSimpleName());
} else {
logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), action, indices);
logger.warn("{}[transport] [anonymous_access]\t{}, action=[{}], indices=[{}]", prefix, originAttributes(message), action, indices);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), action, message.getClass().getSimpleName());
logger.debug("{}[transport] [anonymous_access]\t{}, action=[{}], request=[{}]", prefix, originAttributes(message), action, message.getClass().getSimpleName());
} else {
logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}]", prefix, message.remoteAddress(), action);
logger.warn("{}[transport] [anonymous_access]\t{}, action=[{}]", prefix, originAttributes(message), action);
}
}
}
@ -79,9 +84,9 @@ public class LoggingAuditTrail implements AuditTrail {
@Override
public void anonymousAccess(RestRequest request) {
if (logger.isDebugEnabled()) {
logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], URI=[{}], request=[{}]", prefix, request.getRemoteAddress(), request.uri(), restRequestContent(request));
logger.debug("{}[rest] [anonymous_access]\t{}, uri=[{}], request_body=[{}]", prefix, hostAttributes(request), request.uri(), restRequestContent(request));
} else {
logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], URI=[{}]", prefix, request.getRemoteAddress(), request.uri());
logger.warn("{}[rest] [anonymous_access]\t{}, uri=[{}]", prefix, hostAttributes(request), request.uri());
}
}
@ -90,15 +95,15 @@ public class LoggingAuditTrail implements AuditTrail {
String indices = indices(message);
if (indices != null) {
if (logger.isDebugEnabled()) {
logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName());
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message), token.principal(), action, indices, message.getClass().getSimpleName());
} else {
logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), token.principal(), action, indices);
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, originAttributes(message), token.principal(), action, indices);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName());
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message), token.principal(), action, message.getClass().getSimpleName());
} else {
logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), token.principal(), action);
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}]", prefix, originAttributes(message), token.principal(), action);
}
}
}
@ -106,9 +111,9 @@ public class LoggingAuditTrail implements AuditTrail {
@Override
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
if (logger.isDebugEnabled()) {
logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}], request=[{}]", prefix, request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request));
logger.debug("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}], request_body=[{}]", prefix, hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
} else {
logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}]", prefix, request.getRemoteAddress(), token.principal(), request.uri());
logger.error("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}]", prefix, hostAttributes(request), token.principal(), request.uri());
}
}
@ -117,9 +122,9 @@ public class LoggingAuditTrail implements AuditTrail {
if (logger.isTraceEnabled()) {
String indices = indices(message);
if (indices != null) {
logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, realm, message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName());
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, realm, originAttributes(message), token.principal(), action, indices, message.getClass().getSimpleName());
} else {
logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, realm, message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName());
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], request=[{}]", prefix, realm, originAttributes(message), token.principal(), action, message.getClass().getSimpleName());
}
}
}
@ -127,7 +132,7 @@ public class LoggingAuditTrail implements AuditTrail {
@Override
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
if (logger.isTraceEnabled()) {
logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], URI=[{}], request=[{}]", prefix, realm, request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request));
logger.trace("{}[rest] [authentication_failed]\trealm=[{}], {}, principal=[{}], uri=[{}], request_body=[{}]", prefix, realm, hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
}
}
@ -139,9 +144,9 @@ public class LoggingAuditTrail implements AuditTrail {
if (Privilege.SYSTEM.internalActionPredicate().apply(action)) {
if (logger.isTraceEnabled()) {
if (indices != null) {
logger.trace("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName());
logger.trace("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, indices, message.getClass().getSimpleName());
} else {
logger.trace("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName());
logger.trace("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, message.getClass().getSimpleName());
}
}
return;
@ -149,15 +154,15 @@ public class LoggingAuditTrail implements AuditTrail {
if (indices != null) {
if (logger.isDebugEnabled()) {
logger.debug("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName());
logger.debug("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, indices, message.getClass().getSimpleName());
} else {
logger.info("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices);
logger.info("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, originAttributes(message), user.principal(), action, indices);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName());
logger.debug("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, message.getClass().getSimpleName());
} else {
logger.info("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), user.principal(), action);
logger.info("{}[transport] [access_granted]\t{}, principal=[{}], action=[{}]", prefix, originAttributes(message), user.principal(), action);
}
}
}
@ -167,15 +172,15 @@ public class LoggingAuditTrail implements AuditTrail {
String indices = indices(message);
if (indices != null) {
if (logger.isDebugEnabled()) {
logger.debug("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName());
logger.debug("{}[transport] [access_denied]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, indices, message.getClass().getSimpleName());
} else {
logger.error("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices);
logger.error("{}[transport] [access_denied]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, originAttributes(message), user.principal(), action, indices);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName());
logger.debug("{}[transport] [access_denied]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, originAttributes(message), user.principal(), action, message.getClass().getSimpleName());
} else {
logger.error("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), user.principal(), action);
logger.error("{}[transport] [access_denied]\t{}, principal=[{}], action=[{}]", prefix, originAttributes(message), user.principal(), action);
}
}
}
@ -185,15 +190,15 @@ public class LoggingAuditTrail implements AuditTrail {
String indices = indices(request);
if (indices != null) {
if (logger.isDebugEnabled()) {
logger.debug("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices, request.getClass().getSimpleName());
logger.debug("{}[transport] [tampered_request]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices, request.getClass().getSimpleName());
} else {
logger.error("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices);
logger.error("{}[transport] [tampered_request]\t{}, principal=[{}], action=[{}], indices=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, request.getClass().getSimpleName());
logger.debug("{}[transport] [tampered_request]\t{}, principal=[{}], action=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, request.getClass().getSimpleName());
} else {
logger.error("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}]", prefix, request.remoteAddress(), user.principal(), action);
logger.error("{}[transport] [tampered_request]\t{}, principal=[{}], action=[{}]", prefix, request.remoteAddress(), user.principal(), action);
}
}
}
@ -201,13 +206,13 @@ public class LoggingAuditTrail implements AuditTrail {
@Override
public void connectionGranted(InetAddress inetAddress, String profile, ShieldIpFilterRule rule) {
if (logger.isTraceEnabled()) {
logger.trace("{}CONNECTION_GRANTED\thost=[{}], profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule);
logger.trace("{}[ip_filter] [connection_granted]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule);
}
}
@Override
public void connectionDenied(InetAddress inetAddress, String profile, ShieldIpFilterRule rule) {
logger.error("{}CONNECTION_DENIED\thost=[{}], profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule);
logger.error("{}[ip_filter] [connection_denied]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule);
}
private static String indices(TransportMessage message) {
@ -228,6 +233,39 @@ public class LoggingAuditTrail implements AuditTrail {
return "";
}
private static String hostAttributes(RestRequest request) {
return "origin_address=[" + request.getRemoteAddress() + "]";
}
static String originAttributes(TransportMessage message) {
StringBuilder builder = new StringBuilder();
// first checking if the message originated in a rest call
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(message);
if (restAddress != null) {
builder.append("origin_type=[rest], origin_address=[").append(restAddress).append("]");
return builder.toString();
}
// we'll see if was originated in a remote node
TransportAddress address = message.remoteAddress();
if (address != null) {
builder.append("origin_type=[transport], ");
if (address instanceof InetSocketTransportAddress) {
builder.append("origin_address=[").append(((InetSocketTransportAddress) address).address()).append("]");
} else {
builder.append("origin_address=[").append(address).append("]");
}
return builder.toString();
}
// the call was originated locally on this node
return builder.append("origin_type=[local_node], origin_address=[")
.append(NetworkUtils.getLocalHostAddress("_local"))
.append("]")
.toString();
}
static String resolvePrefix(Settings settings) {
StringBuilder builder = new StringBuilder();
if (settings.getAsBoolean("shield.audit.logfile.prefix.node_host_address", false)) {

View File

@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.shield.rest;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.transport.TransportMessage;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
/**
*
*/
public class RemoteHostHeader {
static final String KEY = "_rest_remote_address";
/**
* Extracts the remote address from the given rest request and puts in the request context. This will
* then be copied to the subsequent action requests.
*/
public static void process(RestRequest request) {
request.putInContext(KEY, request.getRemoteAddress());
}
/**
* Extracts the rest remote address from the message context. If not found, returns {@code null}. transport
* messages that were created by rest handlers, should have this in their context.
*/
public static InetSocketAddress restRemoteAddress(TransportMessage message) {
SocketAddress address = message.getFromContext(KEY);
if (address != null && address instanceof InetSocketAddress) {
return (InetSocketAddress) address;
}
return null;
}
public static void putRestRemoteAddress(TransportMessage message, SocketAddress address) {
message.putInContext(KEY, address);
}
}

View File

@ -35,6 +35,8 @@ public class ShieldRestFilter extends RestFilter {
service.authenticate(request);
}
RemoteHostHeader.process(request);
filterChain.continueProcessing(request, channel);
}
}

View File

@ -10,12 +10,16 @@ import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.LocalTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.authc.AuthenticationToken;
import org.elasticsearch.shield.rest.RemoteHostHeader;
import org.elasticsearch.shield.transport.filter.IPFilter;
import org.elasticsearch.shield.transport.filter.ShieldIpFilterRule;
import org.elasticsearch.test.ElasticsearchTestCase;
@ -115,6 +119,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.anonymousAccess("_action", message);
switch (level) {
case ERROR:
@ -123,17 +128,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
case WARN:
case INFO:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2]");
assertMsg(logger, Level.WARN, prefix + "[transport] [anonymous_access]\t" + origins + ", action=[_action], indices=[idx1,idx2]");
} else {
assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action]");
assertMsg(logger, Level.WARN, prefix + "[transport] [anonymous_access]\t" + origins + ", action=[_action]");
}
break;
case DEBUG:
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [anonymous_access]\t" + origins + ", action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], request=[MockMessage]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [anonymous_access]\t" + origins + ", action=[_action], request=[MockMessage]");
}
}
}
@ -156,11 +161,11 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
break;
case WARN:
case INFO:
assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri]");
assertMsg(logger, Level.WARN, prefix + "[rest] [anonymous_access]\torigin_address=[_hostname:9200], uri=[_uri]");
break;
case DEBUG:
case TRACE:
assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri], request=[" + expectedMessage + "]");
assertMsg(logger, Level.DEBUG, prefix + "[rest] [anonymous_access]\torigin_address=[_hostname:9200], uri=[_uri], request_body=[" + expectedMessage + "]");
}
}
}
@ -171,23 +176,24 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.authenticationFailed(new MockToken(), "_action", message);
switch (level) {
case ERROR:
case WARN:
case INFO:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2]");
assertMsg(logger, Level.ERROR, prefix + "[transport] [authentication_failed]\t" + origins + ", principal=[_principal], action=[_action], indices=[idx1,idx2]");
} else {
assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action]");
assertMsg(logger, Level.ERROR, prefix + "[transport] [authentication_failed]\t" + origins + ", principal=[_principal], action=[_action]");
}
break;
case DEBUG:
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [authentication_failed]\t" + origins + ", principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [authentication_failed]\t" + origins + ", principal=[_principal], action=[_action], request=[MockMessage]");
}
}
}
@ -207,11 +213,11 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
case ERROR:
case WARN:
case INFO:
assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri]");
assertMsg(logger, Level.ERROR, prefix + "[rest] [authentication_failed]\torigin_address=[_hostname:9200], principal=[_principal], uri=[_uri]");
break;
case DEBUG:
case TRACE:
assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]");
assertMsg(logger, Level.DEBUG, prefix + "[rest] [authentication_failed]\torigin_address=[_hostname:9200], principal=[_principal], uri=[_uri], request_body=[" + expectedMessage + "]");
}
}
}
@ -222,6 +228,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message);
switch (level) {
case ERROR:
@ -232,9 +239,9 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
break;
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.TRACE, prefix + "[transport] [authentication_failed]\trealm=[_realm], " + origins + ", principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]");
assertMsg(logger, Level.TRACE, prefix + "[transport] [authentication_failed]\trealm=[_realm], " + origins + ", principal=[_principal], action=[_action], request=[MockMessage]");
}
}
}
@ -258,7 +265,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
assertEmptyLog(logger);
break;
case TRACE:
assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]");
assertMsg(logger, Level.TRACE, prefix + "[rest] [authentication_failed]\trealm=[_realm], origin_address=[_hostname:9200], principal=[_principal], uri=[_uri], request_body=[" + expectedMessage + "]");
}
}
}
@ -269,6 +276,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.accessGranted(new User.Simple("_username", "r1"), "_action", message);
switch (level) {
case ERROR:
@ -277,17 +285,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
break;
case INFO:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.INFO, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]");
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[_action], indices=[idx1,idx2]");
} else {
assertMsg(logger, Level.INFO, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action]");
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[_action]");
}
break;
case DEBUG:
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.DEBUG, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.DEBUG, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[_action], request=[MockMessage]");
}
}
}
@ -299,6 +307,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.accessGranted(new User.Simple("_username", "r1"), "internal:_action", message);
switch (level) {
case ERROR:
@ -309,9 +318,9 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
break;
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.TRACE, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.TRACE, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[internal:_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.TRACE, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], request=[MockMessage]");
assertMsg(logger, Level.TRACE, prefix + "[transport] [access_granted]\t" + origins + ", principal=[_username], action=[internal:_action], request=[MockMessage]");
}
}
}
@ -323,23 +332,24 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
CapturingLogger logger = new CapturingLogger(level);
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger);
TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest();
String origins = LoggingAuditTrail.originAttributes(message);
auditTrail.accessDenied(new User.Simple("_username", "r1"), "_action", message);
switch (level) {
case ERROR:
case WARN:
case INFO:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.ERROR, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]");
assertMsg(logger, Level.ERROR, prefix + "[transport] [access_denied]\t" + origins + ", principal=[_username], action=[_action], indices=[idx1,idx2]");
} else {
assertMsg(logger, Level.ERROR, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action]");
assertMsg(logger, Level.ERROR, prefix + "[transport] [access_denied]\t" + origins + ", principal=[_username], action=[_action]");
}
break;
case DEBUG:
case TRACE:
if (message instanceof IndicesRequest) {
assertMsg(logger, Level.DEBUG, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_denied]\t" + origins + ", principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]");
} else {
assertMsg(logger, Level.DEBUG, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]");
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_denied]\t" + origins + ", principal=[_username], action=[_action], request=[MockMessage]");
}
}
}
@ -355,7 +365,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
auditTrail.connectionDenied(inetAddress, "default", rule);
switch (level) {
case ERROR:
assertMsg(logger, Level.ERROR, String.format(Locale.ROOT, prefix + "CONNECTION_DENIED\thost=[%s], profile=[%s], rule=[deny %s]",
assertMsg(logger, Level.ERROR, String.format(Locale.ROOT, prefix + "[ip_filter] [connection_denied]\torigin_address=[%s], transport_profile=[%s], rule=[deny %s]",
inetAddress.getHostAddress(), "default", "_all"));
break;
case WARN:
@ -383,12 +393,34 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
break;
case TRACE:
assertMsg(logger, Level.TRACE, String.format(Locale.ROOT,
prefix + "CONNECTION_GRANTED\thost=[%s], profile=[default], rule=[allow default:accept_all]",
prefix + "[ip_filter] [connection_granted]\torigin_address=[%s], transport_profile=[default], rule=[allow default:accept_all]",
inetAddress.getHostAddress()));
}
}
}
@Test @Repeat(iterations = 10)
public void testOriginAttributes() throws Exception {
MockMessage message = new MockMessage();
String text = LoggingAuditTrail.originAttributes(message);
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(message);
if (restAddress != null) {
assertThat(text, equalTo("origin_type=[rest], origin_address=[" + restAddress + "]"));
return;
}
TransportAddress address = message.remoteAddress();
if (address == null) {
assertThat(text, equalTo("origin_type=[local_node], origin_address=[" + NetworkUtils.getLocalHostAddress("_local") + "]"));
return;
}
if (address instanceof InetSocketTransportAddress) {
assertThat(text, equalTo("origin_type=[transport], origin_address=[" + ((InetSocketTransportAddress) address).address() + "]"));
} else {
assertThat(text, equalTo("origin_type=[transport], origin_address=[" + address + "]"));
}
}
private void assertMsg(CapturingLogger logger, Level msgLevel, String msg) {
List<CapturingLogger.Msg> output = logger.output(msgLevel);
assertThat(output.size(), is(1));
@ -411,14 +443,28 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase {
private static class MockMessage extends TransportMessage<MockMessage> {
private MockMessage() {
remoteAddress(new LocalTransportAddress("_host"));
if (randomBoolean()) {
if (randomBoolean()) {
remoteAddress(new LocalTransportAddress("local_host"));
} else {
remoteAddress(new InetSocketTransportAddress("remote_host", 1234));
}
}
if (randomBoolean()) {
RemoteHostHeader.putRestRemoteAddress(this, InetSocketAddress.createUnresolved("localhost", 1234));
}
}
}
private static class MockIndicesRequest extends TransportMessage<MockIndicesRequest> implements IndicesRequest {
private MockIndicesRequest() {
remoteAddress(new LocalTransportAddress("_host"));
if (randomBoolean()) {
remoteAddress(new LocalTransportAddress("_host"));
}
if (randomBoolean()) {
RemoteHostHeader.putRestRemoteAddress(this, InetSocketAddress.createUnresolved("localhost", 1234));
}
}
@Override