Realm along the principal in audit authz events (elastic/x-pack-elasticsearch#3260)
Add realm name to all authz audit events: accessDenied, accessGranted, runAsDenied and runAsGranted. These event types receive the following attributes: realm, run_by_realm and run_as_realm to go along with with the existing attributes: principal, run_by_principal and run_as_principal. The 'effective realm name' (run_as_realm or run_by_realm) is certainly filterable by ignore policies. Original commit: elastic/x-pack-elasticsearch@cb3801e197
This commit is contained in:
parent
14acdcb4f7
commit
7ea79c88ab
|
@ -69,6 +69,12 @@
|
|||
"realm": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"run_by_realm": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"run_as_realm": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"transport_profile": {
|
||||
"type": "keyword"
|
||||
},
|
||||
|
|
|
@ -162,15 +162,13 @@ public class SecurityActionFilter extends AbstractComponent implements ActionFil
|
|||
final AuthorizationUtils.AsyncAuthorizer asyncAuthorizer = new AuthorizationUtils.AsyncAuthorizer(authentication, listener,
|
||||
(userRoles, runAsRoles) -> {
|
||||
authzService.authorize(authentication, securityAction, request, userRoles, runAsRoles);
|
||||
final User user = authentication.getUser();
|
||||
|
||||
/*
|
||||
* We use a separate concept for code that needs to be run after authentication and authorization that could
|
||||
* affect the running of the action. This is done to make it more clear of the state of the request.
|
||||
*/
|
||||
for (RequestInterceptor interceptor : requestInterceptors) {
|
||||
if (interceptor.supports(request)) {
|
||||
interceptor.intercept(request, user, runAsRoles != null ? runAsRoles : userRoles, securityAction);
|
||||
interceptor.intercept(request, authentication, runAsRoles != null ? runAsRoles : userRoles, securityAction);
|
||||
}
|
||||
}
|
||||
listener.onResponse(null);
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.license.XPackLicenseState;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
|
@ -35,7 +36,8 @@ public class BulkShardRequestInterceptor extends AbstractComponent implements Re
|
|||
this.licenseState = licenseState;
|
||||
}
|
||||
|
||||
public void intercept(BulkShardRequest request, User user, Role userPermissions, String action) {
|
||||
@Override
|
||||
public void intercept(BulkShardRequest request, Authentication authentication, Role userPermissions, String action) {
|
||||
if (licenseState.isDocumentAndFieldLevelSecurityAllowed() == false) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import org.elasticsearch.common.component.AbstractComponent;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
|
||||
/**
|
||||
* Base class for interceptors that disables features when field level security is configured for indices a request
|
||||
|
@ -32,7 +32,8 @@ abstract class FieldAndDocumentLevelSecurityRequestInterceptor<Request extends I
|
|||
this.licenseState = licenseState;
|
||||
}
|
||||
|
||||
public void intercept(Request request, User user, Role userPermissions, String action) {
|
||||
@Override
|
||||
public void intercept(Request request, Authentication authentication, Role userPermissions, String action) {
|
||||
if (licenseState.isDocumentAndFieldLevelSecurityAllowed() == false) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
|
|||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.support.Exceptions;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -37,7 +37,7 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
|||
}
|
||||
|
||||
@Override
|
||||
public void intercept(IndicesAliasesRequest request, User user, Role userPermissions, String action) {
|
||||
public void intercept(IndicesAliasesRequest request, Authentication authentication, Role userPermissions, String action) {
|
||||
if (licenseState.isDocumentAndFieldLevelSecurityAllowed()) {
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
for (IndicesAliasesRequest.AliasActions aliasAction : request.getAliasActions()) {
|
||||
|
@ -67,7 +67,7 @@ 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(user, action, request, userPermissions.names());
|
||||
auditTrailService.accessDenied(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");
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
package org.elasticsearch.xpack.security.action.interceptor;
|
||||
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
|
||||
/**
|
||||
* A request interceptor can introspect a request and modify it.
|
||||
|
@ -18,7 +18,7 @@ public interface RequestInterceptor<Request> {
|
|||
* If {@link #supports(TransportRequest)} returns <code>true</code> this interceptor will introspect the request
|
||||
* and potentially modify it.
|
||||
*/
|
||||
void intercept(Request request, User user, Role userPermissions, String action);
|
||||
void intercept(Request request, Authentication authentication, Role userPermissions, String action);
|
||||
|
||||
/**
|
||||
* Returns whether this request interceptor should intercept the specified request.
|
||||
|
|
|
@ -16,11 +16,11 @@ import org.elasticsearch.license.XPackLicenseState;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.Role;
|
||||
import org.elasticsearch.xpack.core.security.support.Exceptions;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||
|
||||
public final class ResizeRequestInterceptor extends AbstractComponent implements RequestInterceptor<ResizeRequest> {
|
||||
|
@ -38,7 +38,7 @@ public final class ResizeRequestInterceptor extends AbstractComponent implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void intercept(ResizeRequest request, User user, Role userPermissions, String action) {
|
||||
public void intercept(ResizeRequest request, Authentication authentication, Role userPermissions, String action) {
|
||||
if (licenseState.isDocumentAndFieldLevelSecurityAllowed()) {
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(request.getSourceIndex());
|
||||
|
@ -57,7 +57,7 @@ public final class ResizeRequestInterceptor extends AbstractComponent implements
|
|||
final Automaton targetIndexPermissions = 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(user, action, request, userPermissions.names());
|
||||
auditTrailService.accessDenied(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");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.xpack.security.audit;
|
|||
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||
|
@ -37,9 +38,9 @@ public interface AuditTrail {
|
|||
|
||||
void authenticationFailed(String realm, AuthenticationToken token, RestRequest request);
|
||||
|
||||
void accessGranted(User user, String action, TransportMessage message, String[] roleNames);
|
||||
void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void accessDenied(User user, String action, TransportMessage message, String[] roleNames);
|
||||
void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void tamperedRequest(RestRequest request);
|
||||
|
||||
|
@ -51,9 +52,9 @@ public interface AuditTrail {
|
|||
|
||||
void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule);
|
||||
|
||||
void runAsGranted(User user, String action, TransportMessage message, String[] roleNames);
|
||||
void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void runAsDenied(User user, String action, TransportMessage message, String[] roleNames);
|
||||
void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames);
|
||||
|
||||
void runAsDenied(User user, RestRequest request, String[] roleNames);
|
||||
void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||
|
@ -130,19 +131,19 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.accessGranted(user, action, message, roleNames);
|
||||
auditTrail.accessGranted(authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.accessDenied(user, action, message, roleNames);
|
||||
auditTrail.accessDenied(authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,28 +192,28 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsGranted(user, action, message, roleNames);
|
||||
auditTrail.runAsGranted(authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsDenied(user, action, message, roleNames);
|
||||
auditTrail.runAsDenied(authentication, action, message, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||
public void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
if (licenseState.isAuditingAllowed()) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
auditTrail.runAsDenied(user, request, roleNames);
|
||||
auditTrail.runAsDenied(authentication, request, roleNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.XPackClientPlugin;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
|
@ -437,8 +438,8 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||
try {
|
||||
enqueue(message("authentication_success", realm, user, null, request), "authentication_success");
|
||||
} catch (Exception e) {
|
||||
enqueue(message("authentication_success", new Tuple<>(realm, realm), user, null, request), "authentication_success");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [authentication_success]", e);
|
||||
}
|
||||
}
|
||||
|
@ -448,8 +449,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||
try {
|
||||
enqueue(message("authentication_success", action, user, null, realm, null, message), "authentication_success");
|
||||
} catch (Exception e) {
|
||||
enqueue(message("authentication_success", action, user, null, new Tuple<>(realm, realm), null, message),
|
||||
"authentication_success");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [authentication_success]", e);
|
||||
}
|
||||
}
|
||||
|
@ -555,25 +557,34 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, 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);
|
||||
final boolean shouldLog = logSystemAccessGranted || (isSystem == false && events.contains(ACCESS_GRANTED));
|
||||
if (shouldLog) {
|
||||
try {
|
||||
enqueue(message("access_granted", action, user, roleNames, null, indices(message), message), "access_granted");
|
||||
} catch (Exception e) {
|
||||
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");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [access_granted]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(ACCESS_DENIED) && XPackUser.is(user) == false) {
|
||||
public void accessDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(ACCESS_DENIED) && (XPackUser.is(authentication.getUser()) == false)) {
|
||||
try {
|
||||
enqueue(message("access_denied", action, user, roleNames, null, indices(message), message), "access_denied");
|
||||
} catch (Exception e) {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
final String authRealmName = authentication.getAuthenticatedBy().getName();
|
||||
final String lookRealmName = authentication.getLookedUpBy() == null ? null : authentication.getLookedUpBy().getName();
|
||||
enqueue(message("access_denied", action, authentication.getUser(), roleNames, new Tuple(authRealmName, lookRealmName),
|
||||
indices(message), message), "access_denied");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [access_denied]", e);
|
||||
}
|
||||
}
|
||||
|
@ -635,40 +646,53 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_GRANTED)) {
|
||||
try {
|
||||
enqueue(message("run_as_granted", action, user, roleNames, null, null, message), "run_as_granted");
|
||||
} catch (Exception e) {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
final String authRealmName = authentication.getAuthenticatedBy().getName();
|
||||
final String lookRealmName = authentication.getLookedUpBy() == null ? null : authentication.getLookedUpBy().getName();
|
||||
enqueue(message("run_as_granted", action, authentication.getUser(), roleNames, new Tuple<>(authRealmName, lookRealmName),
|
||||
null, message), "run_as_granted");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [run_as_granted]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(Authentication authentication, String action, TransportMessage message, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)) {
|
||||
try {
|
||||
enqueue(message("run_as_denied", action, user, roleNames, null, null, message), "run_as_denied");
|
||||
} catch (Exception e) {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
final String authRealmName = authentication.getAuthenticatedBy().getName();
|
||||
final String lookRealmName = authentication.getLookedUpBy() == null ? null : authentication.getLookedUpBy().getName();
|
||||
enqueue(message("run_as_denied", action, authentication.getUser(), roleNames, new Tuple<>(authRealmName, lookRealmName),
|
||||
null, message), "run_as_denied");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [run_as_denied]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||
public void runAsDenied(Authentication authentication, RestRequest request, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED)) {
|
||||
try {
|
||||
enqueue(message("run_as_denied", null, user, roleNames, request), "run_as_denied");
|
||||
} catch (Exception e) {
|
||||
assert authentication.getAuthenticatedBy() != null;
|
||||
final String authRealmName = authentication.getAuthenticatedBy().getName();
|
||||
final String lookRealmName = authentication.getLookedUpBy() == null ? null : authentication.getLookedUpBy().getName();
|
||||
enqueue(message("run_as_denied", new Tuple<>(authRealmName, lookRealmName), authentication.getUser(), roleNames, request),
|
||||
"run_as_denied");
|
||||
} catch (final Exception e) {
|
||||
logger.warn("failed to index audit event: [run_as_denied]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Message message(String type, @Nullable String action, @Nullable User user, @Nullable String[] roleNames, @Nullable String realm,
|
||||
@Nullable Set<String> indices, TransportMessage message) throws Exception {
|
||||
private Message message(String type, @Nullable String action, @Nullable User user, @Nullable String[] roleNames,
|
||||
@Nullable Tuple<String, String> realms, @Nullable Set<String> indices, TransportMessage message)
|
||||
throws Exception {
|
||||
|
||||
Message msg = new Message().start();
|
||||
common("transport", type, msg.builder);
|
||||
|
@ -677,34 +701,52 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
if (action != null) {
|
||||
msg.builder.field(Field.ACTION, action);
|
||||
}
|
||||
if (user != null) {
|
||||
if (user.isRunAs()) {
|
||||
if ("run_as_granted".equals(type) || "run_as_denied".equals(type)) {
|
||||
msg.builder.field(Field.PRINCIPAL, user.authenticatedUser().principal());
|
||||
msg.builder.field(Field.RUN_AS_PRINCIPAL, user.principal());
|
||||
} else {
|
||||
// TODO: this doesn't make sense...
|
||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||
msg.builder.field(Field.RUN_BY_PRINCIPAL, user.authenticatedUser().principal());
|
||||
}
|
||||
} else {
|
||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||
}
|
||||
if (roleNames != null) {
|
||||
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||
}
|
||||
addUserAndRealmFields(msg.builder, type, user, realms);
|
||||
if (roleNames != null) {
|
||||
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||
}
|
||||
if (indices != null) {
|
||||
msg.builder.array(Field.INDICES, indices.toArray(Strings.EMPTY_ARRAY));
|
||||
}
|
||||
if (realm != null) {
|
||||
msg.builder.field(Field.REALM, realm);
|
||||
}
|
||||
msg.builder.field(Field.REQUEST, message.getClass().getSimpleName());
|
||||
|
||||
return msg.end();
|
||||
}
|
||||
|
||||
private void addUserAndRealmFields(XContentBuilder builder, String type, @Nullable User user, @Nullable Tuple<String, String> realms)
|
||||
throws IOException {
|
||||
if (user != null) {
|
||||
if (user.isRunAs()) {
|
||||
if ("run_as_granted".equals(type) || "run_as_denied".equals(type)) {
|
||||
builder.field(Field.PRINCIPAL, user.authenticatedUser().principal());
|
||||
builder.field(Field.RUN_AS_PRINCIPAL, user.principal());
|
||||
if (realms != null) {
|
||||
// realms.v1() is the authenticating realm
|
||||
builder.field(Field.REALM, realms.v1());
|
||||
// realms.v2() is the lookup realm
|
||||
builder.field(Field.RUN_AS_REALM, realms.v2());
|
||||
}
|
||||
} else {
|
||||
// TODO: this doesn't make sense...
|
||||
builder.field(Field.PRINCIPAL, user.principal());
|
||||
builder.field(Field.RUN_BY_PRINCIPAL, user.authenticatedUser().principal());
|
||||
if (realms != null) {
|
||||
// realms.v2() is the lookup realm
|
||||
builder.field(Field.REALM, realms.v2());
|
||||
// realms.v1() is the authenticating realm
|
||||
builder.field(Field.RUN_BY_REALM, realms.v1());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
builder.field(Field.PRINCIPAL, user.principal());
|
||||
if (realms != null) {
|
||||
// realms.v1() is the authenticating realm
|
||||
builder.field(Field.REALM, realms.v1());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - clean up the message generation
|
||||
private Message message(String type, @Nullable String action, @Nullable AuthenticationToken token,
|
||||
@Nullable String realm, @Nullable Set<String> indices, TransportMessage message) throws Exception {
|
||||
|
@ -765,25 +807,15 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
return msg.end();
|
||||
}
|
||||
|
||||
private Message message(String type, @Nullable String realm, @Nullable User user, @Nullable String[] roleNames, RestRequest request)
|
||||
throws Exception {
|
||||
private Message message(String type, @Nullable Tuple<String,String> realms, @Nullable User user, @Nullable String[] roleNames,
|
||||
RestRequest request) throws Exception {
|
||||
|
||||
Message msg = new Message().start();
|
||||
common("rest", type, msg.builder);
|
||||
|
||||
if (user != null) {
|
||||
if (user.isRunAs()) {
|
||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||
msg.builder.field(Field.RUN_BY_PRINCIPAL, user.authenticatedUser().principal());
|
||||
} else {
|
||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||
}
|
||||
if (roleNames != null) {
|
||||
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||
}
|
||||
}
|
||||
if (realm != null) {
|
||||
msg.builder.field(Field.REALM, realm);
|
||||
addUserAndRealmFields(msg.builder, type, user, realms);
|
||||
if (roleNames != null) {
|
||||
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||
}
|
||||
if (includeRequestBody) {
|
||||
msg.builder.field(Field.REQUEST_BODY, restRequestContent(request));
|
||||
|
@ -1139,7 +1171,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
|||
String PRINCIPAL = "principal";
|
||||
String ROLE_NAMES = "roles";
|
||||
String RUN_AS_PRINCIPAL = "run_as_principal";
|
||||
String RUN_AS_REALM = "run_as_realm";
|
||||
String RUN_BY_PRINCIPAL = "run_by_principal";
|
||||
String RUN_BY_REALM = "run_by_realm";
|
||||
String ACTION = "action";
|
||||
String INDICES = "indices";
|
||||
String REQUEST = "request";
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.support.Automatons;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
|
@ -334,21 +335,22 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessGranted(Authentication authentication, String action, TransportMessage message, 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);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(user), Optional.empty(), Optional.of(roleNames), indices)) == false) {
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(user),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), indices)) == false) {
|
||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||
if (indices.isPresent()) {
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), subject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, arrayToCommaDelimitedString(indices.get()),
|
||||
message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [access_granted]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||
originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||
originAttributes(threadContext, message, localNodeInfo), subject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
@ -356,20 +358,20 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void accessDenied(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(user), Optional.empty(), Optional.of(roleNames), indices)) == false) {
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), indices)) == false) {
|
||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||
if (indices.isPresent()) {
|
||||
logger.info("{}[transport] [access_denied]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), subject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, arrayToCommaDelimitedString(indices.get()),
|
||||
message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [access_denied]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||
originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||
originAttributes(threadContext, message, localNodeInfo), subject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
@ -444,25 +446,21 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsGranted(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(user), Optional.empty(), Optional.of(roleNames), indices)) == false) {
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), indices)) == false) {
|
||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||
if (indices.isPresent()) {
|
||||
logger.info(
|
||||
"{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}],"
|
||||
+ " action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo),
|
||||
user.authenticatedUser().principal(), user.principal(), arrayToCommaDelimitedString(roleNames), action,
|
||||
arrayToCommaDelimitedString(indices.get()), message.getClass().getSimpleName());
|
||||
logger.info("{}[transport] [run_as_granted]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), runAsSubject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, arrayToCommaDelimitedString(indices.get()),
|
||||
message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info(
|
||||
"{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}],"
|
||||
+ " action=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo),
|
||||
user.authenticatedUser().principal(), user.principal(), arrayToCommaDelimitedString(roleNames), action,
|
||||
logger.info("{}[transport] [run_as_granted]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||
originAttributes(threadContext, message, localNodeInfo), runAsSubject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action,
|
||||
message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
@ -470,46 +468,67 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||
public void runAsDenied(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(user), Optional.empty(), Optional.of(roleNames), indices)) == false) {
|
||||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
Optional.of(effectiveRealmName(authentication)), Optional.of(roleNames), indices)) == false) {
|
||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||
if (indices.isPresent()) {
|
||||
logger.info(
|
||||
"{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}],"
|
||||
+ " action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo),
|
||||
user.authenticatedUser().principal(), user.principal(), arrayToCommaDelimitedString(roleNames), action,
|
||||
arrayToCommaDelimitedString(indices.get()), message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info(
|
||||
"{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}],"
|
||||
+ " action=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo),
|
||||
user.authenticatedUser().principal(), user.principal(), arrayToCommaDelimitedString(roleNames), action,
|
||||
logger.info("{}[transport] [run_as_denied]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), runAsSubject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, arrayToCommaDelimitedString(indices.get()),
|
||||
message.getClass().getSimpleName());
|
||||
} else {
|
||||
logger.info("{}[transport] [run_as_denied]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||
originAttributes(threadContext, message, localNodeInfo), runAsSubject(authentication),
|
||||
arrayToCommaDelimitedString(roleNames), action, message.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||
if (events.contains(RUN_AS_DENIED) && (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(user), Optional.empty(), Optional.of(roleNames), Optional.empty())) == false)) {
|
||||
public void runAsDenied(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)) {
|
||||
if (includeRequestBody) {
|
||||
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], roles=[{}], uri=[{}], request_body=[{}]", localNodeInfo.prefix,
|
||||
hostAttributes(request), user.principal(), arrayToCommaDelimitedString(roleNames), request.uri(),
|
||||
logger.info("{}[rest] [run_as_denied]\t{}, {}, roles=[{}], uri=[{}], request_body=[{}]", localNodeInfo.prefix,
|
||||
hostAttributes(request), runAsSubject(authentication), arrayToCommaDelimitedString(roleNames), request.uri(),
|
||||
restRequestContent(request));
|
||||
} else {
|
||||
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], roles=[{}], uri=[{}]", localNodeInfo.prefix,
|
||||
hostAttributes(request), user.principal(), arrayToCommaDelimitedString(roleNames), request.uri());
|
||||
logger.info("{}[rest] [run_as_denied]\t{}, {}, roles=[{}], uri=[{}]", localNodeInfo.prefix, hostAttributes(request),
|
||||
runAsSubject(authentication), arrayToCommaDelimitedString(roleNames), request.uri());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String runAsSubject(Authentication authentication) {
|
||||
final StringBuilder sb = new StringBuilder("principal=[");
|
||||
sb.append(authentication.getUser().authenticatedUser().principal());
|
||||
sb.append("], realm=[");
|
||||
sb.append(authentication.getAuthenticatedBy().getName());
|
||||
sb.append("], run_as_principal=[");
|
||||
sb.append(authentication.getUser().principal());
|
||||
if (authentication.getLookedUpBy() != null) {
|
||||
sb.append("], run_as_realm=[").append(authentication.getLookedUpBy().getName());
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static String subject(Authentication authentication) {
|
||||
final StringBuilder sb = new StringBuilder("principal=[");
|
||||
sb.append(authentication.getUser().principal()).append("], realm=[");
|
||||
if (authentication.getUser().isRunAs()) {
|
||||
sb.append(authentication.getLookedUpBy().getName()).append("], run_by_principal=[");
|
||||
sb.append(authentication.getUser().authenticatedUser().principal()).append("], run_by_realm=[");
|
||||
}
|
||||
sb.append(authentication.getAuthenticatedBy().getName()).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String hostAttributes(RestRequest request) {
|
||||
String formattedAddress;
|
||||
final SocketAddress socketAddress = request.getRemoteAddress();
|
||||
|
@ -556,6 +575,11 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
static String effectiveRealmName(Authentication authentication) {
|
||||
return authentication.getLookedUpBy() != null ? authentication.getLookedUpBy().getName()
|
||||
: authentication.getAuthenticatedBy().getName();
|
||||
}
|
||||
|
||||
static String principal(User user) {
|
||||
final StringBuilder builder = new StringBuilder("principal=[");
|
||||
builder.append(user.principal());
|
||||
|
@ -583,7 +607,7 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
|||
* that will be ignored, aka filtered out, aka not logged. The event can be
|
||||
* filtered by the following fields : `user`, `realm`, `role` and `index`.
|
||||
* Predicates on each field are ANDed together to form the filter predicate of
|
||||
* the policy.
|
||||
* the policy.
|
||||
*/
|
||||
private static final class EventFilterPolicy {
|
||||
private final String name;
|
||||
|
|
|
@ -364,7 +364,8 @@ public class AuthenticationService extends AbstractComponent {
|
|||
} else {
|
||||
assert runAsUsername.isEmpty() : "the run as username may not be empty";
|
||||
logger.debug("user [{}] attempted to runAs with an empty username", user.principal());
|
||||
listener.onFailure(request.runAsDenied(new User(runAsUsername, null, user), authenticationToken));
|
||||
listener.onFailure(request.runAsDenied(
|
||||
new Authentication(new User(runAsUsername, null, user), authenticatedBy, lookedupBy), authenticationToken));
|
||||
}
|
||||
} else {
|
||||
finishAuthentication(user);
|
||||
|
@ -467,7 +468,7 @@ public class AuthenticationService extends AbstractComponent {
|
|||
|
||||
abstract ElasticsearchSecurityException anonymousAccessDenied();
|
||||
|
||||
abstract ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token);
|
||||
abstract ElasticsearchSecurityException runAsDenied(Authentication authentication, AuthenticationToken token);
|
||||
|
||||
abstract void authenticationSuccess(String realm, User user);
|
||||
|
||||
|
@ -524,8 +525,8 @@ public class AuthenticationService extends AbstractComponent {
|
|||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(user, action, message, Role.EMPTY.names());
|
||||
ElasticsearchSecurityException runAsDenied(Authentication authentication, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(authentication, action, message, Role.EMPTY.names());
|
||||
return failureHandler.failedAuthentication(message, token, action, threadContext);
|
||||
}
|
||||
|
||||
|
@ -586,8 +587,8 @@ public class AuthenticationService extends AbstractComponent {
|
|||
}
|
||||
|
||||
@Override
|
||||
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(user, request, Role.EMPTY.names());
|
||||
ElasticsearchSecurityException runAsDenied(Authentication authentication, AuthenticationToken token) {
|
||||
auditTrail.runAsDenied(authentication, request, Role.EMPTY.names());
|
||||
return failureHandler.failedAuthentication(request, token, threadContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
if (SystemUser.isAuthorized(action)) {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
putTransientIfNonExisting(ROLE_NAMES_KEY, new String[] { SystemUser.ROLE_NAME });
|
||||
grant(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
auditTrail.accessGranted(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||
|
@ -168,7 +168,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
if (authentication.getLookedUpBy() == null) {
|
||||
throw denyRunAs(authentication, action, request, permission.names());
|
||||
} else if (permission.runAs().check(authentication.getUser().principal())) {
|
||||
grantRunAs(authentication, action, request, permission.names());
|
||||
auditTrail.runAsGranted(authentication, action, request, permission.names());
|
||||
permission = runAsRole;
|
||||
} else {
|
||||
throw denyRunAs(authentication, action, request, permission.names());
|
||||
|
@ -181,7 +181,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
ClusterPermission cluster = permission.cluster();
|
||||
if (cluster.check(action) || checkSameUserPermissions(action, request, authentication)) {
|
||||
putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
|
@ -200,7 +200,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
}
|
||||
// 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)) {
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
|
@ -211,7 +211,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
}
|
||||
// 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)) {
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
throw denial(authentication, action, request, permission.names());
|
||||
|
@ -222,7 +222,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
+ action + "] is a proxy action");
|
||||
}
|
||||
if (permission.indices().check(action)) {
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(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
|
||||
|
@ -251,7 +251,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
// 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
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -287,7 +287,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
//'-*' 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);
|
||||
grant(authentication, action, request, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
authorizeBulkItems(authentication, (BulkShardRequest) request, permission, metaData, localIndices, authorizedIndices);
|
||||
}
|
||||
|
||||
grant(authentication, action, originalRequest, permission.names());
|
||||
auditTrail.accessGranted(authentication, action, request, permission.names());
|
||||
}
|
||||
|
||||
private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) {
|
||||
|
@ -421,7 +421,7 @@ public class AuthorizationService extends AbstractComponent {
|
|||
try {
|
||||
return indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices);
|
||||
} catch (Exception e) {
|
||||
auditTrail.accessDenied(authentication.getUser(), action, request, permission.names());
|
||||
auditTrail.accessDenied(authentication, action, request, permission.names());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -548,24 +548,16 @@ public class AuthorizationService extends AbstractComponent {
|
|||
}
|
||||
|
||||
ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||
auditTrail.accessDenied(authentication.getUser(), action, request, roleNames);
|
||||
auditTrail.accessDenied(authentication, action, request, roleNames);
|
||||
return denialException(authentication, action);
|
||||
}
|
||||
|
||||
private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request,
|
||||
String[] roleNames) {
|
||||
auditTrail.runAsDenied(authentication.getUser(), action, request, roleNames);
|
||||
auditTrail.runAsDenied(authentication, action, request, roleNames);
|
||||
return denialException(authentication, action);
|
||||
}
|
||||
|
||||
private void grant(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||
auditTrail.accessGranted(authentication.getUser(), action, request, roleNames);
|
||||
}
|
||||
|
||||
private void grantRunAs(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||
auditTrail.runAsGranted(authentication.getUser(), action, request, roleNames);
|
||||
}
|
||||
|
||||
private ElasticsearchSecurityException denialException(Authentication authentication, String action) {
|
||||
final User authUser = authentication.getUser().authenticatedUser();
|
||||
// Special case for anonymous user
|
||||
|
|
|
@ -94,7 +94,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
|||
|
||||
final boolean sameUser = samePrincipal && sameRealmType;
|
||||
if (sameUser == false) {
|
||||
auditTrailService.accessDenied(current.getUser(), action, request, roleNames);
|
||||
auditTrailService.accessDenied(current, action, request, roleNames);
|
||||
throw new SearchContextMissingException(id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions;
|
||||
|
@ -37,7 +39,8 @@ public class IndicesAliasesRequestInterceptorTests extends ESTestCase {
|
|||
when(licenseState.isDocumentAndFieldLevelSecurityAllowed()).thenReturn(true);
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
AuditTrailService auditTrailService = new AuditTrailService(Settings.EMPTY, Collections.emptyList(), licenseState);
|
||||
User user = new User("john", "role");
|
||||
Authentication authentication = new Authentication(new User("john", "role"), new RealmRef(null, null, null),
|
||||
new RealmRef(null, null, null));
|
||||
final FieldPermissions fieldPermissions;
|
||||
final boolean useFls = randomBoolean();
|
||||
if (useFls) {
|
||||
|
@ -70,7 +73,7 @@ public class IndicesAliasesRequestInterceptorTests extends ESTestCase {
|
|||
indicesAliasesRequest.addAliasAction(IndicesAliasesRequest.AliasActions.removeIndex().index("foofoo"));
|
||||
}
|
||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> interceptor.intercept(indicesAliasesRequest, user, role, action));
|
||||
() -> interceptor.intercept(indicesAliasesRequest, authentication, role, action));
|
||||
assertEquals("Alias requests are not allowed for users who have field or document level security enabled on one of the indices",
|
||||
securityException.getMessage());
|
||||
}
|
||||
|
@ -81,7 +84,8 @@ public class IndicesAliasesRequestInterceptorTests extends ESTestCase {
|
|||
when(licenseState.isDocumentAndFieldLevelSecurityAllowed()).thenReturn(true);
|
||||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
AuditTrailService auditTrailService = new AuditTrailService(Settings.EMPTY, Collections.emptyList(), licenseState);
|
||||
User user = new User("john", "role");
|
||||
Authentication authentication = new Authentication(new User("john", "role"), new RealmRef(null, null, null),
|
||||
new RealmRef(null, null, null));
|
||||
Role role = Role.builder()
|
||||
.add(IndexPrivilege.ALL, "alias")
|
||||
.add(IndexPrivilege.READ, "index")
|
||||
|
@ -102,7 +106,7 @@ public class IndicesAliasesRequestInterceptorTests extends ESTestCase {
|
|||
}
|
||||
|
||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> interceptor.intercept(indicesAliasesRequest, user, role, action));
|
||||
() -> interceptor.intercept(indicesAliasesRequest, authentication, role, action));
|
||||
assertEquals("Adding an alias is not allowed when the alias has more permissions than any of the indices",
|
||||
securityException.getMessage());
|
||||
|
||||
|
@ -115,6 +119,6 @@ public class IndicesAliasesRequestInterceptorTests extends ESTestCase {
|
|||
if (randomBoolean()) {
|
||||
successRequest.addAliasAction(IndicesAliasesRequest.AliasActions.removeIndex().index("foofoo"));
|
||||
}
|
||||
interceptor.intercept(successRequest, user, role, action);
|
||||
interceptor.intercept(successRequest, authentication, role, action);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
|
|||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
|
||||
import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions;
|
||||
|
@ -41,7 +43,7 @@ public class ResizeRequestInterceptorTests extends ESTestCase {
|
|||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext);
|
||||
AuditTrailService auditTrailService = new AuditTrailService(Settings.EMPTY, Collections.emptyList(), licenseState);
|
||||
User user = new User("john", "role");
|
||||
final Authentication authentication = new Authentication(new User("john", "role"), new RealmRef(null, null, null), null);
|
||||
final FieldPermissions fieldPermissions;
|
||||
final boolean useFls = randomBoolean();
|
||||
if (useFls) {
|
||||
|
@ -66,7 +68,7 @@ public class ResizeRequestInterceptorTests extends ESTestCase {
|
|||
new ResizeRequestInterceptor(Settings.EMPTY, threadPool, licenseState, auditTrailService);
|
||||
|
||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> resizeRequestInterceptor.intercept(new ResizeRequest("bar", "foo"), user, role, action));
|
||||
() -> resizeRequestInterceptor.intercept(new ResizeRequest("bar", "foo"), authentication, role, action));
|
||||
assertEquals("Resize requests are not allowed for users when field or document level security is enabled on the source index",
|
||||
securityException.getMessage());
|
||||
}
|
||||
|
@ -79,7 +81,7 @@ public class ResizeRequestInterceptorTests extends ESTestCase {
|
|||
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
when(threadPool.getThreadContext()).thenReturn(threadContext);
|
||||
AuditTrailService auditTrailService = new AuditTrailService(Settings.EMPTY, Collections.emptyList(), licenseState);
|
||||
User user = new User("john", "role");
|
||||
final Authentication authentication = new Authentication(new User("john", "role"), new RealmRef(null, null, null), null);
|
||||
Role role = Role.builder()
|
||||
.add(IndexPrivilege.ALL, "target")
|
||||
.add(IndexPrivilege.READ, "source")
|
||||
|
@ -90,11 +92,11 @@ public class ResizeRequestInterceptorTests extends ESTestCase {
|
|||
ResizeRequestInterceptor resizeRequestInterceptor =
|
||||
new ResizeRequestInterceptor(Settings.EMPTY, threadPool, licenseState, auditTrailService);
|
||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> resizeRequestInterceptor.intercept(new ResizeRequest("target", "source"), user, role, action));
|
||||
() -> resizeRequestInterceptor.intercept(new ResizeRequest("target", "source"), authentication, role, action));
|
||||
assertEquals("Resizing an index is not allowed when the target index has more permissions than the source index",
|
||||
securityException.getMessage());
|
||||
|
||||
// swap target and source for success
|
||||
resizeRequestInterceptor.intercept(new ResizeRequest("source", "target"), user, role, action);
|
||||
resizeRequestInterceptor.intercept(new ResizeRequest("source", "target"), authentication, role, action);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.elasticsearch.license.XPackLicenseState;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
|
||||
|
@ -137,13 +139,14 @@ public class AuditTrailServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAccessGranted() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
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(user, "_action", message, roles);
|
||||
service.accessGranted(authentication, "_action", message, roles);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).accessGranted(user, "_action", message, roles);
|
||||
verify(auditTrail).accessGranted(authentication, "_action", message, roles);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
|
@ -151,13 +154,14 @@ public class AuditTrailServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAccessDenied() throws Exception {
|
||||
User user = new User("_username", "r1");
|
||||
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(user, "_action", message, roles);
|
||||
service.accessDenied(authentication, "_action", message, roles);
|
||||
verify(licenseState).isAuditingAllowed();
|
||||
if (isAuditingAllowed) {
|
||||
for (AuditTrail auditTrail : auditTrails) {
|
||||
verify(auditTrail).accessDenied(user, "_action", message, roles);
|
||||
verify(auditTrail).accessDenied(authentication, "_action", message, roles);
|
||||
}
|
||||
} else {
|
||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import static org.elasticsearch.test.SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.iterableWithSize;
|
||||
|
||||
|
@ -90,7 +91,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationServiceField.RUN_AS_USER_HEADER, EXECUTE_USER));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
} catch (final ResponseException e) {
|
||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(403));
|
||||
}
|
||||
|
||||
|
@ -112,7 +113,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
UsernamePasswordToken.basicAuthHeaderValue(AUTHENTICATE_USER, TEST_PASSWORD_SECURE_STRING)),
|
||||
new BasicHeader(AuthenticationServiceField.RUN_AS_USER_HEADER, ""));
|
||||
fail("request should have failed");
|
||||
} catch (ResponseException e) {
|
||||
} catch (final ResponseException e) {
|
||||
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401));
|
||||
}
|
||||
|
||||
|
@ -121,19 +122,21 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
assertThat(events, iterableWithSize(1));
|
||||
final Map<String, Object> event = events.iterator().next();
|
||||
assertThat(event.get(IndexAuditTrail.Field.TYPE), equalTo("run_as_denied"));
|
||||
assertThat(event.get(IndexAuditTrail.Field.PRINCIPAL), equalTo(""));
|
||||
assertThat(event.get(IndexAuditTrail.Field.RUN_BY_PRINCIPAL), equalTo(AUTHENTICATE_USER));
|
||||
assertThat(event.get(IndexAuditTrail.Field.PRINCIPAL), equalTo(AUTHENTICATE_USER));
|
||||
assertThat(event.get(IndexAuditTrail.Field.RUN_AS_PRINCIPAL), equalTo(""));
|
||||
assertThat(event.get(IndexAuditTrail.Field.REALM), equalTo("file"));
|
||||
assertThat(event.get(IndexAuditTrail.Field.RUN_AS_REALM), nullValue());
|
||||
}
|
||||
|
||||
private Collection<Map<String, Object>> waitForAuditEvents() throws InterruptedException {
|
||||
waitForAuditTrailToBeWritten();
|
||||
AtomicReference<Collection<Map<String, Object>>> eventsRef = new AtomicReference<>();
|
||||
final AtomicReference<Collection<Map<String, Object>>> eventsRef = new AtomicReference<>();
|
||||
awaitBusy(() -> {
|
||||
try {
|
||||
final Collection<Map<String, Object>> events = getAuditEvents();
|
||||
eventsRef.set(events);
|
||||
return events.size() > 0;
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
@ -142,14 +145,14 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
}
|
||||
private Collection<Map<String, Object>> getAuditEvents() throws Exception {
|
||||
final Client client = client();
|
||||
DateTime now = new DateTime(DateTimeZone.UTC);
|
||||
String indexName = IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY);
|
||||
final DateTime now = new DateTime(DateTimeZone.UTC);
|
||||
final String indexName = IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY);
|
||||
|
||||
assertTrue(awaitBusy(() -> indexExists(client, indexName), 5, TimeUnit.SECONDS));
|
||||
|
||||
client.admin().indices().refresh(Requests.refreshRequest(indexName)).get();
|
||||
|
||||
SearchRequest request = client.prepareSearch(indexName)
|
||||
final SearchRequest request = client.prepareSearch(indexName)
|
||||
.setTypes(IndexAuditTrail.DOC_TYPE)
|
||||
.setQuery(QueryBuilders.matchAllQuery())
|
||||
.setSize(1000)
|
||||
|
@ -157,7 +160,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
|
|||
.request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
|
||||
PlainActionFuture<Collection<Map<String, Object>>> listener = new PlainActionFuture();
|
||||
final PlainActionFuture<Collection<Map<String, Object>>> listener = new PlainActionFuture();
|
||||
ScrollHelper.fetchAllByEntity(client, request, listener, SearchHit::getSourceAsMap);
|
||||
|
||||
return listener.get();
|
||||
|
|
|
@ -23,6 +23,8 @@ import org.elasticsearch.threadpool.TestThreadPool;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.MockTransportClient;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
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;
|
||||
|
@ -172,20 +174,19 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
|||
|
||||
public void testAccessGrantedMuted() {
|
||||
createAuditTrail(new String[] { "access_granted" });
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = mock(User.class);
|
||||
auditTrail.accessGranted(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
final TransportMessage message = mock(TransportMessage.class);
|
||||
final Authentication authentication = mock(Authentication.class);
|
||||
auditTrail.accessGranted(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
verifyZeroInteractions(message, user);
|
||||
verifyZeroInteractions(message);
|
||||
}
|
||||
|
||||
public void testSystemAccessGrantedMuted() {
|
||||
createAuditTrail(randomFrom(new String[] { "access_granted" }, null));
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = SystemUser.INSTANCE;
|
||||
auditTrail.accessGranted(user, "internal:foo", message, new String[] { "role" });
|
||||
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" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
|
@ -194,13 +195,13 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
|||
|
||||
public void testAccessDeniedMuted() {
|
||||
createAuditTrail(new String[] { "access_denied" });
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = mock(User.class);
|
||||
auditTrail.accessDenied(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
final TransportMessage message = mock(TransportMessage.class);
|
||||
final Authentication authentication = mock(Authentication.class);
|
||||
auditTrail.accessDenied(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
verifyZeroInteractions(message, user);
|
||||
verifyZeroInteractions(message, authentication);
|
||||
}
|
||||
|
||||
public void testTamperedRequestMuted() {
|
||||
|
@ -248,25 +249,25 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
|||
public void testRunAsGrantedMuted() {
|
||||
createAuditTrail(new String[] { "run_as_granted" });
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = mock(User.class);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
|
||||
auditTrail.runAsGranted(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.runAsGranted(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
verifyZeroInteractions(message, user);
|
||||
verifyZeroInteractions(message, authentication);
|
||||
}
|
||||
|
||||
public void testRunAsDeniedMuted() {
|
||||
createAuditTrail(new String[] { "run_as_denied" });
|
||||
TransportMessage message = mock(TransportMessage.class);
|
||||
User user = mock(User.class);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
|
||||
auditTrail.runAsDenied(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
auditTrail.runAsDenied(authentication, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||
assertThat(messageEnqueued.get(), is(false));
|
||||
assertThat(clientCalled.get(), is(false));
|
||||
|
||||
verifyZeroInteractions(message, user);
|
||||
verifyZeroInteractions(message, authentication);
|
||||
}
|
||||
|
||||
public void testAuthenticationSuccessRest() {
|
||||
|
|
|
@ -44,6 +44,8 @@ import org.elasticsearch.transport.TransportMessage;
|
|||
import org.elasticsearch.transport.TransportRequest;
|
||||
import org.elasticsearch.xpack.core.XPackSettings;
|
||||
import org.elasticsearch.xpack.core.security.SecurityLifecycleServiceField;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
|
@ -563,7 +565,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.accessGranted(user, "_action", message, new String[] { role });
|
||||
auditor.accessGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "access_granted");
|
||||
|
@ -571,9 +573,12 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
assertEquals("transport", sourceMap.get("origin_type"));
|
||||
if (runAs) {
|
||||
assertThat(sourceMap.get("principal"), is("running as"));
|
||||
assertThat(sourceMap.get("realm"), is("lookRealm"));
|
||||
assertThat(sourceMap.get("run_by_principal"), is("_username"));
|
||||
assertThat(sourceMap.get("run_by_realm"), is("authRealm"));
|
||||
} else {
|
||||
assertEquals("_username", sourceMap.get("principal"));
|
||||
assertThat(sourceMap.get("principal"), is("_username"));
|
||||
assertThat(sourceMap.get("realm"), is("authRealm"));
|
||||
}
|
||||
assertEquals("_action", sourceMap.get("action"));
|
||||
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||
|
@ -588,13 +593,14 @@ 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(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||
auditor.accessGranted(createAuthentication(SystemUser.INSTANCE), "internal:_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "access_granted");
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
assertEquals("transport", sourceMap.get("origin_type"));
|
||||
assertEquals(SystemUser.INSTANCE.principal(), sourceMap.get("principal"));
|
||||
assertThat(sourceMap.get("realm"), is("authRealm"));
|
||||
assertEquals("internal:_action", sourceMap.get("action"));
|
||||
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||
|
@ -611,7 +617,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditor.accessDenied(user, "_action", message, new String[] { role });
|
||||
auditor.accessDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
|
@ -619,9 +625,12 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
assertEquals("transport", sourceMap.get("origin_type"));
|
||||
if (runAs) {
|
||||
assertThat(sourceMap.get("principal"), is("running as"));
|
||||
assertThat(sourceMap.get("realm"), is("lookRealm"));
|
||||
assertThat(sourceMap.get("run_by_principal"), is("_username"));
|
||||
assertThat(sourceMap.get("run_by_realm"), is("authRealm"));
|
||||
} else {
|
||||
assertEquals("_username", sourceMap.get("principal"));
|
||||
assertThat(sourceMap.get("principal"), is("_username"));
|
||||
assertThat(sourceMap.get("realm"), is("authRealm"));
|
||||
}
|
||||
assertEquals("_action", sourceMap.get("action"));
|
||||
if (message instanceof IndicesRequest) {
|
||||
|
@ -721,14 +730,16 @@ 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(user, "_action", message, new String[] { role });
|
||||
auditor.runAsGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "run_as_granted");
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
assertEquals("transport", sourceMap.get("origin_type"));
|
||||
assertThat(sourceMap.get("principal"), is("_username"));
|
||||
assertThat(sourceMap.get("realm"), is("authRealm"));
|
||||
assertThat(sourceMap.get("run_as_principal"), is("running as"));
|
||||
assertThat(sourceMap.get("run_as_realm"), is("lookRealm"));
|
||||
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||
assertEquals("_action", sourceMap.get("action"));
|
||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||
|
@ -738,14 +749,16 @@ 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(user, "_action", message, new String[] { "r1" });
|
||||
auditor.runAsDenied(createAuthentication(user), "_action", message, new String[] { "r1" });
|
||||
|
||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||
assertAuditMessage(hit, "transport", "run_as_denied");
|
||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||
assertEquals("transport", sourceMap.get("origin_type"));
|
||||
assertThat(sourceMap.get("principal"), is("_username"));
|
||||
assertThat(sourceMap.get("realm"), is("authRealm"));
|
||||
assertThat(sourceMap.get("run_as_principal"), is("running as"));
|
||||
assertThat(sourceMap.get("run_as_realm"), is("lookRealm"));
|
||||
assertEquals("_action", sourceMap.get("action"));
|
||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||
}
|
||||
|
@ -939,5 +952,10 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
|||
logger.debug("indices {} are yellow", indices.length == 0 ? "[_all]" : indices);
|
||||
return actionGet.getStatus();
|
||||
}
|
||||
|
||||
private static Authentication createAuthentication(User user) {
|
||||
final RealmRef lookedUpBy = user.authenticatedUser() == user ? null : new RealmRef("lookRealm", "up", "by");
|
||||
return new Authentication(user, new RealmRef("authRealm", "test", "foo"), lookedUpBy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.elasticsearch.test.rest.FakeRestRequest;
|
|||
import org.elasticsearch.test.rest.FakeRestRequest.Builder;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.audit.logfile.CapturingLogger;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
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;
|
||||
|
@ -362,18 +364,22 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
Collections.emptyList());
|
||||
}
|
||||
}
|
||||
User filteredUser;
|
||||
final Authentication filteredAuthentication;
|
||||
if (randomBoolean()) {
|
||||
filteredUser = new User(randomFrom(allFilteredUsers), new String[] { "r1" }, new User("authUsername", new String[] { "r2" }));
|
||||
filteredAuthentication = createAuthentication(
|
||||
new User(randomFrom(allFilteredUsers), new String[] { "r1" }, new User("authUsername", new String[] { "r2" })),
|
||||
"effectiveRealmName");
|
||||
} else {
|
||||
filteredUser = new User(randomFrom(allFilteredUsers), new String[] { "r1" });
|
||||
filteredAuthentication = createAuthentication(new User(randomFrom(allFilteredUsers), new String[] { "r1" }),
|
||||
"effectiveRealmName");
|
||||
}
|
||||
User unfilteredUser;
|
||||
final Authentication unfilteredAuthentication;
|
||||
if (randomBoolean()) {
|
||||
unfilteredUser = new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 4), new String[] { "r1" },
|
||||
new User("authUsername", new String[] { "r2" }));
|
||||
unfilteredAuthentication = createAuthentication(new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 4),
|
||||
new String[] { "r1" }, new User("authUsername", new String[] { "r2" })), "effectiveRealmName");
|
||||
} else {
|
||||
unfilteredUser = new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 4), new String[] { "r1" });
|
||||
unfilteredAuthentication = createAuthentication(
|
||||
new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 4), new String[] { "r1" }), "effectiveRealmName");
|
||||
}
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext)
|
||||
: new MockIndicesRequest(threadContext, new String[] { "idx1", "idx2" });
|
||||
|
@ -460,53 +466,55 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// accessGranted
|
||||
auditTrail.accessGranted(unfilteredUser, "_action", message, new String[] { "role1" });
|
||||
auditTrail.accessGranted(unfilteredAuthentication, "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(filteredUser, "_action", message, new String[] { "role1" });
|
||||
auditTrail.accessGranted(filteredAuthentication, "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: system user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(unfilteredUser, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessGranted(unfilteredAuthentication, "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(filteredUser, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessGranted(filteredAuthentication, "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessDenied
|
||||
auditTrail.accessDenied(unfilteredUser, "_action", message, new String[] { "role1" });
|
||||
auditTrail.accessDenied(unfilteredAuthentication, "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(filteredUser, "_action", message, new String[] { "role1" });
|
||||
auditTrail.accessDenied(filteredAuthentication, "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied internal message: system user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(unfilteredUser, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessDenied(unfilteredAuthentication, "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied internal message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(filteredUser, "internal:_action", message, new String[] { "role1" });
|
||||
auditTrail.accessDenied(filteredAuthentication, "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied internal message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
@ -530,12 +538,12 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.tamperedRequest(unfilteredUser, "_action", message);
|
||||
auditTrail.tamperedRequest(unfilteredAuthentication.getUser(), "_action", message);
|
||||
assertThat("Tampered message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.tamperedRequest(filteredUser, "_action", message);
|
||||
auditTrail.tamperedRequest(filteredAuthentication.getUser(), "_action", message);
|
||||
assertThat("Tampered message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
@ -561,54 +569,54 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// runAsGranted
|
||||
auditTrail.runAsGranted(unfilteredUser, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
auditTrail.runAsGranted(unfilteredAuthentication, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
assertThat("RunAsGranted message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(filteredUser, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
auditTrail.runAsGranted(filteredAuthentication, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
assertThat("RunAsGranted message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsDenied
|
||||
auditTrail.runAsDenied(unfilteredUser, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(unfilteredAuthentication, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
assertThat("RunAsDenied message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(filteredUser, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(filteredAuthentication, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
assertThat("RunAsDenied message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(unfilteredUser, getRestRequest(), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(unfilteredAuthentication, getRestRequest(), new String[] { "role1" });
|
||||
assertThat("RunAsDenied rest request: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(filteredUser, getRestRequest(), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(filteredAuthentication, getRestRequest(), new String[] { "role1" });
|
||||
assertThat("RunAsDenied rest request: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// authentication Success
|
||||
auditTrail.authenticationSuccess("_realm", unfilteredUser, getRestRequest());
|
||||
auditTrail.authenticationSuccess("_realm", unfilteredAuthentication.getUser(), getRestRequest());
|
||||
assertThat("AuthenticationSuccess rest request: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", filteredUser, getRestRequest());
|
||||
auditTrail.authenticationSuccess("_realm", filteredAuthentication.getUser(), getRestRequest());
|
||||
assertThat("AuthenticationSuccess rest request: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", unfilteredUser, "_action", message);
|
||||
auditTrail.authenticationSuccess("_realm", unfilteredAuthentication.getUser(), "_action", message);
|
||||
assertThat("AuthenticationSuccess message: unfiltered user is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", filteredUser, "_action", message);
|
||||
auditTrail.authenticationSuccess("_realm", filteredAuthentication.getUser(), "_action", message);
|
||||
assertThat("AuthenticationSuccess message: filtered user is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
@ -728,58 +736,68 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// accessGranted
|
||||
auditTrail.accessGranted(user, "_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessGranted message: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessGranted message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessGranted(createAuthentication(user, filteredRealm), "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessGranted internal message system user: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessGranted internal message system user: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessGranted(createAuthentication(user, unfilteredRealm), "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "internal:_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessGranted internal message: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessGranted internal message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, filteredRealm), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message system user: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, unfilteredRealm), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message system user: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(createAuthentication(user, filteredRealm), "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(createAuthentication(user, unfilteredRealm), "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessDenied
|
||||
auditTrail.accessDenied(user, "_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessDenied message: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessDenied message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessDenied(createAuthentication(user, filteredRealm), "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessDenied internal message system user: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessDenied internal message system user: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessDenied(createAuthentication(user, unfilteredRealm), "_action", message, new String[] { "role1" });
|
||||
assertThat("AccessDenied message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "internal:_action", message, new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("AccessGranted internal message: not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AccessGranted internal message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, filteredRealm), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied internal message system user: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, unfilteredRealm), "internal:_action", message,
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied internal message system user: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(createAuthentication(user, filteredRealm), "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(createAuthentication(user, unfilteredRealm), "internal:_action", message, new String[] { "role1" });
|
||||
assertThat("AccessGranted internal message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
|
@ -832,31 +850,38 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// runAsGranted
|
||||
auditTrail.runAsGranted(user, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("RunAsGranted message: is not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("RunAsGranted message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.runAsGranted(createAuthentication(user, filteredRealm), "_action", new MockMessage(threadContext),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsGranted message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(createAuthentication(user, unfilteredRealm), "_action", new MockMessage(threadContext),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsGranted message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsDenied
|
||||
auditTrail.runAsDenied(user, "_action", new MockMessage(threadContext), new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("RunAsDenied message: is not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("RunAsDenied message: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.runAsDenied(createAuthentication(user, filteredRealm), "_action", new MockMessage(threadContext),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsDenied message: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, getRestRequest(), new String[] { "role1" });
|
||||
if (filterMissingRealm) {
|
||||
assertThat("RunAsDenied rest request: is not filtered out by the missing realm filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("RunAsDenied rest request: is filtered out", logOutput.size(), is(1));
|
||||
}
|
||||
auditTrail.runAsDenied(createAuthentication(user, unfilteredRealm), "_action", new MockMessage(threadContext),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsDenied message: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(createAuthentication(user, filteredRealm), getRestRequest(), new String[] { "role1" });
|
||||
assertThat("RunAsDenied rest request: filtered realm is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(createAuthentication(user, unfilteredRealm), getRestRequest(), new String[] { "role1" });
|
||||
assertThat("RunAsDenied rest request: unfiltered realm is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
|
@ -929,11 +954,12 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.otherPolicy.roles", otherRoles);
|
||||
}
|
||||
final String[] unfilteredRoles = _unfilteredRoles.toArray(new String[0]);
|
||||
User user;
|
||||
final Authentication authentication;
|
||||
if (randomBoolean()) {
|
||||
user = new User("user1", new String[] { "r1" }, new User("authUsername", new String[] { "r2" }));
|
||||
authentication = createAuthentication(new User("user1", new String[] { "r1" }, new User("authUsername", new String[] { "r2" })),
|
||||
"effectiveRealmName");
|
||||
} else {
|
||||
user = new User("user1", new String[] { "r1" });
|
||||
authentication = createAuthentication(new User("user1", new String[] { "r1" }), "effectiveRealmName");
|
||||
}
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext)
|
||||
: new MockIndicesRequest(threadContext, new String[] { "idx1", "idx2" });
|
||||
|
@ -1015,63 +1041,67 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// accessGranted
|
||||
auditTrail.accessGranted(user, "_action", message, unfilteredRoles);
|
||||
auditTrail.accessGranted(authentication, "_action", message, unfilteredRoles);
|
||||
assertThat("AccessGranted message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "_action", message, filteredRoles);
|
||||
auditTrail.accessGranted(authentication, "_action", message, filteredRoles);
|
||||
assertThat("AccessGranted message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, unfilteredRoles);
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
unfilteredRoles);
|
||||
assertThat("AccessGranted internal message system user: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, filteredRoles);
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
filteredRoles);
|
||||
assertThat("AccessGranted internal message system user: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "internal:_action", message, unfilteredRoles);
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, unfilteredRoles);
|
||||
assertThat("AccessGranted internal message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "internal:_action", message, filteredRoles);
|
||||
auditTrail.accessGranted(authentication, "internal:_action", message, filteredRoles);
|
||||
assertThat("AccessGranted internal message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessDenied
|
||||
auditTrail.accessDenied(user, "_action", message, unfilteredRoles);
|
||||
auditTrail.accessDenied(authentication, "_action", message, unfilteredRoles);
|
||||
assertThat("AccessDenied message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "_action", message, filteredRoles);
|
||||
auditTrail.accessDenied(authentication, "_action", message, filteredRoles);
|
||||
assertThat("AccessDenied message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", message, unfilteredRoles);
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
unfilteredRoles);
|
||||
assertThat("AccessDenied internal message system user: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", message, filteredRoles);
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", message,
|
||||
filteredRoles);
|
||||
assertThat("AccessDenied internal message system user: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "internal:_action", message, unfilteredRoles);
|
||||
auditTrail.accessDenied(authentication, "internal:_action", message, unfilteredRoles);
|
||||
assertThat("AccessDenied internal message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "internal:_action", message, filteredRoles);
|
||||
auditTrail.accessDenied(authentication, "internal:_action", message, filteredRoles);
|
||||
assertThat("AccessDenied internal message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
@ -1097,39 +1127,39 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// runAsGranted
|
||||
auditTrail.runAsGranted(user, "_action", new MockMessage(threadContext), unfilteredRoles);
|
||||
auditTrail.runAsGranted(authentication, "_action", new MockMessage(threadContext), unfilteredRoles);
|
||||
assertThat("RunAsGranted message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(user, "_action", new MockMessage(threadContext), filteredRoles);
|
||||
auditTrail.runAsGranted(authentication, "_action", new MockMessage(threadContext), filteredRoles);
|
||||
assertThat("RunAsGranted message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsDenied
|
||||
auditTrail.runAsDenied(user, "_action", new MockMessage(threadContext), unfilteredRoles);
|
||||
auditTrail.runAsDenied(authentication, "_action", new MockMessage(threadContext), unfilteredRoles);
|
||||
assertThat("RunAsDenied message: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, "_action", new MockMessage(threadContext), filteredRoles);
|
||||
auditTrail.runAsDenied(authentication, "_action", new MockMessage(threadContext), filteredRoles);
|
||||
assertThat("RunAsDenied message: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, getRestRequest(), unfilteredRoles);
|
||||
auditTrail.runAsDenied(authentication, getRestRequest(), unfilteredRoles);
|
||||
assertThat("RunAsDenied rest request: unfiltered roles filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, getRestRequest(), filteredRoles);
|
||||
auditTrail.runAsDenied(authentication, getRestRequest(), filteredRoles);
|
||||
assertThat("RunAsDenied rest request: filtered roles not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// authentication Success
|
||||
auditTrail.authenticationSuccess("_realm", user, getRestRequest());
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), getRestRequest());
|
||||
if (filterMissingRoles) {
|
||||
assertThat("AuthenticationSuccess rest request: is not filtered out by the missing roles filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1138,7 +1168,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", user, "_action", message);
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), "_action", message);
|
||||
if (filterMissingRoles) {
|
||||
assertThat("AuthenticationSuccess message: is not filtered out by the missing roles filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1195,11 +1225,12 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.otherPolicy.indices", otherIndices);
|
||||
}
|
||||
final String[] unfilteredIndices = _unfilteredIndices.toArray(new String[0]);
|
||||
User user;
|
||||
final Authentication authentication;
|
||||
if (randomBoolean()) {
|
||||
user = new User("user1", new String[] { "r1" }, new User("authUsername", new String[] { "r2" }));
|
||||
authentication = createAuthentication(new User("user1", new String[] { "r1" }, new User("authUsername", new String[] { "r2" })),
|
||||
"effectiveRealmName");
|
||||
} else {
|
||||
user = new User("user1", new String[] { "r1" });
|
||||
authentication = createAuthentication(new User("user1", new String[] { "r1" }), "effectiveRealmName");
|
||||
}
|
||||
final MockToken authToken = new MockToken("token1");
|
||||
final TransportMessage noIndexMessage = new MockMessage(threadContext);
|
||||
|
@ -1324,7 +1355,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// accessGranted
|
||||
auditTrail.accessGranted(user, "_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.accessGranted(authentication, "_action", noIndexMessage, new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AccessGranted message no index: not filtered out by the missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1333,17 +1364,20 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "_action", new MockIndicesRequest(threadContext, unfilteredIndices), new String[] { "role1" });
|
||||
auditTrail.accessGranted(authentication, "_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted message unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(user, "_action", new MockIndicesRequest(threadContext, filteredIndices), new String[] { "role1" });
|
||||
auditTrail.accessGranted(authentication, "_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted message filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", noIndexMessage,
|
||||
new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AccessGranted message system user no index: not filtered out by the missing indices filter", logOutput.size(),
|
||||
is(0));
|
||||
|
@ -1353,20 +1387,22 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action",
|
||||
new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted message system user unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action",
|
||||
new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted message system user filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessDenied
|
||||
auditTrail.accessDenied(user, "_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.accessDenied(authentication, "_action", noIndexMessage, new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AccessDenied message no index: not filtered out by the missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1375,17 +1411,20 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "_action", new MockIndicesRequest(threadContext, unfilteredIndices), new String[] { "role1" });
|
||||
auditTrail.accessDenied(authentication, "_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied message unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(user, "_action", new MockIndicesRequest(threadContext, filteredIndices), new String[] { "role1" });
|
||||
auditTrail.accessDenied(authentication, "_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied message filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action", noIndexMessage,
|
||||
new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AccessDenied message system user no index: not filtered out by the missing indices filter", logOutput.size(),
|
||||
is(0));
|
||||
|
@ -1395,13 +1434,15 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action",
|
||||
new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessDenied message system user unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(SystemUser.INSTANCE, "internal:_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
auditTrail.accessDenied(createAuthentication(SystemUser.INSTANCE, "effectiveRealmName"), "internal:_action",
|
||||
new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("AccessGranted message system user filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
|
@ -1428,7 +1469,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// runAsGranted
|
||||
auditTrail.runAsGranted(user, "_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.runAsGranted(authentication, "_action", noIndexMessage, new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("RunAsGranted message no index: not filtered out by missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1437,18 +1478,20 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(user, "_action", new MockIndicesRequest(threadContext, unfilteredIndices), new String[] { "role1" });
|
||||
auditTrail.runAsGranted(authentication, "_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsGranted message unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(user, "_action", new MockIndicesRequest(threadContext, filteredIndices), new String[] { "role1" });
|
||||
auditTrail.runAsGranted(authentication, "_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsGranted message filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsDenied
|
||||
auditTrail.runAsDenied(user, "_action", noIndexMessage, new String[] { "role1" });
|
||||
auditTrail.runAsDenied(authentication, "_action", noIndexMessage, new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("RunAsDenied message no index: not filtered out by missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1457,17 +1500,19 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, "_action", new MockIndicesRequest(threadContext, unfilteredIndices), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(authentication, "_action", new MockIndicesRequest(threadContext, unfilteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsDenied message unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, "_action", new MockIndicesRequest(threadContext, filteredIndices), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(authentication, "_action", new MockIndicesRequest(threadContext, filteredIndices),
|
||||
new String[] { "role1" });
|
||||
assertThat("RunAsDenied message filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(user, getRestRequest(), new String[] { "role1" });
|
||||
auditTrail.runAsDenied(authentication, getRestRequest(), new String[] { "role1" });
|
||||
if (filterMissingIndices) {
|
||||
assertThat("RunAsDenied rest request: not filtered out by missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1477,7 +1522,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
|
||||
// authentication Success
|
||||
auditTrail.authenticationSuccess("_realm", user, getRestRequest());
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), getRestRequest());
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AuthenticationSuccess rest request: is not filtered out by the missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1486,7 +1531,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", user, "_action", noIndexMessage);
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), "_action", noIndexMessage);
|
||||
if (filterMissingIndices) {
|
||||
assertThat("AuthenticationSuccess message no index: not filtered out by missing indices filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
|
@ -1495,12 +1540,14 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", user, "_action", new MockIndicesRequest(threadContext, unfilteredIndices));
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), "_action",
|
||||
new MockIndicesRequest(threadContext, unfilteredIndices));
|
||||
assertThat("AuthenticationSuccess message unfiltered indices: filtered out by indices filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess("_realm", user, "_action", new MockIndicesRequest(threadContext, filteredIndices));
|
||||
auditTrail.authenticationSuccess("_realm", authentication.getUser(), "_action",
|
||||
new MockIndicesRequest(threadContext, filteredIndices));
|
||||
assertThat("AuthenticationSuccess message filtered indices: not filtered out by indices filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
@ -1516,6 +1563,15 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
return ans;
|
||||
}
|
||||
|
||||
private static Authentication createAuthentication(User user, String effectiveRealmName) {
|
||||
if (user.isRunAs()) {
|
||||
return new Authentication(user,
|
||||
new RealmRef(UNFILTER_MARKER + randomAlphaOfLength(4), "test", "foo"), new RealmRef(effectiveRealmName, "up", "by"));
|
||||
} else {
|
||||
return new Authentication(user, new RealmRef(effectiveRealmName, "test", "foo"), null);
|
||||
}
|
||||
}
|
||||
|
||||
private ClusterSettings mockClusterSettings() {
|
||||
final List<Setting<?>> settingsList = new ArrayList<>();
|
||||
LoggingAuditTrail.registerSettings(settingsList);
|
||||
|
@ -1593,4 +1649,4 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import org.elasticsearch.test.rest.FakeRestRequest;
|
|||
import org.elasticsearch.test.rest.FakeRestRequest.Builder;
|
||||
import org.elasticsearch.transport.TransportMessage;
|
||||
import org.elasticsearch.xpack.core.security.audit.logfile.CapturingLogger;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
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;
|
||||
|
@ -346,9 +348,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.accessGranted(user, "_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||
", roles=[" + role + "]";
|
||||
auditTrail.accessGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], realm=[lookRealm], run_by_principal=[_username], run_by_realm=[authRealm]"
|
||||
: "principal=[_username], realm=[authRealm]") + ", roles=[" + role + "]";
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||
|
@ -361,7 +363,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessGranted(user, "_action", message, new String[] { role });
|
||||
auditTrail.accessGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
|
@ -370,22 +372,23 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
final TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE), "internal:_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
|
||||
// test enabled
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "system_access_granted").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
final String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||
auditTrail.accessGranted(createAuthentication(SystemUser.INSTANCE), "internal:_action", message, new String[] { role });
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||
SystemUser.INSTANCE.principal()
|
||||
+ "], roles=[" + role + "], action=[internal:_action], indices=[" + indices(message)
|
||||
+ "], realm=[authRealm], roles=[" + role + "], action=[internal:_action], indices=[" + indices(message)
|
||||
+ "], request=[MockIndicesRequest]");
|
||||
} else {
|
||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||
SystemUser.INSTANCE.principal() + "], roles=[" + role + "], action=[internal:_action], request=[MockMessage]");
|
||||
SystemUser.INSTANCE.principal() + "], realm=[authRealm], roles=[" + role
|
||||
+ "], action=[internal:_action], request=[MockMessage]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,9 +405,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.accessGranted(user, "internal:_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||
", roles=[" + role + "]";
|
||||
auditTrail.accessGranted(createAuthentication(user), "internal:_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], realm=[lookRealm], run_by_principal=[_username], run_by_realm=[authRealm]"
|
||||
: "principal=[_username], realm=[authRealm]") + ", roles=[" + role + "]";
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||
", action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||
|
@ -417,7 +420,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessGranted(user, "internal:_action", message, new String[] { role });
|
||||
auditTrail.accessGranted(createAuthentication(user), "internal:_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
|
@ -434,9 +437,9 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
user = new User("_username", new String[]{"r1"});
|
||||
}
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.accessDenied(user, "_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||
", roles=[" + role + "]";
|
||||
auditTrail.accessDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
final String userInfo = (runAs ? "principal=[running as], realm=[lookRealm], run_by_principal=[_username], run_by_realm=[authRealm]"
|
||||
: "principal=[_username], realm=[authRealm]") + ", roles=[" + role + "]";
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||
|
@ -449,7 +452,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_denied").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.accessDenied(user, "_action", message, new String[] { role });
|
||||
auditTrail.accessDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
|
@ -569,14 +572,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
final String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||
final User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.runAsGranted(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO,
|
||||
prefix + "[transport] [run_as_granted]\t" + origins + ", principal=[_username], run_as_principal=[running as], roles=["
|
||||
prefix + "[transport] [run_as_granted]\t" + origins
|
||||
+ ", principal=[_username], realm=[authRealm], run_as_principal=[running as], run_as_realm=[lookRealm], roles=["
|
||||
+ role + "], action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||
} else {
|
||||
assertMsg(logger, Level.INFO,
|
||||
prefix + "[transport] [run_as_granted]\t" + origins + ", principal=[_username], run_as_principal=[running as], roles=["
|
||||
prefix + "[transport] [run_as_granted]\t" + origins
|
||||
+ ", principal=[_username], realm=[authRealm], run_as_principal=[running as], run_as_realm=[lookRealm], roles=["
|
||||
+ role + "], action=[_action], request=[MockMessage]");
|
||||
}
|
||||
|
||||
|
@ -584,7 +589,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_granted").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.runAsGranted(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
|
@ -595,14 +600,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
final String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||
final User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||
final String role = randomAlphaOfLengthBetween(1, 6);
|
||||
auditTrail.runAsDenied(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
if (message instanceof IndicesRequest) {
|
||||
assertMsg(logger, Level.INFO,
|
||||
prefix + "[transport] [run_as_denied]\t" + origins + ", principal=[_username], run_as_principal=[running as], roles=["
|
||||
prefix + "[transport] [run_as_denied]\t" + origins
|
||||
+ ", principal=[_username], realm=[authRealm], run_as_principal=[running as], run_as_realm=[lookRealm], roles=["
|
||||
+ role + "], action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||
} else {
|
||||
assertMsg(logger, Level.INFO,
|
||||
prefix + "[transport] [run_as_denied]\t" + origins + ", principal=[_username], run_as_principal=[running as], roles=["
|
||||
prefix + "[transport] [run_as_denied]\t" + origins
|
||||
+ ", principal=[_username], realm=[authRealm], run_as_principal=[running as], run_as_realm=[lookRealm], roles=["
|
||||
+ role + "], action=[_action], request=[MockMessage]");
|
||||
}
|
||||
|
||||
|
@ -610,7 +617,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_denied").build();
|
||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||
auditTrail.runAsDenied(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertEmptyLog(logger);
|
||||
}
|
||||
|
||||
|
@ -740,10 +747,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
auditTrail.authenticationFailed(realm, new MockToken(), "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.accessGranted(user, "_action", message, new String[] { role });
|
||||
auditTrail.accessGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.accessDenied(user, "_action", message, new String[] { role });
|
||||
auditTrail.accessDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.tamperedRequest("_action", message);
|
||||
|
@ -752,10 +759,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
auditTrail.tamperedRequest(user, "_action", message);
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.runAsGranted(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsGranted(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.runAsDenied(user, "_action", message, new String[] { role });
|
||||
auditTrail.runAsDenied(createAuthentication(user), "_action", message, new String[] { role });
|
||||
assertThat(output.size(), is(logEntriesCount++));
|
||||
assertThat(output.get(logEntriesCount - 2), not(containsString("indices=[")));
|
||||
auditTrail.authenticationSuccess(realm, user, "_action", message);
|
||||
|
@ -800,6 +807,11 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
return Strings.arrayToCommaDelimitedString(((IndicesRequest) message).indices());
|
||||
}
|
||||
|
||||
private static Authentication createAuthentication(User user) {
|
||||
final RealmRef lookedUpBy = user.authenticatedUser() == user ? null : new RealmRef("lookRealm", "up", "by");
|
||||
return new Authentication(user, new RealmRef("authRealm", "test", "foo"), lookedUpBy);
|
||||
}
|
||||
|
||||
private ClusterSettings mockClusterSettings() {
|
||||
final List<Setting<?>> settingsList = new ArrayList<>();
|
||||
LoggingAuditTrail.registerSettings(settingsList);
|
||||
|
|
|
@ -782,7 +782,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
authenticateBlocking(restRequest);
|
||||
fail("exception should be thrown");
|
||||
} catch (ElasticsearchException e) {
|
||||
verify(auditTrail).runAsDenied(any(User.class), eq(restRequest), eq(Role.EMPTY.names()));
|
||||
verify(auditTrail).runAsDenied(any(Authentication.class), eq(restRequest), eq(Role.EMPTY.names()));
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
authenticateBlocking("_action", message, null);
|
||||
fail("exception should be thrown");
|
||||
} catch (ElasticsearchException e) {
|
||||
verify(auditTrail).runAsDenied(any(User.class), eq("_action"), eq(message), eq(Role.EMPTY.names()));
|
||||
verify(auditTrail).runAsDenied(any(Authentication.class), eq("_action"), eq(message), eq(Role.EMPTY.names()));
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,62 +222,67 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
TransportRequest request = mock(TransportRequest.class);
|
||||
|
||||
// A failure would throw an exception
|
||||
authorize(createAuthentication(SystemUser.INSTANCE), "indices:monitor/whatever", request);
|
||||
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "indices:monitor/whatever", request,
|
||||
Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
authorize(authentication, "indices:monitor/whatever", request);
|
||||
verify(auditTrail).accessGranted(authentication, "indices:monitor/whatever", request,
|
||||
new String[] { SystemUser.ROLE_NAME });
|
||||
|
||||
authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
|
||||
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||
authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
authorize(authentication, "internal:whatever", request);
|
||||
verify(auditTrail).accessGranted(authentication, "internal:whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testIndicesActionsAreNotAuthorized() {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request),
|
||||
() -> authorize(authentication, "indices:", request),
|
||||
"indices:", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "indices:", request, new String[] { SystemUser.ROLE_NAME });
|
||||
verify(auditTrail).accessDenied(authentication, "indices:", request, new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testClusterAdminActionsAreNotAuthorized() {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/whatever", request),
|
||||
() -> authorize(authentication, "cluster:admin/whatever", request),
|
||||
"cluster:admin/whatever", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/whatever", request,
|
||||
verify(auditTrail).accessDenied(authentication, "cluster:admin/whatever", request,
|
||||
new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testClusterAdminSnapshotStatusActionIsNotAuthorized() {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(SystemUser.INSTANCE);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/snapshot/status", request),
|
||||
() -> authorize(authentication, "cluster:admin/snapshot/status", request),
|
||||
"cluster:admin/snapshot/status", SystemUser.INSTANCE.principal());
|
||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/snapshot/status", request,
|
||||
verify(auditTrail).accessDenied(authentication, "cluster:admin/snapshot/status", request,
|
||||
new String[] { SystemUser.ROLE_NAME });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testNoRolesCausesDenial() {
|
||||
TransportRequest request = new SearchRequest();
|
||||
User user = new User("test user");
|
||||
final TransportRequest request = new SearchRequest();
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user");
|
||||
verify(auditTrail).accessDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testUserWithNoRolesCanPerformRemoteSearch() {
|
||||
SearchRequest request = new SearchRequest();
|
||||
request.indices("other_cluster:index1", "*_cluster:index2", "other_cluster:other_*");
|
||||
User user = new User("test user");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
authorize(createAuthentication(user), SearchAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
authorize(authentication, SearchAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -289,12 +294,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
public void testUserWithNoRolesCannotPerformLocalSearch() {
|
||||
SearchRequest request = new SearchRequest();
|
||||
request.indices("no_such_cluster:index");
|
||||
User user = new User("test user");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
||||
() -> authorize(authentication, SearchAction.NAME, request),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -305,23 +310,23 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
public void testUserWithNoRolesCanPerformMultiClusterSearch() {
|
||||
SearchRequest request = new SearchRequest();
|
||||
request.indices("local_index", "wildcard_*", "other_cluster:remote_index", "*:foo?");
|
||||
User user = new User("test user");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
||||
() -> authorize(authentication, SearchAction.NAME, request),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testUserWithNoRolesCannotSql() {
|
||||
TransportRequest request = new SqlQueryRequest();
|
||||
User user = new User("test user");
|
||||
Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), SqlQueryAction.NAME, request),
|
||||
() -> authorize(authentication, SqlQueryAction.NAME, request),
|
||||
SqlQueryAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, SqlQueryAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, SqlQueryAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -332,12 +337,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
public void testRemoteIndicesOnlyWorkWithApplicableRequestTypes() {
|
||||
DeleteIndexRequest request = new DeleteIndexRequest();
|
||||
request.indices("other_cluster:index1", "other_cluster:index2");
|
||||
User user = new User("test user");
|
||||
final Authentication authentication = createAuthentication(new User("test user"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), DeleteIndexAction.NAME, request),
|
||||
() -> authorize(authentication, DeleteIndexAction.NAME, request),
|
||||
DeleteIndexAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, DeleteIndexAction.NAME, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, DeleteIndexAction.NAME, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -348,26 +353,26 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
new Tuple<>(SqlQueryAction.NAME, new SqlQueryRequest())));
|
||||
String action = tuple.v1();
|
||||
TransportRequest request = tuple.v2();
|
||||
User user = new User("test user", "non-existent-role");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "non-existent-role"));
|
||||
mockEmptyMetaData();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, request),
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "test user");
|
||||
verify(auditTrail).accessDenied(user, action, request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, action, request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testThatNonIndicesAndNonClusterActionIsDenied() {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
User user = new User("test user", "a_all");
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
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);
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), "whatever", request),
|
||||
() -> authorize(authentication, "whatever", request),
|
||||
"whatever", "test user");
|
||||
verify(auditTrail).accessDenied(user, "whatever", request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, "whatever", request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -379,30 +384,30 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
new Tuple<>(SqlQueryAction.NAME, new SqlQueryRequest()));
|
||||
String action = tuple.v1();
|
||||
TransportRequest request = tuple.v2();
|
||||
User user = new User("test user", "no_indices");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "no_indices"));
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null, null, null);
|
||||
roleMap.put("no_indices", role);
|
||||
mockEmptyMetaData();
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, request),
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "test user");
|
||||
verify(auditTrail).accessDenied(user, action, request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, action, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testElasticUserAuthorizedForNonChangePasswordRequestsWhenNotInSetupMode() {
|
||||
final User user = new ElasticUser(true);
|
||||
Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||
authorize(createAuthentication(user), request.v1(), request.v2());
|
||||
final Authentication authentication = createAuthentication(new ElasticUser(true));
|
||||
final Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||
authorize(authentication, request.v1(), request.v2());
|
||||
|
||||
verify(auditTrail).accessGranted(user, request.v1(), request.v2(), new String[] { ElasticUser.ROLE_NAME });
|
||||
verify(auditTrail).accessGranted(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);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
|
||||
|
@ -413,21 +418,20 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
true, false));
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), SearchAction.NAME, searchRequest),
|
||||
() -> authorize(authentication, SearchAction.NAME, searchRequest),
|
||||
SearchAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, searchRequest, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, SearchAction.NAME, searchRequest, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
{
|
||||
//ignore_unavailable and allow_no_indices both set to true, user is not authorized for this index nor does it exist
|
||||
SearchRequest searchRequest = new SearchRequest("does_not_exist")
|
||||
.indicesOptions(IndicesOptions.fromOptions(true, true,
|
||||
true, false));
|
||||
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
||||
verify(auditTrail).accessGranted(user, SearchAction.NAME, searchRequest, new String[] { role.getName() });
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
||||
.indicesOptions(IndicesOptions.fromOptions(true, true, true, false));
|
||||
authorize(authentication, SearchAction.NAME, searchRequest);
|
||||
verify(auditTrail).accessGranted(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);
|
||||
assertFalse(indexAccessControl.getFieldPermissions().hasFieldLevelSecurity());
|
||||
assertNull(indexAccessControl.getQueries());
|
||||
|
@ -437,38 +441,38 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
public void testScrollRelatedRequestsAllowed() {
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
|
||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest);
|
||||
verify(auditTrail).accessGranted(user, ClearScrollAction.NAME, clearScrollRequest, new String[] { role.getName() });
|
||||
final ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
authorize(authentication, ClearScrollAction.NAME, clearScrollRequest);
|
||||
verify(auditTrail).accessGranted(authentication, ClearScrollAction.NAME, clearScrollRequest, new String[] { role.getName() });
|
||||
|
||||
SearchScrollRequest searchScrollRequest = new SearchScrollRequest();
|
||||
authorize(createAuthentication(user), SearchScrollAction.NAME, searchScrollRequest);
|
||||
verify(auditTrail).accessGranted(user, SearchScrollAction.NAME, searchScrollRequest, 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() });
|
||||
|
||||
// We have to use a mock request for other Scroll actions as the actual requests are package private to SearchTransportService
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
authorize(createAuthentication(user), SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request,
|
||||
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,
|
||||
new String[] { role.getName() });
|
||||
|
||||
authorize(createAuthentication(user), SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request,
|
||||
authorize(authentication, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request,
|
||||
new String[] { role.getName() });
|
||||
|
||||
authorize(createAuthentication(user), SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request,
|
||||
authorize(authentication, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request,
|
||||
new String[] { role.getName() });
|
||||
|
||||
authorize(createAuthentication(user), SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request,
|
||||
authorize(authentication, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request,
|
||||
new String[] { role.getName() });
|
||||
|
||||
authorize(createAuthentication(user), SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(user, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request,
|
||||
authorize(authentication, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request,
|
||||
new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
@ -478,13 +482,13 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mockEmptyMetaData();
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user");
|
||||
verify(auditTrail).accessDenied(user, "indices:a", request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
|
@ -496,13 +500,13 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mockEmptyMetaData();
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), CreateIndexAction.NAME, request),
|
||||
() -> authorize(authentication, CreateIndexAction.NAME, request),
|
||||
IndicesAliasesAction.NAME, "test user");
|
||||
verify(auditTrail).accessDenied(user, IndicesAliasesAction.NAME, request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, IndicesAliasesAction.NAME, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
|
@ -514,12 +518,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mockEmptyMetaData();
|
||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a", "a2").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
authorize(createAuthentication(user), CreateIndexAction.NAME, request);
|
||||
authorize(authentication, CreateIndexAction.NAME, request);
|
||||
|
||||
verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request, new String[] { role.getName()});
|
||||
verify(auditTrail).accessGranted(authentication, CreateIndexAction.NAME, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
|
@ -537,11 +541,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
final Authentication authentication = createAuthentication(anonymousUser);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(anonymousUser), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", anonymousUser.principal());
|
||||
|
||||
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
|
@ -554,7 +558,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
.put(AnonymousUser.ROLES_SETTING.getKey(), "a_all")
|
||||
.put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false)
|
||||
.build();
|
||||
final AnonymousUser anonymousUser = new AnonymousUser(settings);
|
||||
final Authentication authentication = createAuthentication(new AnonymousUser(settings));
|
||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
|
||||
new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(settings));
|
||||
|
||||
|
@ -562,10 +566,10 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> authorize(createAuthentication(anonymousUser), "indices:a", request));
|
||||
final ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||
() -> authorize(authentication, "indices:a", request));
|
||||
assertAuthenticationException(securityException, containsString("action [indices:a] requires authentication"));
|
||||
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService, times(1)).state();
|
||||
verify(state, times(1)).metaData();
|
||||
|
@ -577,28 +581,29 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mockEmptyMetaData();
|
||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
|
||||
final IndexNotFoundException nfe = expectThrows(
|
||||
IndexNotFoundException.class,
|
||||
() -> authorize(createAuthentication(user), GetIndexAction.NAME, request));
|
||||
() -> authorize(authentication, GetIndexAction.NAME, request));
|
||||
assertThat(nfe.getIndex(), is(notNullValue()));
|
||||
assertThat(nfe.getIndex().getName(), is("not-an-index-*"));
|
||||
verify(auditTrail).accessDenied(user, GetIndexAction.NAME, request, new String[]{ role.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, GetIndexAction.NAME, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
verify(clusterService).state();
|
||||
verify(state, times(1)).metaData();
|
||||
}
|
||||
|
||||
public void testRunAsRequestWithNoRolesUser() {
|
||||
TransportRequest request = mock(TransportRequest.class);
|
||||
User user = new User("run as me", null, new User("test user", "admin"));
|
||||
assertNotEquals(user.authenticatedUser(), user);
|
||||
final TransportRequest request = mock(TransportRequest.class);
|
||||
final Authentication authentication = createAuthentication(new User("run as me", null, new User("test user", "admin")));
|
||||
final User user = new User("run as me", null, new User("test user", "admin"));
|
||||
assertNotEquals(authentication.getUser().authenticatedUser(), authentication);
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me"); // run as [run as me]
|
||||
verify(auditTrail).runAsDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).runAsDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -611,7 +616,7 @@ 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(user, AuthenticateAction.NAME, request,
|
||||
verify(auditTrail).runAsDenied(authentication, AuthenticateAction.NAME, request,
|
||||
new String[] { ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
@ -620,15 +625,16 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
TransportRequest request = mock(TransportRequest.class);
|
||||
User user = new User("run as me", new String[] { "doesn't exist" }, new User("test user", "can run as"));
|
||||
assertNotEquals(user.authenticatedUser(), user);
|
||||
RoleDescriptor role = new RoleDescriptor("can run as", null,
|
||||
final Authentication authentication = createAuthentication(user);
|
||||
final RoleDescriptor role = new RoleDescriptor("can run as", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||
new String[] { "not the right user" });
|
||||
roleMap.put("can run as", role);
|
||||
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me");
|
||||
verify(auditTrail).runAsDenied(user, "indices:a", request, new String[] { role.getName() });
|
||||
verify(auditTrail).runAsDenied(authentication, "indices:a", request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -637,7 +643,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
User authenticatedUser = new User("test user", "can run as");
|
||||
User user = new User("run as me", new String[] { "b" }, authenticatedUser);
|
||||
assertNotEquals(user.authenticatedUser(), user);
|
||||
RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||
final Authentication authentication = createAuthentication(user);
|
||||
final RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||
new String[] { "run as me" });
|
||||
roleMap.put("can run as", runAsRole);
|
||||
|
@ -659,13 +666,13 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
assertThrowsAuthorizationExceptionRunAs(
|
||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||
() -> authorize(authentication, "indices:a", request),
|
||||
"indices:a", "test user", "run as me");
|
||||
verify(auditTrail).runAsGranted(user, "indices:a", request, new String[] { runAsRole.getName() });
|
||||
verify(auditTrail).runAsGranted(authentication, "indices:a", request, new String[] { runAsRole.getName() });
|
||||
if (indexExists) {
|
||||
verify(auditTrail).accessDenied(user, "indices:a", request, new String[] { bRole.getName() });
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, new String[] { bRole.getName() });
|
||||
} else {
|
||||
verify(auditTrail).accessDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||
verify(auditTrail).accessDenied(authentication, "indices:a", request, Role.EMPTY.names());
|
||||
}
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
@ -675,7 +682,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
User authenticatedUser = new User("test user", new String[] { "can run as" });
|
||||
User user = new User("run as me", new String[] { "b" }, authenticatedUser);
|
||||
assertNotEquals(user.authenticatedUser(), user);
|
||||
RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||
final Authentication authentication = createAuthentication(user);
|
||||
final RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||
new String[] { "run as me" });
|
||||
roleMap.put("can run as", runAsRole);
|
||||
|
@ -690,16 +698,16 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("all").build() }, null);
|
||||
roleMap.put("b", bRole);
|
||||
|
||||
authorize(createAuthentication(user), "indices:a", request);
|
||||
verify(auditTrail).runAsGranted(user, "indices:a", request, new String[] { runAsRole.getName() });
|
||||
verify(auditTrail).accessGranted(user, "indices:a", request, new String[] { bRole.getName() });
|
||||
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() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() {
|
||||
RoleDescriptor role = new RoleDescriptor("all access", new String[] { "all" },
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("*").privileges("all").build() }, null);
|
||||
User user = new User("all_access_user", "all_access");
|
||||
final Authentication authentication = createAuthentication(new User("all_access_user", "all_access"));
|
||||
roleMap.put("all_access", role);
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
@ -731,25 +739,25 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
String action = requestTuple.v1();
|
||||
TransportRequest request = requestTuple.v2();
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, request),
|
||||
() -> authorize(authentication, action, request),
|
||||
action, "all_access_user");
|
||||
verify(auditTrail).accessDenied(user, action, request, new String[] { role.getName() });
|
||||
verify(auditTrail).accessDenied(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(createAuthentication(user), ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||
authorize(authentication, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||
|
||||
// multiple indices
|
||||
request = new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar");
|
||||
authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||
authorize(authentication, ClusterHealthAction.NAME, request);
|
||||
verify(auditTrail).accessGranted(authentication, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
|
||||
SearchRequest searchRequest = new SearchRequest("_all");
|
||||
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
||||
final SearchRequest searchRequest = new SearchRequest("_all");
|
||||
authorize(authentication, SearchAction.NAME, searchRequest);
|
||||
assertEquals(2, searchRequest.indices().length);
|
||||
assertEquals(IndicesAndAliasesResolver.NO_INDICES_LIST, Arrays.asList(searchRequest.indices()));
|
||||
}
|
||||
|
@ -757,7 +765,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
public void testGrantedNonXPackUserCanExecuteMonitoringOperationsAgainstSecurityIndex() {
|
||||
RoleDescriptor role = new RoleDescriptor("all access", new String[] { "all" },
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("*").privileges("all").build() }, null);
|
||||
User user = new User("all_access_user", "all_access");
|
||||
final Authentication authentication = createAuthentication(new User("all_access_user", "all_access"));
|
||||
roleMap.put("all_access", role);
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
@ -777,11 +785,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
requests.add(new Tuple<>(UpgradeStatusAction.NAME,
|
||||
new UpgradeStatusRequest().indices(SECURITY_INDEX_NAME)));
|
||||
|
||||
for (Tuple<String, ? extends TransportRequest> requestTuple : requests) {
|
||||
String action = requestTuple.v1();
|
||||
TransportRequest request = requestTuple.v2();
|
||||
authorize(createAuthentication(user), action, request);
|
||||
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() });
|
||||
for (final Tuple<String, ? extends TransportRequest> requestTuple : requests) {
|
||||
final String action = requestTuple.v1();
|
||||
final TransportRequest request = requestTuple.v2();
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[] { role.getName() });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,16 +827,18 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
requests.add(new Tuple<>(ClusterHealthAction.NAME,
|
||||
new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar")));
|
||||
|
||||
for (Tuple<String, TransportRequest> requestTuple : requests) {
|
||||
String action = requestTuple.v1();
|
||||
TransportRequest request = requestTuple.v2();
|
||||
authorize(createAuthentication(superuser), action, request);
|
||||
verify(auditTrail).accessGranted(superuser, action, request, superuser.roles());
|
||||
for (final Tuple<String, TransportRequest> requestTuple : requests) {
|
||||
final String action = requestTuple.v1();
|
||||
final TransportRequest request = requestTuple.v2();
|
||||
final Authentication authentication = createAuthentication(superuser);
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, superuser.roles());
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() {
|
||||
final User superuser = new User("custom_admin", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName());
|
||||
final Authentication authentication = createAuthentication(superuser);
|
||||
roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR);
|
||||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
@ -841,7 +851,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
String action = SearchAction.NAME;
|
||||
SearchRequest request = new SearchRequest("_all");
|
||||
authorize(createAuthentication(superuser), action, request);
|
||||
verify(auditTrail).accessGranted(superuser, action, request, superuser.roles());
|
||||
verify(auditTrail).accessGranted(authentication, action, request, superuser.roles());
|
||||
assertThat(request.indices(), arrayContaining(".security"));
|
||||
}
|
||||
|
||||
|
@ -888,30 +898,30 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
|
||||
public void testCompositeActionsAreImmediatelyRejected() {
|
||||
//if the user has no permission for composite actions against any index, the request fails straight-away in the main action
|
||||
Tuple<String, TransportRequest> compositeRequest = randomCompositeRequest();
|
||||
String action = compositeRequest.v1();
|
||||
TransportRequest request = compositeRequest.v2();
|
||||
User user = new User("test user", "no_indices");
|
||||
RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||
final Tuple<String, TransportRequest> compositeRequest = randomCompositeRequest();
|
||||
final String action = compositeRequest.v1();
|
||||
final TransportRequest request = compositeRequest.v2();
|
||||
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);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, request), action, "test user");
|
||||
verify(auditTrail).accessDenied(user, action, request, new String[] { role.getName() });
|
||||
() -> authorize(authentication, action, request), action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testCompositeActionsIndicesAreNotChecked() {
|
||||
//if the user has permission for some index, the request goes through without looking at the indices, they will be checked later
|
||||
Tuple<String, TransportRequest> compositeRequest = randomCompositeRequest();
|
||||
String action = compositeRequest.v1();
|
||||
TransportRequest request = compositeRequest.v2();
|
||||
User user = new User("test user", "role");
|
||||
RoleDescriptor role = new RoleDescriptor("role", null,
|
||||
final Tuple<String, TransportRequest> compositeRequest = randomCompositeRequest();
|
||||
final String action = compositeRequest.v1();
|
||||
final TransportRequest request = compositeRequest.v2();
|
||||
final Authentication authentication = createAuthentication(new User("test user", "role"));
|
||||
final RoleDescriptor role = new RoleDescriptor("role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices(randomBoolean() ? "a" : "index").privileges("all").build() },
|
||||
null);
|
||||
roleMap.put("role", role);
|
||||
authorize(createAuthentication(user), action, request);
|
||||
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() });
|
||||
authorize(authentication, action, request);
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -983,7 +993,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
final ShardId shardId = new ShardId("concrete-index", UUID.randomUUID().toString(), 1);
|
||||
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
||||
|
||||
User user = new User("user", "my-role");
|
||||
final Authentication authentication = createAuthentication(new User("user", "my-role"));
|
||||
RoleDescriptor role = new RoleDescriptor("my-role", null, new IndicesPrivileges[] {
|
||||
IndicesPrivileges.builder().indices("concrete-index").privileges("all").build(),
|
||||
IndicesPrivileges.builder().indices("alias-1").privileges("index").build(),
|
||||
|
@ -992,11 +1002,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
roleMap.put("my-role", role);
|
||||
|
||||
mockEmptyMetaData();
|
||||
authorize(createAuthentication(user), action, request);
|
||||
authorize(authentication, action, request);
|
||||
|
||||
verify(auditTrail).accessDenied(user, DeleteAction.NAME, request, new String[] { role.getName() }); // alias-1 delete
|
||||
verify(auditTrail).accessDenied(user, IndexAction.NAME, request, new String[] { role.getName() }); // alias-2 index
|
||||
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() }); // bulk request is allowed
|
||||
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
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -1013,19 +1023,19 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
final ShardId shardId = new ShardId("concrete-index", UUID.randomUUID().toString(), 1);
|
||||
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
||||
|
||||
User user = new User("user", "my-role");
|
||||
RoleDescriptor role = new RoleDescriptor("my-role", null,
|
||||
final Authentication authentication = createAuthentication(new User("user", "my-role"));
|
||||
final RoleDescriptor role = new RoleDescriptor("my-role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("datemath-*").privileges("index").build() }, null);
|
||||
roleMap.put("my-role", role);
|
||||
|
||||
mockEmptyMetaData();
|
||||
authorize(createAuthentication(user), action, request);
|
||||
authorize(authentication, action, request);
|
||||
|
||||
verify(auditTrail, Mockito.times(2)).accessDenied(user, DeleteAction.NAME, request,
|
||||
new String[] { role.getName() }); // both
|
||||
// deletes
|
||||
// should fail
|
||||
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() }); // bulk request is allowed
|
||||
// both deletes should fail
|
||||
verify(auditTrail, Mockito.times(2)).accessDenied(authentication, DeleteAction.NAME, request,
|
||||
new String[] { role.getName() });
|
||||
// bulk request is allowed
|
||||
verify(auditTrail).accessGranted(authentication, action, request, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
|
@ -1253,52 +1263,52 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testProxyRequestAuthenticationDenied() {
|
||||
TransportRequest proxiedRequest = new SearchRequest();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, proxiedRequest);
|
||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.QUERY_ACTION_NAME);
|
||||
User user = new User("test user", "no_indices");
|
||||
RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||
final TransportRequest proxiedRequest = new SearchRequest();
|
||||
final DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
final TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, proxiedRequest);
|
||||
final String action = TransportActionProxy.getProxyAction(SearchTransportService.QUERY_ACTION_NAME);
|
||||
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);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(user, action, proxiedRequest, new String[] { role.getName() });
|
||||
() -> authorize(authentication, action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(authentication, action, proxiedRequest, new String[] { role.getName() });
|
||||
verifyNoMoreInteractions(auditTrail);
|
||||
}
|
||||
|
||||
public void testProxyRequestAuthenticationGrantedWithAllPrivileges() {
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
|
||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
authorize(createAuthentication(user), action, transportRequest);
|
||||
verify(auditTrail).accessGranted(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||
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() });
|
||||
}
|
||||
|
||||
public void testProxyRequestAuthenticationGranted() {
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("read_cross_cluster").build() }, null);
|
||||
User user = new User("test user", "a_all");
|
||||
final Authentication authentication = createAuthentication(new User("test user", "a_all"));
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
|
||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
authorize(createAuthentication(user), action, transportRequest);
|
||||
verify(auditTrail).accessGranted(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||
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() });
|
||||
}
|
||||
|
||||
public void testProxyRequestAuthenticationDeniedWithReadPrivileges() {
|
||||
User user = new User("test user", "a_all");
|
||||
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||
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("read").build() }, null);
|
||||
roleMap.put("a_all", role);
|
||||
mockEmptyMetaData();
|
||||
|
@ -1307,7 +1317,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||
assertThrowsAuthorizationException(
|
||||
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||
() -> authorize(authentication, action, transportRequest), action, "test user");
|
||||
verify(auditTrail).accessDenied(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.getUser(), "action", request, authentication.getUser().roles());
|
||||
verify(auditTrailService).accessDenied(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.getUser(), "action", request, authentication.getUser().roles());
|
||||
verify(auditTrailService).accessDenied(authentication, "action", request, authentication.getUser().roles());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|||
() -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, id, action, request,
|
||||
original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(differentRealmType.getUser(), action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(differentRealmType, action, request, original.getUser().roles());
|
||||
|
||||
// wrong user
|
||||
Authentication differentUser =
|
||||
|
@ -197,7 +197,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, id, action, request, original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(differentUser.getUser(), action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(differentUser, action, request, original.getUser().roles());
|
||||
|
||||
// run as different user
|
||||
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
||||
|
@ -205,7 +205,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, id, action, request, original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(diffRunAs.getUser(), action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(diffRunAs, action, request, original.getUser().roles());
|
||||
|
||||
// run as different looked up by type
|
||||
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||
|
@ -213,7 +213,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|||
e = expectThrows(SearchContextMissingException.class,
|
||||
() -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, id, action, request, original.getUser().roles()));
|
||||
assertEquals(id, e.id());
|
||||
verify(auditTrail).accessDenied(runAsDiffType.getUser(), action, request, original.getUser().roles());
|
||||
verify(auditTrail).accessDenied(runAsDiffType, action, request, original.getUser().roles());
|
||||
}
|
||||
|
||||
static class TestScrollSearchContext extends TestSearchContext {
|
||||
|
|
|
@ -17,6 +17,9 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.NotEqualMessageBuilder;
|
||||
import org.elasticsearch.xpack.qa.sql.security.SqlSecurityTestCase.AuditLogAsserter;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -24,10 +27,8 @@ import java.sql.JDBCType;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -36,7 +37,6 @@ import static org.elasticsearch.xpack.qa.sql.rest.RestSqlTestCase.randomMode;
|
|||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
public class RestSqlSecurityIT extends SqlSecurityTestCase {
|
||||
private static class RestActions implements Actions {
|
||||
|
@ -205,6 +205,11 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
|
|||
super(new RestActions());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuditLogAsserter createAuditLogAsserter() {
|
||||
return new RestAuditLogAsserter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the hijacking a scroll fails. This test is only implemented for
|
||||
* REST because it is the only API where it is simple to hijack a scroll.
|
||||
|
@ -226,15 +231,37 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
|
|||
assertThat(e.getMessage(), containsString("No search context found for id"));
|
||||
assertEquals(404, e.getResponse().getStatusLine().getStatusCode());
|
||||
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expect(true, SQL_ACTION_NAME, "full_access", empty())
|
||||
// One scroll access denied per shard
|
||||
.expect(false, SQL_ACTION_NAME, "full_access", empty(), "InternalScrollSearchRequest")
|
||||
.expect(false, SQL_ACTION_NAME, "full_access", empty(), "InternalScrollSearchRequest")
|
||||
.expect(false, SQL_ACTION_NAME, "full_access", empty(), "InternalScrollSearchRequest")
|
||||
.expect(false, SQL_ACTION_NAME, "full_access", empty(), "InternalScrollSearchRequest")
|
||||
.expect(false, SQL_ACTION_NAME, "full_access", empty(), "InternalScrollSearchRequest")
|
||||
.expect("access_denied", SQL_ACTION_NAME, "full_access", "default_native", empty(), "InternalScrollSearchRequest")
|
||||
.expect("access_denied", SQL_ACTION_NAME, "full_access", "default_native", empty(), "InternalScrollSearchRequest")
|
||||
.expect("access_denied", SQL_ACTION_NAME, "full_access", "default_native", empty(), "InternalScrollSearchRequest")
|
||||
.expect("access_denied", SQL_ACTION_NAME, "full_access", "default_native", empty(), "InternalScrollSearchRequest")
|
||||
.expect("access_denied", SQL_ACTION_NAME, "full_access", "default_native", empty(), "InternalScrollSearchRequest")
|
||||
.assertLogs();
|
||||
}
|
||||
|
||||
protected class RestAuditLogAsserter extends AuditLogAsserter {
|
||||
@Override
|
||||
public AuditLogAsserter expect(String eventType, String action, String principal, String realm,
|
||||
Matcher<? extends Iterable<? extends String>> indicesMatcher, String request) {
|
||||
final Matcher<String> runByPrincipalMatcher = principal.equals("test_admin") ? Matchers.nullValue(String.class)
|
||||
: Matchers.is("test_admin");
|
||||
final Matcher<String> runByRealmMatcher = realm.equals("default_file") ? Matchers.nullValue(String.class)
|
||||
: Matchers.is("default_file");
|
||||
logCheckers.add(
|
||||
m -> eventType.equals(m.get("event_type"))
|
||||
&& action.equals(m.get("action"))
|
||||
&& principal.equals(m.get("principal"))
|
||||
&& realm.equals(m.get("realm"))
|
||||
&& runByPrincipalMatcher.matches(m.get("run_by_principal"))
|
||||
&& runByRealmMatcher.matches(m.get("run_by_realm"))
|
||||
&& indicesMatcher.matches(m.get("indices"))
|
||||
&& request.equals(m.get("request")));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -192,7 +193,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
|
||||
public void testQueryWorksAsAdmin() throws Exception {
|
||||
actions.queryWorksAsAdmin();
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -201,7 +202,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("full_access", actions.minimalPermissionsForAllActions());
|
||||
|
||||
actions.expectMatchesAdmin("SELECT * FROM test ORDER BY a", "full_access", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("full_access", "test")
|
||||
.assertLogs();
|
||||
|
@ -211,7 +212,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("full_access", actions.minimalPermissionsForAllActions());
|
||||
|
||||
actions.expectScrollMatchesAdmin("SELECT * FROM test ORDER BY a", "full_access", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
/* Scrolling doesn't have to access the index again, at least not through sql.
|
||||
* If we asserted query and scroll logs then we would see the scroll. */
|
||||
|
@ -227,7 +228,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("no_access", "read_nothing");
|
||||
|
||||
actions.expectForbidden("no_access", "SELECT * FROM test");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expect(false, SQL_ACTION_NAME, "no_access", empty())
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -236,7 +237,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("wrong_access", "read_something_else");
|
||||
|
||||
actions.expectUnknownIndex("wrong_access", "SELECT * FROM test");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
//This user has permission to run sql queries so they are given preliminary authorization
|
||||
.expect(true, SQL_ACTION_NAME, "wrong_access", empty())
|
||||
//the following get index is granted too but against the no indices placeholder, as ignore_unavailable=true
|
||||
|
@ -248,7 +249,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("only_a", "read_test_a");
|
||||
|
||||
actions.expectMatchesAdmin("SELECT a FROM test ORDER BY a", "only_a", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("only_a", "test")
|
||||
.assertLogs();
|
||||
|
@ -258,7 +259,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("only_a", "read_test_a");
|
||||
|
||||
actions.expectScrollMatchesAdmin("SELECT a FROM test ORDER BY a", "only_a", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
/* Scrolling doesn't have to access the index again, at least not through sql.
|
||||
* If we asserted query and scroll logs then we would see the scoll. */
|
||||
|
@ -280,7 +281,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
* query from the audit side because all the permissions checked
|
||||
* out but it failed in SQL because it couldn't compile the
|
||||
* query without the metadata for the missing field. */
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("only_a", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("not_c", "read_test_a_and_b");
|
||||
|
||||
actions.expectMatchesAdmin("SELECT a, b FROM test ORDER BY a", "not_c", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("not_c", "test")
|
||||
.assertLogs();
|
||||
|
@ -299,7 +300,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("not_c", "read_test_a_and_b");
|
||||
|
||||
actions.expectScrollMatchesAdmin("SELECT a, b FROM test ORDER BY a", "not_c", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
/* Scrolling doesn't have to access the index again, at least not through sql.
|
||||
* If we asserted query and scroll logs then we would see the scroll. */
|
||||
|
@ -321,7 +322,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
* query from the audit side because all the permissions checked
|
||||
* out but it failed in SQL because it couldn't compile the
|
||||
* query without the metadata for the missing field. */
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("not_c", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -330,7 +331,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("no_3s", "read_test_without_c_3");
|
||||
|
||||
actions.expectMatchesAdmin("SELECT * FROM test WHERE c != 3 ORDER BY a", "no_3s", "SELECT * FROM test ORDER BY a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("no_3s", "test")
|
||||
.assertLogs();
|
||||
|
@ -338,7 +339,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
|
||||
public void testShowTablesWorksAsAdmin() throws Exception {
|
||||
actions.expectShowTables(Arrays.asList("bort", "test"), null);
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "bort", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -347,7 +348,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("full_access", actions.minimalPermissionsForAllActions());
|
||||
|
||||
actions.expectMatchesAdmin("SHOW TABLES LIKE '%t'", "full_access", "SHOW TABLES");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "bort", "test")
|
||||
.expectSqlCompositeAction("full_access", "bort", "test")
|
||||
.assertLogs();
|
||||
|
@ -357,7 +358,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("no_access", "read_nothing");
|
||||
|
||||
actions.expectForbidden("no_access", "SHOW TABLES");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expect(false, SQL_ACTION_NAME, "no_access", empty())
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -366,7 +367,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("read_bort", "read_bort");
|
||||
|
||||
actions.expectMatchesAdmin("SHOW TABLES LIKE 'bort'", "read_bort", "SHOW TABLES");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "bort")
|
||||
.expectSqlCompositeAction("read_bort", "bort")
|
||||
.assertLogs();
|
||||
|
@ -376,7 +377,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("read_bort", "read_bort");
|
||||
|
||||
actions.expectMatchesAdmin("SHOW TABLES LIKE 'not-created'", "read_bort", "SHOW TABLES LIKE 'test'");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expect(true, SQL_ACTION_NAME, "test_admin", empty())
|
||||
.expect(true, GetIndexAction.NAME, "test_admin", contains("*", "-*"))
|
||||
.expect(true, SQL_ACTION_NAME, "read_bort", empty())
|
||||
|
@ -390,7 +391,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
expected.put("b", "BIGINT");
|
||||
expected.put("c", "BIGINT");
|
||||
actions.expectDescribe(expected, null);
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -399,7 +400,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("full_access", actions.minimalPermissionsForAllActions());
|
||||
|
||||
actions.expectMatchesAdmin("DESCRIBE test", "full_access", "DESCRIBE test");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("full_access", "test")
|
||||
.assertLogs();
|
||||
|
@ -409,7 +410,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("no_access", "read_nothing");
|
||||
|
||||
actions.expectForbidden("no_access", "DESCRIBE test");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expect(false, SQL_ACTION_NAME, "no_access", empty())
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -418,7 +419,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("wrong_access", "read_something_else");
|
||||
|
||||
actions.expectDescribe(Collections.emptyMap(), "wrong_access");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
//This user has permission to run sql queries so they are given preliminary authorization
|
||||
.expect(true, SQL_ACTION_NAME, "wrong_access", empty())
|
||||
//the following get index is granted too but against the no indices placeholder, as ignore_unavailable=true
|
||||
|
@ -430,7 +431,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("only_a", "read_test_a");
|
||||
|
||||
actions.expectDescribe(singletonMap("a", "BIGINT"), "only_a");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("only_a", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -442,7 +443,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
expected.put("a", "BIGINT");
|
||||
expected.put("b", "BIGINT");
|
||||
actions.expectDescribe(expected, "not_c");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("not_c", "test")
|
||||
.assertLogs();
|
||||
}
|
||||
|
@ -451,7 +452,7 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
createUser("no_3s", "read_test_without_c_3");
|
||||
|
||||
actions.expectMatchesAdmin("DESCRIBE test", "no_3s", "DESCRIBE test");
|
||||
new AuditLogAsserter()
|
||||
createAuditLogAsserter()
|
||||
.expectSqlCompositeAction("test_admin", "test")
|
||||
.expectSqlCompositeAction("no_3s", "test")
|
||||
.assertLogs();
|
||||
|
@ -480,13 +481,17 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
new StringEntity(Strings.toString(user), ContentType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
protected AuditLogAsserter createAuditLogAsserter() {
|
||||
return new AuditLogAsserter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to assert audit logs. Logs are asserted to match in any order because
|
||||
* we don't always scroll in the same order but each log checker must match a
|
||||
* single log and all logs must be matched.
|
||||
*/
|
||||
protected final class AuditLogAsserter {
|
||||
private final List<Function<Map<String, Object>, Boolean>> logCheckers = new ArrayList<>();
|
||||
protected class AuditLogAsserter {
|
||||
protected final List<Function<Map<String, Object>, Boolean>> logCheckers = new ArrayList<>();
|
||||
|
||||
public AuditLogAsserter expectSqlCompositeAction(String user, String... indices) {
|
||||
expect(true, SQL_ACTION_NAME, user, empty());
|
||||
|
@ -507,15 +512,19 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
default:
|
||||
throw new IllegalArgumentException("Unknown action [" + action + "]");
|
||||
}
|
||||
return expect(granted, action, principal, indicesMatcher, request);
|
||||
final String eventType = granted ? "access_granted" : "access_denied";
|
||||
final String realm = principal.equals("test_admin") ? "default_file" : "default_native";
|
||||
return expect(eventType, action, principal, realm, indicesMatcher, request);
|
||||
}
|
||||
|
||||
public AuditLogAsserter expect(boolean granted, String action, String principal,
|
||||
public AuditLogAsserter expect(String eventType, String action, String principal, String realm,
|
||||
Matcher<? extends Iterable<? extends String>> indicesMatcher, String request) {
|
||||
String eventType = granted ? "access_granted" : "access_denied";
|
||||
logCheckers.add(m -> eventType.equals(m.get("event_type"))
|
||||
&& action.equals(m.get("action"))
|
||||
&& principal.equals(m.get("principal"))
|
||||
&& realm.equals(m.get("realm"))
|
||||
&& Matchers.nullValue(String.class).matches(m.get("run_by_principal"))
|
||||
&& Matchers.nullValue(String.class).matches(m.get("run_by_realm"))
|
||||
&& indicesMatcher.matches(m.get("indices"))
|
||||
&& request.equals(m.get("request"))
|
||||
);
|
||||
|
@ -543,10 +552,10 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
List<Map<String, Object>> logs = new ArrayList<>();
|
||||
String line;
|
||||
Pattern logPattern = Pattern.compile(
|
||||
("PART PART PART origin_type=PART, origin_address=PART, "
|
||||
+ "principal=PART, (?:run_as_principal=PART, )?(?:run_by_principal=PART, )?"
|
||||
("PART PART PART origin_type=PART, origin_address=PART, principal=PART, realm=PART, "
|
||||
+ "(?:run_as_principal=IGN, )?(?:run_as_realm=IGN, )?(?:run_by_principal=PART, )?(?:run_by_realm=PART, )?"
|
||||
+ "roles=PART, action=\\[(.*?)\\], (?:indices=PART, )?request=PART")
|
||||
.replace(" ", "\\s+").replace("PART", "\\[([^\\]]*)\\]"));
|
||||
.replace(" ", "\\s+").replace("PART", "\\[([^\\]]*)\\]").replace("IGN", "\\[[^\\]]*\\]"));
|
||||
// fail(logPattern.toString());
|
||||
while ((line = logReader.readLine()) != null) {
|
||||
java.util.regex.Matcher m = logPattern.matcher(line);
|
||||
|
@ -568,8 +577,9 @@ public abstract class SqlSecurityTestCase extends ESRestTestCase {
|
|||
log.put("origin_address", m.group(i++));
|
||||
String principal = m.group(i++);
|
||||
log.put("principal", principal);
|
||||
log.put("run_as_principal", m.group(i++));
|
||||
log.put("realm", m.group(i++));
|
||||
log.put("run_by_principal", m.group(i++));
|
||||
log.put("run_by_realm", m.group(i++));
|
||||
log.put("roles", m.group(i++));
|
||||
String action = m.group(i++);
|
||||
if (false == (SQL_ACTION_NAME.equals(action) || GetIndexAction.NAME.equals(action))) {
|
||||
|
|
Loading…
Reference in New Issue