mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-27 18:38:41 +00:00
Add "request.id" to file audit logs (#35536)
This generates a synthesized "id" for each incoming request that is included in the audit logs (file only). This id can be used to correlate events for the same request (e.g. authentication success with access granted). This request.id is specific to the audit logs and is not used for any other purpose The request.id is consistent across nodes if a single request requires execution on multiple nodes (e.g. search acros multiple shards).
This commit is contained in:
parent
a18b219f79
commit
5b427d415e
@ -23,6 +23,7 @@ appender.audit_rolling.layout.pattern = {\
|
||||
%varsNotEmpty{, "url.path":"%enc{%map{url.path}}{JSON}"}\
|
||||
%varsNotEmpty{, "url.query":"%enc{%map{url.query}}{JSON}"}\
|
||||
%varsNotEmpty{, "request.body":"%enc{%map{request.body}}{JSON}"}\
|
||||
%varsNotEmpty{, "request.id":"%enc{%map{request.id}}{JSON}"}\
|
||||
%varsNotEmpty{, "action":"%enc{%map{action}}{JSON}"}\
|
||||
%varsNotEmpty{, "request.name":"%enc{%map{request.name}}{JSON}"}\
|
||||
%varsNotEmpty{, "indices":%map{indices}}\
|
||||
@ -50,6 +51,7 @@ appender.audit_rolling.layout.pattern = {\
|
||||
# "url.path" the URI component between the port and the query string; it is percent (URL) encoded
|
||||
# "url.query" the URI component after the path and before the fragment; it is percent (URL) encoded
|
||||
# "request.body" the content of the request body entity, JSON escaped
|
||||
# "request.id" a synthentic identifier for the incoming request, this is unique per incoming request, and consistent across all audit events generated by that request
|
||||
# "action" an action is the most granular operation that is authorized and this identifies it in a namespaced way (internal)
|
||||
# "request.name" if the event is in connection to a transport message this is the name of the request class, similar to how rest requests are identified by the url path (internal)
|
||||
# "indices" the array of indices that the "action" is acting upon
|
||||
|
@ -19,6 +19,7 @@ import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessCo
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.support.Exceptions;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -70,7 +71,8 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
||||
permissionsMap.computeIfAbsent(alias, userPermissions.indices()::allowedActionsMatcher);
|
||||
if (Operations.subsetOf(aliasPermissions, indexPermissions) == false) {
|
||||
// TODO we've already audited a access granted event so this is going to look ugly
|
||||
auditTrailService.accessDenied(authentication, action, request, userPermissions.names());
|
||||
auditTrailService.accessDenied(AuditUtil.extractRequestId(threadContext), authentication, action, request,
|
||||
userPermissions.names());
|
||||
throw Exceptions.authorizationError("Adding an alias is not allowed when the alias " +
|
||||
"has more permissions than any of the indices");
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.support.Exceptions;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
|
||||
import static org.elasticsearch.xpack.security.audit.AuditUtil.extractRequestId;
|
||||
|
||||
public final class ResizeRequestInterceptor implements RequestInterceptor<ResizeRequest> {
|
||||
|
||||
private final ThreadContext threadContext;
|
||||
@ -59,7 +61,7 @@ public final class ResizeRequestInterceptor implements RequestInterceptor<Resize
|
||||
userPermissions.indices().allowedActionsMatcher(request.getTargetIndexRequest().index());
|
||||
if (Operations.subsetOf(targetIndexPermissions, sourceIndexPermissions) == false) {
|
||||
// TODO we've already audited a access granted event so this is going to look ugly
|
||||
auditTrailService.accessDenied(authentication, action, request, userPermissions.names());
|
||||
auditTrailService.accessDenied(extractRequestId(threadContext), authentication, action, request, userPermissions.names());
|
||||
throw Exceptions.authorizationError("Resizing an index is not allowed when the target index " +
|
||||
"has more permissions than the source index");
|
||||
}
|
||||
|
@ -18,43 +18,50 @@ public interface AuditTrail {
|
||||
|
||||
String name();
|
||||
|
||||
void authenticationSuccess(String realm, User user, RestRequest request);
|
||||
void authenticationSuccess(String requestId, String realm, User user, RestRequest request);
|
||||
|
||||
void authenticationSuccess(String realm, User user, String action, TransportMessage message);
|
||||
void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message);
|
||||
|
||||
void anonymousAccessDenied(String action, TransportMessage message);
|
||||
void anonymousAccessDenied(String requestId, String action, TransportMessage message);
|
||||
|
||||
void anonymousAccessDenied(RestRequest request);
|
||||
void anonymousAccessDenied(String requestId, RestRequest request);
|
||||
|
||||
void authenticationFailed(RestRequest request);
|
||||
void authenticationFailed(String requestId, RestRequest request);
|
||||
|
||||
void authenticationFailed(String action, TransportMessage message);
|
||||
void authenticationFailed(String requestId, String action, TransportMessage message);
|
||||
|
||||
void authenticationFailed(AuthenticationToken token, String action, TransportMessage message);
|
||||
void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message);
|
||||
|
||||
void authenticationFailed(AuthenticationToken token, RestRequest request);
|
||||
void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request);
|
||||
|
||||
void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message);
|
||||
void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, TransportMessage message);
|
||||
|
||||
void authenticationFailed(String realm, AuthenticationToken token, RestRequest request);
|
||||
void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request);
|
||||
|
||||
void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
void accessGranted(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void tamperedRequest(RestRequest request);
|
||||
void tamperedRequest(String requestId, RestRequest request);
|
||||
|
||||
void tamperedRequest(String action, TransportMessage message);
|
||||
void tamperedRequest(String requestId, String action, TransportMessage message);
|
||||
|
||||
void tamperedRequest(User user, String action, TransportMessage request);
|
||||
void tamperedRequest(String requestId, User user, String action, TransportMessage request);
|
||||
|
||||
/**
|
||||
* The {@link #connectionGranted(InetAddress, String, SecurityIpFilterRule)} and
|
||||
* {@link #connectionDenied(InetAddress, String, SecurityIpFilterRule)} methods do not have a requestId because they related to a
|
||||
* potentially long-lived TCP connection, not a single request. For both Transport and Rest connections, a single connection
|
||||
* granted/denied event is generated even if that connection is used for multiple Elasticsearch actions (potentially as different users)
|
||||
*/
|
||||
void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule);
|
||||
|
||||
void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule);
|
||||
|
||||
void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void runAsDenied(String requestId, Authentication authentication, RestRequest request, String[] roleNames);
|
||||
|
||||
void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames);
|
||||
}
|
||||
|
@ -38,136 +38,136 @@ public class AuditTrailService implements AuditTrail {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationSuccess(realm, user, request);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationSuccess(realm, user, action, message);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(String action, TransportMessage message) {
|
||||
public void anonymousAccessDenied(String requestId, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.anonymousAccessDenied(action, message);
|
||||
auditTrail.anonymousAccessDenied(requestId, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(RestRequest request) {
|
||||
public void anonymousAccessDenied(String requestId, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
auditTrail.anonymousAccessDenied(requestId, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(RestRequest request) {
|
||||
public void authenticationFailed(String requestId, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(request);
|
||||
auditTrail.authenticationFailed(requestId, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(action, message);
|
||||
auditTrail.authenticationFailed(requestId, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(token, action, message);
|
||||
auditTrail.authenticationFailed(requestId, token, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(realm, token, action, message);
|
||||
auditTrail.authenticationFailed(requestId, realm, token, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(token, request);
|
||||
auditTrail.authenticationFailed(requestId, token, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.authenticationFailed(realm, token, request);
|
||||
auditTrail.authenticationFailed(requestId, realm, token, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage msg, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.accessGranted(authentication, action, message, roleNames);
|
||||
auditTrail.accessGranted(requestId, authentication, action, msg, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.accessDenied(authentication, action, message, roleNames);
|
||||
auditTrail.accessDenied(requestId, authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(RestRequest request) {
|
||||
public void tamperedRequest(String requestId, RestRequest request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.tamperedRequest(request);
|
||||
auditTrail.tamperedRequest(requestId, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(String action, TransportMessage message) {
|
||||
public void tamperedRequest(String requestId, String action, TransportMessage message) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.tamperedRequest(action, message);
|
||||
auditTrail.tamperedRequest(requestId, action, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(User user, String action, TransportMessage request) {
|
||||
public void tamperedRequest(String requestId, User user, String action, TransportMessage request) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.tamperedRequest(user, action, request);
|
||||
auditTrail.tamperedRequest(requestId, user, action, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,28 +191,28 @@ public class AuditTrailService implements AuditTrail {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsGranted(authentication, action, message, roleNames);
|
||||
auditTrail.runAsGranted(requestId, authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsDenied(authentication, action, message, roleNames);
|
||||
auditTrail.runAsDenied(requestId, authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsDenied(authentication, request, roleNames);
|
||||
auditTrail.runAsDenied(requestId, authentication, request, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@
|
||||
package org.elasticsearch.xpack.security.audit;
|
||||
|
||||
import org.elasticsearch.action.IndicesRequest;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.UUIDs;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
@ -17,6 +20,8 @@ import java.util.Set;
|
||||
|
||||
public class AuditUtil {
|
||||
|
||||
private static final String AUDIT_REQUEST_ID = "_xpack_audit_request_id";
|
||||
|
||||
public static String restRequestContent(RestRequest request) {
|
||||
if (request.hasContent()) {
|
||||
try {
|
||||
@ -38,4 +43,34 @@ public class AuditUtil {
|
||||
private static Set<String> arrayToSetOrNull(String[] indices) {
|
||||
return indices == null ? null : new HashSet<>(Arrays.asList(indices));
|
||||
}
|
||||
|
||||
public static String generateRequestId(ThreadContext threadContext) {
|
||||
return generateRequestId(threadContext, true);
|
||||
}
|
||||
|
||||
public static String getOrGenerateRequestId(ThreadContext threadContext) {
|
||||
final String requestId = extractRequestId(threadContext);
|
||||
if (Strings.isEmpty(requestId)) {
|
||||
return generateRequestId(threadContext, false);
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
private static String generateRequestId(ThreadContext threadContext, boolean checkExisting) {
|
||||
if (checkExisting) {
|
||||
final String existing = extractRequestId(threadContext);
|
||||
if (existing != null) {
|
||||
throw new IllegalStateException("Cannot generate a new audit request id - existing id ["
|
||||
+ existing + "] already registered");
|
||||
}
|
||||
}
|
||||
final String requestId = UUIDs.randomBase64UUID();
|
||||
// Store as a header (not transient) so that it is passed over the network if this request requires execution on other nodes
|
||||
threadContext.putHeader(AUDIT_REQUEST_ID, requestId);
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public static String extractRequestId(ThreadContext threadContext) {
|
||||
return threadContext.getHeader(AUDIT_REQUEST_ID);
|
||||
}
|
||||
}
|
||||
|
@ -470,7 +470,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||
try {
|
||||
enqueue(message("authentication_success", new Tuple<>(realm, realm), user, null, request), "authentication_success");
|
||||
@ -481,7 +481,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||
try {
|
||||
enqueue(message("authentication_success", action, user, null, new Tuple<>(realm, realm), null, message),
|
||||
@ -493,7 +493,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(String action, TransportMessage message) {
|
||||
public void anonymousAccessDenied(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||
try {
|
||||
enqueue(message("anonymous_access_denied", action, (User) null, null, null, indices(message), message),
|
||||
@ -505,7 +505,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(RestRequest request) {
|
||||
public void anonymousAccessDenied(String requestId, RestRequest request) {
|
||||
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||
try {
|
||||
enqueue(message("anonymous_access_denied", null, null, null, null, request), "anonymous_access_denied");
|
||||
@ -516,7 +516,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
try {
|
||||
enqueue(message("authentication_failed", action, (User) null, null, null, indices(message), message),
|
||||
@ -528,7 +528,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(RestRequest request) {
|
||||
public void authenticationFailed(String requestId, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
try {
|
||||
enqueue(message("authentication_failed", null, null, null, null, request), "authentication_failed");
|
||||
@ -539,7 +539,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
if (XPackUser.is(token.principal()) == false) {
|
||||
try {
|
||||
@ -552,7 +552,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
if (XPackUser.is(token.principal()) == false) {
|
||||
try {
|
||||
@ -565,7 +565,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||
if (XPackUser.is(token.principal()) == false) {
|
||||
try {
|
||||
@ -579,7 +579,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||
if (XPackUser.is(token.principal()) == false) {
|
||||
try {
|
||||
@ -592,7 +592,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage msg, String[] roleNames) {
|
||||
final User user = authentication.getUser();
|
||||
final boolean isSystem = SystemUser.is(user) || XPackUser.is(user);
|
||||
final boolean logSystemAccessGranted = isSystem && events.contains(SYSTEM_ACCESS_GRANTED);
|
||||
@ -602,8 +602,8 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
final String authRealmName = authentication.getAuthenticatedBy().getName();
|
||||
final String lookRealmName = authentication.getLookedUpBy() == null ? null : authentication.getLookedUpBy().getName();
|
||||
enqueue(message("access_granted", action, user, roleNames, new Tuple(authRealmName, lookRealmName), indices(message),
|
||||
message), "access_granted");
|
||||
enqueue(message("access_granted", action, user, roleNames, new Tuple(authRealmName, lookRealmName), indices(msg),
|
||||
msg), "access_granted");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [access_granted]", e);
|
||||
}
|
||||
@ -611,7 +611,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(ACCESS_DENIED) && (XPackUser.is(authentication.getUser()) == false)) {
|
||||
try {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
@ -626,7 +626,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(RestRequest request) {
|
||||
public void tamperedRequest(String requestId, RestRequest request) {
|
||||
if (events.contains(TAMPERED_REQUEST)) {
|
||||
try {
|
||||
enqueue(message("tampered_request", null, null, null, null, request), "tampered_request");
|
||||
@ -637,7 +637,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(String action, TransportMessage message) {
|
||||
public void tamperedRequest(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(TAMPERED_REQUEST)) {
|
||||
try {
|
||||
enqueue(message("tampered_request", action, (User) null, null, null, indices(message), message), "tampered_request");
|
||||
@ -648,7 +648,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(User user, String action, TransportMessage request) {
|
||||
public void tamperedRequest(String requestId, User user, String action, TransportMessage request) {
|
||||
if (events.contains(TAMPERED_REQUEST) && XPackUser.is(user) == false) {
|
||||
try {
|
||||
enqueue(message("tampered_request", action, user, null, null, indices(request), request), "tampered_request");
|
||||
@ -681,7 +681,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_GRANTED)) {
|
||||
try {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
@ -696,7 +696,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)) {
|
||||
try {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
@ -711,7 +711,7 @@ public class IndexAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)) {
|
||||
try {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
|
@ -100,6 +100,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
public static final String URL_PATH_FIELD_NAME = "url.path";
|
||||
public static final String URL_QUERY_FIELD_NAME = "url.query";
|
||||
public static final String REQUEST_BODY_FIELD_NAME = "request.body";
|
||||
public static final String REQUEST_ID_FIELD_NAME = "request.id";
|
||||
public static final String ACTION_FIELD_NAME = "action";
|
||||
public static final String INDICES_FIELD_NAME = "indices";
|
||||
public static final String REQUEST_NAME_FIELD_NAME = "request.name";
|
||||
@ -201,7 +202,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS) && eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(user), Optional.of(realm), Optional.empty(), Optional.empty())) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
@ -209,6 +210,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_success")
|
||||
.with(REALM_FIELD_NAME, realm)
|
||||
.withRestUri(request)
|
||||
.withRequestId(requestId)
|
||||
.withPrincipal(user)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
@ -219,7 +221,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
||||
public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -230,6 +232,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(REALM_FIELD_NAME, realm)
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withPrincipal(user)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
@ -241,7 +244,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(String action, TransportMessage message) {
|
||||
public void anonymousAccessDenied(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -251,6 +254,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.withOpaqueId(threadContext)
|
||||
@ -261,7 +265,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anonymousAccessDenied(RestRequest request) {
|
||||
public void anonymousAccessDenied(String requestId, RestRequest request) {
|
||||
if (events.contains(ANONYMOUS_ACCESS_DENIED)
|
||||
&& eventFilterPolicyRegistry.ignorePredicate().test(AuditEventMetaInfo.EMPTY) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
@ -270,6 +274,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRestUri(request)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -277,7 +282,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -288,6 +293,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(PRINCIPAL_FIELD_NAME, token.principal())
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.withOpaqueId(threadContext)
|
||||
@ -298,7 +304,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(RestRequest request) {
|
||||
public void authenticationFailed(String requestId, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_FAILED) && eventFilterPolicyRegistry.ignorePredicate().test(AuditEventMetaInfo.EMPTY) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
|
||||
@ -306,6 +312,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRestUri(request)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -313,7 +320,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -323,6 +330,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.withOpaqueId(threadContext)
|
||||
@ -333,7 +341,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_FAILED) && eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.empty(), Optional.empty())) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
@ -343,6 +351,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRestUri(request)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -350,7 +359,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, TransportMessage message) {
|
||||
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -362,6 +371,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(PRINCIPAL_FIELD_NAME, token.principal())
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.withOpaqueId(threadContext)
|
||||
@ -372,7 +382,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(REALM_AUTHENTICATION_FAILED) && eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.of(realm), Optional.empty())) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
@ -383,6 +393,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRestUri(request)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -390,20 +401,21 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage msg, String[] roleNames) {
|
||||
final User user = authentication.getUser();
|
||||
final boolean isSystem = SystemUser.is(user) || XPackUser.is(user);
|
||||
if ((isSystem && events.contains(SYSTEM_ACCESS_GRANTED)) || ((isSystem == false) && events.contains(ACCESS_GRANTED))) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
final Optional<String[]> indices = indices(msg);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(user),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), indices)) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "access_granted")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.with(REQUEST_NAME_FIELD_NAME, msg.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withSubject(authentication)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.withRestOrTransportOrigin(msg, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.with(PRINCIPAL_ROLES_FIELD_NAME, roleNames)
|
||||
.withOpaqueId(threadContext)
|
||||
@ -414,7 +426,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(ACCESS_DENIED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
@ -424,6 +436,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "access_denied")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withSubject(authentication)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
@ -436,7 +449,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(RestRequest request) {
|
||||
public void tamperedRequest(String requestId, RestRequest request) {
|
||||
if (events.contains(TAMPERED_REQUEST) && eventFilterPolicyRegistry.ignorePredicate().test(AuditEventMetaInfo.EMPTY) == false) {
|
||||
final StringMapMessage logEntry = new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
|
||||
@ -444,6 +457,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRestUri(request)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -451,7 +465,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(String action, TransportMessage message) {
|
||||
public void tamperedRequest(String requestId, String action, TransportMessage message) {
|
||||
if (events.contains(TAMPERED_REQUEST)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -461,6 +475,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
.withOpaqueId(threadContext)
|
||||
@ -471,7 +486,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tamperedRequest(User user, String action, TransportMessage message) {
|
||||
public void tamperedRequest(String requestId, User user, String action, TransportMessage message) {
|
||||
if (events.contains(TAMPERED_REQUEST)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
@ -481,6 +496,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.withPrincipal(user)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
@ -524,7 +540,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_GRANTED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
@ -534,6 +550,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "run_as_granted")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRunAsSubject(authentication)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
@ -546,7 +563,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)) {
|
||||
final Optional<String[]> indices = indices(message);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
@ -556,6 +573,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.with(EVENT_ACTION_FIELD_NAME, "run_as_denied")
|
||||
.with(ACTION_FIELD_NAME, action)
|
||||
.with(REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.withRequestId(requestId)
|
||||
.withRunAsSubject(authentication)
|
||||
.withRestOrTransportOrigin(message, threadContext)
|
||||
.with(INDICES_FIELD_NAME, indices.orElse(null))
|
||||
@ -568,7 +586,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
public void runAsDenied(String requestId, Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)
|
||||
&& eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), Optional.empty())) == false) {
|
||||
@ -580,6 +598,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
.withRunAsSubject(authentication)
|
||||
.withRestOrigin(request)
|
||||
.withRequestBody(request)
|
||||
.withRequestId(requestId)
|
||||
.withOpaqueId(threadContext)
|
||||
.build();
|
||||
logger.info(logEntry);
|
||||
@ -659,6 +678,13 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
||||
return this;
|
||||
}
|
||||
|
||||
LogEntryBuilder withRequestId(String requestId) {
|
||||
if (requestId != null) {
|
||||
logEntry.with(REQUEST_ID_FIELD_NAME, requestId);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
LogEntryBuilder withOpaqueId(ThreadContext threadContext) {
|
||||
final String opaqueId = threadContext.getHeader(Task.X_OPAQUE_ID);
|
||||
if (opaqueId != null) {
|
||||
|
@ -36,6 +36,7 @@ import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
import org.elasticsearch.xpack.security.authc.support.RealmUserLookup;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@ -149,7 +150,8 @@ public class AuthenticationService {
|
||||
}
|
||||
|
||||
Authenticator(String action, TransportMessage message, User fallbackUser, ActionListener<Authentication> listener) {
|
||||
this(new AuditableTransportRequest(auditTrail, failureHandler, threadContext, action, message), fallbackUser, listener);
|
||||
this(new AuditableTransportRequest(auditTrail, failureHandler, threadContext, action, message
|
||||
), fallbackUser, listener);
|
||||
}
|
||||
|
||||
private Authenticator(AuditableRequest auditableRequest, User fallbackUser, ActionListener<Authentication> listener) {
|
||||
@ -473,55 +475,58 @@ public class AuthenticationService {
|
||||
|
||||
private final String action;
|
||||
private final TransportMessage message;
|
||||
private final String requestId;
|
||||
|
||||
AuditableTransportRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext,
|
||||
String action, TransportMessage message) {
|
||||
super(auditTrail, failureHandler, threadContext);
|
||||
this.action = action;
|
||||
this.message = message;
|
||||
// There might be an existing audit-id (e.g. generated by the rest request) but there might not be (e.g. an internal action)
|
||||
this.requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
void authenticationSuccess(String realm, User user) {
|
||||
auditTrail.authenticationSuccess(realm, user, action, message);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, action, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
void realmAuthenticationFailed(AuthenticationToken token, String realm) {
|
||||
auditTrail.authenticationFailed(realm, token, action, message);
|
||||
auditTrail.authenticationFailed(requestId, realm, token, action, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException tamperedRequest() {
|
||||
auditTrail.tamperedRequest(action, message);
|
||||
auditTrail.tamperedRequest(requestId, action, message);
|
||||
return new ElasticsearchSecurityException("failed to verify signed authentication information");
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) {
|
||||
if (token != null) {
|
||||
auditTrail.authenticationFailed(token, action, message);
|
||||
auditTrail.authenticationFailed(requestId, token, action, message);
|
||||
} else {
|
||||
auditTrail.authenticationFailed(action, message);
|
||||
auditTrail.authenticationFailed(requestId, action, message);
|
||||
}
|
||||
return failureHandler.exceptionProcessingRequest(message, action, e, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) {
|
||||
auditTrail.authenticationFailed(token, action, message);
|
||||
auditTrail.authenticationFailed(requestId, token, action, message);
|
||||
return failureHandler.failedAuthentication(message, token, action, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException anonymousAccessDenied() {
|
||||
auditTrail.anonymousAccessDenied(action, message);
|
||||
auditTrail.anonymousAccessDenied(requestId, action, message);
|
||||
return failureHandler.missingToken(message, action, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException runAsDenied(Authentication authentication, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(authentication, action, message, Role.EMPTY.names());
|
||||
auditTrail.runAsDenied(requestId, authentication, action, message, Role.EMPTY.names());
|
||||
return failureHandler.failedAuthentication(message, token, action, threadContext);
|
||||
}
|
||||
|
||||
@ -535,54 +540,57 @@ public class AuthenticationService {
|
||||
static class AuditableRestRequest extends AuditableRequest {
|
||||
|
||||
private final RestRequest request;
|
||||
private final String requestId;
|
||||
|
||||
AuditableRestRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext,
|
||||
RestRequest request) {
|
||||
super(auditTrail, failureHandler, threadContext);
|
||||
this.request = request;
|
||||
// There should never be an existing audit-id when processing a rest request.
|
||||
this.requestId = AuditUtil.generateRequestId(threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
void authenticationSuccess(String realm, User user) {
|
||||
auditTrail.authenticationSuccess(realm, user, request);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
void realmAuthenticationFailed(AuthenticationToken token, String realm) {
|
||||
auditTrail.authenticationFailed(realm, token, request);
|
||||
auditTrail.authenticationFailed(requestId, realm, token, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException tamperedRequest() {
|
||||
auditTrail.tamperedRequest(request);
|
||||
auditTrail.tamperedRequest(requestId, request);
|
||||
return new ElasticsearchSecurityException("rest request attempted to inject a user");
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) {
|
||||
if (token != null) {
|
||||
auditTrail.authenticationFailed(token, request);
|
||||
auditTrail.authenticationFailed(requestId, token, request);
|
||||
} else {
|
||||
auditTrail.authenticationFailed(request);
|
||||
auditTrail.authenticationFailed(requestId, request);
|
||||
}
|
||||
return failureHandler.exceptionProcessingRequest(request, e, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) {
|
||||
auditTrail.authenticationFailed(token, request);
|
||||
auditTrail.authenticationFailed(requestId, token, request);
|
||||
return failureHandler.failedAuthentication(request, token, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException anonymousAccessDenied() {
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
auditTrail.anonymousAccessDenied(requestId, request);
|
||||
return failureHandler.missingToken(request, threadContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException runAsDenied(Authentication authentication, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(authentication, request, Role.EMPTY.names());
|
||||
auditTrail.runAsDenied(requestId, authentication, request, Role.EMPTY.names());
|
||||
return failureHandler.failedAuthentication(request, token, threadContext);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.core.security.user.XPackSecurityUser;
|
||||
import org.elasticsearch.xpack.core.security.user.XPackUser;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver.ResolvedIndices;
|
||||
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
||||
@ -82,13 +83,13 @@ import static org.elasticsearch.xpack.core.security.support.Exceptions.authoriza
|
||||
|
||||
public class AuthorizationService {
|
||||
public static final Setting<Boolean> ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING =
|
||||
Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope);
|
||||
Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope);
|
||||
public static final String ORIGINATING_ACTION_KEY = "_originating_action_name";
|
||||
public static final String ROLE_NAMES_KEY = "_effective_role_names";
|
||||
|
||||
private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate();
|
||||
private static final Predicate<String> SAME_USER_PRIVILEGE = Automatons.predicate(
|
||||
ChangePasswordAction.NAME, AuthenticateAction.NAME, HasPrivilegesAction.NAME, GetUserPrivilegesAction.NAME);
|
||||
ChangePasswordAction.NAME, AuthenticateAction.NAME, HasPrivilegesAction.NAME, GetUserPrivilegesAction.NAME);
|
||||
|
||||
private static final String INDEX_SUB_REQUEST_PRIMARY = IndexAction.NAME + "[p]";
|
||||
private static final String INDEX_SUB_REQUEST_REPLICA = IndexAction.NAME + "[r]";
|
||||
@ -135,6 +136,22 @@ public class AuthorizationService {
|
||||
public void authorize(Authentication authentication, String action, TransportRequest request, Role userRole,
|
||||
Role runAsRole) throws ElasticsearchSecurityException {
|
||||
final TransportRequest originalRequest = request;
|
||||
|
||||
String auditId = AuditUtil.extractRequestId(threadContext);
|
||||
if (auditId == null) {
|
||||
// We would like to assert that there is an existing request-id, but if this is a system action, then that might not be
|
||||
// true because the request-id is generated during authentication
|
||||
if (isInternalUser(authentication.getUser()) != false) {
|
||||
auditId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
} else {
|
||||
auditTrail.tamperedRequest(null, authentication.getUser(), action, request);
|
||||
final String message = "Attempt to authorize action [" + action + "] for [" + authentication.getUser().principal()
|
||||
+ "] without an existing request-id";
|
||||
assert false : message;
|
||||
throw new ElasticsearchSecurityException(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (request instanceof ConcreteShardRequest) {
|
||||
request = ((ConcreteShardRequest<?>) request).getRequest();
|
||||
assert TransportActionProxy.isProxyRequest(request) == false : "expected non-proxy request for action: " + action;
|
||||
@ -142,7 +159,7 @@ public class AuthorizationService {
|
||||
request = TransportActionProxy.unwrapRequest(request);
|
||||
if (TransportActionProxy.isProxyRequest(originalRequest) && TransportActionProxy.isProxyAction(action) == false) {
|
||||
throw new IllegalStateException("originalRequest is a proxy request for: [" + request + "] but action: ["
|
||||
+ action + "] isn't");
|
||||
+ action + "] isn't");
|
||||
}
|
||||
}
|
||||
// prior to doing any authorization lets set the originating action in the context only
|
||||
@ -153,10 +170,10 @@ public class AuthorizationService {
|
||||
if (SystemUser.isAuthorized(action)) {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
putTransientIfNonExisting(ROLE_NAMES_KEY, new String[] { SystemUser.ROLE_NAME });
|
||||
auditTrail.accessGranted(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
throw denial(auditId, authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
}
|
||||
|
||||
// get the roles of the authenticated user, which may be different than the effective
|
||||
@ -168,12 +185,12 @@ public class AuthorizationService {
|
||||
// if we are running as a user we looked up then the authentication must contain a lookedUpBy. If it doesn't then this user
|
||||
// doesn't really exist but the authc service allowed it through to avoid leaking users that exist in the system
|
||||
if (authentication.getLookedUpBy() == null) {
|
||||
throw denyRunAs(authentication, action, request, permission.names());
|
||||
throw denyRunAs(auditId, authentication, action, request, permission.names());
|
||||
} else if (permission.runAs().check(authentication.getUser().principal())) {
|
||||
auditTrail.runAsGranted(authentication, action, request, permission.names());
|
||||
auditTrail.runAsGranted(auditId, authentication, action, request, permission.names());
|
||||
permission = runAsRole;
|
||||
} else {
|
||||
throw denyRunAs(authentication, action, request, permission.names());
|
||||
throw denyRunAs(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
}
|
||||
putTransientIfNonExisting(ROLE_NAMES_KEY, permission.names());
|
||||
@ -181,55 +198,55 @@ public class AuthorizationService {
|
||||
// first, we'll check if the action is a cluster action. If it is, we'll only check it against the cluster permissions
|
||||
if (ClusterPrivilege.ACTION_MATCHER.test(action)) {
|
||||
final ClusterPermission cluster = permission.cluster();
|
||||
if (cluster.check(action, request) || checkSameUserPermissions(action, request, authentication) ) {
|
||||
if (cluster.check(action, request) || checkSameUserPermissions(action, request, authentication)) {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
// ok... this is not a cluster action, let's verify it's an indices action
|
||||
if (!IndexPrivilege.ACTION_MATCHER.test(action)) {
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
//composite actions are explicitly listed and will be authorized at the sub-request / shard level
|
||||
if (isCompositeAction(action)) {
|
||||
if (request instanceof CompositeIndicesRequest == false) {
|
||||
throw new IllegalStateException("Composite actions must implement " + CompositeIndicesRequest.class.getSimpleName()
|
||||
+ ", " + request.getClass().getSimpleName() + " doesn't");
|
||||
+ ", " + request.getClass().getSimpleName() + " doesn't");
|
||||
}
|
||||
// we check if the user can execute the action, without looking at indices, which will be authorized at the shard level
|
||||
if (permission.indices().check(action)) {
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
} else if (isTranslatedToBulkAction(action)) {
|
||||
if (request instanceof CompositeIndicesRequest == false) {
|
||||
throw new IllegalStateException("Bulk translated actions must implement " + CompositeIndicesRequest.class.getSimpleName()
|
||||
+ ", " + request.getClass().getSimpleName() + " doesn't");
|
||||
+ ", " + request.getClass().getSimpleName() + " doesn't");
|
||||
}
|
||||
// we check if the user can execute the action, without looking at indices, which will be authorized at the shard level
|
||||
if (permission.indices().check(action)) {
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
} else if (TransportActionProxy.isProxyAction(action)) {
|
||||
// we authorize proxied actions once they are "unwrapped" on the next node
|
||||
if (TransportActionProxy.isProxyRequest(originalRequest) == false) {
|
||||
throw new IllegalStateException("originalRequest is not a proxy request: [" + originalRequest + "] but action: ["
|
||||
+ action + "] is a proxy action");
|
||||
+ action + "] is a proxy action");
|
||||
}
|
||||
if (permission.indices().check(action)) {
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
} else {
|
||||
// we do this here in addition to the denial below since we might run into an assertion on scroll request below if we
|
||||
// don't have permission to read cross cluster but wrap a scroll request.
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,63 +265,63 @@ public class AuthorizationService {
|
||||
// index and if they cannot, we can fail the request early before we allow the execution of the action and in
|
||||
// turn the shard actions
|
||||
if (SearchScrollAction.NAME.equals(action) && permission.indices().check(action) == false) {
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
} else {
|
||||
// we store the request as a transient in the ThreadContext in case of a authorization failure at the shard
|
||||
// level. If authorization fails we will audit a access_denied message and will use the request to retrieve
|
||||
// information such as the index and the incoming address of the request
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
assert false :
|
||||
"only scroll related requests are known indices api that don't support retrieving the indices they relate to";
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
"only scroll related requests are known indices api that don't support retrieving the indices they relate to";
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
}
|
||||
|
||||
final boolean allowsRemoteIndices = request instanceof IndicesRequest
|
||||
&& IndicesAndAliasesResolver.allowsRemoteIndices((IndicesRequest) request);
|
||||
&& IndicesAndAliasesResolver.allowsRemoteIndices((IndicesRequest) request);
|
||||
|
||||
// If this request does not allow remote indices
|
||||
// then the user must have permission to perform this action on at least 1 local index
|
||||
if (allowsRemoteIndices == false && permission.indices().check(action) == false) {
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
final MetaData metaData = clusterService.state().metaData();
|
||||
final AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData);
|
||||
final ResolvedIndices resolvedIndices = resolveIndexNames(authentication, action, request,
|
||||
metaData, authorizedIndices, permission);
|
||||
final ResolvedIndices resolvedIndices = resolveIndexNames(auditId, authentication, action, request, metaData,
|
||||
authorizedIndices, permission);
|
||||
assert !resolvedIndices.isEmpty()
|
||||
: "every indices request needs to have its indices set thus the resolved indices must not be empty";
|
||||
: "every indices request needs to have its indices set thus the resolved indices must not be empty";
|
||||
|
||||
// If this request does reference any remote indices
|
||||
// then the user must have permission to perform this action on at least 1 local index
|
||||
if (resolvedIndices.getRemote().isEmpty() && permission.indices().check(action) == false) {
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
//all wildcard expressions have been resolved and only the security plugin could have set '-*' here.
|
||||
//'-*' matches no indices so we allow the request to go through, which will yield an empty response
|
||||
if (resolvedIndices.isNoIndicesPlaceholder()) {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_NO_INDICES);
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<String> localIndices = new HashSet<>(resolvedIndices.getLocal());
|
||||
IndicesAccessControl indicesAccessControl = permission.authorize(action, localIndices, metaData, fieldPermissionsCache);
|
||||
if (!indicesAccessControl.isGranted()) {
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
} else if (hasSecurityIndexAccess(indicesAccessControl)
|
||||
&& MONITOR_INDEX_PREDICATE.test(action) == false
|
||||
&& isSuperuser(authentication.getUser()) == false) {
|
||||
&& MONITOR_INDEX_PREDICATE.test(action) == false
|
||||
&& isSuperuser(authentication.getUser()) == false) {
|
||||
// only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging
|
||||
// purposes. These monitor requests also sometimes resolve indices concretely and then requests them
|
||||
logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]",
|
||||
authentication.getUser().principal(), action, SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
authentication.getUser().principal(), action, SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
throw denial(auditId, authentication, action, request, permission.names());
|
||||
} else {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, indicesAccessControl);
|
||||
}
|
||||
@ -320,7 +337,7 @@ public class AuthorizationService {
|
||||
}
|
||||
indicesAccessControl = permission.authorize("indices:admin/aliases", aliasesAndIndices, metaData, fieldPermissionsCache);
|
||||
if (!indicesAccessControl.isGranted()) {
|
||||
throw denial(authentication, "indices:admin/aliases", request, permission.names());
|
||||
throw denial(auditId, authentication, "indices:admin/aliases", request, permission.names());
|
||||
}
|
||||
// no need to re-add the indicesAccessControl in the context,
|
||||
// because the create index call doesn't do anything FLS or DLS
|
||||
@ -330,12 +347,16 @@ public class AuthorizationService {
|
||||
if (action.equals(TransportShardBulkAction.ACTION_NAME)) {
|
||||
// is this is performing multiple actions on the index, then check each of those actions.
|
||||
assert request instanceof BulkShardRequest
|
||||
: "Action " + action + " requires " + BulkShardRequest.class + " but was " + request.getClass();
|
||||
: "Action " + action + " requires " + BulkShardRequest.class + " but was " + request.getClass();
|
||||
|
||||
authorizeBulkItems(authentication, (BulkShardRequest) request, permission, metaData, localIndices, authorizedIndices);
|
||||
authorizeBulkItems(auditId, authentication, (BulkShardRequest) request, permission, metaData, localIndices, authorizedIndices);
|
||||
}
|
||||
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(auditId, authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
private boolean isInternalUser(User user) {
|
||||
return SystemUser.is(user) || XPackUser.is(user) || XPackSecurityUser.is(user);
|
||||
}
|
||||
|
||||
private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) {
|
||||
@ -355,14 +376,14 @@ public class AuthorizationService {
|
||||
* and then checks whether that action is allowed on the targeted index. Items
|
||||
* that fail this checks are {@link BulkItemRequest#abort(String, Exception)
|
||||
* aborted}, with an
|
||||
* {@link #denial(Authentication, String, TransportRequest, String[]) access
|
||||
* {@link #denial(String, Authentication, String, TransportRequest, String[]) access
|
||||
* denied} exception. Because a shard level request is for exactly 1 index, and
|
||||
* there are a small number of possible item {@link DocWriteRequest.OpType
|
||||
* types}, the number of distinct authorization checks that need to be performed
|
||||
* is very small, but the results must be cached, to avoid adding a high
|
||||
* overhead to each bulk request.
|
||||
*/
|
||||
private void authorizeBulkItems(Authentication authentication, BulkShardRequest request, Role permission,
|
||||
private void authorizeBulkItems(String auditRequestId, Authentication authentication, BulkShardRequest request, Role permission,
|
||||
MetaData metaData, Set<String> indices, AuthorizedIndices authorizedIndices) {
|
||||
// Maps original-index -> expanded-index-name (expands date-math, but not aliases)
|
||||
final Map<String, String> resolvedIndexNames = new HashMap<>();
|
||||
@ -371,14 +392,14 @@ public class AuthorizationService {
|
||||
for (BulkItemRequest item : request.items()) {
|
||||
String resolvedIndex = resolvedIndexNames.computeIfAbsent(item.index(), key -> {
|
||||
final ResolvedIndices resolvedIndices = indicesAndAliasesResolver.resolveIndicesAndAliases(item.request(), metaData,
|
||||
authorizedIndices);
|
||||
authorizedIndices);
|
||||
if (resolvedIndices.getRemote().size() != 0) {
|
||||
throw illegalArgument("Bulk item should not write to remote indices, but request writes to "
|
||||
+ String.join(",", resolvedIndices.getRemote()));
|
||||
+ String.join(",", resolvedIndices.getRemote()));
|
||||
}
|
||||
if (resolvedIndices.getLocal().size() != 1) {
|
||||
throw illegalArgument("Bulk item should write to exactly 1 index, but request writes to "
|
||||
+ String.join(",", resolvedIndices.getLocal()));
|
||||
+ String.join(",", resolvedIndices.getLocal()));
|
||||
}
|
||||
final String resolved = resolvedIndices.getLocal().get(0);
|
||||
if (indices.contains(resolved) == false) {
|
||||
@ -390,11 +411,11 @@ public class AuthorizationService {
|
||||
final Tuple<String, String> indexAndAction = new Tuple<>(resolvedIndex, itemAction);
|
||||
final boolean granted = indexActionAuthority.computeIfAbsent(indexAndAction, key -> {
|
||||
final IndicesAccessControl itemAccessControl = permission.authorize(itemAction, Collections.singleton(resolvedIndex),
|
||||
metaData, fieldPermissionsCache);
|
||||
metaData, fieldPermissionsCache);
|
||||
return itemAccessControl.isGranted();
|
||||
});
|
||||
if (granted == false) {
|
||||
item.abort(resolvedIndex, denial(authentication, itemAction, request, permission.names()));
|
||||
item.abort(resolvedIndex, denial(auditRequestId, authentication, itemAction, request, permission.names()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,12 +439,12 @@ public class AuthorizationService {
|
||||
throw new IllegalArgumentException("No equivalent action for opType [" + docWriteRequest.opType() + "]");
|
||||
}
|
||||
|
||||
private ResolvedIndices resolveIndexNames(Authentication authentication, String action, TransportRequest request,
|
||||
private ResolvedIndices resolveIndexNames(String auditRequestId, Authentication authentication, String action, TransportRequest request,
|
||||
MetaData metaData, AuthorizedIndices authorizedIndices, Role permission) {
|
||||
try {
|
||||
return indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices);
|
||||
} catch (Exception e) {
|
||||
auditTrail.accessDenied(authentication, action, request, permission.names());
|
||||
auditTrail.accessDenied(auditRequestId, authentication, action, request, permission.names());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -442,7 +463,7 @@ public class AuthorizationService {
|
||||
// passed into this method. The XPackUser has the Superuser role and we can simply return that
|
||||
if (SystemUser.is(user)) {
|
||||
throw new IllegalArgumentException("the user [" + user.principal() + "] is the system user and we should never try to get its" +
|
||||
" roles");
|
||||
" roles");
|
||||
}
|
||||
if (XPackUser.is(user)) {
|
||||
assert XPackUser.INSTANCE.roles().length == 1;
|
||||
@ -474,35 +495,35 @@ public class AuthorizationService {
|
||||
|
||||
private static boolean isCompositeAction(String action) {
|
||||
return action.equals(BulkAction.NAME) ||
|
||||
action.equals(MultiGetAction.NAME) ||
|
||||
action.equals(MultiTermVectorsAction.NAME) ||
|
||||
action.equals(MultiSearchAction.NAME) ||
|
||||
action.equals("indices:data/read/mpercolate") ||
|
||||
action.equals("indices:data/read/msearch/template") ||
|
||||
action.equals("indices:data/read/search/template") ||
|
||||
action.equals("indices:data/write/reindex") ||
|
||||
action.equals("indices:data/read/sql") ||
|
||||
action.equals("indices:data/read/sql/translate");
|
||||
action.equals(MultiGetAction.NAME) ||
|
||||
action.equals(MultiTermVectorsAction.NAME) ||
|
||||
action.equals(MultiSearchAction.NAME) ||
|
||||
action.equals("indices:data/read/mpercolate") ||
|
||||
action.equals("indices:data/read/msearch/template") ||
|
||||
action.equals("indices:data/read/search/template") ||
|
||||
action.equals("indices:data/write/reindex") ||
|
||||
action.equals("indices:data/read/sql") ||
|
||||
action.equals("indices:data/read/sql/translate");
|
||||
}
|
||||
|
||||
private static boolean isTranslatedToBulkAction(String action) {
|
||||
return action.equals(IndexAction.NAME) ||
|
||||
action.equals(DeleteAction.NAME) ||
|
||||
action.equals(INDEX_SUB_REQUEST_PRIMARY) ||
|
||||
action.equals(INDEX_SUB_REQUEST_REPLICA) ||
|
||||
action.equals(DELETE_SUB_REQUEST_PRIMARY) ||
|
||||
action.equals(DELETE_SUB_REQUEST_REPLICA);
|
||||
action.equals(DeleteAction.NAME) ||
|
||||
action.equals(INDEX_SUB_REQUEST_PRIMARY) ||
|
||||
action.equals(INDEX_SUB_REQUEST_REPLICA) ||
|
||||
action.equals(DELETE_SUB_REQUEST_PRIMARY) ||
|
||||
action.equals(DELETE_SUB_REQUEST_REPLICA);
|
||||
}
|
||||
|
||||
private static boolean isScrollRelatedAction(String action) {
|
||||
return action.equals(SearchScrollAction.NAME) ||
|
||||
action.equals(SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.QUERY_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME) ||
|
||||
action.equals(ClearScrollAction.NAME) ||
|
||||
action.equals("indices:data/read/sql/close_cursor") ||
|
||||
action.equals(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
action.equals(SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.QUERY_SCROLL_ACTION_NAME) ||
|
||||
action.equals(SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME) ||
|
||||
action.equals(ClearScrollAction.NAME) ||
|
||||
action.equals("indices:data/read/sql/close_cursor") ||
|
||||
action.equals(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
}
|
||||
|
||||
static boolean checkSameUserPermissions(String action, TransportRequest request, Authentication authentication) {
|
||||
@ -526,7 +547,7 @@ public class AuthorizationService {
|
||||
|
||||
assert AuthenticateAction.NAME.equals(action) || HasPrivilegesAction.NAME.equals(action)
|
||||
|| GetUserPrivilegesAction.NAME.equals(action) || sameUsername == false
|
||||
: "Action '" + action + "' should not be possible when sameUsername=" + sameUsername;
|
||||
: "Action '" + action + "' should not be possible when sameUsername=" + sameUsername;
|
||||
return sameUsername;
|
||||
}
|
||||
return false;
|
||||
@ -550,14 +571,15 @@ public class AuthorizationService {
|
||||
return ReservedRealm.TYPE.equals(realmType) || NativeRealmSettings.TYPE.equals(realmType);
|
||||
}
|
||||
|
||||
ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||
auditTrail.accessDenied(authentication, action, request, roleNames);
|
||||
ElasticsearchSecurityException denial(String auditRequestId, Authentication authentication, String action, TransportRequest request,
|
||||
String[] roleNames) {
|
||||
auditTrail.accessDenied(auditRequestId, authentication, action, request, roleNames);
|
||||
return denialException(authentication, action);
|
||||
}
|
||||
|
||||
private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request,
|
||||
String[] roleNames) {
|
||||
auditTrail.runAsDenied(authentication, action, request, roleNames);
|
||||
private ElasticsearchSecurityException denyRunAs(String auditRequestId, Authentication authentication, String action,
|
||||
TransportRequest request, String[] roleNames) {
|
||||
auditTrail.runAsDenied(auditRequestId, authentication, action, request, roleNames);
|
||||
return denialException(authentication, action);
|
||||
}
|
||||
|
||||
@ -572,9 +594,9 @@ public class AuthorizationService {
|
||||
// check for run as
|
||||
if (authentication.getUser().isRunAs()) {
|
||||
logger.debug("action [{}] is unauthorized for user [{}] run as [{}]", action, authUser.principal(),
|
||||
authentication.getUser().principal());
|
||||
authentication.getUser().principal());
|
||||
return authorizationError("action [{}] is unauthorized for user [{}] run as [{}]", action, authUser.principal(),
|
||||
authentication.getUser().principal());
|
||||
authentication.getUser().principal());
|
||||
}
|
||||
logger.debug("action [{}] is unauthorized for user [{}]", action, authUser.principal());
|
||||
return authorizationError("action [{}] is unauthorized for user [{}]", action, authUser.principal());
|
||||
@ -582,7 +604,7 @@ public class AuthorizationService {
|
||||
|
||||
static boolean isSuperuser(User user) {
|
||||
return Arrays.stream(user.roles())
|
||||
.anyMatch(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()::equals);
|
||||
.anyMatch(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()::equals);
|
||||
}
|
||||
|
||||
public static void addSettings(List<Setting<?>> settings) {
|
||||
|
@ -15,6 +15,7 @@ import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationField;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
||||
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ROLE_NAMES_KEY;
|
||||
@ -63,7 +64,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||
final Authentication current = Authentication.getAuthentication(threadContext);
|
||||
final String action = threadContext.getTransient(ORIGINATING_ACTION_KEY);
|
||||
ensureAuthenticatedUserIsSame(originalAuth, current, auditTrailService, searchContext.id(), action, request,
|
||||
threadContext.getTransient(ROLE_NAMES_KEY));
|
||||
AuditUtil.extractRequestId(threadContext), threadContext.getTransient(ROLE_NAMES_KEY));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +76,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||
* (or lookup) realm. To work around this we compare the username and the originating realm type.
|
||||
*/
|
||||
static void ensureAuthenticatedUserIsSame(Authentication original, Authentication current, AuditTrailService auditTrailService,
|
||||
long id, String action, TransportRequest request, String[] roleNames) {
|
||||
long id, String action, TransportRequest request, String requestId, String[] roleNames) {
|
||||
// this is really a best effort attempt since we cannot guarantee principal uniqueness
|
||||
// and realm names can change between nodes.
|
||||
final boolean samePrincipal = original.getUser().principal().equals(current.getUser().principal());
|
||||
@ -94,7 +95,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||
|
||||
final boolean sameUser = samePrincipal && sameRealmType;
|
||||
if (sameUser == false) {
|
||||
auditTrailService.accessDenied(current, action, request, roleNames);
|
||||
auditTrailService.accessDenied(requestId, current, action, request, roleNames);
|
||||
throw new SearchContextMissingException(id);
|
||||
}
|
||||
}
|
||||
|
@ -54,11 +54,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailed() throws Exception {
|
||||
service.authenticationFailed(token, "_action", message);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, token, "_action", message);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(requestId, token, "_action", message);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -66,11 +67,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedNoToken() throws Exception {
|
||||
service.authenticationFailed("_action", message);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, "_action", message);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed("_action", message);
|
||||
verify(auditTrail).authenticationFailed(requestId, "_action", message);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -78,11 +80,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedRestNoToken() throws Exception {
|
||||
service.authenticationFailed(restRequest);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, restRequest);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed(restRequest);
|
||||
verify(auditTrail).authenticationFailed(requestId, restRequest);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -90,11 +93,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedRest() throws Exception {
|
||||
service.authenticationFailed(token, restRequest);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, token, restRequest);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
verify(auditTrail).authenticationFailed(requestId, token, restRequest);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -102,11 +106,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedRealm() throws Exception {
|
||||
service.authenticationFailed("_realm", token, "_action", message);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, "_realm", token, "_action", message);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed("_realm", token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(requestId, "_realm", token, "_action", message);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -114,11 +119,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedRestRealm() throws Exception {
|
||||
service.authenticationFailed("_realm", token, restRequest);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationFailed(requestId, "_realm", token, restRequest);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationFailed("_realm", token, restRequest);
|
||||
verify(auditTrail).authenticationFailed(requestId, "_realm", token, restRequest);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -126,11 +132,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAnonymousAccess() throws Exception {
|
||||
service.anonymousAccessDenied("_action", message);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.anonymousAccessDenied(requestId, "_action", message);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).anonymousAccessDenied("_action", message);
|
||||
verify(auditTrail).anonymousAccessDenied(requestId, "_action", message);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -141,11 +148,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
Authentication authentication =new Authentication(new User("_username", "r1"), new RealmRef(null, null, null),
|
||||
new RealmRef(null, null, null));
|
||||
String[] roles = new String[] { randomAlphaOfLengthBetween(1, 6) };
|
||||
service.accessGranted(authentication, "_action", message, roles);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.accessGranted(requestId, authentication, "_action", message, roles);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).accessGranted(authentication, "_action", message, roles);
|
||||
verify(auditTrail).accessGranted(requestId, authentication, "_action", message, roles);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -156,11 +164,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
Authentication authentication = new Authentication(new User("_username", "r1"), new RealmRef(null, null, null),
|
||||
new RealmRef(null, null, null));
|
||||
String[] roles = new String[] { randomAlphaOfLengthBetween(1, 6) };
|
||||
service.accessDenied(authentication, "_action", message, roles);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.accessDenied(requestId, authentication, "_action", message, roles);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).accessDenied(authentication, "_action", message, roles);
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "_action", message, roles);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -198,11 +207,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
public void testAuthenticationSuccessRest() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
String realm = "_realm";
|
||||
service.authenticationSuccess(realm, user, restRequest);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationSuccess(requestId, realm, user, restRequest);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationSuccess(realm, user, restRequest);
|
||||
verify(auditTrail).authenticationSuccess(requestId, realm, user, restRequest);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
@ -212,11 +222,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||
public void testAuthenticationSuccessTransport() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
String realm = "_realm";
|
||||
service.authenticationSuccess(realm, user, "_action", message);
|
||||
final String requestId = randomAlphaOfLengthBetween(6, 12);
|
||||
service.authenticationSuccess(requestId, realm, user, "_action", message);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).authenticationSuccess(realm, user, "_action", message);
|
||||
verify(auditTrail).authenticationSuccess(requestId, realm, user, "_action", message);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
|
@ -92,7 +92,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
public void testAnonymousAccessDeniedMutedTransport() {
|
||||
createAuditTrail(new String[] { "anonymous_access_denied" });
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
auditTrail.anonymousAccessDenied("_action", message);
|
||||
auditTrail.anonymousAccessDenied(randomAlphaOfLengthBetween(6, 12), "_action", message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -102,7 +102,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
public void testAnonymousAccessDeniedMutedRest() {
|
||||
createAuditTrail(new String[] { "anonymous_access_denied" });
|
||||
RestRequest restRequest = mock(RestRequest.class);
|
||||
auditTrail.anonymousAccessDenied(restRequest);
|
||||
auditTrail.anonymousAccessDenied(randomAlphaOfLengthBetween(6, 12), restRequest);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -115,12 +115,12 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
|
||||
// without realm
|
||||
auditTrail.authenticationFailed(token, "_action", message);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), token, "_action", message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
// without the token
|
||||
auditTrail.authenticationFailed("_action", message);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), "_action", message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -133,12 +133,12 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
|
||||
// without the realm
|
||||
auditTrail.authenticationFailed(token, restRequest);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), token, restRequest);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
// without the token
|
||||
auditTrail.authenticationFailed(restRequest);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), restRequest);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -151,7 +151,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
|
||||
// with realm
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(2, 10), token, "_action", message);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), randomAlphaOfLengthBetween(2, 10), token, "_action", message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -164,7 +164,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
|
||||
// with realm
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(2, 10), token, restRequest);
|
||||
auditTrail.authenticationFailed(randomAlphaOfLengthBetween(6, 12), randomAlphaOfLengthBetween(2, 10), token, restRequest);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
verifyZeroInteractions(token, restRequest);
|
||||
@ -174,7 +174,8 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
createAuditTrail(new String[] { "access_granted" });
|
||||
final TransportMessage message = mock(TransportMessage.class);
|
||||
final Authentication authentication = mock(Authentication.class);
|
||||
auditTrail.accessGranted(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.accessGranted(randomAlphaOfLengthBetween(6, 12), authentication, randomAlphaOfLengthBetween(6, 40), message,
|
||||
new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
verifyZeroInteractions(message);
|
||||
@ -184,7 +185,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
createAuditTrail(randomFrom(new String[] { "access_granted" }, null));
|
||||
final TransportMessage message = mock(TransportMessage.class);
|
||||
final Authentication authentication = new Authentication(SystemUser.INSTANCE, new RealmRef(null, null, null), null);
|
||||
auditTrail.accessGranted(authentication, "internal:foo", message, new String[] { "role" });
|
||||
auditTrail.accessGranted(randomAlphaOfLengthBetween(6, 12), authentication, "internal:foo", message, new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -195,7 +196,8 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
createAuditTrail(new String[] { "access_denied" });
|
||||
final TransportMessage message = mock(TransportMessage.class);
|
||||
final Authentication authentication = mock(Authentication.class);
|
||||
auditTrail.accessDenied(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.accessDenied(randomAlphaOfLengthBetween(6, 12), authentication, randomAlphaOfLengthBetween(6, 40), message,
|
||||
new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -208,12 +210,12 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
User user = mock(User.class);
|
||||
|
||||
// with user
|
||||
auditTrail.tamperedRequest(user, randomAlphaOfLengthBetween(6, 40), message);
|
||||
auditTrail.tamperedRequest(randomAlphaOfLengthBetween(6, 12), user, randomAlphaOfLengthBetween(6, 40), message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
// without user
|
||||
auditTrail.tamperedRequest(randomAlphaOfLengthBetween(6, 40), message);
|
||||
auditTrail.tamperedRequest(randomAlphaOfLengthBetween(6, 12), randomAlphaOfLengthBetween(6, 40), message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -249,7 +251,8 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
|
||||
auditTrail.runAsGranted(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.runAsGranted(randomAlphaOfLengthBetween(6, 12), authentication, randomAlphaOfLengthBetween(6, 40), message,
|
||||
new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -261,7 +264,8 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
|
||||
auditTrail.runAsDenied(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.runAsDenied(randomAlphaOfLengthBetween(6, 12), authentication, randomAlphaOfLengthBetween(6, 40), message,
|
||||
new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -274,7 +278,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
User user = mock(User.class);
|
||||
String realm = "_realm";
|
||||
|
||||
auditTrail.authenticationSuccess(realm, user, restRequest);
|
||||
auditTrail.authenticationSuccess(randomAlphaOfLengthBetween(6, 12), realm, user, restRequest);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
@ -286,7 +290,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = mock(User.class);
|
||||
String realm = "_realm";
|
||||
auditTrail.authenticationSuccess(realm, user, randomAlphaOfLengthBetween(6, 40), message);
|
||||
auditTrail.authenticationSuccess(randomAlphaOfLengthBetween(6, 12), realm, user, randomAlphaOfLengthBetween(6, 40), message);
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
|
@ -431,7 +431,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAnonymousAccessDeniedTransport() throws Exception {
|
||||
initialize();
|
||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||
auditor.anonymousAccessDenied("_action", message);
|
||||
auditor.anonymousAccessDenied(randomAlphaOfLengthBetween(6, 12), "_action", message);
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "anonymous_access_denied");
|
||||
@ -454,7 +454,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAnonymousAccessDeniedRest() throws Exception {
|
||||
initialize();
|
||||
RestRequest request = mockRestRequest();
|
||||
auditor.anonymousAccessDenied(request);
|
||||
auditor.anonymousAccessDenied(randomAlphaOfLengthBetween(6, 12), request);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "rest", "anonymous_access_denied");
|
||||
@ -468,7 +468,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedTransport() throws Exception {
|
||||
initialize();
|
||||
TransportMessage message = randomBoolean() ? new RemoteHostMockMessage() : new LocalHostMockMessage();
|
||||
auditor.authenticationFailed(new MockToken(), "_action", message);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), new MockToken(), "_action", message);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
assertAuditMessage(hit, "transport", "authentication_failed");
|
||||
@ -488,7 +488,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedTransportNoToken() throws Exception {
|
||||
initialize();
|
||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||
auditor.authenticationFailed("_action", message);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), "_action", message);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "transport", "authentication_failed");
|
||||
@ -512,7 +512,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedRest() throws Exception {
|
||||
initialize();
|
||||
RestRequest request = mockRestRequest();
|
||||
auditor.authenticationFailed(new MockToken(), request);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), new MockToken(), request);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "rest", "authentication_failed");
|
||||
@ -527,7 +527,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedRestNoToken() throws Exception {
|
||||
initialize();
|
||||
RestRequest request = mockRestRequest();
|
||||
auditor.authenticationFailed(request);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), request);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "rest", "authentication_failed");
|
||||
@ -542,7 +542,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedTransportRealm() throws Exception {
|
||||
initialize();
|
||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||
auditor.authenticationFailed("_realm", new MockToken(), "_action", message);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), "_realm", new MockToken(), "_action", message);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "transport", "realm_authentication_failed");
|
||||
@ -568,7 +568,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testAuthenticationFailedRestRealm() throws Exception {
|
||||
initialize();
|
||||
RestRequest request = mockRestRequest();
|
||||
auditor.authenticationFailed("_realm", new MockToken(), request);
|
||||
auditor.authenticationFailed(randomAlphaOfLengthBetween(6, 12), "_realm", new MockToken(), request);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "rest", "realm_authentication_failed");
|
||||
@ -591,7 +591,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.accessGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
auditor.accessGranted(randomAlphaOfLengthBetween(6, 12), createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "access_granted");
|
||||
@ -619,7 +619,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
initialize(new String[] { "system_access_granted" }, null);
|
||||
TransportMessage message = randomBoolean() ? new RemoteHostMockMessage() : new LocalHostMockMessage();
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.accessGranted(createAuthentication(SystemUser.INSTANCE), "internal:_action", message, new String[] { role });
|
||||
auditor.accessGranted(randomAlphaOfLength(8), createAuthentication(SystemUser.INSTANCE), "internal:_action", message,
|
||||
new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "access_granted");
|
||||
@ -643,7 +644,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.accessDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
auditor.accessDenied(randomAlphaOfLengthBetween(6, 12), createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
@ -670,7 +671,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testTamperedRequestRest() throws Exception {
|
||||
initialize();
|
||||
RestRequest request = mockRestRequest();
|
||||
auditor.tamperedRequest(request);
|
||||
auditor.tamperedRequest(randomAlphaOfLengthBetween(6, 12), request);
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "rest", "tampered_request");
|
||||
@ -685,7 +686,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
public void testTamperedRequest() throws Exception {
|
||||
initialize();
|
||||
TransportRequest message = new RemoteHostMockTransportRequest();
|
||||
auditor.tamperedRequest("_action", message);
|
||||
auditor.tamperedRequest(randomAlphaOfLengthBetween(6, 12), "_action", message);
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
@ -706,7 +707,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
} else {
|
||||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
auditor.tamperedRequest(user, "_action", message);
|
||||
auditor.tamperedRequest(randomAlphaOfLengthBetween(6, 12), user, "_action", message);
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
@ -756,7 +757,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.runAsGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
auditor.runAsGranted(randomAlphaOfLengthBetween(6, 12), createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "run_as_granted");
|
||||
@ -775,7 +776,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
initialize();
|
||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||
auditor.runAsDenied(createAuthentication(user), "_action", message, new String[] { "r1" });
|
||||
auditor.runAsDenied(randomAlphaOfLengthBetween(6, 12), createAuthentication(user), "_action", message, new String[] { "r1" });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "run_as_denied");
|
||||
@ -800,7 +801,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
user = new User("_username", new String[] { "r1" });
|
||||
}
|
||||
String realm = "_realm";
|
||||
auditor.authenticationSuccess(realm, user, request);
|
||||
auditor.authenticationSuccess(randomAlphaOfLengthBetween(6, 12), realm, user, request);
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
|
||||
assertAuditMessage(hit, "rest", "authentication_success");
|
||||
@ -827,7 +828,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||
user = new User("_username", new String[] { "r1" });
|
||||
}
|
||||
String realm = "_realm";
|
||||
auditor.authenticationSuccess(realm, user, "_action", message);
|
||||
auditor.authenticationSuccess(randomAlphaOfLengthBetween(6, 12), realm, user, "_action", message);
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@ import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
||||
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
|
||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||
@ -200,12 +201,14 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
public void testAnonymousAccessDeniedTransport() throws Exception {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
|
||||
auditTrail.anonymousAccessDenied("_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.anonymousAccessDenied(requestId, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action");
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -218,7 +221,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "anonymous_access_denied")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.anonymousAccessDenied("_action", message);
|
||||
auditTrail.anonymousAccessDenied(requestId, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -229,7 +232,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final String expectedMessage = tuple.v1().expectedMessage();
|
||||
final RestRequest request = tuple.v2();
|
||||
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.anonymousAccessDenied(requestId, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
|
||||
@ -237,6 +241,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, null);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -249,7 +254,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "anonymous_access_denied")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.anonymousAccessDenied(request);
|
||||
auditTrail.anonymousAccessDenied(requestId, request);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -257,14 +262,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final AuthenticationToken mockToken = new MockToken();
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
|
||||
auditTrail.authenticationFailed(mockToken, "_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, mockToken, "_action", message);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, mockToken.principal())
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -277,20 +284,22 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
||||
auditTrail.authenticationFailed(requestId, new MockToken(), "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
public void testAuthenticationFailedNoToken() throws Exception {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
|
||||
auditTrail.authenticationFailed("_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -303,7 +312,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed("_action", message);
|
||||
auditTrail.authenticationFailed(requestId, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -319,7 +328,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final RestRequest request = tuple.v2();
|
||||
final AuthenticationToken mockToken = new MockToken();
|
||||
|
||||
auditTrail.authenticationFailed(mockToken, request);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, mockToken, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
@ -329,6 +339,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, params.isEmpty() ? null : "foo=bar");
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -341,7 +352,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed(new MockToken(), request);
|
||||
auditTrail.authenticationFailed(requestId, new MockToken(), request);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -356,7 +367,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final String expectedMessage = tuple.v1().expectedMessage();
|
||||
final RestRequest request = tuple.v2();
|
||||
|
||||
auditTrail.authenticationFailed(request);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
@ -366,6 +378,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, params.isEmpty() ? null : "bar=baz");
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -378,7 +391,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed(request);
|
||||
auditTrail.authenticationFailed(requestId, request);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -386,7 +399,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final AuthenticationToken mockToken = new MockToken();
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String realm = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.authenticationFailed(realm, mockToken, "_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, realm, mockToken, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
|
||||
// test enabled
|
||||
@ -395,7 +409,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.include", "realm_authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed(realm, mockToken, "_action", message);
|
||||
auditTrail.authenticationFailed(requestId, realm, mockToken, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
@ -403,7 +417,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.REALM_FIELD_NAME, realm)
|
||||
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, mockToken.principal())
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -422,7 +437,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final RestRequest request = tuple.v2();
|
||||
final AuthenticationToken mockToken = new MockToken();
|
||||
final String realm = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.authenticationFailed(realm, mockToken, request);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.authenticationFailed(requestId, realm, mockToken, request);
|
||||
assertEmptyLog(logger);
|
||||
|
||||
// test enabled
|
||||
@ -431,7 +447,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.include", "realm_authentication_failed")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationFailed(realm, mockToken, request);
|
||||
auditTrail.authenticationFailed(requestId, realm, mockToken, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "realm_authentication_failed")
|
||||
@ -442,6 +458,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, null)
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, params.isEmpty() ? null : "_param=baz");
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -452,14 +469,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String[] roles = randomArray(0, 4, String[]::new, () -> randomBoolean() ? null : randomAlphaOfLengthBetween(1, 4));
|
||||
final Authentication authentication = createAuthentication();
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
auditTrail.accessGranted(authentication, "_action", message, roles);
|
||||
auditTrail.accessGranted(requestId, authentication, "_action", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "access_granted")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
subject(authentication, checkedFields);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
@ -474,7 +493,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "access_granted")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessGranted(authentication, "_action", message, roles);
|
||||
auditTrail.accessGranted(requestId, authentication, "_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -482,7 +501,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String[] roles = randomArray(0, 4, String[]::new, () -> randomBoolean() ? null : randomAlphaOfLengthBetween(1, 4));
|
||||
final Authentication authentication = new Authentication(SystemUser.INSTANCE, new RealmRef("_reserved", "test", "foo"), null);
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, roles);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.accessGranted(requestId, authentication, "internal:_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
|
||||
// test enabled
|
||||
@ -491,7 +511,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.include", "system_access_granted")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, roles);
|
||||
auditTrail.accessGranted(requestId, authentication, "internal:_action", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
@ -499,7 +519,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, SystemUser.INSTANCE.principal())
|
||||
.put(LoggingAuditTrail.PRINCIPAL_REALM_FIELD_NAME, "_reserved")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "internal:_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
@ -511,14 +532,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String[] roles = randomArray(0, 4, String[]::new, () -> randomBoolean() ? null : randomAlphaOfLengthBetween(1, 4));
|
||||
final Authentication authentication = createAuthentication();
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, roles);
|
||||
auditTrail.accessGranted(requestId, authentication, "internal:_action", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "access_granted")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "internal:_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "access_granted")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "internal:_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
subject(authentication, checkedFields);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
@ -533,7 +556,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "access_granted")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, roles);
|
||||
auditTrail.accessGranted(requestId, authentication, "internal:_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -541,14 +564,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String[] roles = randomArray(0, 4, String[]::new, () -> randomBoolean() ? null : randomAlphaOfLengthBetween(1, 4));
|
||||
final Authentication authentication = createAuthentication();
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
auditTrail.accessDenied(authentication, "_action/bar", message, roles);
|
||||
auditTrail.accessDenied(requestId, authentication, "_action/bar", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "access_denied")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action/bar")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
subject(authentication, checkedFields);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
@ -563,7 +588,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "access_denied")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessDenied(authentication, "_action", message, roles);
|
||||
auditTrail.accessDenied(requestId, authentication, "_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -577,7 +602,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final Tuple<RestContent, RestRequest> tuple = prepareRestContent("_uri", address, params);
|
||||
final String expectedMessage = tuple.v1().expectedMessage();
|
||||
final RestRequest request = tuple.v2();
|
||||
auditTrail.tamperedRequest(request);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.tamperedRequest(requestId, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
@ -585,6 +611,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, params.isEmpty() ? null : "_param=baz");
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -597,20 +624,22 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "tampered_request")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.tamperedRequest(request);
|
||||
auditTrail.tamperedRequest(requestId, request);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
public void testTamperedRequest() throws Exception {
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
|
||||
auditTrail.tamperedRequest("_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.tamperedRequest(requestId, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
opaqueId(threadContext, checkedFields);
|
||||
@ -623,7 +652,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "tampered_request")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.tamperedRequest("_action", message);
|
||||
auditTrail.tamperedRequest(requestId, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -637,13 +666,15 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
user = new User("_username", new String[] { "r1" });
|
||||
}
|
||||
|
||||
auditTrail.tamperedRequest(user, "_action", message);
|
||||
final String requestId = randomRequestId();
|
||||
auditTrail.tamperedRequest(requestId, user, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
if (runAs) {
|
||||
checkedFields.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, "running_as");
|
||||
checkedFields.put(LoggingAuditTrail.PRINCIPAL_RUN_BY_FIELD_NAME, "_username");
|
||||
@ -662,7 +693,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "tampered_request")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.tamperedRequest(user, "_action", message);
|
||||
auditTrail.tamperedRequest(requestId, user, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -726,8 +757,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
new User("running as", new String[] { "r2" }, new User("_username", new String[] { "r1" })),
|
||||
new RealmRef("authRealm", "test", "foo"),
|
||||
new RealmRef("lookRealm", "up", "by"));
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
auditTrail.runAsGranted(authentication, "_action", message, roles);
|
||||
auditTrail.runAsGranted(requestId, authentication, "_action", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
@ -737,7 +769,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.PRINCIPAL_RUN_AS_FIELD_NAME, "running as")
|
||||
.put(LoggingAuditTrail.PRINCIPAL_RUN_AS_REALM_FIELD_NAME, "lookRealm")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
@ -751,7 +784,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "run_as_granted")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.runAsGranted(authentication, "_action", message, roles);
|
||||
auditTrail.runAsGranted(requestId, authentication, "_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -762,8 +795,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
new User("running as", new String[] { "r2" }, new User("_username", new String[] { "r1" })),
|
||||
new RealmRef("authRealm", "test", "foo"),
|
||||
new RealmRef("lookRealm", "up", "by"));
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
auditTrail.runAsDenied(authentication, "_action", message, roles);
|
||||
auditTrail.runAsDenied(requestId, authentication, "_action", message, roles);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
@ -773,7 +807,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.PRINCIPAL_RUN_AS_FIELD_NAME, "running as")
|
||||
.put(LoggingAuditTrail.PRINCIPAL_RUN_AS_REALM_FIELD_NAME, "lookRealm")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
checkedArrayFields.put(LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME, roles);
|
||||
restOrTransportOrigin(message, threadContext, checkedFields);
|
||||
indicesRequest(message, checkedFields, checkedArrayFields);
|
||||
@ -787,7 +822,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.exclude", "run_as_denied")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.runAsDenied(authentication, "_action", message, roles);
|
||||
auditTrail.runAsDenied(requestId, authentication, "_action", message, roles);
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
@ -809,9 +844,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
} else {
|
||||
user = new User("_username", new String[] { "r1" });
|
||||
}
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
// event by default disabled
|
||||
auditTrail.authenticationSuccess(realm, user, request);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, request);
|
||||
assertEmptyLog(logger);
|
||||
|
||||
settings = Settings.builder()
|
||||
@ -819,7 +855,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.include", "authentication_success")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationSuccess(realm, user, request);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, request);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.REST_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_success")
|
||||
@ -828,6 +864,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put(LoggingAuditTrail.ORIGIN_ADDRESS_FIELD_NAME, NetworkAddress.format(address))
|
||||
.put(LoggingAuditTrail.REQUEST_BODY_FIELD_NAME,
|
||||
includeRequestBody && Strings.hasLength(expectedMessage) ? expectedMessage : null)
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId)
|
||||
.put(LoggingAuditTrail.URL_PATH_FIELD_NAME, "_uri")
|
||||
.put(LoggingAuditTrail.URL_QUERY_FIELD_NAME, params.isEmpty() ? null : "foo=bar&evac=true");
|
||||
if (user.isRunAs()) {
|
||||
@ -849,9 +886,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
user = new User("_username", new String[] { "r1" });
|
||||
}
|
||||
final String realm = randomAlphaOfLengthBetween(1, 6);
|
||||
final String requestId = randomRequestId();
|
||||
|
||||
// event by default disabled
|
||||
auditTrail.authenticationSuccess(realm, user, "_action", message);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, "_action", message);
|
||||
assertEmptyLog(logger);
|
||||
|
||||
settings = Settings.builder()
|
||||
@ -859,14 +897,15 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
.put("xpack.security.audit.logfile.events.include", "authentication_success")
|
||||
.build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.authenticationSuccess(realm, user, "_action", message);
|
||||
auditTrail.authenticationSuccess(requestId, realm, user, "_action", message);
|
||||
final MapBuilder<String, String> checkedFields = new MapBuilder<>(commonFields);
|
||||
final MapBuilder<String, String[]> checkedArrayFields = new MapBuilder<>();
|
||||
checkedFields.put(LoggingAuditTrail.EVENT_TYPE_FIELD_NAME, LoggingAuditTrail.TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.put(LoggingAuditTrail.EVENT_ACTION_FIELD_NAME, "authentication_success")
|
||||
.put(LoggingAuditTrail.ACTION_FIELD_NAME, "_action")
|
||||
.put(LoggingAuditTrail.REALM_FIELD_NAME, realm)
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName());
|
||||
.put(LoggingAuditTrail.REQUEST_NAME_FIELD_NAME, message.getClass().getSimpleName())
|
||||
.put(LoggingAuditTrail.REQUEST_ID_FIELD_NAME, requestId);
|
||||
if (user.isRunAs()) {
|
||||
checkedFields.put(LoggingAuditTrail.PRINCIPAL_FIELD_NAME, "running as");
|
||||
checkedFields.put(LoggingAuditTrail.PRINCIPAL_RUN_BY_FIELD_NAME, "_username");
|
||||
@ -895,37 +934,37 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
final List<String> output = CapturingLogger.output(logger.getName(), Level.INFO);
|
||||
int logEntriesCount = 1;
|
||||
for (final TransportMessage message : messages) {
|
||||
auditTrail.anonymousAccessDenied("_action", message);
|
||||
auditTrail.anonymousAccessDenied("_req_id", "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.authenticationFailed(new MockToken(), "_action", message);
|
||||
auditTrail.authenticationFailed("_req_id", new MockToken(), "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.authenticationFailed("_action", message);
|
||||
auditTrail.authenticationFailed("_req_id", "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.authenticationFailed(realm, new MockToken(), "_action", message);
|
||||
auditTrail.authenticationFailed("_req_id", realm, new MockToken(), "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.accessGranted(createAuthentication(), "_action", message, new String[] { role });
|
||||
auditTrail.accessGranted("_req_id", createAuthentication(), "_action", message, new String[]{role});
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.accessDenied(createAuthentication(), "_action", message, new String[] { role });
|
||||
auditTrail.accessDenied("_req_id", createAuthentication(), "_action", message, new String[]{role});
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.tamperedRequest("_action", message);
|
||||
auditTrail.tamperedRequest("_req_id", "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.tamperedRequest(user, "_action", message);
|
||||
auditTrail.tamperedRequest("_req_id", user, "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.runAsGranted(createAuthentication(), "_action", message, new String[] { role });
|
||||
auditTrail.runAsGranted("_req_id", createAuthentication(), "_action", message, new String[]{role});
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.runAsDenied(createAuthentication(), "_action", message, new String[] { role });
|
||||
auditTrail.runAsDenied("_req_id", createAuthentication(), "_action", message, new String[]{role});
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
auditTrail.authenticationSuccess(realm, user, "_action", message);
|
||||
auditTrail.authenticationSuccess("_req_id", realm, user, "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=")));
|
||||
}
|
||||
@ -1092,6 +1131,13 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A tuple of ( id-to-pass-to-audit-trail, id-to-check-in-audit-message )
|
||||
*/
|
||||
private String randomRequestId() {
|
||||
return randomBoolean() ? randomAlphaOfLengthBetween(8, 24) : AuditUtil.generateRequestId(threadContext);
|
||||
}
|
||||
|
||||
private static void restOrTransportOrigin(TransportMessage message, ThreadContext threadContext,
|
||||
MapBuilder<String, String> checkedFields) {
|
||||
final InetSocketAddress restAddress = RemoteHostHeader.restRemoteAddress(threadContext);
|
||||
|
@ -66,6 +66,7 @@ import org.elasticsearch.xpack.core.security.user.AnonymousUser;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticator;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
@ -94,12 +95,15 @@ import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isEmptyOrNullString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@ -220,6 +224,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testTokenMissing() throws Exception {
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
PlainActionFuture<Authentication> future = new PlainActionFuture<>();
|
||||
Authenticator authenticator = service.createAuthenticator("_action", message, null, future);
|
||||
authenticator.extractToken((token) -> {
|
||||
@ -229,7 +234,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
|
||||
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class, () -> future.actionGet());
|
||||
assertThat(e.getMessage(), containsString("missing authentication token"));
|
||||
verify(auditTrail).anonymousAccessDenied("_action", message);
|
||||
verify(auditTrail).anonymousAccessDenied(reqId, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -244,6 +249,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
} else {
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
}
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final AtomicBoolean completed = new AtomicBoolean(false);
|
||||
service.authenticate("_action", message, (User)null, ActionListener.wrap(result -> {
|
||||
@ -255,7 +261,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
setCompletedToTrue(completed);
|
||||
}, this::logAndFail));
|
||||
assertTrue(completed.get());
|
||||
verify(auditTrail).authenticationFailed(firstRealm.name(), token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, firstRealm.name(), token, "_action", message);
|
||||
}
|
||||
|
||||
public void testAuthenticateFirstNotSupportingSecondSucceeds() throws Exception {
|
||||
@ -264,6 +270,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
mockAuthenticate(secondRealm, token, user);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final AtomicBoolean completed = new AtomicBoolean(false);
|
||||
service.authenticate("_action", message, (User)null, ActionListener.wrap(result -> {
|
||||
@ -272,7 +279,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
assertThreadContextContainsAuthentication(result);
|
||||
setCompletedToTrue(completed);
|
||||
}, this::logAndFail));
|
||||
verify(auditTrail).authenticationSuccess(secondRealm.name(), user, "_action", message);
|
||||
verify(auditTrail).authenticationSuccess(reqId, secondRealm.name(), user, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class));
|
||||
assertTrue(completed.get());
|
||||
@ -334,6 +341,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
public void testAuthenticateTransportAnonymous() throws Exception {
|
||||
when(firstRealm.token(threadContext)).thenReturn(null);
|
||||
when(secondRealm.token(threadContext)).thenReturn(null);
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("expected an authentication exception when trying to authenticate an anonymous message");
|
||||
@ -341,7 +349,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
// expected
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
verify(auditTrail).anonymousAccessDenied("_action", message);
|
||||
verify(auditTrail).anonymousAccessDenied(reqId, "_action", message);
|
||||
}
|
||||
|
||||
public void testAuthenticateRestAnonymous() throws Exception {
|
||||
@ -354,7 +362,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
// expected
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
verify(auditTrail).anonymousAccessDenied(restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).anonymousAccessDenied(reqId, restRequest);
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportFallback() throws Exception {
|
||||
@ -369,6 +378,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportDisabledUser() throws Exception {
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
User user = new User("username", new String[] { "r1", "r2" }, null, null, null, false);
|
||||
User fallback = randomBoolean() ? SystemUser.INSTANCE : null;
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
@ -377,7 +387,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
|
||||
ElasticsearchSecurityException e =
|
||||
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking("_action", message, fallback));
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
@ -390,12 +400,14 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
|
||||
ElasticsearchSecurityException e =
|
||||
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking(restRequest));
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, token, restRequest);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
|
||||
public void testAuthenticateTransportSuccess() throws Exception {
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
User user = new User("username", "r1", "r2");
|
||||
User fallback = randomBoolean() ? SystemUser.INSTANCE : null;
|
||||
when(firstRealm.token(threadContext)).thenReturn(token);
|
||||
@ -410,7 +422,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
setCompletedToTrue(completed);
|
||||
}, this::logAndFail));
|
||||
|
||||
verify(auditTrail).authenticationSuccess(firstRealm.name(), user, "_action", message);
|
||||
verify(auditTrail).authenticationSuccess(reqId, firstRealm.name(), user, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertTrue(completed.get());
|
||||
}
|
||||
@ -428,7 +440,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
assertThreadContextContainsAuthentication(authentication);
|
||||
setCompletedToTrue(completed);
|
||||
}, this::logAndFail));
|
||||
verify(auditTrail).authenticationSuccess(firstRealm.name(), user1, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationSuccess(reqId, firstRealm.name(), user1, restRequest);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertTrue(completed.get());
|
||||
}
|
||||
@ -516,12 +529,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
public void testAuthenticateTamperedUser() throws Exception {
|
||||
InternalMessage message = new InternalMessage();
|
||||
threadContext.putHeader(AuthenticationField.AUTHENTICATION_KEY, "_signed_auth");
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
try {
|
||||
authenticateBlocking("_action", message, randomBoolean() ? SystemUser.INSTANCE : null);
|
||||
} catch (Exception e) {
|
||||
//expected
|
||||
verify(auditTrail).tamperedRequest("_action", message);
|
||||
verify(auditTrail).tamperedRequest(reqId, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
@ -544,7 +558,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result.getUser(), sameInstance((Object) anonymousUser));
|
||||
assertThreadContextContainsAuthentication(result);
|
||||
verify(auditTrail).authenticationSuccess("__anonymous", new AnonymousUser(settings), request);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationSuccess(reqId, "__anonymous", new AnonymousUser(settings), request);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -580,13 +595,14 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
}
|
||||
|
||||
public void testRealmTokenThrowingException() throws Exception {
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
when(firstRealm.token(threadContext)).thenThrow(authenticationError("realm doesn't like tokens"));
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like tokens"));
|
||||
verify(auditTrail).authenticationFailed("_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, "_action", message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +613,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like tokens"));
|
||||
verify(auditTrail).authenticationFailed(restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, restRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,12 +622,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenThrow(authenticationError("realm doesn't like supports"));
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like supports"));
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,11 +641,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like supports"));
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, token, restRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRealmAuthenticateTerminatingAuthenticationProcess() throws Exception {
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
final AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
@ -663,8 +683,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
assertThat(e.getHeader("WWW-Authenticate"), contains(basicScheme));
|
||||
}
|
||||
}
|
||||
verify(auditTrail).authenticationFailed(secondRealm.name(), token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, secondRealm.name(), token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -674,12 +694,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
doThrow(authenticationError("realm doesn't like authenticate"))
|
||||
.when(secondRealm).authenticate(eq(token), any(ActionListener.class));
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like authenticate"));
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,7 +715,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchSecurityException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't like authenticate"));
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, token, restRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -707,13 +729,14 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
mockRealmLookupReturnsNull(firstRealm, "run_as");
|
||||
doThrow(authenticationError("realm doesn't want to lookup"))
|
||||
.when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
try {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't want to lookup"));
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -726,13 +749,13 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
mockRealmLookupReturnsNull(firstRealm, "run_as");
|
||||
doThrow(authenticationError("realm doesn't want to lookup"))
|
||||
.when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
|
||||
|
||||
try {
|
||||
authenticateBlocking(restRequest);
|
||||
fail("exception should bubble out");
|
||||
} catch (ElasticsearchException e) {
|
||||
assertThat(e.getMessage(), is("realm doesn't want to lookup"));
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, token, restRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -832,7 +855,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
authenticateBlocking(restRequest);
|
||||
fail("exception should be thrown");
|
||||
} catch (ElasticsearchException e) {
|
||||
verify(auditTrail).runAsDenied(any(Authentication.class), eq(restRequest), eq(Role.EMPTY.names()));
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).runAsDenied(eq(reqId), any(Authentication.class), eq(restRequest), eq(Role.EMPTY.names()));
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
@ -841,6 +865,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
User user = new User("lookup user", new String[]{"user"});
|
||||
threadContext.putHeader(AuthenticationServiceField.RUN_AS_USER_HEADER, "");
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
mockAuthenticate(secondRealm, token, user);
|
||||
@ -849,7 +874,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should be thrown");
|
||||
} catch (ElasticsearchException e) {
|
||||
verify(auditTrail).runAsDenied(any(Authentication.class), eq("_action"), eq(message), eq(Role.EMPTY.names()));
|
||||
verify(auditTrail).runAsDenied(eq(reqId), any(Authentication.class), eq("_action"), eq(message), eq(Role.EMPTY.names()));
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
@ -858,6 +883,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
public void testAuthenticateTransportDisabledRunAsUser() throws Exception {
|
||||
AuthenticationToken token = mock(AuthenticationToken.class);
|
||||
threadContext.putHeader(AuthenticationServiceField.RUN_AS_USER_HEADER, "run_as");
|
||||
final String reqId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
when(secondRealm.token(threadContext)).thenReturn(token);
|
||||
when(secondRealm.supports(token)).thenReturn(true);
|
||||
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
|
||||
@ -870,7 +896,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
User fallback = randomBoolean() ? SystemUser.INSTANCE : null;
|
||||
ElasticsearchSecurityException e =
|
||||
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking("_action", message, fallback));
|
||||
verify(auditTrail).authenticationFailed(token, "_action", message);
|
||||
verify(auditTrail).authenticationFailed(reqId, token, "_action", message);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
@ -891,7 +917,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
|
||||
ElasticsearchSecurityException e =
|
||||
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking(restRequest));
|
||||
verify(auditTrail).authenticationFailed(token, restRequest);
|
||||
String reqId = expectAuditRequestId();
|
||||
verify(auditTrail).authenticationFailed(reqId, token, restRequest);
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
assertAuthenticationException(e);
|
||||
}
|
||||
@ -923,7 +950,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
}, this::logAndFail));
|
||||
}
|
||||
assertTrue(completed.get());
|
||||
verify(auditTrail).authenticationSuccess("realm", user, "_action", message);
|
||||
verify(auditTrail).authenticationSuccess(anyString(), eq("realm"), eq(user), eq("_action"), same(message));
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -973,7 +1000,8 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
// we need to use a latch here because the key computation goes async on another thread!
|
||||
latch.await();
|
||||
if (success.get()) {
|
||||
verify(auditTrail).authenticationSuccess(firstRealm.name(), user, "_action", message);
|
||||
final String realmName = firstRealm.name();
|
||||
verify(auditTrail).authenticationSuccess(anyString(), eq(realmName), eq(user), eq("_action"), same(message));
|
||||
}
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
@ -1087,6 +1115,12 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||
return future.actionGet();
|
||||
}
|
||||
|
||||
private String expectAuditRequestId() {
|
||||
String reqId = AuditUtil.extractRequestId(threadContext);
|
||||
assertThat(reqId, not(isEmptyOrNullString()));
|
||||
return reqId;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void mockRealmLookupReturnsNull(Realm realm, String username) {
|
||||
doAnswer((i) -> {
|
||||
|
@ -125,6 +125,7 @@ import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.core.security.user.XPackUser;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
import org.elasticsearch.xpack.security.audit.AuditUtil;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
||||
import org.elasticsearch.xpack.security.authz.store.NativePrivilegeStore;
|
||||
@ -242,6 +243,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
|
||||
public void testActionsForSystemUserIsAuthorized() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
// A failure would throw an exception
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
@ -250,7 +252,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
"indices:admin/settings/update" };
|
||||
for (String action : actions) {
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
}
|
||||
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
@ -259,30 +261,35 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
public void testIndicesActionsForSystemUserWhichAreNotAuthorized() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "indices:", request),
|
||||
"indices:", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(authentication, "indices:", request, new String[]{SystemUser.ROLE_NAME});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:", request, new String[]{SystemUser.ROLE_NAME});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testClusterAdminActionsForSystemUserWhichAreNotAuthorized() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "cluster:admin/whatever", request),
|
||||
"cluster:admin/whatever", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(authentication, "cluster:admin/whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "cluster:admin/whatever", request,
|
||||
new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testClusterAdminSnapshotStatusActionForSystemUserWhichIsNotAuthorized() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "cluster:admin/snapshot/status", request),
|
||||
"cluster:admin/snapshot/status", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(authentication, "cluster:admin/snapshot/status", request, new String[] { SystemUser.ROLE_NAME });
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "cluster:admin/snapshot/status", request,
|
||||
new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -297,11 +304,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final ConditionalClusterPrivilege[] conditionalClusterPrivileges = new ConditionalClusterPrivilege[] {
|
||||
conditionalClusterPrivilege
|
||||
};
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
RoleDescriptor role = new RoleDescriptor("role1", null, null, null, conditionalClusterPrivileges, null, null ,null);
|
||||
roleMap.put("role1", role);
|
||||
|
||||
authorize(authentication, DeletePrivilegesAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, DeletePrivilegesAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, DeletePrivilegesAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -316,13 +324,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final ConditionalClusterPrivilege[] conditionalClusterPrivileges = new ConditionalClusterPrivilege[] {
|
||||
conditionalClusterPrivilege
|
||||
};
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
RoleDescriptor role = new RoleDescriptor("role1", null, null, null, conditionalClusterPrivileges, null, null ,null);
|
||||
roleMap.put("role1", role);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, DeletePrivilegesAction.NAME, request),
|
||||
DeletePrivilegesAction.NAME, "user1");
|
||||
verify(auditTrail).accessDenied(authentication, DeletePrivilegesAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, DeletePrivilegesAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -330,10 +339,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final TransportRequest request = new SearchRequest();
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user");
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -342,8 +352,9 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
request.indices("other_cluster:index1", "*_cluster:index2", "other_cluster:other_*");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
authorize(authentication, SearchAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -357,10 +368,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
request.indices("no_such_cluster:index");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, SearchAction.NAME, request),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -373,10 +385,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
request.indices("local_index", "wildcard_*", "other_cluster:remote_index", "*:foo?");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, SearchAction.NAME, request),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -384,10 +397,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
TransportRequest request = new SqlQueryRequest();
|
||||
Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, SqlQueryAction.NAME, request),
|
||||
SqlQueryAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, SqlQueryAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, SqlQueryAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
/**
|
||||
@ -399,10 +413,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
request.indices("other_cluster:index1", "other_cluster:index2");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, DeleteIndexAction.NAME, request),
|
||||
DeleteIndexAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, DeleteIndexAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, DeleteIndexAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -414,16 +429,18 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
String action = tuple.v1();
|
||||
TransportRequest request = tuple.v2();
|
||||
final Authentication authentication = createAuthentication(new User("test user", "non-existent-role"));
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testThatNonIndicesAndNonClusterActionIsDenied() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
final RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
@ -432,7 +449,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "whatever", request),
|
||||
"whatever", "test user");
|
||||
verify(auditTrail).accessDenied(authentication, "whatever", request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "whatever", request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -444,6 +461,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new Tuple<>(SqlQueryAction.NAME, new SqlQueryRequest()));
|
||||
String action = tuple.v1();
|
||||
TransportRequest request = tuple.v2();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "no_indices"));
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null, null, null);
|
||||
roleMap.put("no_indices", role);
|
||||
@ -452,22 +470,24 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testElasticUserAuthorizedForNonChangePasswordRequestsWhenNotInSetupMode() {
|
||||
final Authentication authentication = createAuthentication(new ElasticUser(true));
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
final Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||
authorize(authentication, request.v1(), request.v2());
|
||||
|
||||
verify(auditTrail).accessGranted(authentication, request.v1(), request.v2(), new String[]{ElasticUser.ROLE_NAME});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, request.v1(), request.v2(), new String[]{ElasticUser.ROLE_NAME});
|
||||
}
|
||||
|
||||
public void testSearchAgainstEmptyCluster() {
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
|
||||
@ -480,7 +500,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, SearchAction.NAME, searchRequest),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, searchRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, SearchAction.NAME, searchRequest, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -489,7 +509,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
SearchRequest searchRequest = new SearchRequest("does_not_exist")
|
||||
.indicesOptions(IndicesOptions.fromOptions(true, true, true, false));
|
||||
authorize(authentication, SearchAction.NAME, searchRequest);
|
||||
verify(auditTrail).accessGranted(authentication, SearchAction.NAME, searchRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchAction.NAME, searchRequest, new String[]{role.getName()});
|
||||
final IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
final IndicesAccessControl.IndexAccessControl indexAccessControl =
|
||||
indicesAccessControl.getIndexPermissions(IndicesAndAliasesResolverField.NO_INDEX_PLACEHOLDER);
|
||||
@ -504,35 +524,38 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
authorize(authentication, ClearScrollAction.NAME, clearScrollRequest);
|
||||
verify(auditTrail).accessGranted(authentication, ClearScrollAction.NAME, clearScrollRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, ClearScrollAction.NAME, clearScrollRequest,
|
||||
new String[]{role.getName()});
|
||||
|
||||
final SearchScrollRequest searchScrollRequest = new SearchScrollRequest();
|
||||
authorize(authentication, SearchScrollAction.NAME, searchScrollRequest);
|
||||
verify(auditTrail).accessGranted(authentication, SearchScrollAction.NAME, searchScrollRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchScrollAction.NAME, searchScrollRequest,
|
||||
new String[]{role.getName()});
|
||||
|
||||
// We have to use a mock request for other Scroll actions as the actual requests are package private to SearchTransportService
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
authorize(authentication, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request,
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request,
|
||||
new String[]{role.getName()});
|
||||
|
||||
authorize(authentication, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request,
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request,
|
||||
new String[]{role.getName()});
|
||||
|
||||
authorize(authentication, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request,
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request,
|
||||
new String[]{role.getName()});
|
||||
|
||||
authorize(authentication, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request,
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request,
|
||||
new String[]{role.getName()});
|
||||
|
||||
authorize(authentication, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request,
|
||||
verify(auditTrail).accessGranted(requestId, authentication, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request,
|
||||
new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
@ -544,11 +567,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user");
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -562,11 +586,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, CreateIndexAction.NAME, request),
|
||||
IndicesAliasesAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, IndicesAliasesAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, IndicesAliasesAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -580,10 +605,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a", "a2").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
authorize(authentication, CreateIndexAction.NAME, request);
|
||||
|
||||
verify(auditTrail).accessGranted(authentication, CreateIndexAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, CreateIndexAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -600,12 +626,13 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final Authentication authentication = createAuthentication(anonymousUser);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", anonymousUser.principal());
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -625,11 +652,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> authorize(authentication, "indices:a", request));
|
||||
assertAuthenticationException(securityException, containsString("action [indices:a] requires authentication"));
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -643,13 +671,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final IndexNotFoundException nfe = expectThrows(
|
||||
IndexNotFoundException.class,
|
||||
() -> authorize(authentication, GetIndexAction.NAME, request));
|
||||
assertThat(nfe.getIndex(), is(notNullValue()));
|
||||
assertThat(nfe.getIndex().getName(), is("not-an-index-*"));
|
||||
verify(auditTrail).accessDenied(authentication, GetIndexAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, GetIndexAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
@ -657,16 +686,18 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
|
||||
public void testRunAsRequestWithNoRolesUser() {
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
final Authentication authentication = createAuthentication(new User("run as me", null, new User("test user", "admin")));
|
||||
assertNotEquals(authentication.getUser().authenticatedUser(), authentication);
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me"); // run as [run as me]
|
||||
verify(auditTrail).runAsDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).runAsDenied(requestId, authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testRunAsRequestWithoutLookedUpBy() {
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
AuthenticateRequest request = new AuthenticateRequest("run as me");
|
||||
roleMap.put("can run as", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR);
|
||||
User user = new User("run as me", Strings.EMPTY_ARRAY, new User("test user", new String[]{"can run as"}));
|
||||
@ -675,8 +706,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(authentication, AuthenticateAction.NAME, request),
|
||||
AuthenticateAction.NAME, "test user", "run as me"); // run as [run as me]
|
||||
verify(auditTrail).runAsDenied(authentication, AuthenticateAction.NAME, request,
|
||||
new String[]{ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()});
|
||||
verify(auditTrail).runAsDenied(requestId, authentication, AuthenticateAction.NAME, request,
|
||||
new String[] { ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -689,11 +720,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()},
|
||||
new String[]{"not the right user"});
|
||||
roleMap.put("can run as", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me");
|
||||
verify(auditTrail).runAsDenied(authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verify(auditTrail).runAsDenied(requestId, authentication, "indices:a", request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -723,15 +755,16 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
} else {
|
||||
mockEmptyMetaData();
|
||||
}
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me");
|
||||
verify(auditTrail).runAsGranted(authentication, "indices:a", request, new String[]{runAsRole.getName()});
|
||||
verify(auditTrail).runAsGranted(requestId, authentication, "indices:a", request, new String[]{runAsRole.getName()});
|
||||
if (indexExists) {
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[]{bRole.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, new String[]{bRole.getName()});
|
||||
} else {
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(requestId, authentication, "indices:a", request, Role.EMPTY.names());
|
||||
}
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
@ -756,10 +789,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
RoleDescriptor bRole = new RoleDescriptor("b", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("b").privileges("all").build()}, null);
|
||||
roleMap.put("b", bRole);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
authorize(authentication, "indices:a", request);
|
||||
verify(auditTrail).runAsGranted(authentication, "indices:a", request, new String[]{runAsRole.getName()});
|
||||
verify(auditTrail).accessGranted(authentication, "indices:a", request, new String[]{bRole.getName()});
|
||||
verify(auditTrail).runAsGranted(requestId, authentication, "indices:a", request, new String[]{runAsRole.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, "indices:a", request, new String[]{bRole.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -775,6 +809,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
|
||||
@ -800,19 +835,19 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "all_access_user");
|
||||
verify(auditTrail).accessDenied(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
// we should allow waiting for the health of the index or any index if the user has this permission
|
||||
ClusterHealthRequest request = new ClusterHealthRequest(SECURITY_INDEX_NAME);
|
||||
authorize(authentication, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()});
|
||||
|
||||
// multiple indices
|
||||
request = new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar");
|
||||
authorize(authentication, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
|
||||
final SearchRequest searchRequest = new SearchRequest("_all");
|
||||
@ -833,6 +868,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
List<Tuple<String, ? extends TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_INDEX_NAME)));
|
||||
@ -848,7 +884,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final String action = requestTuple.v1();
|
||||
final TransportRequest request = requestTuple.v2();
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
}
|
||||
}
|
||||
|
||||
@ -862,6 +898,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(DeleteAction.NAME,
|
||||
@ -891,7 +928,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final TransportRequest request = requestTuple.v2();
|
||||
final Authentication authentication = createAuthentication(superuser);
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, superuser.roles());
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, superuser.roles());
|
||||
}
|
||||
}
|
||||
|
||||
@ -906,11 +943,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||
.build());
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
String action = SearchAction.NAME;
|
||||
SearchRequest request = new SearchRequest("_all");
|
||||
authorize(createAuthentication(superuser), action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, superuser.roles());
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, superuser.roles());
|
||||
assertThat(request.indices(), arrayContaining(".security"));
|
||||
}
|
||||
|
||||
@ -923,6 +961,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
roleMap.put("anonymous_user_role", new RoleDescriptor("anonymous_user_role", new String[]{"all"},
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null));
|
||||
mockEmptyMetaData();
|
||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
// sanity check the anonymous user
|
||||
authorize(createAuthentication(anonymousUser), ClusterHealthAction.NAME, request);
|
||||
@ -963,9 +1002,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final Authentication authentication = createAuthentication(new User("test user", "no_indices"));
|
||||
final RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||
roleMap.put("no_indices", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, request), action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -979,14 +1020,17 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices(randomBoolean() ? "a" : "index").privileges("all").build()},
|
||||
null);
|
||||
roleMap.put("role", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testCompositeActionsMustImplementCompositeIndicesRequest() {
|
||||
String action = randomCompositeRequest().v1();
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
User user = new User("test user", "role");
|
||||
roleMap.put("role", new RoleDescriptor("role", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices(randomBoolean() ? "a" : "index").privileges("all").build()},
|
||||
@ -1033,6 +1077,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
User userDenied = new User("userDenied", "roleDenied");
|
||||
roleMap.put("roleDenied", new RoleDescriptor("roleDenied", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null));
|
||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
mockEmptyMetaData();
|
||||
authorize(createAuthentication(userAllowed), action, request);
|
||||
assertThrowsAuthorizationException(
|
||||
@ -1061,11 +1106,15 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
roleMap.put("my-role", role);
|
||||
|
||||
mockEmptyMetaData();
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
authorize(authentication, action, request);
|
||||
|
||||
verify(auditTrail).accessDenied(authentication, DeleteAction.NAME, request, new String[]{role.getName()}); // alias-1 delete
|
||||
verify(auditTrail).accessDenied(authentication, IndexAction.NAME, request, new String[]{role.getName()}); // alias-2 index
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[]{role.getName()}); // bulk request is allowed
|
||||
verify(auditTrail).accessDenied(requestId, authentication, DeleteAction.NAME, request,
|
||||
new String[] { role.getName() }); // alias-1 delete
|
||||
verify(auditTrail).accessDenied(requestId, authentication, IndexAction.NAME, request,
|
||||
new String[] { role.getName() }); // alias-2 index
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request,
|
||||
new String[] { role.getName() }); // bulk request is allowed
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -1086,15 +1135,16 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final RoleDescriptor role = new RoleDescriptor("my-role", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("datemath-*").privileges("index").build()}, null);
|
||||
roleMap.put("my-role", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
mockEmptyMetaData();
|
||||
authorize(authentication, action, request);
|
||||
|
||||
// both deletes should fail
|
||||
verify(auditTrail, Mockito.times(2)).accessDenied(authentication, DeleteAction.NAME, request,
|
||||
verify(auditTrail, Mockito.times(2)).accessDenied(requestId, authentication, DeleteAction.NAME, request,
|
||||
new String[]{role.getName()});
|
||||
// bulk request is allowed
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, request, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -1302,6 +1352,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
TransportRequest request = TransportRequest.Empty.INSTANCE;
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, request);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
User user = new User("test user", "role");
|
||||
IllegalStateException illegalStateException = expectThrows(IllegalStateException.class,
|
||||
() -> authorize(createAuthentication(user), "indices:some/action", transportRequest));
|
||||
@ -1313,6 +1364,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
public void testProxyRequestFailsOnNonProxyRequest() {
|
||||
TransportRequest request = TransportRequest.Empty.INSTANCE;
|
||||
User user = new User("test user", "role");
|
||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
IllegalStateException illegalStateException = expectThrows(IllegalStateException.class,
|
||||
() -> authorize(createAuthentication(user), TransportActionProxy.getProxyAction("indices:some/action"), request));
|
||||
assertThat(illegalStateException.getMessage(),
|
||||
@ -1329,9 +1381,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final Authentication authentication = createAuthentication(new User("test user", "no_indices"));
|
||||
final RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||
roleMap.put("no_indices", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, proxiedRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, proxiedRequest, new String[]{role.getName()});
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
@ -1340,6 +1394,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
mockEmptyMetaData();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
|
||||
@ -1347,7 +1403,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||
final String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
authorize(authentication, action, transportRequest);
|
||||
verify(auditTrail).accessGranted(authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
}
|
||||
|
||||
public void testProxyRequestAuthenticationGranted() {
|
||||
@ -1357,12 +1413,13 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
final ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
final TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||
final String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
authorize(authentication, action, transportRequest);
|
||||
verify(auditTrail).accessGranted(authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessGranted(requestId, authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
}
|
||||
|
||||
public void testProxyRequestAuthenticationDeniedWithReadPrivileges() {
|
||||
@ -1370,6 +1427,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("read").build()}, null);
|
||||
roleMap.put("a_all", role);
|
||||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
mockEmptyMetaData();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
@ -1377,6 +1435,6 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(authentication, action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
verify(auditTrail).accessDenied(requestId, authentication, action, clearScrollRequest, new String[]{role.getName()});
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
||||
assertEquals(testSearchContext.id(), expected.id());
|
||||
verify(licenseState, times(3)).isAuthAllowed();
|
||||
verify(auditTrailService).accessDenied(authentication, "action", request, authentication.getUser().roles());
|
||||
verify(auditTrailService).accessDenied(null, authentication, "action", request, authentication.getUser().roles());
|
||||
}
|
||||
|
||||
// another user running as the original user
|
||||
@ -152,7 +152,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
||||
assertEquals(testSearchContext.id(), expected.id());
|
||||
verify(licenseState, times(5)).isAuthAllowed();
|
||||
verify(auditTrailService).accessDenied(authentication, "action", request, authentication.getUser().roles());
|
||||
verify(auditTrailService).accessDenied(null, authentication, "action", request, authentication.getUser().roles());
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,55 +165,59 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||
TransportRequest request = Empty.INSTANCE;
|
||||
AuditTrailService auditTrail = mock(AuditTrailService.class);
|
||||
|
||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, original.getUser().roles());
|
||||
final String auditId = randomAlphaOfLengthBetween(8, 20);
|
||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, auditId, original.getUser().roles());
|
||||
verifyZeroInteractions(auditTrail);
|
||||
|
||||
// original user being run as
|
||||
User user = new User(new User("test", "role"), new User("authenticated", "runas"));
|
||||
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, original.getUser().roles());
|
||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, auditId, original.getUser().roles());
|
||||
verifyZeroInteractions(auditTrail);
|
||||
|
||||
// both user are run as
|
||||
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
||||
Authentication runAs = current;
|
||||
ensureAuthenticatedUserIsSame(runAs, current, auditTrail, id, action, request, original.getUser().roles());
|
||||
ensureAuthenticatedUserIsSame(runAs, current, auditTrail, id, action, request, auditId, original.getUser().roles());
|
||||
verifyZeroInteractions(auditTrail);
|
||||
|
||||
// different authenticated by type
|
||||
Authentication differentRealmType =
|
||||
new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null);
|
||||
SearchContextMissingException e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, id, action, request,
|
||||
() -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, id, action, request, auditId,
|
||||
original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(differentRealmType, action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(auditId, differentRealmType, action, request, original.getUser().roles());
|
||||
|
||||
// wrong user
|
||||
Authentication differentUser =
|
||||
new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null);
|
||||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, id, action, request, original.getUser().roles()));
|
||||
() -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, id, action, request, auditId,
|
||||
original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(differentUser, action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(auditId, differentUser, action, request, original.getUser().roles());
|
||||
|
||||
// run as different user
|
||||
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
||||
new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1"));
|
||||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, id, action, request, original.getUser().roles()));
|
||||
() -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, id, action, request, auditId,
|
||||
original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(diffRunAs, action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(auditId, diffRunAs, action, request, original.getUser().roles());
|
||||
|
||||
// run as different looked up by type
|
||||
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node"));
|
||||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, id, action, request, original.getUser().roles()));
|
||||
() -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, id, action, request, auditId,
|
||||
original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(runAsDiffType, action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(auditId, runAsDiffType, action, request, original.getUser().roles());
|
||||
}
|
||||
|
||||
static class TestScrollSearchContext extends TestSearchContext {
|
||||
|
Loading…
x
Reference in New Issue
Block a user