security: make control of logfile audit output consistent with index output
This change moves the logfile audit output from determining what to log based on the logger level to a enum based configuration that is used by the index output. A few notable changes were made: * We alway log all the information we have except for the request body * The request body is no longer logged by default for REST events; the user needs to explicitly opt in as there could be sensitive data in the body * Added a `realm_authentication_failed` event that separates overall authentication failure from that of an individual realm Original commit: elastic/x-pack-elasticsearch@343a2bcdd9
This commit is contained in:
parent
89ce4ebb08
commit
7965608add
|
@ -3,7 +3,7 @@ appender.audit_rolling.name = audit_rolling
|
||||||
appender.audit_rolling.fileName = ${sys:es.logs}_access.log
|
appender.audit_rolling.fileName = ${sys:es.logs}_access.log
|
||||||
appender.audit_rolling.layout.type = PatternLayout
|
appender.audit_rolling.layout.type = PatternLayout
|
||||||
appender.audit_rolling.layout.pattern = [%d{ISO8601}] %m%n
|
appender.audit_rolling.layout.pattern = [%d{ISO8601}] %m%n
|
||||||
appender.audit_rolling.filePattern = ${sys:es.logs}-%d{yyyy-MM-dd}.log
|
appender.audit_rolling.filePattern = ${sys:es.logs}_access-%d{yyyy-MM-dd}.log
|
||||||
appender.audit_rolling.policies.type = Policies
|
appender.audit_rolling.policies.type = Policies
|
||||||
appender.audit_rolling.policies.time.type = TimeBasedTriggeringPolicy
|
appender.audit_rolling.policies.time.type = TimeBasedTriggeringPolicy
|
||||||
appender.audit_rolling.policies.time.interval = 1
|
appender.audit_rolling.policies.time.interval = 1
|
||||||
|
|
|
@ -3,17 +3,18 @@
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.security.audit.index;
|
package org.elasticsearch.xpack.security.audit;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public enum IndexAuditLevel {
|
public enum AuditLevel {
|
||||||
|
|
||||||
ANONYMOUS_ACCESS_DENIED,
|
ANONYMOUS_ACCESS_DENIED,
|
||||||
AUTHENTICATION_FAILED,
|
AUTHENTICATION_FAILED,
|
||||||
|
REALM_AUTHENTICATION_FAILED,
|
||||||
ACCESS_GRANTED,
|
ACCESS_GRANTED,
|
||||||
ACCESS_DENIED,
|
ACCESS_DENIED,
|
||||||
TAMPERED_REQUEST,
|
TAMPERED_REQUEST,
|
||||||
|
@ -23,13 +24,13 @@ public enum IndexAuditLevel {
|
||||||
RUN_AS_GRANTED,
|
RUN_AS_GRANTED,
|
||||||
RUN_AS_DENIED;
|
RUN_AS_DENIED;
|
||||||
|
|
||||||
static EnumSet<IndexAuditLevel> parse(List<String> levels) {
|
static EnumSet<AuditLevel> parse(List<String> levels) {
|
||||||
EnumSet<IndexAuditLevel> enumSet = EnumSet.noneOf(IndexAuditLevel.class);
|
EnumSet<AuditLevel> enumSet = EnumSet.noneOf(AuditLevel.class);
|
||||||
for (String level : levels) {
|
for (String level : levels) {
|
||||||
String lowerCaseLevel = level.trim().toLowerCase(Locale.ROOT);
|
String lowerCaseLevel = level.trim().toLowerCase(Locale.ROOT);
|
||||||
switch (lowerCaseLevel) {
|
switch (lowerCaseLevel) {
|
||||||
case "_all":
|
case "_all":
|
||||||
enumSet.addAll(Arrays.asList(IndexAuditLevel.values()));
|
enumSet.addAll(Arrays.asList(AuditLevel.values()));
|
||||||
break;
|
break;
|
||||||
case "anonymous_access_denied":
|
case "anonymous_access_denied":
|
||||||
enumSet.add(ANONYMOUS_ACCESS_DENIED);
|
enumSet.add(ANONYMOUS_ACCESS_DENIED);
|
||||||
|
@ -37,6 +38,9 @@ public enum IndexAuditLevel {
|
||||||
case "authentication_failed":
|
case "authentication_failed":
|
||||||
enumSet.add(AUTHENTICATION_FAILED);
|
enumSet.add(AUTHENTICATION_FAILED);
|
||||||
break;
|
break;
|
||||||
|
case "realm_authentication_failed":
|
||||||
|
enumSet.add(REALM_AUTHENTICATION_FAILED);
|
||||||
|
break;
|
||||||
case "access_granted":
|
case "access_granted":
|
||||||
enumSet.add(ACCESS_GRANTED);
|
enumSet.add(ACCESS_GRANTED);
|
||||||
break;
|
break;
|
||||||
|
@ -68,9 +72,9 @@ public enum IndexAuditLevel {
|
||||||
return enumSet;
|
return enumSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EnumSet<IndexAuditLevel> parse(List<String> includeLevels, List<String> excludeLevels) {
|
public static EnumSet<AuditLevel> parse(List<String> includeLevels, List<String> excludeLevels) {
|
||||||
EnumSet<IndexAuditLevel> included = parse(includeLevels);
|
EnumSet<AuditLevel> included = parse(includeLevels);
|
||||||
EnumSet<IndexAuditLevel> excluded = parse(excludeLevels);
|
EnumSet<AuditLevel> excluded = parse(excludeLevels);
|
||||||
included.removeAll(excluded);
|
included.removeAll(excluded);
|
||||||
return included;
|
return included;
|
||||||
}
|
}
|
|
@ -51,6 +51,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.transport.TransportMessage;
|
import org.elasticsearch.transport.TransportMessage;
|
||||||
import org.elasticsearch.xpack.XPackPlugin;
|
import org.elasticsearch.xpack.XPackPlugin;
|
||||||
import org.elasticsearch.xpack.security.InternalClient;
|
import org.elasticsearch.xpack.security.InternalClient;
|
||||||
|
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||||
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
||||||
|
@ -85,19 +86,20 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.elasticsearch.xpack.security.Security.setting;
|
import static org.elasticsearch.xpack.security.Security.setting;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.REALM_AUTHENTICATION_FAILED;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
|
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
|
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.ACCESS_DENIED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_DENIED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.ACCESS_GRANTED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_GRANTED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.ANONYMOUS_ACCESS_DENIED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ANONYMOUS_ACCESS_DENIED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.AUTHENTICATION_FAILED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.AUTHENTICATION_FAILED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.CONNECTION_DENIED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.CONNECTION_DENIED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.CONNECTION_GRANTED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.CONNECTION_GRANTED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.RUN_AS_DENIED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.RUN_AS_DENIED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.RUN_AS_GRANTED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.RUN_AS_GRANTED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.SYSTEM_ACCESS_GRANTED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.SYSTEM_ACCESS_GRANTED;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.TAMPERED_REQUEST;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.TAMPERED_REQUEST;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexAuditLevel.parse;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.parse;
|
||||||
import static org.elasticsearch.xpack.security.audit.index.IndexNameResolver.resolve;
|
import static org.elasticsearch.xpack.security.audit.index.IndexNameResolver.resolve;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,27 +107,30 @@ import static org.elasticsearch.xpack.security.audit.index.IndexNameResolver.res
|
||||||
*/
|
*/
|
||||||
public class IndexAuditTrail extends AbstractComponent implements AuditTrail, ClusterStateListener {
|
public class IndexAuditTrail extends AbstractComponent implements AuditTrail, ClusterStateListener {
|
||||||
|
|
||||||
public static final int DEFAULT_BULK_SIZE = 1000;
|
|
||||||
public static final int MAX_BULK_SIZE = 10000;
|
|
||||||
public static final int DEFAULT_MAX_QUEUE_SIZE = 1000;
|
|
||||||
public static final TimeValue DEFAULT_FLUSH_INTERVAL = TimeValue.timeValueSeconds(1);
|
|
||||||
public static final IndexNameResolver.Rollover DEFAULT_ROLLOVER = IndexNameResolver.Rollover.DAILY;
|
|
||||||
public static final String NAME = "index";
|
public static final String NAME = "index";
|
||||||
public static final String INDEX_NAME_PREFIX = ".security_audit_log";
|
public static final String INDEX_NAME_PREFIX = ".security_audit_log";
|
||||||
public static final String DOC_TYPE = "event";
|
public static final String DOC_TYPE = "event";
|
||||||
public static final Setting<IndexNameResolver.Rollover> ROLLOVER_SETTING =
|
public static final String INDEX_TEMPLATE_NAME = "security_audit_log";
|
||||||
|
|
||||||
|
private static final int DEFAULT_BULK_SIZE = 1000;
|
||||||
|
private static final int MAX_BULK_SIZE = 10000;
|
||||||
|
private static final int DEFAULT_MAX_QUEUE_SIZE = 1000;
|
||||||
|
private static final TimeValue DEFAULT_FLUSH_INTERVAL = TimeValue.timeValueSeconds(1);
|
||||||
|
private static final IndexNameResolver.Rollover DEFAULT_ROLLOVER = IndexNameResolver.Rollover.DAILY;
|
||||||
|
private static final Setting<IndexNameResolver.Rollover> ROLLOVER_SETTING =
|
||||||
new Setting<>(setting("audit.index.rollover"), (s) -> DEFAULT_ROLLOVER.name(),
|
new Setting<>(setting("audit.index.rollover"), (s) -> DEFAULT_ROLLOVER.name(),
|
||||||
s -> IndexNameResolver.Rollover.valueOf(s.toUpperCase(Locale.ENGLISH)), Property.NodeScope);
|
s -> IndexNameResolver.Rollover.valueOf(s.toUpperCase(Locale.ENGLISH)), Property.NodeScope);
|
||||||
public static final Setting<Integer> QUEUE_SIZE_SETTING =
|
private static final Setting<Integer> QUEUE_SIZE_SETTING =
|
||||||
Setting.intSetting(setting("audit.index.queue_max_size"), DEFAULT_MAX_QUEUE_SIZE, 1, Property.NodeScope);
|
Setting.intSetting(setting("audit.index.queue_max_size"), DEFAULT_MAX_QUEUE_SIZE, 1, Property.NodeScope);
|
||||||
public static final String INDEX_TEMPLATE_NAME = "security_audit_log";
|
private static final String DEFAULT_CLIENT_NAME = "security-audit-client";
|
||||||
public static final String DEFAULT_CLIENT_NAME = "security-audit-client";
|
|
||||||
|
|
||||||
static final List<String> DEFAULT_EVENT_INCLUDES = Arrays.asList(
|
private static final List<String> DEFAULT_EVENT_INCLUDES = Arrays.asList(
|
||||||
ACCESS_DENIED.toString(),
|
ACCESS_DENIED.toString(),
|
||||||
ACCESS_GRANTED.toString(),
|
ACCESS_GRANTED.toString(),
|
||||||
ANONYMOUS_ACCESS_DENIED.toString(),
|
ANONYMOUS_ACCESS_DENIED.toString(),
|
||||||
AUTHENTICATION_FAILED.toString(),
|
AUTHENTICATION_FAILED.toString(),
|
||||||
|
REALM_AUTHENTICATION_FAILED.toString(),
|
||||||
CONNECTION_DENIED.toString(),
|
CONNECTION_DENIED.toString(),
|
||||||
CONNECTION_GRANTED.toString(),
|
CONNECTION_GRANTED.toString(),
|
||||||
TAMPERED_REQUEST.toString(),
|
TAMPERED_REQUEST.toString(),
|
||||||
|
@ -134,23 +139,24 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
);
|
);
|
||||||
private static final String FORBIDDEN_INDEX_SETTING = "index.mapper.dynamic";
|
private static final String FORBIDDEN_INDEX_SETTING = "index.mapper.dynamic";
|
||||||
|
|
||||||
public static final Setting<Settings> INDEX_SETTINGS =
|
private static final Setting<Settings> INDEX_SETTINGS =
|
||||||
Setting.groupSetting(setting("audit.index.settings.index."), Property.NodeScope);
|
Setting.groupSetting(setting("audit.index.settings.index."), Property.NodeScope);
|
||||||
public static final Setting<List<String>> INCLUDE_EVENT_SETTINGS =
|
private static final Setting<List<String>> INCLUDE_EVENT_SETTINGS =
|
||||||
Setting.listSetting(setting("audit.index.events.include"), DEFAULT_EVENT_INCLUDES, Function.identity(),
|
Setting.listSetting(setting("audit.index.events.include"), DEFAULT_EVENT_INCLUDES, Function.identity(),
|
||||||
Property.NodeScope);
|
Property.NodeScope);
|
||||||
public static final Setting<List<String>> EXCLUDE_EVENT_SETTINGS =
|
private static final Setting<List<String>> EXCLUDE_EVENT_SETTINGS =
|
||||||
Setting.listSetting(setting("audit.index.events.exclude"), Collections.emptyList(),
|
Setting.listSetting(setting("audit.index.events.exclude"), Collections.emptyList(),
|
||||||
Function.identity(), Property.NodeScope);
|
Function.identity(), Property.NodeScope);
|
||||||
public static final Setting<Settings> REMOTE_CLIENT_SETTINGS =
|
private static final Setting<Boolean> INCLUDE_REQUEST_BODY =
|
||||||
|
Setting.boolSetting(setting("audit.index.events.emit_request_body"), false, Property.NodeScope);
|
||||||
|
private static final Setting<Settings> REMOTE_CLIENT_SETTINGS =
|
||||||
Setting.groupSetting(setting("audit.index.client."), Property.NodeScope);
|
Setting.groupSetting(setting("audit.index.client."), Property.NodeScope);
|
||||||
public static final Setting<Integer> BULK_SIZE_SETTING =
|
private static final Setting<Integer> BULK_SIZE_SETTING =
|
||||||
Setting.intSetting(setting("audit.index.bulk_size"), DEFAULT_BULK_SIZE, 1, MAX_BULK_SIZE, Property.NodeScope);
|
Setting.intSetting(setting("audit.index.bulk_size"), DEFAULT_BULK_SIZE, 1, MAX_BULK_SIZE, Property.NodeScope);
|
||||||
public static final Setting<TimeValue> FLUSH_TIMEOUT_SETTING =
|
private static final Setting<TimeValue> FLUSH_TIMEOUT_SETTING =
|
||||||
Setting.timeSetting(setting("audit.index.flush_interval"), DEFAULT_FLUSH_INTERVAL,
|
Setting.timeSetting(setting("audit.index.flush_interval"), DEFAULT_FLUSH_INTERVAL,
|
||||||
TimeValue.timeValueMillis(1L), Property.NodeScope);
|
TimeValue.timeValueMillis(1L), Property.NodeScope);
|
||||||
|
|
||||||
|
|
||||||
private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
|
private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
|
||||||
private final String nodeName;
|
private final String nodeName;
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
@ -160,12 +166,13 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
private final Lock putMappingLock = new ReentrantLock();
|
private final Lock putMappingLock = new ReentrantLock();
|
||||||
private final ClusterService clusterService;
|
private final ClusterService clusterService;
|
||||||
private final boolean indexToRemoteCluster;
|
private final boolean indexToRemoteCluster;
|
||||||
|
private final EnumSet<AuditLevel> events;
|
||||||
|
private final IndexNameResolver.Rollover rollover;
|
||||||
|
private final boolean includeRequestBody;
|
||||||
|
|
||||||
private BulkProcessor bulkProcessor;
|
private BulkProcessor bulkProcessor;
|
||||||
private IndexNameResolver.Rollover rollover;
|
|
||||||
private String nodeHostName;
|
private String nodeHostName;
|
||||||
private String nodeHostAddress;
|
private String nodeHostAddress;
|
||||||
private EnumSet<IndexAuditLevel> events;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public String name() {
|
||||||
|
@ -180,25 +187,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
this.queueConsumer = new QueueConsumer(EsExecutors.threadName(settings, "audit-queue-consumer"));
|
this.queueConsumer = new QueueConsumer(EsExecutors.threadName(settings, "audit-queue-consumer"));
|
||||||
int maxQueueSize = QUEUE_SIZE_SETTING.get(settings);
|
int maxQueueSize = QUEUE_SIZE_SETTING.get(settings);
|
||||||
this.eventQueue = createQueue(maxQueueSize);
|
this.eventQueue = createQueue(maxQueueSize);
|
||||||
|
this.rollover = ROLLOVER_SETTING.get(settings);
|
||||||
// we have to initialize this here since we use rollover in determining if we can start...
|
this.events = parse(INCLUDE_EVENT_SETTINGS.get(settings), EXCLUDE_EVENT_SETTINGS.get(settings));
|
||||||
rollover = ROLLOVER_SETTING.get(settings);
|
|
||||||
|
|
||||||
// we have to initialize the events here since we can receive events before starting...
|
|
||||||
List<String> includedEvents = INCLUDE_EVENT_SETTINGS.get(settings);
|
|
||||||
List<String> excludedEvents = EXCLUDE_EVENT_SETTINGS.get(settings);
|
|
||||||
try {
|
|
||||||
events = parse(includedEvents, excludedEvents);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
logger.warn(
|
|
||||||
(Supplier<?>) () -> new ParameterizedMessage(
|
|
||||||
"invalid event type specified, using default for audit index output. include events [{}], exclude events [{}]",
|
|
||||||
includedEvents,
|
|
||||||
excludedEvents),
|
|
||||||
e);
|
|
||||||
events = parse(DEFAULT_EVENT_INCLUDES, Collections.emptyList());
|
|
||||||
}
|
|
||||||
this.indexToRemoteCluster = REMOTE_CLIENT_SETTINGS.get(settings).names().size() > 0;
|
this.indexToRemoteCluster = REMOTE_CLIENT_SETTINGS.get(settings).names().size() > 0;
|
||||||
|
this.includeRequestBody = INCLUDE_REQUEST_BODY.get(settings);
|
||||||
|
|
||||||
if (indexToRemoteCluster == false) {
|
if (indexToRemoteCluster == false) {
|
||||||
// in the absence of client settings for remote indexing, fall back to the client that was passed in.
|
// in the absence of client settings for remote indexing, fall back to the client that was passed in.
|
||||||
|
@ -391,7 +383,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||||
if (XPackUser.is(token.principal()) == false) {
|
if (XPackUser.is(token.principal()) == false) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("authentication_failed", action, token, realm, indices(message), message), "authentication_failed");
|
enqueue(message("authentication_failed", action, token, realm, indices(message), message), "authentication_failed");
|
||||||
|
@ -404,7 +396,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
||||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||||
if (XPackUser.is(token.principal()) == false) {
|
if (XPackUser.is(token.principal()) == false) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("authentication_failed", null, token, realm, null, request), "authentication_failed");
|
enqueue(message("authentication_failed", null, token, realm, null, request), "authentication_failed");
|
||||||
|
@ -610,7 +602,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
msg.builder.array(Field.INDICES, indices.toArray(Strings.EMPTY_ARRAY));
|
msg.builder.array(Field.INDICES, indices.toArray(Strings.EMPTY_ARRAY));
|
||||||
}
|
}
|
||||||
|
if (includeRequestBody) {
|
||||||
msg.builder.field(Field.REQUEST_BODY, restRequestContent(request));
|
msg.builder.field(Field.REQUEST_BODY, restRequestContent(request));
|
||||||
|
}
|
||||||
msg.builder.field(Field.ORIGIN_TYPE, "rest");
|
msg.builder.field(Field.ORIGIN_TYPE, "rest");
|
||||||
SocketAddress address = request.getRemoteAddress();
|
SocketAddress address = request.getRemoteAddress();
|
||||||
if (address instanceof InetSocketAddress) {
|
if (address instanceof InetSocketAddress) {
|
||||||
|
@ -630,7 +624,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
common("rest", type, msg.builder);
|
common("rest", type, msg.builder);
|
||||||
|
|
||||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||||
|
if (includeRequestBody) {
|
||||||
msg.builder.field(Field.REQUEST_BODY, restRequestContent(request));
|
msg.builder.field(Field.REQUEST_BODY, restRequestContent(request));
|
||||||
|
}
|
||||||
msg.builder.field(Field.ORIGIN_TYPE, "rest");
|
msg.builder.field(Field.ORIGIN_TYPE, "rest");
|
||||||
SocketAddress address = request.getRemoteAddress();
|
SocketAddress address = request.getRemoteAddress();
|
||||||
if (address instanceof InetSocketAddress) {
|
if (address instanceof InetSocketAddress) {
|
||||||
|
@ -905,6 +901,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
|
||||||
settings.add(FLUSH_TIMEOUT_SETTING);
|
settings.add(FLUSH_TIMEOUT_SETTING);
|
||||||
settings.add(QUEUE_SIZE_SETTING);
|
settings.add(QUEUE_SIZE_SETTING);
|
||||||
settings.add(REMOTE_CLIENT_SETTINGS);
|
settings.add(REMOTE_CLIENT_SETTINGS);
|
||||||
|
settings.add(INCLUDE_REQUEST_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class QueueConsumer extends Thread {
|
private class QueueConsumer extends Thread {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.rest.RestRequest;
|
import org.elasticsearch.rest.RestRequest;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.transport.TransportMessage;
|
import org.elasticsearch.transport.TransportMessage;
|
||||||
|
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||||
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
||||||
|
@ -32,11 +33,27 @@ import org.elasticsearch.xpack.security.user.XPackUser;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString;
|
import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString;
|
||||||
import static org.elasticsearch.xpack.security.Security.setting;
|
import static org.elasticsearch.xpack.security.Security.setting;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_DENIED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_GRANTED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ANONYMOUS_ACCESS_DENIED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.AUTHENTICATION_FAILED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.REALM_AUTHENTICATION_FAILED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.CONNECTION_DENIED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.CONNECTION_GRANTED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.RUN_AS_DENIED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.RUN_AS_GRANTED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.SYSTEM_ACCESS_GRANTED;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.TAMPERED_REQUEST;
|
||||||
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.parse;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
|
import static org.elasticsearch.xpack.security.audit.AuditUtil.indices;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
|
import static org.elasticsearch.xpack.security.audit.AuditUtil.restRequestContent;
|
||||||
|
|
||||||
|
@ -52,10 +69,28 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
Setting.boolSetting(setting("audit.logfile.prefix.emit_node_host_name"), false, Property.NodeScope);
|
Setting.boolSetting(setting("audit.logfile.prefix.emit_node_host_name"), false, Property.NodeScope);
|
||||||
public static final Setting<Boolean> NODE_NAME_SETTING =
|
public static final Setting<Boolean> NODE_NAME_SETTING =
|
||||||
Setting.boolSetting(setting("audit.logfile.prefix.emit_node_name"), true, Property.NodeScope);
|
Setting.boolSetting(setting("audit.logfile.prefix.emit_node_name"), true, Property.NodeScope);
|
||||||
|
private static final List<String> DEFAULT_EVENT_INCLUDES = Arrays.asList(
|
||||||
|
ACCESS_DENIED.toString(),
|
||||||
|
ACCESS_GRANTED.toString(),
|
||||||
|
ANONYMOUS_ACCESS_DENIED.toString(),
|
||||||
|
AUTHENTICATION_FAILED.toString(),
|
||||||
|
CONNECTION_DENIED.toString(),
|
||||||
|
TAMPERED_REQUEST.toString(),
|
||||||
|
RUN_AS_DENIED.toString(),
|
||||||
|
RUN_AS_GRANTED.toString()
|
||||||
|
);
|
||||||
|
private static final Setting<List<String>> INCLUDE_EVENT_SETTINGS =
|
||||||
|
Setting.listSetting(setting("audit.logfile.events.include"), DEFAULT_EVENT_INCLUDES, Function.identity(), Property.NodeScope);
|
||||||
|
private static final Setting<List<String>> EXCLUDE_EVENT_SETTINGS =
|
||||||
|
Setting.listSetting(setting("audit.logfile.events.exclude"), Collections.emptyList(), Function.identity(), Property.NodeScope);
|
||||||
|
private static final Setting<Boolean> INCLUDE_REQUEST_BODY =
|
||||||
|
Setting.boolSetting(setting("audit.logfile.events.emit_request_body"), false, Property.NodeScope);
|
||||||
|
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final ClusterService clusterService;
|
private final ClusterService clusterService;
|
||||||
private final ThreadContext threadContext;
|
private final ThreadContext threadContext;
|
||||||
|
private final EnumSet<AuditLevel> events;
|
||||||
|
private final boolean includeRequestBody;
|
||||||
|
|
||||||
private String prefix;
|
private String prefix;
|
||||||
|
|
||||||
|
@ -73,6 +108,8 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.clusterService = clusterService;
|
this.clusterService = clusterService;
|
||||||
this.threadContext = threadContext;
|
this.threadContext = threadContext;
|
||||||
|
this.events = parse(INCLUDE_EVENT_SETTINGS.get(settings), EXCLUDE_EVENT_SETTINGS.get(settings));
|
||||||
|
this.includeRequestBody = INCLUDE_REQUEST_BODY.get(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPrefix() {
|
private String getPrefix() {
|
||||||
|
@ -84,115 +121,98 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void anonymousAccessDenied(String action, TransportMessage message) {
|
public void anonymousAccessDenied(String action, TransportMessage message) {
|
||||||
|
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [anonymous_access_denied]\t{}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [anonymous_access_denied]\t{}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, message.getClass().getSimpleName());
|
originAttributes(message, clusterService.localNode(), threadContext), action, message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.warn("{}[transport] [anonymous_access_denied]\t{}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void anonymousAccessDenied(RestRequest request) {
|
public void anonymousAccessDenied(RestRequest request) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||||
logger.debug("{}[rest] [anonymous_access_denied]\t{}, uri=[{}], request_body=[{}]", getPrefix(),
|
if (includeRequestBody) {
|
||||||
|
logger.info("{}[rest] [anonymous_access_denied]\t{}, uri=[{}], request_body=[{}]", getPrefix(),
|
||||||
hostAttributes(request), request.uri(), restRequestContent(request));
|
hostAttributes(request), request.uri(), restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.warn("{}[rest] [anonymous_access_denied]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
logger.info("{}[rest] [anonymous_access_denied]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
|
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
|
||||||
|
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}], request=[{}]",
|
|
||||||
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), token.principal(),
|
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), token.principal(),
|
||||||
action, indices, message.getClass().getSimpleName());
|
action, indices, message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), token.principal(), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), token.principal(), action,
|
originAttributes(message, clusterService.localNode(), threadContext), token.principal(), action,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.error("{}[transport] [authentication_failed]\t{}, principal=[{}], action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), token.principal(), action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(RestRequest request) {
|
public void authenticationFailed(RestRequest request) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||||
logger.debug("{}[rest] [authentication_failed]\t{}, uri=[{}], request_body=[{}]", getPrefix(), hostAttributes(request),
|
if (includeRequestBody) {
|
||||||
|
logger.info("{}[rest] [authentication_failed]\t{}, uri=[{}], request_body=[{}]", getPrefix(), hostAttributes(request),
|
||||||
request.uri(), restRequestContent(request));
|
request.uri(), restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[rest] [authentication_failed]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
logger.info("{}[rest] [authentication_failed]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(String action, TransportMessage message) {
|
public void authenticationFailed(String action, TransportMessage message) {
|
||||||
|
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [authentication_failed]\t{}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [authentication_failed]\t{}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, message.getClass().getSimpleName());
|
originAttributes(message, clusterService.localNode(), threadContext), action, message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.error("{}[transport] [authentication_failed]\t{}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
|
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||||
logger.debug("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}], request_body=[{}]", getPrefix(),
|
if (includeRequestBody) {
|
||||||
|
logger.info("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}], request_body=[{}]", getPrefix(),
|
||||||
hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
|
hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}]", getPrefix(), hostAttributes(request),
|
logger.info("{}[rest] [authentication_failed]\t{}, principal=[{}], uri=[{}]", getPrefix(), hostAttributes(request),
|
||||||
token.principal(), request.uri());
|
token.principal(), request.uri());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], indices=[{}], " +
|
logger.info("{}[transport] [realm_authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], indices=[{}], " +
|
||||||
"request=[{}]", getPrefix(), realm, originAttributes(message, clusterService.localNode(), threadContext),
|
"request=[{}]", getPrefix(), realm, originAttributes(message, clusterService.localNode(), threadContext),
|
||||||
token.principal(), action, indices, message.getClass().getSimpleName());
|
token.principal(), action, indices, message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.trace("{}[transport] [authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], request=[{}]",
|
logger.info("{}[transport] [realm_authentication_failed]\trealm=[{}], {}, principal=[{}], action=[{}], request=[{}]",
|
||||||
getPrefix(), realm, originAttributes(message, clusterService.localNode(), threadContext), token.principal(),
|
getPrefix(), realm, originAttributes(message, clusterService.localNode(), threadContext), token.principal(),
|
||||||
action, message.getClass().getSimpleName());
|
action, message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -201,185 +221,142 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||||
logger.trace("{}[rest] [authentication_failed]\trealm=[{}], {}, principal=[{}], uri=[{}], request_body=[{}]", getPrefix(),
|
if (includeRequestBody) {
|
||||||
realm, hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
|
logger.info("{}[rest] [realm_authentication_failed]\trealm=[{}], {}, principal=[{}], uri=[{}], request_body=[{}]",
|
||||||
|
getPrefix(), realm, hostAttributes(request), token.principal(), request.uri(), restRequestContent(request));
|
||||||
|
} else {
|
||||||
|
logger.info("{}[rest] [realm_authentication_failed]\trealm=[{}], {}, principal=[{}], uri=[{}]", getPrefix(),
|
||||||
|
realm, hostAttributes(request), token.principal(), request.uri());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessGranted(User user, String action, TransportMessage message) {
|
public void accessGranted(User user, String action, TransportMessage message) {
|
||||||
|
final boolean isSystem = (SystemUser.is(user) && SystemPrivilege.INSTANCE.predicate().test(action)) || XPackUser.is(user);
|
||||||
|
final boolean logSystemAccessGranted = isSystem && events.contains(SYSTEM_ACCESS_GRANTED);
|
||||||
|
final boolean shouldLog = logSystemAccessGranted || (isSystem == false && events.contains(ACCESS_GRANTED));
|
||||||
|
if (shouldLog) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
|
|
||||||
// special treatment for internal system actions - only log on trace
|
|
||||||
if ((SystemUser.is(user) && SystemPrivilege.INSTANCE.predicate().test(action)) || XPackUser.is(user)) {
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices,
|
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.trace("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action,
|
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices != null) {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices,
|
|
||||||
message.getClass().getSimpleName());
|
|
||||||
} else {
|
|
||||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action,
|
|
||||||
message.getClass().getSimpleName());
|
|
||||||
} else {
|
|
||||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessDenied(User user, String action, TransportMessage message) {
|
public void accessDenied(User user, String action, TransportMessage message) {
|
||||||
|
if (events.contains(ACCESS_DENIED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices,
|
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [access_denied]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [access_denied]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action,
|
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.error("{}[transport] [access_denied]\t{}, {}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), principal(user), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tamperedRequest(RestRequest request) {
|
public void tamperedRequest(RestRequest request) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(TAMPERED_REQUEST)) {
|
||||||
logger.debug("{}[rest] [tampered_request]\t{}, uri=[{}], request_body=[{}]", getPrefix(), hostAttributes(request),
|
if (includeRequestBody) {
|
||||||
|
logger.info("{}[rest] [tampered_request]\t{}, uri=[{}], request_body=[{}]", getPrefix(), hostAttributes(request),
|
||||||
request.uri(), restRequestContent(request));
|
request.uri(), restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[rest] [tampered_request]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
logger.info("{}[rest] [tampered_request]\t{}, uri=[{}]", getPrefix(), hostAttributes(request), request.uri());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tamperedRequest(String action, TransportMessage message) {
|
public void tamperedRequest(String action, TransportMessage message) {
|
||||||
|
if (events.contains(TAMPERED_REQUEST)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
originAttributes(message, clusterService.localNode(), threadContext), action, indices,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [tampered_request]\t{}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [tampered_request]\t{}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action,
|
originAttributes(message, clusterService.localNode(), threadContext), action,
|
||||||
message.getClass().getSimpleName());
|
message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.error("{}[transport] [tampered_request]\t{}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tamperedRequest(User user, String action, TransportMessage request) {
|
public void tamperedRequest(User user, String action, TransportMessage request) {
|
||||||
|
if (events.contains(TAMPERED_REQUEST)) {
|
||||||
String indices = indicesString(request);
|
String indices = indicesString(request);
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
||||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action, indices,
|
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action, indices,
|
||||||
request.getClass().getSimpleName());
|
request.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}], indices=[{}]", getPrefix(),
|
logger.info("{}[transport] [tampered_request]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
||||||
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action, indices);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("{}[transport] [tampered_request]\t{}, {}, action=[{}], request=[{}]", getPrefix(),
|
|
||||||
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action,
|
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action,
|
||||||
request.getClass().getSimpleName());
|
request.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.error("{}[transport] [tampered_request]\t{}, {}, action=[{}]", getPrefix(),
|
|
||||||
originAttributes(request, clusterService.localNode(), threadContext), principal(user), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
|
public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (events.contains(CONNECTION_GRANTED)) {
|
||||||
logger.trace("{}[ip_filter] [connection_granted]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", getPrefix(),
|
logger.info("{}[ip_filter] [connection_granted]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", getPrefix(),
|
||||||
NetworkAddress.format(inetAddress), profile, rule);
|
NetworkAddress.format(inetAddress), profile, rule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
|
public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
|
||||||
logger.error("{}[ip_filter] [connection_denied]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", getPrefix(),
|
if (events.contains(CONNECTION_DENIED)) {
|
||||||
|
logger.info("{}[ip_filter] [connection_denied]\torigin_address=[{}], transport_profile=[{}], rule=[{}]", getPrefix(),
|
||||||
NetworkAddress.format(inetAddress), profile, rule);
|
NetworkAddress.format(inetAddress), profile, rule);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsGranted(User user, String action, TransportMessage message) {
|
public void runAsGranted(User user, String action, TransportMessage message) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(RUN_AS_GRANTED)) {
|
||||||
logger.debug("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
||||||
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
||||||
user.runAs().principal(), action, message.getClass().getSimpleName());
|
user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
|
||||||
user.runAs().principal(), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, String action, TransportMessage message) {
|
public void runAsDenied(User user, String action, TransportMessage message) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
logger.debug("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
||||||
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
getPrefix(), originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
||||||
user.runAs().principal(), action, message.getClass().getSimpleName());
|
user.runAs().principal(), action, message.getClass().getSimpleName());
|
||||||
} else {
|
|
||||||
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}]", getPrefix(),
|
|
||||||
originAttributes(message, clusterService.localNode(), threadContext), user.principal(),
|
|
||||||
user.runAs().principal(), action);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, RestRequest request) {
|
public void runAsDenied(User user, RestRequest request) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
logger.debug("{}[rest] [run_as_denied]\t{}, principal=[{}], uri=[{}], request_body=[{}]", getPrefix(),
|
if (includeRequestBody) {
|
||||||
|
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], uri=[{}], request_body=[{}]", getPrefix(),
|
||||||
hostAttributes(request), user.principal(), request.uri(), restRequestContent(request));
|
hostAttributes(request), user.principal(), request.uri(), restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], uri=[{}]", getPrefix(),
|
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], uri=[{}]", getPrefix(),
|
||||||
hostAttributes(request), user.principal(), request.uri());
|
hostAttributes(request), user.principal(), request.uri());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String hostAttributes(RestRequest request) {
|
private static String hostAttributes(RestRequest request) {
|
||||||
String formattedAddress;
|
String formattedAddress;
|
||||||
|
@ -465,5 +442,8 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
settings.add(HOST_ADDRESS_SETTING);
|
settings.add(HOST_ADDRESS_SETTING);
|
||||||
settings.add(HOST_NAME_SETTING);
|
settings.add(HOST_NAME_SETTING);
|
||||||
settings.add(NODE_NAME_SETTING);
|
settings.add(NODE_NAME_SETTING);
|
||||||
|
settings.add(INCLUDE_EVENT_SETTINGS);
|
||||||
|
settings.add(EXCLUDE_EVENT_SETTINGS);
|
||||||
|
settings.add(INCLUDE_REQUEST_BODY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.xpack.security.audit;
|
||||||
|
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
public class AuditLevelTests extends ESTestCase {
|
||||||
|
public void testAllIndexAuditLevel() {
|
||||||
|
EnumSet<AuditLevel> enumSet = AuditLevel.parse(Collections.singletonList("_all"));
|
||||||
|
AuditLevel[] levels = AuditLevel.values();
|
||||||
|
assertThat(enumSet.size(), is(levels.length));
|
||||||
|
for (AuditLevel level : levels) {
|
||||||
|
assertThat(enumSet.contains(level), is(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExcludeHasPreference() {
|
||||||
|
EnumSet<AuditLevel> enumSet = AuditLevel.parse(Collections.singletonList("_all"), Collections.singletonList("_all"));
|
||||||
|
assertThat(enumSet.size(), is(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testExcludeHasPreferenceSingle() {
|
||||||
|
String excluded = randomFrom(AuditLevel.values()).toString().toLowerCase(Locale.ROOT);
|
||||||
|
EnumSet<AuditLevel> enumSet = AuditLevel.parse(Collections.singletonList("_all"), Collections.singletonList(excluded));
|
||||||
|
EnumSet<AuditLevel> expected = EnumSet.allOf(AuditLevel.class);
|
||||||
|
expected.remove(AuditLevel.valueOf(excluded.toUpperCase(Locale.ROOT)));
|
||||||
|
assertThat(enumSet, equalTo(expected));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.xpack.security.audit.index;
|
|
||||||
|
|
||||||
import org.elasticsearch.test.ESTestCase;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.is;
|
|
||||||
|
|
||||||
public class IndexAuditLevelTests extends ESTestCase {
|
|
||||||
public void testAllIndexAuditLevel() {
|
|
||||||
EnumSet<IndexAuditLevel> enumSet = IndexAuditLevel.parse(Collections.singletonList("_all"));
|
|
||||||
IndexAuditLevel[] levels = IndexAuditLevel.values();
|
|
||||||
assertThat(enumSet.size(), is(levels.length));
|
|
||||||
for (IndexAuditLevel level : levels) {
|
|
||||||
assertThat(enumSet.contains(level), is(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testExcludeHasPreference() {
|
|
||||||
EnumSet<IndexAuditLevel> enumSet = IndexAuditLevel.parse(Collections.singletonList("_all"), Collections.singletonList("_all"));
|
|
||||||
assertThat(enumSet.size(), is(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testExcludeHasPreferenceSingle() {
|
|
||||||
String excluded = randomFrom(IndexAuditLevel.values()).toString().toLowerCase(Locale.ROOT);
|
|
||||||
EnumSet<IndexAuditLevel> enumSet = IndexAuditLevel.parse(Collections.singletonList("_all"), Collections.singletonList(excluded));
|
|
||||||
EnumSet<IndexAuditLevel> expected = EnumSet.allOf(IndexAuditLevel.class);
|
|
||||||
expected.remove(IndexAuditLevel.valueOf(excluded.toUpperCase(Locale.ROOT)));
|
|
||||||
assertThat(enumSet, equalTo(expected));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -113,11 +113,6 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||||
|
|
||||||
// with realm
|
|
||||||
auditTrail.authenticationFailed(randomAsciiOfLengthBetween(2, 10), token, "_action", message);
|
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
|
||||||
assertThat(clientCalled.get(), is(false));
|
|
||||||
|
|
||||||
// without realm
|
// without realm
|
||||||
auditTrail.authenticationFailed(token, "_action", message);
|
auditTrail.authenticationFailed(token, "_action", message);
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
|
@ -136,11 +131,6 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
RestRequest restRequest = mock(RestRequest.class);
|
RestRequest restRequest = mock(RestRequest.class);
|
||||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||||
|
|
||||||
// with realm
|
|
||||||
auditTrail.authenticationFailed(randomAsciiOfLengthBetween(2, 10), token, restRequest);
|
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
|
||||||
assertThat(clientCalled.get(), is(false));
|
|
||||||
|
|
||||||
// without the realm
|
// without the realm
|
||||||
auditTrail.authenticationFailed(token, restRequest);
|
auditTrail.authenticationFailed(token, restRequest);
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
|
@ -154,6 +144,31 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
verifyZeroInteractions(token, restRequest);
|
verifyZeroInteractions(token, restRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAuthenticationFailedRealmMutedTransport() {
|
||||||
|
createAuditTrail(new String[] { "realm_authentication_failed" });
|
||||||
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
|
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||||
|
|
||||||
|
// with realm
|
||||||
|
auditTrail.authenticationFailed(randomAsciiOfLengthBetween(2, 10), token, "_action", message);
|
||||||
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
verifyZeroInteractions(token, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAuthenticationFailedRealmMutedRest() {
|
||||||
|
createAuditTrail(new String[]{"realm_authentication_failed"});
|
||||||
|
RestRequest restRequest = mock(RestRequest.class);
|
||||||
|
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||||
|
|
||||||
|
// with realm
|
||||||
|
auditTrail.authenticationFailed(randomAsciiOfLengthBetween(2, 10), token, restRequest);
|
||||||
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
verifyZeroInteractions(token, restRequest);
|
||||||
|
}
|
||||||
|
|
||||||
public void testAccessGrantedMuted() {
|
public void testAccessGrantedMuted() {
|
||||||
createAuditTrail(new String[] { "access_granted" });
|
createAuditTrail(new String[] { "access_granted" });
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
|
|
|
@ -96,6 +96,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
private int numShards;
|
private int numShards;
|
||||||
private int numReplicas;
|
private int numReplicas;
|
||||||
private ThreadPool threadPool;
|
private ThreadPool threadPool;
|
||||||
|
private boolean includeRequestBody;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void configureBeforeClass() {
|
public static void configureBeforeClass() {
|
||||||
|
@ -241,6 +242,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
Settings.Builder builder = Settings.builder();
|
Settings.Builder builder = Settings.builder();
|
||||||
builder.put(levelSettings(includes, excludes));
|
builder.put(levelSettings(includes, excludes));
|
||||||
builder.put(commonSettings(rollover));
|
builder.put(commonSettings(rollover));
|
||||||
|
builder.put("xpack.security.audit.index.events.emit_request_body", includeRequestBody);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,6 +258,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
rollover = randomFrom(HOURLY, DAILY, WEEKLY, MONTHLY);
|
rollover = randomFrom(HOURLY, DAILY, WEEKLY, MONTHLY);
|
||||||
numReplicas = numberOfReplicas();
|
numReplicas = numberOfReplicas();
|
||||||
numShards = numberOfShards();
|
numShards = numberOfShards();
|
||||||
|
includeRequestBody = randomBoolean();
|
||||||
Settings.Builder builder = Settings.builder();
|
Settings.Builder builder = Settings.builder();
|
||||||
if (remoteIndexing) {
|
if (remoteIndexing) {
|
||||||
builder.put(remoteSettings);
|
builder.put(remoteSettings);
|
||||||
|
@ -314,7 +317,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertThat(NetworkAddress.format(InetAddress.getLoopbackAddress()), equalTo(sourceMap.get("origin_address")));
|
assertThat(NetworkAddress.format(InetAddress.getLoopbackAddress()), equalTo(sourceMap.get("origin_address")));
|
||||||
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
||||||
assertThat(sourceMap.get("origin_type"), is("rest"));
|
assertThat(sourceMap.get("origin_type"), is("rest"));
|
||||||
assertThat(sourceMap.get("request_body"), notNullValue());
|
assertRequestBody(sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedTransport() throws Exception {
|
public void testAuthenticationFailedTransport() throws Exception {
|
||||||
|
@ -373,7 +376,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
||||||
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
||||||
assertThat(sourceMap.get("origin_type"), is("rest"));
|
assertThat(sourceMap.get("origin_type"), is("rest"));
|
||||||
assertThat(sourceMap.get("request_body"), notNullValue());
|
assertRequestBody(sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedRestNoToken() throws Exception {
|
public void testAuthenticationFailedRestNoToken() throws Exception {
|
||||||
|
@ -388,7 +391,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
||||||
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
||||||
assertThat(sourceMap.get("origin_type"), is("rest"));
|
assertThat(sourceMap.get("origin_type"), is("rest"));
|
||||||
assertThat(sourceMap.get("request_body"), notNullValue());
|
assertRequestBody(sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedTransportRealm() throws Exception {
|
public void testAuthenticationFailedTransportRealm() throws Exception {
|
||||||
|
@ -429,7 +432,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
||||||
assertEquals("_realm", sourceMap.get("realm"));
|
assertEquals("_realm", sourceMap.get("realm"));
|
||||||
assertThat(sourceMap.get("origin_type"), is("rest"));
|
assertThat(sourceMap.get("origin_type"), is("rest"));
|
||||||
assertThat(sourceMap.get("request_body"), notNullValue());
|
assertRequestBody(sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccessGranted() throws Exception {
|
public void testAccessGranted() throws Exception {
|
||||||
|
@ -520,7 +523,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address")));
|
||||||
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
assertThat("_uri", equalTo(sourceMap.get("uri")));
|
||||||
assertThat(sourceMap.get("origin_type"), is("rest"));
|
assertThat(sourceMap.get("origin_type"), is("rest"));
|
||||||
assertThat(sourceMap.get("request_body"), notNullValue());
|
assertRequestBody(sourceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTamperedRequest() throws Exception {
|
public void testTamperedRequest() throws Exception {
|
||||||
|
@ -638,6 +641,13 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals(type, sourceMap.get("event_type"));
|
assertEquals(type, sourceMap.get("event_type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertRequestBody(Map<String, Object> sourceMap) {
|
||||||
|
if (includeRequestBody) {
|
||||||
|
assertThat(sourceMap.get("request_body"), notNullValue());
|
||||||
|
} else {
|
||||||
|
assertThat(sourceMap.get("request_body"), nullValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
private static class LocalHostMockMessage extends TransportMessage {
|
private static class LocalHostMockMessage extends TransportMessage {
|
||||||
LocalHostMockMessage() {
|
LocalHostMockMessage() {
|
||||||
remoteAddress(new LocalTransportAddress("local_host"));
|
remoteAddress(new LocalTransportAddress("local_host"));
|
||||||
|
|
|
@ -14,7 +14,6 @@ import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||||
import org.apache.logging.log4j.core.config.Configuration;
|
import org.apache.logging.log4j.core.config.Configuration;
|
||||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||||
import org.apache.logging.log4j.core.filter.RegexFilter;
|
import org.apache.logging.log4j.core.filter.RegexFilter;
|
||||||
import org.apache.logging.log4j.core.impl.MutableLogEvent;
|
|
||||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
import org.elasticsearch.common.logging.TestLoggers;
|
import org.elasticsearch.common.logging.TestLoggers;
|
||||||
|
|
|
@ -105,53 +105,45 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
private DiscoveryNode localNode;
|
private DiscoveryNode localNode;
|
||||||
private ClusterService clusterService;
|
private ClusterService clusterService;
|
||||||
private ThreadContext threadContext;
|
private ThreadContext threadContext;
|
||||||
|
private boolean includeRequestBody;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
|
includeRequestBody = randomBoolean();
|
||||||
settings = Settings.builder()
|
settings = Settings.builder()
|
||||||
.put("xpack.security.audit.logfile.prefix.emit_node_host_address", randomBoolean())
|
.put("xpack.security.audit.logfile.prefix.emit_node_host_address", randomBoolean())
|
||||||
.put("xpack.security.audit.logfile.prefix.emit_node_host_name", randomBoolean())
|
.put("xpack.security.audit.logfile.prefix.emit_node_host_name", randomBoolean())
|
||||||
.put("xpack.security.audit.logfile.prefix.emit_node_name", randomBoolean())
|
.put("xpack.security.audit.logfile.prefix.emit_node_name", randomBoolean())
|
||||||
|
.put("xpack.security.audit.logfile.events.emit_request_body", includeRequestBody)
|
||||||
.build();
|
.build();
|
||||||
localNode = mock(DiscoveryNode.class);
|
localNode = mock(DiscoveryNode.class);
|
||||||
when(localNode.getHostAddress()).thenReturn(LocalTransportAddress.buildUnique().toString());
|
when(localNode.getHostAddress()).thenReturn(LocalTransportAddress.buildUnique().toString());
|
||||||
clusterService = mock(ClusterService.class);
|
clusterService = mock(ClusterService.class);
|
||||||
when(clusterService.localNode()).thenReturn(localNode);
|
when(clusterService.localNode()).thenReturn(localNode);
|
||||||
prefix = LoggingAuditTrail.resolvePrefix(settings, localNode);
|
prefix = LoggingAuditTrail.resolvePrefix(settings, localNode);
|
||||||
|
threadContext = new ThreadContext(Settings.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAnonymousAccessDeniedTransport() throws Exception {
|
public void testAnonymousAccessDeniedTransport() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, clusterService.localNode(), threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, clusterService.localNode(), threadContext);
|
||||||
auditTrail.anonymousAccessDenied("_action", message);
|
auditTrail.anonymousAccessDenied("_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.WARN, prefix + "[transport] [anonymous_access_denied]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [anonymous_access_denied]\t" + origins +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.WARN, prefix + "[transport] [anonymous_access_denied]\t" + origins + ", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [anonymous_access_denied]\t" + origins +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [anonymous_access_denied]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [anonymous_access_denied]\t" + origins +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "anonymous_access_denied").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.anonymousAccessDenied("_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAnonymousAccessDeniedRest() throws Exception {
|
public void testAnonymousAccessDeniedRest() throws Exception {
|
||||||
|
@ -160,207 +152,172 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||||
when(request.uri()).thenReturn("_uri");
|
when(request.uri()).thenReturn("_uri");
|
||||||
String expectedMessage = prepareRestContent(request);
|
String expectedMessage = prepareRestContent(request);
|
||||||
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.anonymousAccessDenied(request);
|
auditTrail.anonymousAccessDenied(request);
|
||||||
switch (level.toString()) {
|
if (includeRequestBody) {
|
||||||
case "ERROR":
|
assertMsg(logger, Level.INFO, prefix + "[rest] [anonymous_access_denied]\torigin_address=[" +
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.WARN, prefix + "[rest] [anonymous_access_denied]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[rest] [anonymous_access_denied]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
||||||
|
} else {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [anonymous_access_denied]\torigin_address=[" +
|
||||||
|
NetworkAddress.format(address) + "], uri=[_uri]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "anonymous_access_denied").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.anonymousAccessDenied(request);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailed() throws Exception {
|
public void testAuthenticationFailed() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
||||||
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [authentication_failed]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [authentication_failed]\t" + origins +
|
||||||
", principal=[_principal], action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
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 + "[transport] [authentication_failed]\t" + origins +
|
|
||||||
", principal=[_principal], action=[_action], indices=[" + indices(message) +
|
", principal=[_principal], action=[_action], indices=[" + indices(message) +
|
||||||
"], request=[MockIndicesRequest]");
|
"], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [authentication_failed]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [authentication_failed]\t" + origins +
|
||||||
", principal=[_principal], action=[_action], request=[MockMessage]");
|
", principal=[_principal], action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedNoToken() throws Exception {
|
public void testAuthenticationFailedNoToken() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
||||||
auditTrail.authenticationFailed("_action", message);
|
auditTrail.authenticationFailed("_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [authentication_failed]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [authentication_failed]\t" + origins +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [authentication_failed]\t" + origins +
|
|
||||||
", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [authentication_failed]\t" + origins +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [authentication_failed]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [authentication_failed]\t" + origins +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed("_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedRest() throws Exception {
|
public void testAuthenticationFailedRest() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
RestRequest request = mock(RestRequest.class);
|
RestRequest request = mock(RestRequest.class);
|
||||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||||
when(request.uri()).thenReturn("_uri");
|
when(request.uri()).thenReturn("_uri");
|
||||||
String expectedMessage = prepareRestContent(request);
|
String expectedMessage = prepareRestContent(request);
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.authenticationFailed(new MockToken(), request);
|
auditTrail.authenticationFailed(new MockToken(), request);
|
||||||
switch (level.toString()) {
|
if (includeRequestBody) {
|
||||||
case "ERROR":
|
assertMsg(logger, Level.INFO, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri], request_body=[" +
|
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri], request_body=[" +
|
||||||
expectedMessage + "]");
|
expectedMessage + "]");
|
||||||
|
} else {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
||||||
|
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed(new MockToken(), request);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedRestNoToken() throws Exception {
|
public void testAuthenticationFailedRestNoToken() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
RestRequest request = mock(RestRequest.class);
|
RestRequest request = mock(RestRequest.class);
|
||||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||||
when(request.uri()).thenReturn("_uri");
|
when(request.uri()).thenReturn("_uri");
|
||||||
String expectedMessage = prepareRestContent(request);
|
String expectedMessage = prepareRestContent(request);
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.authenticationFailed(request);
|
auditTrail.authenticationFailed(request);
|
||||||
switch (level.toString()) {
|
if (includeRequestBody) {
|
||||||
case "ERROR":
|
assertMsg(logger, Level.INFO, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
||||||
|
} else {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [authentication_failed]\torigin_address=[" +
|
||||||
|
NetworkAddress.format(address) + "], uri=[_uri]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed(request);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthenticationFailedRealm() throws Exception {
|
public void testAuthenticationFailedRealm() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message);
|
auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
case "DEBUG":
|
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
break;
|
|
||||||
case "TRACE":
|
// test enabled
|
||||||
|
settings =
|
||||||
|
Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "realm_authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message);
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.TRACE, prefix + "[transport] [authentication_failed]\trealm=[_realm], " + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [realm_authentication_failed]\trealm=[_realm], " + origins +
|
||||||
", principal=[_principal], action=[_action], indices=[" + indices(message) + "], " +
|
", principal=[_principal], action=[_action], indices=[" + indices(message) + "], " +
|
||||||
"request=[MockIndicesRequest]");
|
"request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.TRACE, prefix + "[transport] [authentication_failed]\trealm=[_realm], " + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [realm_authentication_failed]\trealm=[_realm], " + origins +
|
||||||
", principal=[_principal], action=[_action], request=[MockMessage]");
|
", principal=[_principal], action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAuthenticationFailedRealmRest() throws Exception {
|
public void testAuthenticationFailedRealmRest() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
RestRequest request = mock(RestRequest.class);
|
RestRequest request = mock(RestRequest.class);
|
||||||
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
InetAddress address = forge("_hostname", randomBoolean() ? "127.0.0.1" : "::1");
|
||||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||||
when(request.uri()).thenReturn("_uri");
|
when(request.uri()).thenReturn("_uri");
|
||||||
String expectedMessage = prepareRestContent(request);
|
String expectedMessage = prepareRestContent(request);
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.authenticationFailed("_realm", new MockToken(), request);
|
auditTrail.authenticationFailed("_realm", new MockToken(), request);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
case "DEBUG":
|
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
break;
|
|
||||||
case "TRACE":
|
// test enabled
|
||||||
assertMsg(logger, Level.TRACE, prefix + "[rest] [authentication_failed]\trealm=[_realm], origin_address=[" +
|
settings =
|
||||||
|
Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "realm_authentication_failed").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.authenticationFailed("_realm", new MockToken(), request);
|
||||||
|
if (includeRequestBody) {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [realm_authentication_failed]\trealm=[_realm], origin_address=[" +
|
||||||
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri], request_body=[" +
|
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri], request_body=[" +
|
||||||
expectedMessage + "]");
|
expectedMessage + "]");
|
||||||
}
|
} else {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [realm_authentication_failed]\trealm=[_realm], origin_address=[" +
|
||||||
|
NetworkAddress.format(address) + "], principal=[_principal], uri=[_uri]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccessGranted() throws Exception {
|
public void testAccessGranted() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
|
@ -374,65 +331,46 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
||||||
auditTrail.accessGranted(user, "_action", message);
|
auditTrail.accessGranted(user, "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.accessGranted(user, "_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccessGrantedInternalSystemAction() throws Exception {
|
public void testAccessGrantedInternalSystemAction() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
case "DEBUG":
|
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
break;
|
|
||||||
case "TRACE":
|
// test enabled
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "system_access_granted").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.TRACE, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||||
SystemUser.INSTANCE.principal()
|
SystemUser.INSTANCE.principal()
|
||||||
+ "], action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
+ "], action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.TRACE, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||||
SystemUser.INSTANCE.principal() + "], action=[internal:_action], request=[MockMessage]");
|
SystemUser.INSTANCE.principal() + "], action=[internal:_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAccessGrantedInternalSystemActionNonSystemUser() throws Exception {
|
public void testAccessGrantedInternalSystemActionNonSystemUser() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
|
@ -446,37 +384,24 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
||||||
auditTrail.accessGranted(user, "internal:_action", message);
|
auditTrail.accessGranted(user, "internal:_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[internal:_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[internal:_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[internal:_action], request=[MockMessage]");
|
", action=[internal:_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.accessGranted(user, "internal:_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccessDenied() throws Exception {
|
public void testAccessDenied() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
|
@ -490,29 +415,20 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
||||||
auditTrail.accessDenied(user, "_action", message);
|
auditTrail.accessDenied(user, "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_denied").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.accessDenied(user, "_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTamperedRequestRest() throws Exception {
|
public void testTamperedRequestRest() throws Exception {
|
||||||
|
@ -521,58 +437,42 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
when(request.getRemoteAddress()).thenReturn(new InetSocketAddress(address, 9200));
|
||||||
when(request.uri()).thenReturn("_uri");
|
when(request.uri()).thenReturn("_uri");
|
||||||
String expectedMessage = prepareRestContent(request);
|
String expectedMessage = prepareRestContent(request);
|
||||||
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.tamperedRequest(request);
|
auditTrail.tamperedRequest(request);
|
||||||
switch (level.toString()) {
|
if (includeRequestBody) {
|
||||||
case "ERROR":
|
assertMsg(logger, Level.INFO, prefix + "[rest] [tampered_request]\torigin_address=[" +
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[rest] [tampered_request]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[rest] [tampered_request]\torigin_address=[" +
|
|
||||||
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
NetworkAddress.format(address) + "], uri=[_uri], request_body=[" + expectedMessage + "]");
|
||||||
|
} else {
|
||||||
|
assertMsg(logger, Level.INFO, prefix + "[rest] [tampered_request]\torigin_address=[" +
|
||||||
|
NetworkAddress.format(address) + "], uri=[_uri]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "tampered_request").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.tamperedRequest(request);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTamperedRequest() throws Exception {
|
public void testTamperedRequest() throws Exception {
|
||||||
String action = "_action";
|
String action = "_action";
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.tamperedRequest(action, message);
|
auditTrail.tamperedRequest(action, message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [tampered_request]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [tampered_request]\t" + origins +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [tampered_request]\t" + origins + ", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [tampered_request]\t" + origins +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [tampered_request]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [tampered_request]\t" + origins +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTamperedRequestWithUser() throws Exception {
|
public void testTamperedRequestWithUser() throws Exception {
|
||||||
|
@ -585,137 +485,100 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
||||||
for (Level level : Level.values()) {
|
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.tamperedRequest(user, action, message);
|
auditTrail.tamperedRequest(user, action, message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], indices=[" + indices(message) + "]");
|
|
||||||
} else {
|
|
||||||
assertMsg(logger, Level.ERROR, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
if (message instanceof IndicesRequest) {
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [tampered_request]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], request=[MockMessage]");
|
", action=[_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "tampered_request").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.tamperedRequest(user, action, message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConnectionDenied() throws Exception {
|
public void testConnectionDenied() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
||||||
SecurityIpFilterRule rule = new SecurityIpFilterRule(false, "_all");
|
SecurityIpFilterRule rule = new SecurityIpFilterRule(false, "_all");
|
||||||
auditTrail.connectionDenied(inetAddress, "default", rule);
|
auditTrail.connectionDenied(inetAddress, "default", rule);
|
||||||
switch (level.toString()) {
|
assertMsg(logger, Level.INFO, String.format(Locale.ROOT, prefix +
|
||||||
case "ERROR":
|
|
||||||
assertMsg(logger, Level.ERROR, String.format(Locale.ROOT, prefix +
|
|
||||||
"[ip_filter] [connection_denied]\torigin_address=[%s], transport_profile=[%s], rule=[deny %s]",
|
"[ip_filter] [connection_denied]\torigin_address=[%s], transport_profile=[%s], rule=[deny %s]",
|
||||||
NetworkAddress.format(inetAddress), "default", "_all"));
|
NetworkAddress.format(inetAddress), "default", "_all"));
|
||||||
break;
|
|
||||||
case "WARN":
|
// test disabled
|
||||||
case "INFO":
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
case "DEBUG":
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "connection_denied").build();
|
||||||
case "TRACE":
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
}
|
auditTrail.connectionDenied(inetAddress, "default", rule);
|
||||||
}
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConnectionGranted() throws Exception {
|
public void testConnectionGranted() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
InetAddress inetAddress = InetAddress.getLoopbackAddress();
|
||||||
SecurityIpFilterRule rule = IPFilter.DEFAULT_PROFILE_ACCEPT_ALL;
|
SecurityIpFilterRule rule = IPFilter.DEFAULT_PROFILE_ACCEPT_ALL;
|
||||||
auditTrail.connectionGranted(inetAddress, "default", rule);
|
auditTrail.connectionGranted(inetAddress, "default", rule);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
case "INFO":
|
|
||||||
case "DEBUG":
|
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
break;
|
|
||||||
case "TRACE":
|
// test enabled
|
||||||
assertMsg(logger, Level.TRACE, String.format(Locale.ROOT, prefix + "[ip_filter] " +
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
"[connection_granted]\torigin_address=[%s], transport_profile=[default], rule=[allow default:accept_all]",
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "connection_granted").build();
|
||||||
NetworkAddress.format(inetAddress)));
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
}
|
auditTrail.connectionGranted(inetAddress, "default", rule);
|
||||||
}
|
assertMsg(logger, Level.INFO, String.format(Locale.ROOT, prefix + "[ip_filter] [connection_granted]\torigin_address=[%s], " +
|
||||||
|
"transport_profile=[default], rule=[allow default:accept_all]", NetworkAddress.format(inetAddress)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRunAsGranted() throws Exception {
|
public void testRunAsGranted() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = new MockMessage(threadContext);
|
TransportMessage message = new MockMessage(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
||||||
auditTrail.runAsGranted(user, "_action", message);
|
auditTrail.runAsGranted(user, "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_granted]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_granted]\t" + origins +
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [run_as_granted]\t" + origins +
|
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_granted").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.runAsGranted(user, "_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRunAsDenied() throws Exception {
|
public void testRunAsDenied() throws Exception {
|
||||||
for (Level level : Level.values()) {
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(level);
|
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = new MockMessage(threadContext);
|
TransportMessage message = new MockMessage(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
String origins = LoggingAuditTrail.originAttributes(message, localNode, threadContext);
|
||||||
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
User user = new User("_username", new String[]{"r1"}, new User("running as", new String[] {"r2"}));
|
||||||
auditTrail.runAsDenied(user, "_action", message);
|
auditTrail.runAsDenied(user, "_action", message);
|
||||||
switch (level.toString()) {
|
|
||||||
case "ERROR":
|
|
||||||
case "WARN":
|
|
||||||
assertEmptyLog(logger);
|
|
||||||
break;
|
|
||||||
case "INFO":
|
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_denied]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_denied]\t" + origins +
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action]");
|
|
||||||
break;
|
|
||||||
case "DEBUG":
|
|
||||||
case "TRACE":
|
|
||||||
assertMsg(logger, Level.DEBUG, prefix + "[transport] [run_as_denied]\t" + origins +
|
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
||||||
}
|
|
||||||
}
|
// test disabled
|
||||||
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_denied").build();
|
||||||
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
|
auditTrail.runAsDenied(user, "_action", message);
|
||||||
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOriginAttributes() throws Exception {
|
public void testOriginAttributes() throws Exception {
|
||||||
threadContext = new ThreadContext(Settings.EMPTY);
|
|
||||||
MockMessage message = new MockMessage(threadContext);
|
MockMessage message = new MockMessage(threadContext);
|
||||||
String text = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
String text = LoggingAuditTrail.originAttributes(message, localNode, threadContext);;
|
||||||
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
||||||
|
|
Loading…
Reference in New Issue