Augment audit authz event with role names data (elastic/x-pack-elasticsearch#3100)
Audit authz events (accessGranted, accessDenied, runAsGranted and runAsDenied) include role names. Original commit: elastic/x-pack-elasticsearch@6a94f65962
This commit is contained in:
parent
4262b29188
commit
3ea5a6df91
|
@ -6,19 +6,20 @@
|
||||||
package org.elasticsearch.xpack.security.action.user;
|
package org.elasticsearch.xpack.security.action.user;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||||
import org.apache.lucene.util.automaton.Automaton;
|
import org.apache.lucene.util.automaton.Automaton;
|
||||||
import org.apache.lucene.util.automaton.Operations;
|
import org.apache.lucene.util.automaton.Operations;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.support.ActionFilters;
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
import org.elasticsearch.action.support.HandledTransportAction;
|
import org.elasticsearch.action.support.HandledTransportAction;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
@ -68,10 +69,9 @@ public class TransportHasPrivilegesAction extends HandledTransportAction<HasPriv
|
||||||
|
|
||||||
private void checkPrivileges(HasPrivilegesRequest request, Role userRole,
|
private void checkPrivileges(HasPrivilegesRequest request, Role userRole,
|
||||||
ActionListener<HasPrivilegesResponse> listener) {
|
ActionListener<HasPrivilegesResponse> listener) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.debug(() -> new ParameterizedMessage("Check whether role [{}] has privileges cluster=[{}] index=[{}]",
|
||||||
logger.debug("Check whether role [{}] has privileges cluster=[{}] index=[{}]", userRole.name(),
|
Strings.arrayToCommaDelimitedString(userRole.names()), Strings.arrayToCommaDelimitedString(request.clusterPrivileges()),
|
||||||
Arrays.toString(request.clusterPrivileges()), Arrays.toString(request.indexPrivileges()));
|
Strings.arrayToCommaDelimitedString(request.indexPrivileges())));
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Boolean> cluster = new HashMap<>();
|
Map<String, Boolean> cluster = new HashMap<>();
|
||||||
for (String checkAction : request.clusterPrivileges()) {
|
for (String checkAction : request.clusterPrivileges()) {
|
||||||
|
@ -93,10 +93,12 @@ public class TransportHasPrivilegesAction extends HandledTransportAction<HasPriv
|
||||||
}
|
}
|
||||||
for (String privilege : check.getPrivileges()) {
|
for (String privilege : check.getPrivileges()) {
|
||||||
if (testIndexMatch(index, privilege, userRole, predicateCache)) {
|
if (testIndexMatch(index, privilege, userRole, predicateCache)) {
|
||||||
logger.debug("Role [{}] has [{}] on [{}]", userRole.name(), privilege, index);
|
logger.debug(() -> new ParameterizedMessage("Role [{}] has [{}] on [{}]",
|
||||||
|
Strings.arrayToCommaDelimitedString(userRole.names()), privilege, index));
|
||||||
privileges.put(privilege, true);
|
privileges.put(privilege, true);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Role [{}] does not have [{}] on [{}]", userRole.name(), privilege, index);
|
logger.debug(() -> new ParameterizedMessage("Role [{}] does not have [{}] on [{}]",
|
||||||
|
Strings.arrayToCommaDelimitedString(userRole.names()), privilege, index));
|
||||||
privileges.put(privilege, false);
|
privileges.put(privilege, false);
|
||||||
allMatch = false;
|
allMatch = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ public interface AuditTrail {
|
||||||
|
|
||||||
void authenticationFailed(String realm, AuthenticationToken token, RestRequest request);
|
void authenticationFailed(String realm, AuthenticationToken token, RestRequest request);
|
||||||
|
|
||||||
void accessGranted(User user, String action, TransportMessage message);
|
void accessGranted(User user, String action, TransportMessage message, String[] roleNames);
|
||||||
|
|
||||||
void accessDenied(User user, String action, TransportMessage message);
|
void accessDenied(User user, String action, TransportMessage message, String[] roleNames);
|
||||||
|
|
||||||
void tamperedRequest(RestRequest request);
|
void tamperedRequest(RestRequest request);
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ public interface AuditTrail {
|
||||||
|
|
||||||
void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule);
|
void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule);
|
||||||
|
|
||||||
void runAsGranted(User user, String action, TransportMessage message);
|
void runAsGranted(User user, String action, TransportMessage message, String[] roleNames);
|
||||||
|
|
||||||
void runAsDenied(User user, String action, TransportMessage message);
|
void runAsDenied(User user, String action, TransportMessage message, String[] roleNames);
|
||||||
|
|
||||||
void runAsDenied(User user, RestRequest request);
|
void runAsDenied(User user, RestRequest request, String[] roleNames);
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,19 +130,19 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessGranted(User user, String action, TransportMessage message) {
|
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (licenseState.isAuditingAllowed()) {
|
if (licenseState.isAuditingAllowed()) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
auditTrail.accessGranted(user, action, message);
|
auditTrail.accessGranted(user, action, message, roleNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessDenied(User user, String action, TransportMessage message) {
|
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (licenseState.isAuditingAllowed()) {
|
if (licenseState.isAuditingAllowed()) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
auditTrail.accessDenied(user, action, message);
|
auditTrail.accessDenied(user, action, message, roleNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,28 +191,28 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsGranted(User user, String action, TransportMessage message) {
|
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (licenseState.isAuditingAllowed()) {
|
if (licenseState.isAuditingAllowed()) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
auditTrail.runAsGranted(user, action, message);
|
auditTrail.runAsGranted(user, action, message, roleNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, String action, TransportMessage message) {
|
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (licenseState.isAuditingAllowed()) {
|
if (licenseState.isAuditingAllowed()) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
auditTrail.runAsDenied(user, action, message);
|
auditTrail.runAsDenied(user, action, message, roleNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, RestRequest request) {
|
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||||
if (licenseState.isAuditingAllowed()) {
|
if (licenseState.isAuditingAllowed()) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
auditTrail.runAsDenied(user, request);
|
auditTrail.runAsDenied(user, request, roleNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ import org.elasticsearch.xpack.XPackPlugin;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||||
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
|
||||||
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
||||||
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
import org.elasticsearch.xpack.security.support.IndexLifecycleManager;
|
||||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||||
|
@ -356,7 +355,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
public void authenticationSuccess(String realm, User user, RestRequest request) {
|
||||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("authentication_success", realm, user, request), "authentication_success");
|
enqueue(message("authentication_success", realm, user, null, request), "authentication_success");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [authentication_success]", e);
|
logger.warn("failed to index audit event: [authentication_success]", e);
|
||||||
}
|
}
|
||||||
|
@ -367,7 +366,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
public void authenticationSuccess(String realm, User user, String action, TransportMessage message) {
|
||||||
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
if (events.contains(AUTHENTICATION_SUCCESS)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("authentication_success", action, user, realm, null, message), "authentication_success");
|
enqueue(message("authentication_success", action, user, null, realm, null, message), "authentication_success");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [authentication_success]", e);
|
logger.warn("failed to index audit event: [authentication_success]", e);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +377,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void anonymousAccessDenied(String action, TransportMessage message) {
|
public void anonymousAccessDenied(String action, TransportMessage message) {
|
||||||
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("anonymous_access_denied", action, (User) null, null, indices(message), message),
|
enqueue(message("anonymous_access_denied", action, (User) null, null, null, indices(message), message),
|
||||||
"anonymous_access_denied");
|
"anonymous_access_denied");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [anonymous_access_denied]", e);
|
logger.warn("failed to index audit event: [anonymous_access_denied]", e);
|
||||||
|
@ -401,7 +400,8 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void authenticationFailed(String action, TransportMessage message) {
|
public void authenticationFailed(String action, TransportMessage message) {
|
||||||
if (events.contains(AUTHENTICATION_FAILED)) {
|
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("authentication_failed", action, (User) null, null, indices(message), message), "authentication_failed");
|
enqueue(message("authentication_failed", action, (User) null, null, null, indices(message), message),
|
||||||
|
"authentication_failed");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [authentication_failed]", e);
|
logger.warn("failed to index audit event: [authentication_failed]", e);
|
||||||
}
|
}
|
||||||
|
@ -473,19 +473,13 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessGranted(User user, String action, TransportMessage message) {
|
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
// special treatment for internal system actions - only log if explicitly told to
|
final boolean isSystem = SystemUser.is(user) || XPackUser.is(user);
|
||||||
if ((SystemUser.is(user) && SystemPrivilege.INSTANCE.predicate().test(action))) {
|
final boolean logSystemAccessGranted = isSystem && events.contains(SYSTEM_ACCESS_GRANTED);
|
||||||
if (events.contains(SYSTEM_ACCESS_GRANTED)) {
|
final boolean shouldLog = logSystemAccessGranted || (isSystem == false && events.contains(ACCESS_GRANTED));
|
||||||
try {
|
if (shouldLog) {
|
||||||
enqueue(message("access_granted", action, user, null, indices(message), message), "access_granted");
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("failed to index audit event: [access_granted]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (events.contains(ACCESS_GRANTED) && XPackUser.is(user) == false) {
|
|
||||||
try {
|
try {
|
||||||
enqueue(message("access_granted", action, user, null, indices(message), message), "access_granted");
|
enqueue(message("access_granted", action, user, roleNames, null, indices(message), message), "access_granted");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [access_granted]", e);
|
logger.warn("failed to index audit event: [access_granted]", e);
|
||||||
}
|
}
|
||||||
|
@ -493,10 +487,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessDenied(User user, String action, TransportMessage message) {
|
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(ACCESS_DENIED) && XPackUser.is(user) == false) {
|
if (events.contains(ACCESS_DENIED) && XPackUser.is(user) == false) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("access_denied", action, user, null, indices(message), message), "access_denied");
|
enqueue(message("access_denied", action, user, roleNames, null, indices(message), message), "access_denied");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [access_denied]", e);
|
logger.warn("failed to index audit event: [access_denied]", e);
|
||||||
}
|
}
|
||||||
|
@ -518,7 +512,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void tamperedRequest(String action, TransportMessage message) {
|
public void tamperedRequest(String action, TransportMessage message) {
|
||||||
if (events.contains(TAMPERED_REQUEST)) {
|
if (events.contains(TAMPERED_REQUEST)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("tampered_request", action, (User) null, null, indices(message), message), "tampered_request");
|
enqueue(message("tampered_request", action, (User) null, null, null, indices(message), message), "tampered_request");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [tampered_request]", e);
|
logger.warn("failed to index audit event: [tampered_request]", e);
|
||||||
}
|
}
|
||||||
|
@ -529,7 +523,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
public void tamperedRequest(User user, String action, TransportMessage request) {
|
public void tamperedRequest(User user, String action, TransportMessage request) {
|
||||||
if (events.contains(TAMPERED_REQUEST) && XPackUser.is(user) == false) {
|
if (events.contains(TAMPERED_REQUEST) && XPackUser.is(user) == false) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("tampered_request", action, user, null, indices(request), request), "tampered_request");
|
enqueue(message("tampered_request", action, user, null, null, indices(request), request), "tampered_request");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [tampered_request]", e);
|
logger.warn("failed to index audit event: [tampered_request]", e);
|
||||||
}
|
}
|
||||||
|
@ -559,10 +553,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsGranted(User user, String action, TransportMessage message) {
|
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_GRANTED)) {
|
if (events.contains(RUN_AS_GRANTED)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("run_as_granted", action, user, null, null, message), "run_as_granted");
|
enqueue(message("run_as_granted", action, user, roleNames, null, null, message), "run_as_granted");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [run_as_granted]", e);
|
logger.warn("failed to index audit event: [run_as_granted]", e);
|
||||||
}
|
}
|
||||||
|
@ -570,10 +564,10 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, String action, TransportMessage message) {
|
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_DENIED)) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("run_as_denied", action, user, null, null, message), "run_as_denied");
|
enqueue(message("run_as_denied", action, user, roleNames, null, null, message), "run_as_denied");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [run_as_denied]", e);
|
logger.warn("failed to index audit event: [run_as_denied]", e);
|
||||||
}
|
}
|
||||||
|
@ -581,17 +575,17 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, RestRequest request) {
|
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_DENIED)) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
try {
|
try {
|
||||||
enqueue(message("run_as_denied", null, user, request), "run_as_denied");
|
enqueue(message("run_as_denied", null, user, roleNames, request), "run_as_denied");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("failed to index audit event: [run_as_denied]", 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 realm,
|
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 {
|
@Nullable Set<String> indices, TransportMessage message) throws Exception {
|
||||||
|
|
||||||
Message msg = new Message().start();
|
Message msg = new Message().start();
|
||||||
|
@ -614,6 +608,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
} else {
|
} else {
|
||||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||||
}
|
}
|
||||||
|
if (roleNames != null) {
|
||||||
|
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
msg.builder.array(Field.INDICES, indices.toArray(Strings.EMPTY_ARRAY));
|
msg.builder.array(Field.INDICES, indices.toArray(Strings.EMPTY_ARRAY));
|
||||||
|
@ -686,7 +683,8 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
return msg.end();
|
return msg.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message message(String type, String realm, User user, RestRequest request) throws Exception {
|
private Message message(String type, @Nullable String realm, @Nullable User user, @Nullable String[] roleNames, RestRequest request)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
Message msg = new Message().start();
|
Message msg = new Message().start();
|
||||||
common("rest", type, msg.builder);
|
common("rest", type, msg.builder);
|
||||||
|
@ -698,6 +696,9 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
} else {
|
} else {
|
||||||
msg.builder.field(Field.PRINCIPAL, user.principal());
|
msg.builder.field(Field.PRINCIPAL, user.principal());
|
||||||
}
|
}
|
||||||
|
if (roleNames != null) {
|
||||||
|
msg.builder.array(Field.ROLE_NAMES, roleNames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (realm != null) {
|
if (realm != null) {
|
||||||
msg.builder.field(Field.REALM, realm);
|
msg.builder.field(Field.REALM, realm);
|
||||||
|
@ -1051,6 +1052,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail {
|
||||||
String ORIGIN_ADDRESS = "origin_address";
|
String ORIGIN_ADDRESS = "origin_address";
|
||||||
String ORIGIN_TYPE = "origin_type";
|
String ORIGIN_TYPE = "origin_type";
|
||||||
String PRINCIPAL = "principal";
|
String PRINCIPAL = "principal";
|
||||||
|
String ROLE_NAMES = "roles";
|
||||||
String RUN_AS_PRINCIPAL = "run_as_principal";
|
String RUN_AS_PRINCIPAL = "run_as_principal";
|
||||||
String RUN_BY_PRINCIPAL = "run_by_principal";
|
String RUN_BY_PRINCIPAL = "run_by_principal";
|
||||||
String ACTION = "action";
|
String ACTION = "action";
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.elasticsearch.transport.TransportMessage;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
import org.elasticsearch.xpack.security.audit.AuditLevel;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||||
import org.elasticsearch.xpack.security.authz.privilege.SystemPrivilege;
|
|
||||||
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
import org.elasticsearch.xpack.security.rest.RemoteHostHeader;
|
||||||
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
|
||||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||||
|
@ -44,6 +43,7 @@ import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString;
|
import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString;
|
||||||
|
import static org.elasticsearch.common.Strings.arrayToCommaDelimitedString;
|
||||||
import static org.elasticsearch.xpack.security.Security.setting;
|
import static org.elasticsearch.xpack.security.Security.setting;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_DENIED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_DENIED;
|
||||||
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_GRANTED;
|
import static org.elasticsearch.xpack.security.audit.AuditLevel.ACCESS_GRANTED;
|
||||||
|
@ -255,38 +255,38 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessGranted(User user, String action, TransportMessage message) {
|
public void accessGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
final boolean isSystem = (SystemUser.is(user) && SystemPrivilege.INSTANCE.predicate().test(action)) || XPackUser.is(user);
|
final boolean isSystem = SystemUser.is(user) || XPackUser.is(user);
|
||||||
final boolean logSystemAccessGranted = isSystem && events.contains(SYSTEM_ACCESS_GRANTED);
|
final boolean logSystemAccessGranted = isSystem && events.contains(SYSTEM_ACCESS_GRANTED);
|
||||||
final boolean shouldLog = logSystemAccessGranted || (isSystem == false && events.contains(ACCESS_GRANTED));
|
final boolean shouldLog = logSystemAccessGranted || (isSystem == false && events.contains(ACCESS_GRANTED));
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], indices=[{}], request=[{}]", localNodeInfo.prefix,
|
logger.info("{}[transport] [access_granted]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||||
originAttributes(threadContext, message, localNodeInfo), principal(user), action, indices,
|
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||||
message.getClass().getSimpleName());
|
arrayToCommaDelimitedString(roleNames), action, indices, message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.info("{}[transport] [access_granted]\t{}, {}, action=[{}], request=[{}]", localNodeInfo.prefix,
|
logger.info("{}[transport] [access_granted]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||||
originAttributes(threadContext, message, localNodeInfo), principal(user), action,
|
originAttributes(threadContext, message, localNodeInfo), principal(user), arrayToCommaDelimitedString(roleNames),
|
||||||
message.getClass().getSimpleName());
|
action, message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accessDenied(User user, String action, TransportMessage message) {
|
public void accessDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(ACCESS_DENIED)) {
|
if (events.contains(ACCESS_DENIED)) {
|
||||||
String indices = indicesString(message);
|
String indices = indicesString(message);
|
||||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||||
if (indices != null) {
|
if (indices != null) {
|
||||||
logger.info("{}[transport] [access_denied]\t{}, {}, action=[{}], indices=[{}], request=[{}]", localNodeInfo.prefix,
|
logger.info("{}[transport] [access_denied]\t{}, {}, roles=[{}], action=[{}], indices=[{}], request=[{}]",
|
||||||
originAttributes(threadContext, message, localNodeInfo), principal(user), action, indices,
|
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), principal(user),
|
||||||
message.getClass().getSimpleName());
|
arrayToCommaDelimitedString(roleNames), action, indices, message.getClass().getSimpleName());
|
||||||
} else {
|
} else {
|
||||||
logger.info("{}[transport] [access_denied]\t{}, {}, action=[{}], request=[{}]", localNodeInfo.prefix,
|
logger.info("{}[transport] [access_denied]\t{}, {}, roles=[{}], action=[{}], request=[{}]", localNodeInfo.prefix,
|
||||||
originAttributes(threadContext, message, localNodeInfo), principal(user), action,
|
originAttributes(threadContext, message, localNodeInfo), principal(user), arrayToCommaDelimitedString(roleNames),
|
||||||
message.getClass().getSimpleName());
|
action, message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,34 +352,35 @@ public class LoggingAuditTrail extends AbstractComponent implements AuditTrail,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsGranted(User user, String action, TransportMessage message) {
|
public void runAsGranted(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_GRANTED)) {
|
if (events.contains(RUN_AS_GRANTED)) {
|
||||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||||
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
logger.info("{}[transport] [run_as_granted]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}], action=[{}], request=[{}]",
|
||||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), user.authenticatedUser().principal(),
|
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), user.authenticatedUser().principal(),
|
||||||
user.principal(), action, message.getClass().getSimpleName());
|
user.principal(), arrayToCommaDelimitedString(roleNames), action, message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, String action, TransportMessage message) {
|
public void runAsDenied(User user, String action, TransportMessage message, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_DENIED)) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
final LocalNodeInfo localNodeInfo = this.localNodeInfo;
|
||||||
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], action=[{}], request=[{}]",
|
logger.info("{}[transport] [run_as_denied]\t{}, principal=[{}], run_as_principal=[{}], roles=[{}], action=[{}], request=[{}]",
|
||||||
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), user.authenticatedUser().principal(),
|
localNodeInfo.prefix, originAttributes(threadContext, message, localNodeInfo), user.authenticatedUser().principal(),
|
||||||
user.principal(), action, message.getClass().getSimpleName());
|
user.principal(), arrayToCommaDelimitedString(roleNames), action, message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runAsDenied(User user, RestRequest request) {
|
public void runAsDenied(User user, RestRequest request, String[] roleNames) {
|
||||||
if (events.contains(RUN_AS_DENIED)) {
|
if (events.contains(RUN_AS_DENIED)) {
|
||||||
if (includeRequestBody) {
|
if (includeRequestBody) {
|
||||||
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], uri=[{}], request_body=[{}]", localNodeInfo.prefix,
|
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], roles=[{}], uri=[{}], request_body=[{}]", localNodeInfo.prefix,
|
||||||
hostAttributes(request), user.principal(), request.uri(), restRequestContent(request));
|
hostAttributes(request), user.principal(), arrayToCommaDelimitedString(roleNames), request.uri(),
|
||||||
|
restRequestContent(request));
|
||||||
} else {
|
} else {
|
||||||
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], uri=[{}]", localNodeInfo.prefix, hostAttributes(request),
|
logger.info("{}[rest] [run_as_denied]\t{}, principal=[{}], roles=[{}], uri=[{}]", localNodeInfo.prefix,
|
||||||
user.principal(), request.uri());
|
hostAttributes(request), user.principal(), arrayToCommaDelimitedString(roleNames), request.uri());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.elasticsearch.xpack.security.audit.AuditTrail;
|
||||||
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||||
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
|
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
|
||||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||||
|
import org.elasticsearch.xpack.security.authz.permission.Role;
|
||||||
import org.elasticsearch.xpack.security.support.Exceptions;
|
import org.elasticsearch.xpack.security.support.Exceptions;
|
||||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||||
import org.elasticsearch.xpack.security.user.User;
|
import org.elasticsearch.xpack.security.user.User;
|
||||||
|
@ -531,7 +532,7 @@ public class AuthenticationService extends AbstractComponent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
||||||
auditTrail.runAsDenied(user, action, message);
|
auditTrail.runAsDenied(user, action, message, Role.EMPTY.names());
|
||||||
return failureHandler.failedAuthentication(message, token, action, threadContext);
|
return failureHandler.failedAuthentication(message, token, action, threadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +594,7 @@ public class AuthenticationService extends AbstractComponent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) {
|
||||||
auditTrail.runAsDenied(user, request);
|
auditTrail.runAsDenied(user, request, Role.EMPTY.names());
|
||||||
return failureHandler.failedAuthentication(request, token, threadContext);
|
return failureHandler.failedAuthentication(request, token, threadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope);
|
Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope);
|
||||||
public static final String INDICES_PERMISSIONS_KEY = "_indices_permissions";
|
public static final String INDICES_PERMISSIONS_KEY = "_indices_permissions";
|
||||||
public static final String ORIGINATING_ACTION_KEY = "_originating_action_name";
|
public static final String ORIGINATING_ACTION_KEY = "_originating_action_name";
|
||||||
|
public static final String ROLE_NAMES_KEY = "_effective_role_names";
|
||||||
|
|
||||||
private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate();
|
private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate();
|
||||||
private static final Predicate<String> SAME_USER_PRIVILEGE = Automatons.predicate(
|
private static final Predicate<String> SAME_USER_PRIVILEGE = Automatons.predicate(
|
||||||
|
@ -148,12 +149,13 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
|
|
||||||
// first we need to check if the user is the system. If it is, we'll just authorize the system access
|
// first we need to check if the user is the system. If it is, we'll just authorize the system access
|
||||||
if (SystemUser.is(authentication.getUser())) {
|
if (SystemUser.is(authentication.getUser())) {
|
||||||
if (SystemUser.isAuthorized(action) && SystemUser.is(authentication.getUser())) {
|
if (SystemUser.isAuthorized(action)) {
|
||||||
setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL);
|
putTransientIfNonExisting(INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||||
grant(authentication, action, request);
|
putTransientIfNonExisting(ROLE_NAMES_KEY, new String[] { SystemUser.ROLE_NAME });
|
||||||
|
grant(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, new String[] { SystemUser.ROLE_NAME });
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the roles of the authenticated user, which may be different than the effective
|
// get the roles of the authenticated user, which may be different than the effective
|
||||||
|
@ -165,29 +167,30 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
// if we are running as a user we looked up then the authentication must contain a lookedUpBy. If it doesn't then this user
|
// if we are running as a user we looked up then the authentication must contain a lookedUpBy. If it doesn't then this user
|
||||||
// doesn't really exist but the authc service allowed it through to avoid leaking users that exist in the system
|
// doesn't really exist but the authc service allowed it through to avoid leaking users that exist in the system
|
||||||
if (authentication.getLookedUpBy() == null) {
|
if (authentication.getLookedUpBy() == null) {
|
||||||
throw denyRunAs(authentication, action, request);
|
throw denyRunAs(authentication, action, request, permission.names());
|
||||||
} else if (permission.runAs().check(authentication.getUser().principal())) {
|
} else if (permission.runAs().check(authentication.getUser().principal())) {
|
||||||
grantRunAs(authentication, action, request);
|
grantRunAs(authentication, action, request, permission.names());
|
||||||
permission = runAsRole;
|
permission = runAsRole;
|
||||||
} else {
|
} else {
|
||||||
throw denyRunAs(authentication, action, request);
|
throw denyRunAs(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
putTransientIfNonExisting(ROLE_NAMES_KEY, permission.names());
|
||||||
|
|
||||||
// first, we'll check if the action is a cluster action. If it is, we'll only check it against the cluster permissions
|
// first, we'll check if the action is a cluster action. If it is, we'll only check it against the cluster permissions
|
||||||
if (ClusterPrivilege.ACTION_MATCHER.test(action)) {
|
if (ClusterPrivilege.ACTION_MATCHER.test(action)) {
|
||||||
ClusterPermission cluster = permission.cluster();
|
ClusterPermission cluster = permission.cluster();
|
||||||
if (cluster.check(action) || checkSameUserPermissions(action, request, authentication)) {
|
if (cluster.check(action) || checkSameUserPermissions(action, request, authentication)) {
|
||||||
setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL);
|
putTransientIfNonExisting(INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL);
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok... this is not a cluster action, let's verify it's an indices action
|
// ok... this is not a cluster action, let's verify it's an indices action
|
||||||
if (!IndexPrivilege.ACTION_MATCHER.test(action)) {
|
if (!IndexPrivilege.ACTION_MATCHER.test(action)) {
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
|
|
||||||
//composite actions are explicitly listed and will be authorized at the sub-request / shard level
|
//composite actions are explicitly listed and will be authorized at the sub-request / shard level
|
||||||
|
@ -198,10 +201,10 @@ 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
|
// 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)) {
|
if (permission.indices().check(action)) {
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
} else if (isTranslatedToBulkAction(action)) {
|
} else if (isTranslatedToBulkAction(action)) {
|
||||||
if (request instanceof CompositeIndicesRequest == false) {
|
if (request instanceof CompositeIndicesRequest == false) {
|
||||||
throw new IllegalStateException("Bulk translated actions must implement " + CompositeIndicesRequest.class.getSimpleName()
|
throw new IllegalStateException("Bulk translated actions must implement " + CompositeIndicesRequest.class.getSimpleName()
|
||||||
|
@ -209,10 +212,10 @@ 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
|
// 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)) {
|
if (permission.indices().check(action)) {
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
} else if (TransportActionProxy.isProxyAction(action)) {
|
} else if (TransportActionProxy.isProxyAction(action)) {
|
||||||
// we authorize proxied actions once they are "unwrapped" on the next node
|
// we authorize proxied actions once they are "unwrapped" on the next node
|
||||||
if (TransportActionProxy.isProxyRequest(originalRequest) == false) {
|
if (TransportActionProxy.isProxyRequest(originalRequest) == false) {
|
||||||
|
@ -220,12 +223,12 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
+ action + "] is a proxy action");
|
+ action + "] is a proxy action");
|
||||||
}
|
}
|
||||||
if (permission.indices().check(action)) {
|
if (permission.indices().check(action)) {
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// we do this here in addition to the denial below since we might run into an assertion on scroll requrest below if we
|
// we do this here in addition to the denial below since we might run into an assertion on scroll requrest below if we
|
||||||
// don't have permission to read cross cluster but wrap a scroll request.
|
// don't have permission to read cross cluster but wrap a scroll request.
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,18 +247,18 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
// index and if they cannot, we can fail the request early before we allow the execution of the action and in
|
// index and if they cannot, we can fail the request early before we allow the execution of the action and in
|
||||||
// turn the shard actions
|
// turn the shard actions
|
||||||
if (SearchScrollAction.NAME.equals(action) && permission.indices().check(action) == false) {
|
if (SearchScrollAction.NAME.equals(action) && permission.indices().check(action) == false) {
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
} else {
|
} else {
|
||||||
// we store the request as a transient in the ThreadContext in case of a authorization failure at the shard
|
// 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
|
// 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
|
// information such as the index and the incoming address of the request
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert false :
|
assert false :
|
||||||
"only scroll related requests are known indices api that don't support retrieving the indices they relate to";
|
"only scroll related requests are known indices api that don't support retrieving the indices they relate to";
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,33 +268,33 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
// If this request does not allow remote indices
|
// If this request does not allow remote indices
|
||||||
// then the user must have permission to perform this action on at least 1 local index
|
// then the user must have permission to perform this action on at least 1 local index
|
||||||
if (allowsRemoteIndices == false && permission.indices().check(action) == false) {
|
if (allowsRemoteIndices == false && permission.indices().check(action) == false) {
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
|
|
||||||
final MetaData metaData = clusterService.state().metaData();
|
final MetaData metaData = clusterService.state().metaData();
|
||||||
final AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData);
|
final AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData);
|
||||||
final ResolvedIndices resolvedIndices = resolveIndexNames(authentication, action, request, metaData, authorizedIndices);
|
final ResolvedIndices resolvedIndices = resolveIndexNames(authentication, action, request, metaData, authorizedIndices, permission);
|
||||||
assert !resolvedIndices.isEmpty()
|
assert !resolvedIndices.isEmpty()
|
||||||
: "every indices request needs to have its indices set thus the resolved indices must not be empty";
|
: "every indices request needs to have its indices set thus the resolved indices must not be empty";
|
||||||
|
|
||||||
// If this request does reference any remote indices
|
// If this request does reference any remote indices
|
||||||
// then the user must have permission to perform this action on at least 1 local index
|
// then the user must have permission to perform this action on at least 1 local index
|
||||||
if (resolvedIndices.getRemote().isEmpty() && permission.indices().check(action) == false) {
|
if (resolvedIndices.getRemote().isEmpty() && permission.indices().check(action) == false) {
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
}
|
}
|
||||||
|
|
||||||
//all wildcard expressions have been resolved and only the security plugin could have set '-*' here.
|
//all wildcard expressions have been resolved and only the security plugin could have set '-*' here.
|
||||||
//'-*' matches no indices so we allow the request to go through, which will yield an empty response
|
//'-*' matches no indices so we allow the request to go through, which will yield an empty response
|
||||||
if (resolvedIndices.isNoIndicesPlaceholder()) {
|
if (resolvedIndices.isNoIndicesPlaceholder()) {
|
||||||
setIndicesAccessControl(IndicesAccessControl.ALLOW_NO_INDICES);
|
putTransientIfNonExisting(INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_NO_INDICES);
|
||||||
grant(authentication, action, request);
|
grant(authentication, action, request, permission.names());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<String> localIndices = new HashSet<>(resolvedIndices.getLocal());
|
final Set<String> localIndices = new HashSet<>(resolvedIndices.getLocal());
|
||||||
IndicesAccessControl indicesAccessControl = permission.authorize(action, localIndices, metaData, fieldPermissionsCache);
|
IndicesAccessControl indicesAccessControl = permission.authorize(action, localIndices, metaData, fieldPermissionsCache);
|
||||||
if (!indicesAccessControl.isGranted()) {
|
if (!indicesAccessControl.isGranted()) {
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
} else if (hasSecurityIndexAccess(indicesAccessControl)
|
} else if (hasSecurityIndexAccess(indicesAccessControl)
|
||||||
&& MONITOR_INDEX_PREDICATE.test(action) == false
|
&& MONITOR_INDEX_PREDICATE.test(action) == false
|
||||||
&& isSuperuser(authentication.getUser()) == false) {
|
&& isSuperuser(authentication.getUser()) == false) {
|
||||||
|
@ -299,9 +302,9 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
// purposes. These monitor requests also sometimes resolve indices concretely and then requests them
|
// purposes. These monitor requests also sometimes resolve indices concretely and then requests them
|
||||||
logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]",
|
logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]",
|
||||||
authentication.getUser().principal(), action, SecurityLifecycleService.SECURITY_INDEX_NAME);
|
authentication.getUser().principal(), action, SecurityLifecycleService.SECURITY_INDEX_NAME);
|
||||||
throw denial(authentication, action, request);
|
throw denial(authentication, action, request, permission.names());
|
||||||
} else {
|
} else {
|
||||||
setIndicesAccessControl(indicesAccessControl);
|
putTransientIfNonExisting(INDICES_PERMISSIONS_KEY, indicesAccessControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if we are creating an index we need to authorize potential aliases created at the same time
|
//if we are creating an index we need to authorize potential aliases created at the same time
|
||||||
|
@ -315,7 +318,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
}
|
}
|
||||||
indicesAccessControl = permission.authorize("indices:admin/aliases", aliasesAndIndices, metaData, fieldPermissionsCache);
|
indicesAccessControl = permission.authorize("indices:admin/aliases", aliasesAndIndices, metaData, fieldPermissionsCache);
|
||||||
if (!indicesAccessControl.isGranted()) {
|
if (!indicesAccessControl.isGranted()) {
|
||||||
throw denial(authentication, "indices:admin/aliases", request);
|
throw denial(authentication, "indices:admin/aliases", request, permission.names());
|
||||||
}
|
}
|
||||||
// no need to re-add the indicesAccessControl in the context,
|
// no need to re-add the indicesAccessControl in the context,
|
||||||
// because the create index call doesn't do anything FLS or DLS
|
// because the create index call doesn't do anything FLS or DLS
|
||||||
|
@ -330,7 +333,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
authorizeBulkItems(authentication, (BulkShardRequest) request, permission, metaData, localIndices, authorizedIndices);
|
authorizeBulkItems(authentication, (BulkShardRequest) request, permission, metaData, localIndices, authorizedIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
grant(authentication, action, originalRequest);
|
grant(authentication, action, originalRequest, permission.names());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) {
|
private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) {
|
||||||
|
@ -345,13 +348,17 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs authorization checks on the items within a {@link BulkShardRequest}.
|
* Performs authorization checks on the items within a {@link BulkShardRequest}.
|
||||||
* This inspects the {@link BulkItemRequest items} within the request, computes an <em>implied</em> action for each item's
|
* This inspects the {@link BulkItemRequest items} within the request, computes
|
||||||
* {@link DocWriteRequest#opType()}, and then checks whether that action is allowed on the targeted index.
|
* an <em>implied</em> action for each item's {@link DocWriteRequest#opType()},
|
||||||
* Items that fail this checks are {@link BulkItemRequest#abort(String, Exception) aborted}, with an
|
* and then checks whether that action is allowed on the targeted index. Items
|
||||||
* {@link #denial(Authentication, String, TransportRequest) access denied} exception.
|
* that fail this checks are {@link BulkItemRequest#abort(String, Exception)
|
||||||
* Because a shard level request is for exactly 1 index, and there are a small number of possible item
|
* aborted}, with an
|
||||||
* {@link DocWriteRequest.OpType types}, the number of distinct authorization checks that need to be performed is very small, but the
|
* {@link #denial(Authentication, String, TransportRequest, String[]) access
|
||||||
* results must be cached, to avoid adding a high overhead to each bulk request.
|
* denied} exception. Because a shard level request is for exactly 1 index, and
|
||||||
|
* there are a small number of possible item {@link DocWriteRequest.OpType
|
||||||
|
* types}, the number of distinct authorization checks that need to be performed
|
||||||
|
* is very small, but the results must be cached, to avoid adding a high
|
||||||
|
* overhead to each bulk request.
|
||||||
*/
|
*/
|
||||||
private void authorizeBulkItems(Authentication authentication, BulkShardRequest request, Role permission,
|
private void authorizeBulkItems(Authentication authentication, BulkShardRequest request, Role permission,
|
||||||
MetaData metaData, Set<String> indices, AuthorizedIndices authorizedIndices) {
|
MetaData metaData, Set<String> indices, AuthorizedIndices authorizedIndices) {
|
||||||
|
@ -385,7 +392,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
return itemAccessControl.isGranted();
|
return itemAccessControl.isGranted();
|
||||||
});
|
});
|
||||||
if (granted == false) {
|
if (granted == false) {
|
||||||
item.abort(resolvedIndex, denial(authentication, itemAction, request));
|
item.abort(resolvedIndex, denial(authentication, itemAction, request, permission.names()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,21 +417,15 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResolvedIndices resolveIndexNames(Authentication authentication, String action, TransportRequest request, MetaData metaData,
|
private ResolvedIndices resolveIndexNames(Authentication authentication, String action, TransportRequest request, MetaData metaData,
|
||||||
AuthorizedIndices authorizedIndices) {
|
AuthorizedIndices authorizedIndices, Role permission) {
|
||||||
try {
|
try {
|
||||||
return indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices);
|
return indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
auditTrail.accessDenied(authentication.getUser(), action, request);
|
auditTrail.accessDenied(authentication.getUser(), action, request, permission.names());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIndicesAccessControl(IndicesAccessControl accessControl) {
|
|
||||||
if (threadContext.getTransient(INDICES_PERMISSIONS_KEY) == null) {
|
|
||||||
threadContext.putTransient(INDICES_PERMISSIONS_KEY, accessControl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void putTransientIfNonExisting(String key, Object value) {
|
private void putTransientIfNonExisting(String key, Object value) {
|
||||||
Object existing = threadContext.getTransient(key);
|
Object existing = threadContext.getTransient(key);
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
|
@ -462,7 +463,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
|
|
||||||
if (roleNames.isEmpty()) {
|
if (roleNames.isEmpty()) {
|
||||||
roleActionListener.onResponse(Role.EMPTY);
|
roleActionListener.onResponse(Role.EMPTY);
|
||||||
} else if (roleNames.contains(ReservedRolesStore.SUPERUSER_ROLE.name())) {
|
} else if (roleNames.contains(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName())) {
|
||||||
roleActionListener.onResponse(ReservedRolesStore.SUPERUSER_ROLE);
|
roleActionListener.onResponse(ReservedRolesStore.SUPERUSER_ROLE);
|
||||||
} else {
|
} else {
|
||||||
rolesStore.roles(roleNames, fieldPermissionsCache, roleActionListener);
|
rolesStore.roles(roleNames, fieldPermissionsCache, roleActionListener);
|
||||||
|
@ -543,22 +544,23 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
return ReservedRealm.TYPE.equals(realmType) || NativeRealm.TYPE.equals(realmType);
|
return ReservedRealm.TYPE.equals(realmType) || NativeRealm.TYPE.equals(realmType);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request) {
|
ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||||
auditTrail.accessDenied(authentication.getUser(), action, request);
|
auditTrail.accessDenied(authentication.getUser(), action, request, roleNames);
|
||||||
return denialException(authentication, action);
|
return denialException(authentication, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request) {
|
private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request,
|
||||||
auditTrail.runAsDenied(authentication.getUser(), action, request);
|
String[] roleNames) {
|
||||||
|
auditTrail.runAsDenied(authentication.getUser(), action, request, roleNames);
|
||||||
return denialException(authentication, action);
|
return denialException(authentication, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grant(Authentication authentication, String action, TransportRequest request) {
|
private void grant(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||||
auditTrail.accessGranted(authentication.getUser(), action, request);
|
auditTrail.accessGranted(authentication.getUser(), action, request, roleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantRunAs(Authentication authentication, String action, TransportRequest request) {
|
private void grantRunAs(Authentication authentication, String action, TransportRequest request, String[] roleNames) {
|
||||||
auditTrail.runAsGranted(authentication.getUser(), action, request);
|
auditTrail.runAsGranted(authentication.getUser(), action, request, roleNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ElasticsearchSecurityException denialException(Authentication authentication, String action) {
|
private ElasticsearchSecurityException denialException(Authentication authentication, String action) {
|
||||||
|
@ -579,7 +581,7 @@ public class AuthorizationService extends AbstractComponent {
|
||||||
|
|
||||||
static boolean isSuperuser(User user) {
|
static boolean isSuperuser(User user) {
|
||||||
return Arrays.stream(user.roles())
|
return Arrays.stream(user.roles())
|
||||||
.anyMatch(ReservedRolesStore.SUPERUSER_ROLE.name()::equals);
|
.anyMatch(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()::equals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addSettings(List<Setting<?>> settings) {
|
public static void addSettings(List<Setting<?>> settings) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
||||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||||
|
|
||||||
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
||||||
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ROLE_NAMES_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link SearchOperationListener} that is used to provide authorization for scroll requests.
|
* A {@link SearchOperationListener} that is used to provide authorization for scroll requests.
|
||||||
|
@ -59,7 +60,8 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||||
final Authentication originalAuth = searchContext.scrollContext().getFromContext(Authentication.AUTHENTICATION_KEY);
|
final Authentication originalAuth = searchContext.scrollContext().getFromContext(Authentication.AUTHENTICATION_KEY);
|
||||||
final Authentication current = Authentication.getAuthentication(threadContext);
|
final Authentication current = Authentication.getAuthentication(threadContext);
|
||||||
final String action = threadContext.getTransient(ORIGINATING_ACTION_KEY);
|
final String action = threadContext.getTransient(ORIGINATING_ACTION_KEY);
|
||||||
ensureAuthenticatedUserIsSame(originalAuth, current, auditTrailService, searchContext.id(), action, request);
|
ensureAuthenticatedUserIsSame(originalAuth, current, auditTrailService, searchContext.id(), action, request,
|
||||||
|
threadContext.getTransient(ROLE_NAMES_KEY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +73,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||||
* (or lookup) realm. To work around this we compare the username and the originating realm type.
|
* (or lookup) realm. To work around this we compare the username and the originating realm type.
|
||||||
*/
|
*/
|
||||||
static void ensureAuthenticatedUserIsSame(Authentication original, Authentication current, AuditTrailService auditTrailService,
|
static void ensureAuthenticatedUserIsSame(Authentication original, Authentication current, AuditTrailService auditTrailService,
|
||||||
long id, String action, TransportRequest request) {
|
long id, String action, TransportRequest request, String[] roleNames) {
|
||||||
// this is really a best effort attempt since we cannot guarantee principal uniqueness
|
// this is really a best effort attempt since we cannot guarantee principal uniqueness
|
||||||
// and realm names can change between nodes.
|
// and realm names can change between nodes.
|
||||||
final boolean samePrincipal = original.getUser().principal().equals(current.getUser().principal());
|
final boolean samePrincipal = original.getUser().principal().equals(current.getUser().principal());
|
||||||
|
@ -90,7 +92,7 @@ public final class SecuritySearchOperationListener implements SearchOperationLis
|
||||||
|
|
||||||
final boolean sameUser = samePrincipal && sameRealmType;
|
final boolean sameUser = samePrincipal && sameRealmType;
|
||||||
if (sameUser == false) {
|
if (sameUser == false) {
|
||||||
auditTrailService.accessDenied(current.getUser(), action, request);
|
auditTrailService.accessDenied(current.getUser(), action, request, roleNames);
|
||||||
throw new SearchContextMissingException(id);
|
throw new SearchContextMissingException(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,20 +27,20 @@ public final class Role {
|
||||||
|
|
||||||
public static final Role EMPTY = Role.builder("__empty").build();
|
public static final Role EMPTY = Role.builder("__empty").build();
|
||||||
|
|
||||||
private final String name;
|
private final String[] names;
|
||||||
private final ClusterPermission cluster;
|
private final ClusterPermission cluster;
|
||||||
private final IndicesPermission indices;
|
private final IndicesPermission indices;
|
||||||
private final RunAsPermission runAs;
|
private final RunAsPermission runAs;
|
||||||
|
|
||||||
Role(String name, ClusterPermission cluster, IndicesPermission indices, RunAsPermission runAs) {
|
Role(String[] names, ClusterPermission cluster, IndicesPermission indices, RunAsPermission runAs) {
|
||||||
this.name = name;
|
this.names = names;
|
||||||
this.cluster = Objects.requireNonNull(cluster);
|
this.cluster = Objects.requireNonNull(cluster);
|
||||||
this.indices = Objects.requireNonNull(indices);
|
this.indices = Objects.requireNonNull(indices);
|
||||||
this.runAs = Objects.requireNonNull(runAs);
|
this.runAs = Objects.requireNonNull(runAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String[] names() {
|
||||||
return name;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClusterPermission cluster() {
|
public ClusterPermission cluster() {
|
||||||
|
@ -55,12 +55,12 @@ public final class Role {
|
||||||
return runAs;
|
return runAs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder(String name) {
|
public static Builder builder(String... names) {
|
||||||
return new Builder(name, null);
|
return new Builder(names, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder(String name, FieldPermissionsCache fieldPermissionsCache) {
|
public static Builder builder(String[] names, FieldPermissionsCache fieldPermissionsCache) {
|
||||||
return new Builder(name, fieldPermissionsCache);
|
return new Builder(names, fieldPermissionsCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder(RoleDescriptor rd, FieldPermissionsCache fieldPermissionsCache) {
|
public static Builder builder(RoleDescriptor rd, FieldPermissionsCache fieldPermissionsCache) {
|
||||||
|
@ -91,19 +91,19 @@ public final class Role {
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private final String name;
|
private final String[] names;
|
||||||
private ClusterPermission cluster = ClusterPermission.NONE;
|
private ClusterPermission cluster = ClusterPermission.NONE;
|
||||||
private RunAsPermission runAs = RunAsPermission.NONE;
|
private RunAsPermission runAs = RunAsPermission.NONE;
|
||||||
private List<IndicesPermission.Group> groups = new ArrayList<>();
|
private List<IndicesPermission.Group> groups = new ArrayList<>();
|
||||||
private FieldPermissionsCache fieldPermissionsCache = null;
|
private FieldPermissionsCache fieldPermissionsCache = null;
|
||||||
|
|
||||||
private Builder(String name, FieldPermissionsCache fieldPermissionsCache) {
|
private Builder(String[] names, FieldPermissionsCache fieldPermissionsCache) {
|
||||||
this.name = name;
|
this.names = names;
|
||||||
this.fieldPermissionsCache = fieldPermissionsCache;
|
this.fieldPermissionsCache = fieldPermissionsCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder(RoleDescriptor rd, @Nullable FieldPermissionsCache fieldPermissionsCache) {
|
private Builder(RoleDescriptor rd, @Nullable FieldPermissionsCache fieldPermissionsCache) {
|
||||||
this.name = rd.getName();
|
this.names = new String[] { rd.getName() };
|
||||||
this.fieldPermissionsCache = fieldPermissionsCache;
|
this.fieldPermissionsCache = fieldPermissionsCache;
|
||||||
if (rd.getClusterPrivileges().length == 0) {
|
if (rd.getClusterPrivileges().length == 0) {
|
||||||
cluster = ClusterPermission.NONE;
|
cluster = ClusterPermission.NONE;
|
||||||
|
@ -140,7 +140,7 @@ public final class Role {
|
||||||
public Role build() {
|
public Role build() {
|
||||||
IndicesPermission indices = groups.isEmpty() ? IndicesPermission.NONE :
|
IndicesPermission indices = groups.isEmpty() ? IndicesPermission.NONE :
|
||||||
new IndicesPermission(groups.toArray(new IndicesPermission.Group[groups.size()]));
|
new IndicesPermission(groups.toArray(new IndicesPermission.Group[groups.size()]));
|
||||||
return new Role(name, cluster, indices, runAs);
|
return new Role(names, cluster, indices, runAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<IndicesPermission.Group> convertFromIndicesPrivileges(RoleDescriptor.IndicesPrivileges[] indicesPrivileges,
|
static List<IndicesPermission.Group> convertFromIndicesPrivileges(RoleDescriptor.IndicesPrivileges[] indicesPrivileges,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.security.authz.store;
|
package org.elasticsearch.xpack.security.authz.store;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -239,13 +240,12 @@ public class CompositeRolesStore extends AbstractComponent {
|
||||||
if (roleDescriptors.isEmpty()) {
|
if (roleDescriptors.isEmpty()) {
|
||||||
return Role.EMPTY;
|
return Role.EMPTY;
|
||||||
}
|
}
|
||||||
StringBuilder nameBuilder = new StringBuilder();
|
|
||||||
Set<String> clusterPrivileges = new HashSet<>();
|
Set<String> clusterPrivileges = new HashSet<>();
|
||||||
Set<String> runAs = new HashSet<>();
|
Set<String> runAs = new HashSet<>();
|
||||||
Map<Set<String>, MergeableIndicesPrivilege> indicesPrivilegesMap = new HashMap<>();
|
Map<Set<String>, MergeableIndicesPrivilege> indicesPrivilegesMap = new HashMap<>();
|
||||||
|
List<String> roleNames = new ArrayList<>(roleDescriptors.size());
|
||||||
for (RoleDescriptor descriptor : roleDescriptors) {
|
for (RoleDescriptor descriptor : roleDescriptors) {
|
||||||
nameBuilder.append(descriptor.getName());
|
roleNames.add(descriptor.getName());
|
||||||
nameBuilder.append('_');
|
|
||||||
if (descriptor.getClusterPrivileges() != null) {
|
if (descriptor.getClusterPrivileges() != null) {
|
||||||
clusterPrivileges.addAll(Arrays.asList(descriptor.getClusterPrivileges()));
|
clusterPrivileges.addAll(Arrays.asList(descriptor.getClusterPrivileges()));
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ public class CompositeRolesStore extends AbstractComponent {
|
||||||
|
|
||||||
final Set<String> clusterPrivs = clusterPrivileges.isEmpty() ? null : clusterPrivileges;
|
final Set<String> clusterPrivs = clusterPrivileges.isEmpty() ? null : clusterPrivileges;
|
||||||
final Privilege runAsPrivilege = runAs.isEmpty() ? Privilege.NONE : new Privilege(runAs, runAs.toArray(Strings.EMPTY_ARRAY));
|
final Privilege runAsPrivilege = runAs.isEmpty() ? Privilege.NONE : new Privilege(runAs, runAs.toArray(Strings.EMPTY_ARRAY));
|
||||||
Role.Builder builder = Role.builder(nameBuilder.toString(), fieldPermissionsCache)
|
Role.Builder builder = Role.builder(roleNames.toArray(new String[roleNames.size()]), fieldPermissionsCache)
|
||||||
.cluster(ClusterPrivilege.get(clusterPrivs))
|
.cluster(ClusterPrivilege.get(clusterPrivs))
|
||||||
.runAs(runAsPrivilege);
|
.runAs(runAsPrivilege);
|
||||||
indicesPrivilegesMap.entrySet().forEach((entry) -> {
|
indicesPrivilegesMap.entrySet().forEach((entry) -> {
|
||||||
|
|
|
@ -7,8 +7,6 @@ package org.elasticsearch.xpack.security.user;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.security.support.MetadataUtils;
|
import org.elasticsearch.xpack.security.support.MetadataUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reserved {@code elastic} superuser. Has full permission/access to the cluster/indices and can
|
* The reserved {@code elastic} superuser. Has full permission/access to the cluster/indices and can
|
||||||
|
@ -17,7 +15,8 @@ import java.util.Map;
|
||||||
public class ElasticUser extends User {
|
public class ElasticUser extends User {
|
||||||
|
|
||||||
public static final String NAME = "elastic";
|
public static final String NAME = "elastic";
|
||||||
private static final String ROLE_NAME = "superuser";
|
// used for testing in a different package
|
||||||
|
public static final String ROLE_NAME = "superuser";
|
||||||
|
|
||||||
public ElasticUser(boolean enabled) {
|
public ElasticUser(boolean enabled) {
|
||||||
super(NAME, new String[] { ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled);
|
super(NAME, new String[] { ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled);
|
||||||
|
|
|
@ -40,6 +40,9 @@
|
||||||
"principal": {
|
"principal": {
|
||||||
"type": "keyword"
|
"type": "keyword"
|
||||||
},
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
"run_by_principal": {
|
"run_by_principal": {
|
||||||
"type": "keyword"
|
"type": "keyword"
|
||||||
},
|
},
|
||||||
|
|
|
@ -138,11 +138,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||||
|
|
||||||
public void testAccessGranted() throws Exception {
|
public void testAccessGranted() throws Exception {
|
||||||
User user = new User("_username", "r1");
|
User user = new User("_username", "r1");
|
||||||
service.accessGranted(user, "_action", message);
|
String[] roles = new String[] { randomAlphaOfLengthBetween(1, 6) };
|
||||||
|
service.accessGranted(user, "_action", message, roles);
|
||||||
verify(licenseState).isAuditingAllowed();
|
verify(licenseState).isAuditingAllowed();
|
||||||
if (isAuditingAllowed) {
|
if (isAuditingAllowed) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
verify(auditTrail).accessGranted(user, "_action", message);
|
verify(auditTrail).accessGranted(user, "_action", message, roles);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||||
|
@ -151,11 +152,12 @@ public class AuditTrailServiceTests extends ESTestCase {
|
||||||
|
|
||||||
public void testAccessDenied() throws Exception {
|
public void testAccessDenied() throws Exception {
|
||||||
User user = new User("_username", "r1");
|
User user = new User("_username", "r1");
|
||||||
service.accessDenied(user, "_action", message);
|
String[] roles = new String[] { randomAlphaOfLengthBetween(1, 6) };
|
||||||
|
service.accessDenied(user, "_action", message, roles);
|
||||||
verify(licenseState).isAuditingAllowed();
|
verify(licenseState).isAuditingAllowed();
|
||||||
if (isAuditingAllowed) {
|
if (isAuditingAllowed) {
|
||||||
for (AuditTrail auditTrail : auditTrails) {
|
for (AuditTrail auditTrail : auditTrails) {
|
||||||
verify(auditTrail).accessDenied(user, "_action", message);
|
verify(auditTrail).accessDenied(user, "_action", message, roles);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
verifyZeroInteractions(auditTrails.toArray((Object[]) new AuditTrail[auditTrails.size()]));
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
createAuditTrail(new String[] { "access_granted" });
|
createAuditTrail(new String[] { "access_granted" });
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
User user = mock(User.class);
|
User user = mock(User.class);
|
||||||
auditTrail.accessGranted(user, randomAlphaOfLengthBetween(6, 40), message);
|
auditTrail.accessGranted(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
assertThat(clientCalled.get(), is(false));
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
createAuditTrail(randomFrom(new String[] { "access_granted" }, null));
|
createAuditTrail(randomFrom(new String[] { "access_granted" }, null));
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
User user = SystemUser.INSTANCE;
|
User user = SystemUser.INSTANCE;
|
||||||
auditTrail.accessGranted(user, "internal:foo", message);
|
auditTrail.accessGranted(user, "internal:foo", message, new String[] { "role" });
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
assertThat(clientCalled.get(), is(false));
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
createAuditTrail(new String[] { "access_denied" });
|
createAuditTrail(new String[] { "access_denied" });
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
User user = mock(User.class);
|
User user = mock(User.class);
|
||||||
auditTrail.accessDenied(user, randomAlphaOfLengthBetween(6, 40), message);
|
auditTrail.accessDenied(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
assertThat(clientCalled.get(), is(false));
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
User user = mock(User.class);
|
User user = mock(User.class);
|
||||||
|
|
||||||
auditTrail.runAsGranted(user, randomAlphaOfLengthBetween(6, 40), message);
|
auditTrail.runAsGranted(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
assertThat(clientCalled.get(), is(false));
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
|
||||||
TransportMessage message = mock(TransportMessage.class);
|
TransportMessage message = mock(TransportMessage.class);
|
||||||
User user = mock(User.class);
|
User user = mock(User.class);
|
||||||
|
|
||||||
auditTrail.runAsDenied(user, randomAlphaOfLengthBetween(6, 40), message);
|
auditTrail.runAsDenied(user, randomAlphaOfLengthBetween(6, 40), message, new String[] { "role" });
|
||||||
assertThat(messageEnqueued.get(), is(false));
|
assertThat(messageEnqueued.get(), is(false));
|
||||||
assertThat(clientCalled.get(), is(false));
|
assertThat(clientCalled.get(), is(false));
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals("_realm", sourceMap.get("realm"));
|
assertEquals("_realm", sourceMap.get("realm"));
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
||||||
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest)message).indices()));
|
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest) message).indices()));
|
||||||
}
|
}
|
||||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
} else {
|
} else {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
auditor.accessGranted(user, "_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditor.accessGranted(user, "_action", message, new String[] { role });
|
||||||
|
|
||||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||||
assertAuditMessage(hit, "transport", "access_granted");
|
assertAuditMessage(hit, "transport", "access_granted");
|
||||||
|
@ -520,9 +521,10 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals("_username", sourceMap.get("principal"));
|
assertEquals("_username", sourceMap.get("principal"));
|
||||||
}
|
}
|
||||||
assertEquals("_action", sourceMap.get("action"));
|
assertEquals("_action", sourceMap.get("action"));
|
||||||
|
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
||||||
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest)message).indices()));
|
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest) message).indices()));
|
||||||
}
|
}
|
||||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -530,7 +532,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
public void testSystemAccessGranted() throws Exception {
|
public void testSystemAccessGranted() throws Exception {
|
||||||
initialize(new String[] { "system_access_granted" }, null);
|
initialize(new String[] { "system_access_granted" }, null);
|
||||||
TransportMessage message = randomBoolean() ? new RemoteHostMockMessage() : new LocalHostMockMessage();
|
TransportMessage message = randomBoolean() ? new RemoteHostMockMessage() : new LocalHostMockMessage();
|
||||||
auditor.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditor.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||||
|
|
||||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||||
assertAuditMessage(hit, "transport", "access_granted");
|
assertAuditMessage(hit, "transport", "access_granted");
|
||||||
|
@ -538,6 +541,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals("transport", sourceMap.get("origin_type"));
|
assertEquals("transport", sourceMap.get("origin_type"));
|
||||||
assertEquals(SystemUser.INSTANCE.principal(), sourceMap.get("principal"));
|
assertEquals(SystemUser.INSTANCE.principal(), sourceMap.get("principal"));
|
||||||
assertEquals("internal:_action", sourceMap.get("action"));
|
assertEquals("internal:_action", sourceMap.get("action"));
|
||||||
|
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,7 +555,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
} else {
|
} else {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
auditor.accessDenied(user, "_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditor.accessDenied(user, "_action", message, new String[] { role });
|
||||||
|
|
||||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||||
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
Map<String, Object> sourceMap = hit.getSourceAsMap();
|
||||||
|
@ -566,9 +571,10 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals("_action", sourceMap.get("action"));
|
assertEquals("_action", sourceMap.get("action"));
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
List<Object> indices = (List<Object>) sourceMap.get("indices");
|
||||||
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest)message).indices()));
|
assertThat(indices, containsInAnyOrder((Object[]) ((IndicesRequest) message).indices()));
|
||||||
}
|
}
|
||||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||||
|
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTamperedRequestRest() throws Exception {
|
public void testTamperedRequestRest() throws Exception {
|
||||||
|
@ -659,7 +665,8 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
initialize();
|
initialize();
|
||||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||||
auditor.runAsGranted(user, "_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditor.runAsGranted(user, "_action", message, new String[] { role });
|
||||||
|
|
||||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||||
assertAuditMessage(hit, "transport", "run_as_granted");
|
assertAuditMessage(hit, "transport", "run_as_granted");
|
||||||
|
@ -667,6 +674,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
assertEquals("transport", sourceMap.get("origin_type"));
|
assertEquals("transport", sourceMap.get("origin_type"));
|
||||||
assertThat(sourceMap.get("principal"), is("_username"));
|
assertThat(sourceMap.get("principal"), is("_username"));
|
||||||
assertThat(sourceMap.get("run_as_principal"), is("running as"));
|
assertThat(sourceMap.get("run_as_principal"), is("running as"));
|
||||||
|
assertThat((Iterable<String>) sourceMap.get(IndexAuditTrail.Field.ROLE_NAMES), containsInAnyOrder(role));
|
||||||
assertEquals("_action", sourceMap.get("action"));
|
assertEquals("_action", sourceMap.get("action"));
|
||||||
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
assertEquals(sourceMap.get("request"), message.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -675,7 +683,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
|
||||||
initialize();
|
initialize();
|
||||||
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
TransportMessage message = randomFrom(new RemoteHostMockMessage(), new LocalHostMockMessage(), new MockIndicesTransportMessage());
|
||||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||||
auditor.runAsDenied(user, "_action", message);
|
auditor.runAsDenied(user, "_action", message, new String[] { "r1" });
|
||||||
|
|
||||||
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
SearchHit hit = getIndexedAuditMessage(enqueuedMessage.get());
|
||||||
assertAuditMessage(hit, "transport", "run_as_denied");
|
assertAuditMessage(hit, "transport", "run_as_denied");
|
||||||
|
|
|
@ -337,8 +337,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
} else {
|
} else {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
auditTrail.accessGranted(user, "_action", message);
|
auditTrail.accessGranted(user, "_action", message, new String[] { role });
|
||||||
|
String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||||
|
", roles=[" + role + "]";
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
|
@ -351,7 +353,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.accessGranted(user, "_action", message);
|
auditTrail.accessGranted(user, "_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,21 +361,23 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
Logger logger = CapturingLogger.newCapturingLogger(Level.INFO);
|
||||||
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
TransportMessage message = randomBoolean() ? new MockMessage(threadContext) : new MockIndicesRequest(threadContext);
|
||||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
|
|
||||||
// test enabled
|
// test enabled
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "system_access_granted").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.include", "system_access_granted").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||||
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message);
|
auditTrail.accessGranted(SystemUser.INSTANCE, "internal:_action", message, new String[] { role });
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||||
SystemUser.INSTANCE.principal()
|
SystemUser.INSTANCE.principal()
|
||||||
+ "], action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
+ "], roles=[" + role + "], action=[internal:_action], indices=[" + indices(message)
|
||||||
|
+ "], request=[MockIndicesRequest]");
|
||||||
} else {
|
} else {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", principal=[" +
|
||||||
SystemUser.INSTANCE.principal() + "], action=[internal:_action], request=[MockMessage]");
|
SystemUser.INSTANCE.principal() + "], roles=[" + role + "], action=[internal:_action], request=[MockMessage]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,8 +393,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
} else {
|
} else {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
auditTrail.accessGranted(user, "internal:_action", message);
|
auditTrail.accessGranted(user, "internal:_action", message, new String[] { role });
|
||||||
|
String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||||
|
", roles=[" + role + "]";
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_granted]\t" + origins + ", " + userInfo +
|
||||||
", action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[internal:_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
|
@ -403,7 +409,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_granted").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.accessGranted(user, "internal:_action", message);
|
auditTrail.accessGranted(user, "internal:_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,8 +425,10 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
} else {
|
} else {
|
||||||
user = new User("_username", new String[]{"r1"});
|
user = new User("_username", new String[]{"r1"});
|
||||||
}
|
}
|
||||||
String userInfo = runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]";
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
auditTrail.accessDenied(user, "_action", message);
|
auditTrail.accessDenied(user, "_action", message, new String[] { role });
|
||||||
|
String userInfo = (runAs ? "principal=[running as], run_by_principal=[_username]" : "principal=[_username]") +
|
||||||
|
", roles=[" + role + "]";
|
||||||
if (message instanceof IndicesRequest) {
|
if (message instanceof IndicesRequest) {
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [access_denied]\t" + origins + ", " + userInfo +
|
||||||
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
", action=[_action], indices=[" + indices(message) + "], request=[MockIndicesRequest]");
|
||||||
|
@ -433,7 +441,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_denied").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "access_denied").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.accessDenied(user, "_action", message);
|
auditTrail.accessDenied(user, "_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,15 +560,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
TransportMessage message = new MockMessage(threadContext);
|
TransportMessage message = new MockMessage(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||||
auditTrail.runAsGranted(user, "_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditTrail.runAsGranted(user, "_action", message, new String[] { role });
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_granted]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_granted]\t" + origins +
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
", principal=[_username], run_as_principal=[running as], roles=[" + role + "], action=[_action], request=[MockMessage]");
|
||||||
|
|
||||||
// test disabled
|
// test disabled
|
||||||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_granted").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_granted").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.runAsGranted(user, "_action", message);
|
auditTrail.runAsGranted(user, "_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,15 +579,16 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||||
TransportMessage message = new MockMessage(threadContext);
|
TransportMessage message = new MockMessage(threadContext);
|
||||||
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
String origins = LoggingAuditTrail.originAttributes(threadContext, message, auditTrail.localNodeInfo);
|
||||||
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
User user = new User("running as", new String[]{"r2"}, new User("_username", new String[] {"r1"}));
|
||||||
auditTrail.runAsDenied(user, "_action", message);
|
String role = randomAlphaOfLengthBetween(1, 6);
|
||||||
|
auditTrail.runAsDenied(user, "_action", message, new String[] { role });
|
||||||
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_denied]\t" + origins +
|
assertMsg(logger, Level.INFO, prefix + "[transport] [run_as_denied]\t" + origins +
|
||||||
", principal=[_username], run_as_principal=[running as], action=[_action], request=[MockMessage]");
|
", principal=[_username], run_as_principal=[running as], roles=[" + role + "], action=[_action], request=[MockMessage]");
|
||||||
|
|
||||||
// test disabled
|
// test disabled
|
||||||
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
CapturingLogger.output(logger.getName(), Level.INFO).clear();
|
||||||
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_denied").build();
|
settings = Settings.builder().put(settings).put("xpack.security.audit.logfile.events.exclude", "run_as_denied").build();
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
auditTrail.runAsDenied(user, "_action", message);
|
auditTrail.runAsDenied(user, "_action", message, new String[] { role });
|
||||||
assertEmptyLog(logger);
|
assertEmptyLog(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticato
|
||||||
import org.elasticsearch.xpack.security.authc.Realm.Factory;
|
import org.elasticsearch.xpack.security.authc.Realm.Factory;
|
||||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||||
|
import org.elasticsearch.xpack.security.authz.permission.Role;
|
||||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||||
import org.elasticsearch.xpack.security.user.SystemUser;
|
import org.elasticsearch.xpack.security.user.SystemUser;
|
||||||
import org.elasticsearch.xpack.security.user.User;
|
import org.elasticsearch.xpack.security.user.User;
|
||||||
|
@ -738,7 +739,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||||
authenticateBlocking(restRequest);
|
authenticateBlocking(restRequest);
|
||||||
fail("exception should be thrown");
|
fail("exception should be thrown");
|
||||||
} catch (ElasticsearchException e) {
|
} catch (ElasticsearchException e) {
|
||||||
verify(auditTrail).runAsDenied(any(User.class), eq(restRequest));
|
verify(auditTrail).runAsDenied(any(User.class), eq(restRequest), eq(Role.EMPTY.names()));
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -755,7 +756,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
||||||
authenticateBlocking("_action", message, null);
|
authenticateBlocking("_action", message, null);
|
||||||
fail("exception should be thrown");
|
fail("exception should be thrown");
|
||||||
} catch (ElasticsearchException e) {
|
} catch (ElasticsearchException e) {
|
||||||
verify(auditTrail).runAsDenied(any(User.class), eq("_action"), eq(message));
|
verify(auditTrail).runAsDenied(any(User.class), eq("_action"), eq(message), eq(Role.EMPTY.names()));
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,7 @@ import static org.hamcrest.Matchers.arrayContaining;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
@ -216,10 +217,10 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
|
|
||||||
// A failure would throw an exception
|
// A failure would throw an exception
|
||||||
authorize(createAuthentication(SystemUser.INSTANCE), "indices:monitor/whatever", request);
|
authorize(createAuthentication(SystemUser.INSTANCE), "indices:monitor/whatever", request);
|
||||||
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "indices:monitor/whatever", request);
|
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "indices:monitor/whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||||
|
|
||||||
authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
|
authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
|
||||||
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request);
|
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +229,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request),
|
() -> authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request),
|
||||||
"indices:", SystemUser.INSTANCE.principal());
|
"indices:", SystemUser.INSTANCE.principal());
|
||||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "indices:", request);
|
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "indices:", request, new String[] { SystemUser.ROLE_NAME });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +238,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/whatever", request),
|
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/whatever", request),
|
||||||
"cluster:admin/whatever", SystemUser.INSTANCE.principal());
|
"cluster:admin/whatever", SystemUser.INSTANCE.principal());
|
||||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/whatever", request);
|
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/whatever", request, new String[] { SystemUser.ROLE_NAME });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +247,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/snapshot/status", request),
|
() -> authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/snapshot/status", request),
|
||||||
"cluster:admin/snapshot/status", SystemUser.INSTANCE.principal());
|
"cluster:admin/snapshot/status", SystemUser.INSTANCE.principal());
|
||||||
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/snapshot/status", request);
|
verify(auditTrail).accessDenied(SystemUser.INSTANCE, "cluster:admin/snapshot/status", request,
|
||||||
|
new String[] { SystemUser.ROLE_NAME });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +259,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user");
|
"indices:a", "test user");
|
||||||
verify(auditTrail).accessDenied(user, "indices:a", request);
|
verify(auditTrail).accessDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +269,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
User user = new User("test user");
|
User user = new User("test user");
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
authorize(createAuthentication(user), SearchAction.NAME, request);
|
authorize(createAuthentication(user), SearchAction.NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchAction.NAME, request);
|
verify(auditTrail).accessGranted(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +286,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
||||||
SearchAction.NAME, "test user");
|
SearchAction.NAME, "test user");
|
||||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, request);
|
verify(auditTrail).accessDenied(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +302,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
|
||||||
SearchAction.NAME, "test user");
|
SearchAction.NAME, "test user");
|
||||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, request);
|
verify(auditTrail).accessDenied(user, SearchAction.NAME, request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +318,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), DeleteIndexAction.NAME, request),
|
() -> authorize(createAuthentication(user), DeleteIndexAction.NAME, request),
|
||||||
DeleteIndexAction.NAME, "test user");
|
DeleteIndexAction.NAME, "test user");
|
||||||
verify(auditTrail).accessDenied(user, DeleteIndexAction.NAME, request);
|
verify(auditTrail).accessDenied(user, DeleteIndexAction.NAME, request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,33 +329,35 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user");
|
"indices:a", "test user");
|
||||||
verify(auditTrail).accessDenied(user, "indices:a", request);
|
verify(auditTrail).accessDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testThatNonIndicesAndNonClusterActionIsDenied() {
|
public void testThatNonIndicesAndNonClusterActionIsDenied() {
|
||||||
TransportRequest request = mock(TransportRequest.class);
|
TransportRequest request = mock(TransportRequest.class);
|
||||||
User user = new User("test user", "a_all");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||||
|
roleMap.put("a_all", role);
|
||||||
|
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), "whatever", request),
|
() -> authorize(createAuthentication(user), "whatever", request),
|
||||||
"whatever", "test user");
|
"whatever", "test user");
|
||||||
verify(auditTrail).accessDenied(user, "whatever", request);
|
verify(auditTrail).accessDenied(user, "whatever", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testThatRoleWithNoIndicesIsDenied() {
|
public void testThatRoleWithNoIndicesIsDenied() {
|
||||||
TransportRequest request = new IndicesExistsRequest("a");
|
TransportRequest request = new IndicesExistsRequest("a");
|
||||||
User user = new User("test user", "no_indices");
|
User user = new User("test user", "no_indices");
|
||||||
roleMap.put("no_indices", new RoleDescriptor("a_role", null, null, null));
|
RoleDescriptor role = new RoleDescriptor("a_role", null, null, null);
|
||||||
|
roleMap.put("no_indices", role);
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
|
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user");
|
"indices:a", "test user");
|
||||||
verify(auditTrail).accessDenied(user, "indices:a", request);
|
verify(auditTrail).accessDenied(user, "indices:a", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,13 +366,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
Tuple<String, TransportRequest> request = randomCompositeRequest();
|
Tuple<String, TransportRequest> request = randomCompositeRequest();
|
||||||
authorize(createAuthentication(user), request.v1(), request.v2());
|
authorize(createAuthentication(user), request.v1(), request.v2());
|
||||||
|
|
||||||
verify(auditTrail).accessGranted(user, request.v1(), request.v2());
|
verify(auditTrail).accessGranted(user, request.v1(), request.v2(), new String[] { ElasticUser.ROLE_NAME });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchAgainstEmptyCluster() {
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -379,7 +384,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), SearchAction.NAME, searchRequest),
|
() -> authorize(createAuthentication(user), SearchAction.NAME, searchRequest),
|
||||||
SearchAction.NAME, "test user");
|
SearchAction.NAME, "test user");
|
||||||
verify(auditTrail).accessDenied(user, SearchAction.NAME, searchRequest);
|
verify(auditTrail).accessDenied(user, SearchAction.NAME, searchRequest, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +393,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
SearchRequest searchRequest = new SearchRequest("does_not_exist")
|
SearchRequest searchRequest = new SearchRequest("does_not_exist")
|
||||||
.indicesOptions(IndicesOptions.fromOptions(true, true, true, false));
|
.indicesOptions(IndicesOptions.fromOptions(true, true, true, false));
|
||||||
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
||||||
verify(auditTrail).accessGranted(user, SearchAction.NAME, searchRequest);
|
verify(auditTrail).accessGranted(user, SearchAction.NAME, searchRequest, new String[] { role.getName() });
|
||||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY);
|
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY);
|
||||||
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
||||||
indicesAccessControl.getIndexPermissions(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER);
|
indicesAccessControl.getIndexPermissions(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER);
|
||||||
|
@ -398,49 +403,55 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testScrollRelatedRequestsAllowed() {
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
|
|
||||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||||
authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest);
|
authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest);
|
||||||
verify(auditTrail).accessGranted(user, ClearScrollAction.NAME, clearScrollRequest);
|
verify(auditTrail).accessGranted(user, ClearScrollAction.NAME, clearScrollRequest, new String[] { role.getName() });
|
||||||
|
|
||||||
SearchScrollRequest searchScrollRequest = new SearchScrollRequest();
|
SearchScrollRequest searchScrollRequest = new SearchScrollRequest();
|
||||||
authorize(createAuthentication(user), SearchScrollAction.NAME, searchScrollRequest);
|
authorize(createAuthentication(user), SearchScrollAction.NAME, searchScrollRequest);
|
||||||
verify(auditTrail).accessGranted(user, SearchScrollAction.NAME, searchScrollRequest);
|
verify(auditTrail).accessGranted(user, 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
|
// 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);
|
TransportRequest request = mock(TransportRequest.class);
|
||||||
authorize(createAuthentication(user), SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request);
|
authorize(createAuthentication(user), SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request);
|
verify(auditTrail).accessGranted(user, SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME, request,
|
||||||
|
new String[] { role.getName() });
|
||||||
|
|
||||||
authorize(createAuthentication(user), SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
authorize(createAuthentication(user), SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request);
|
verify(auditTrail).accessGranted(user, SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request,
|
||||||
|
new String[] { role.getName() });
|
||||||
|
|
||||||
authorize(createAuthentication(user), SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
authorize(createAuthentication(user), SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request);
|
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request,
|
||||||
|
new String[] { role.getName() });
|
||||||
|
|
||||||
authorize(createAuthentication(user), SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
authorize(createAuthentication(user), SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request);
|
verify(auditTrail).accessGranted(user, SearchTransportService.QUERY_SCROLL_ACTION_NAME, request, new String[] { role.getName() });
|
||||||
|
|
||||||
authorize(createAuthentication(user), SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
authorize(createAuthentication(user), SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request);
|
verify(auditTrail).accessGranted(user, SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request,
|
||||||
|
new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAuthorizeIndicesFailures() {
|
public void testAuthorizeIndicesFailures() {
|
||||||
TransportRequest request = new GetIndexRequest().indices("b");
|
TransportRequest request = new GetIndexRequest().indices("b");
|
||||||
ClusterState state = mockEmptyMetaData();
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
|
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user");
|
"indices:a", "test user");
|
||||||
verify(auditTrail).accessDenied(user, "indices:a", request);
|
verify(auditTrail).accessDenied(user, "indices:a", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService, times(1)).state();
|
verify(clusterService, times(1)).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -450,14 +461,15 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
CreateIndexRequest request = new CreateIndexRequest("a");
|
CreateIndexRequest request = new CreateIndexRequest("a");
|
||||||
request.alias(new Alias("a2"));
|
request.alias(new Alias("a2"));
|
||||||
ClusterState state = mockEmptyMetaData();
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
|
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), CreateIndexAction.NAME, request),
|
() -> authorize(createAuthentication(user), CreateIndexAction.NAME, request),
|
||||||
IndicesAliasesAction.NAME, "test user");
|
IndicesAliasesAction.NAME, "test user");
|
||||||
verify(auditTrail).accessDenied(user, IndicesAliasesAction.NAME, request);
|
verify(auditTrail).accessDenied(user, IndicesAliasesAction.NAME, request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService).state();
|
verify(clusterService).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -467,13 +479,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
CreateIndexRequest request = new CreateIndexRequest("a");
|
CreateIndexRequest request = new CreateIndexRequest("a");
|
||||||
request.alias(new Alias("a2"));
|
request.alias(new Alias("a2"));
|
||||||
ClusterState state = mockEmptyMetaData();
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_all", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a", "a2").privileges("all").build() }, null));
|
|
||||||
|
|
||||||
authorize(createAuthentication(user), CreateIndexAction.NAME, request);
|
authorize(createAuthentication(user), CreateIndexAction.NAME, request);
|
||||||
|
|
||||||
verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request);
|
verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request, new String[] { role.getName()});
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService).state();
|
verify(clusterService).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -487,13 +500,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
|
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
|
||||||
new DefaultAuthenticationFailureHandler(), threadPool, anonymousUser);
|
new DefaultAuthenticationFailureHandler(), threadPool, anonymousUser);
|
||||||
|
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_all", null,
|
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||||
|
roleMap.put("a_all", role);
|
||||||
|
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(anonymousUser), "indices:a", request),
|
() -> authorize(createAuthentication(anonymousUser), "indices:a", request),
|
||||||
"indices:a", anonymousUser.principal());
|
"indices:a", anonymousUser.principal());
|
||||||
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request);
|
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService, times(1)).state();
|
verify(clusterService, times(1)).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -510,13 +524,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
|
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail,
|
||||||
new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(settings));
|
new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(settings));
|
||||||
|
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_all", null,
|
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||||
|
roleMap.put("a_all", role);
|
||||||
|
|
||||||
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class,
|
||||||
() -> authorize(createAuthentication(anonymousUser), "indices:a", request));
|
() -> authorize(createAuthentication(anonymousUser), "indices:a", request));
|
||||||
assertAuthenticationException(securityException, containsString("action [indices:a] requires authentication"));
|
assertAuthenticationException(securityException, containsString("action [indices:a] requires authentication"));
|
||||||
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request);
|
verify(auditTrail).accessDenied(anonymousUser, "indices:a", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService, times(1)).state();
|
verify(clusterService, times(1)).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -526,16 +541,17 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
IndicesOptions options = IndicesOptions.fromOptions(false, false, true, true);
|
IndicesOptions options = IndicesOptions.fromOptions(false, false, true, true);
|
||||||
TransportRequest request = new GetIndexRequest().indices("not-an-index-*").indicesOptions(options);
|
TransportRequest request = new GetIndexRequest().indices("not-an-index-*").indicesOptions(options);
|
||||||
ClusterState state = mockEmptyMetaData();
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_all", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
|
|
||||||
final IndexNotFoundException nfe = expectThrows(
|
final IndexNotFoundException nfe = expectThrows(
|
||||||
IndexNotFoundException.class,
|
IndexNotFoundException.class,
|
||||||
() -> authorize(createAuthentication(user), GetIndexAction.NAME, request));
|
() -> authorize(createAuthentication(user), GetIndexAction.NAME, request));
|
||||||
assertThat(nfe.getIndex(), is(notNullValue()));
|
assertThat(nfe.getIndex(), is(notNullValue()));
|
||||||
assertThat(nfe.getIndex().getName(), is("not-an-index-*"));
|
assertThat(nfe.getIndex().getName(), is("not-an-index-*"));
|
||||||
verify(auditTrail).accessDenied(user, GetIndexAction.NAME, request);
|
verify(auditTrail).accessDenied(user, GetIndexAction.NAME, request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
verify(clusterService).state();
|
verify(clusterService).state();
|
||||||
verify(state, times(1)).metaData();
|
verify(state, times(1)).metaData();
|
||||||
|
@ -548,7 +564,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationExceptionRunAs(
|
assertThrowsAuthorizationExceptionRunAs(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user", "run as me"); // run as [run as me]
|
"indices:a", "test user", "run as me"); // run as [run as me]
|
||||||
verify(auditTrail).runAsDenied(user, "indices:a", request);
|
verify(auditTrail).runAsDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +577,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationExceptionRunAs(
|
assertThrowsAuthorizationExceptionRunAs(
|
||||||
() -> authorize(authentication, AuthenticateAction.NAME, request),
|
() -> authorize(authentication, AuthenticateAction.NAME, request),
|
||||||
AuthenticateAction.NAME, "test user", "run as me"); // run as [run as me]
|
AuthenticateAction.NAME, "test user", "run as me"); // run as [run as me]
|
||||||
verify(auditTrail).runAsDenied(user, AuthenticateAction.NAME, request);
|
verify(auditTrail).runAsDenied(user, AuthenticateAction.NAME, request,
|
||||||
|
new String[] { ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,26 +586,32 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
TransportRequest request = mock(TransportRequest.class);
|
TransportRequest request = mock(TransportRequest.class);
|
||||||
User user = new User("run as me", new String[] { "doesn't exist" }, new User("test user", "can run as"));
|
User user = new User("run as me", new String[] { "doesn't exist" }, new User("test user", "can run as"));
|
||||||
assertNotEquals(user.authenticatedUser(), user);
|
assertNotEquals(user.authenticatedUser(), user);
|
||||||
roleMap.put("can run as", new RoleDescriptor("can run as", null,
|
RoleDescriptor role = new RoleDescriptor("can run as", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||||
new String[] { "not the right user" }));
|
new String[] { "not the right user" });
|
||||||
|
roleMap.put("can run as", role);
|
||||||
|
|
||||||
assertThrowsAuthorizationExceptionRunAs(
|
assertThrowsAuthorizationExceptionRunAs(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user", "run as me");
|
"indices:a", "test user", "run as me");
|
||||||
verify(auditTrail).runAsDenied(user, "indices:a", request);
|
verify(auditTrail).runAsDenied(user, "indices:a", request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRunAsRequestWithRunAsUserWithoutPermission() {
|
public void testRunAsRequestWithRunAsUserWithoutPermission() {
|
||||||
TransportRequest request = new GetIndexRequest().indices("a");
|
TransportRequest request = new GetIndexRequest().indices("a");
|
||||||
User user = new User("run as me", new String[] { "b" }, new User("test user", "can run as"));
|
User authenticatedUser = new User("test user", "can run as");
|
||||||
|
User user = new User("run as me", new String[] { "b" }, authenticatedUser);
|
||||||
assertNotEquals(user.authenticatedUser(), user);
|
assertNotEquals(user.authenticatedUser(), user);
|
||||||
roleMap.put("can run as", new RoleDescriptor("can run as", null,
|
RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||||
new String[] { "run as me" }));
|
new String[] { "run as me" });
|
||||||
|
roleMap.put("can run as", runAsRole);
|
||||||
|
|
||||||
if (randomBoolean()) {
|
RoleDescriptor bRole = new RoleDescriptor("b", null,
|
||||||
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("all").build() }, null);
|
||||||
|
boolean indexExists = randomBoolean();
|
||||||
|
if (indexExists) {
|
||||||
ClusterState state = mock(ClusterState.class);
|
ClusterState state = mock(ClusterState.class);
|
||||||
when(clusterService.state()).thenReturn(state);
|
when(clusterService.state()).thenReturn(state);
|
||||||
when(state.metaData()).thenReturn(MetaData.builder()
|
when(state.metaData()).thenReturn(MetaData.builder()
|
||||||
|
@ -596,8 +619,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||||
.build());
|
.build());
|
||||||
roleMap.put("b", new RoleDescriptor("b", null,
|
roleMap.put("b", bRole);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("all").build() }, null));
|
|
||||||
} else {
|
} else {
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
}
|
}
|
||||||
|
@ -605,18 +627,24 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationExceptionRunAs(
|
assertThrowsAuthorizationExceptionRunAs(
|
||||||
() -> authorize(createAuthentication(user), "indices:a", request),
|
() -> authorize(createAuthentication(user), "indices:a", request),
|
||||||
"indices:a", "test user", "run as me");
|
"indices:a", "test user", "run as me");
|
||||||
verify(auditTrail).runAsGranted(user, "indices:a", request);
|
verify(auditTrail).runAsGranted(user, "indices:a", request, new String[] { runAsRole.getName() });
|
||||||
verify(auditTrail).accessDenied(user, "indices:a", request);
|
if (indexExists) {
|
||||||
|
verify(auditTrail).accessDenied(user, "indices:a", request, new String[] { bRole.getName() });
|
||||||
|
} else {
|
||||||
|
verify(auditTrail).accessDenied(user, "indices:a", request, Role.EMPTY.names());
|
||||||
|
}
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRunAsRequestWithValidPermissions() {
|
public void testRunAsRequestWithValidPermissions() {
|
||||||
TransportRequest request = new GetIndexRequest().indices("b");
|
TransportRequest request = new GetIndexRequest().indices("b");
|
||||||
User user = new User("run as me", new String[] { "b" }, new User("test user", new String[] { "can run as" }));
|
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);
|
assertNotEquals(user.authenticatedUser(), user);
|
||||||
roleMap.put("can run as", new RoleDescriptor("can run as", null,
|
RoleDescriptor runAsRole = new RoleDescriptor("can run as", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() },
|
||||||
new String[] { "run as me" }));
|
new String[] { "run as me" });
|
||||||
|
roleMap.put("can run as", runAsRole);
|
||||||
ClusterState state = mock(ClusterState.class);
|
ClusterState state = mock(ClusterState.class);
|
||||||
when(clusterService.state()).thenReturn(state);
|
when(clusterService.state()).thenReturn(state);
|
||||||
when(state.metaData()).thenReturn(MetaData.builder()
|
when(state.metaData()).thenReturn(MetaData.builder()
|
||||||
|
@ -624,19 +652,21 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||||
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
.numberOfShards(1).numberOfReplicas(0).build(), true)
|
||||||
.build());
|
.build());
|
||||||
roleMap.put("b", new RoleDescriptor("b", null,
|
RoleDescriptor bRole = new RoleDescriptor("b", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("all").build() }, null));
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("all").build() }, null);
|
||||||
|
roleMap.put("b", bRole);
|
||||||
|
|
||||||
authorize(createAuthentication(user), "indices:a", request);
|
authorize(createAuthentication(user), "indices:a", request);
|
||||||
verify(auditTrail).runAsGranted(user, "indices:a", request);
|
verify(auditTrail).runAsGranted(user, "indices:a", request, new String[] { runAsRole.getName() });
|
||||||
verify(auditTrail).accessGranted(user, "indices:a", request);
|
verify(auditTrail).accessGranted(user, "indices:a", request, new String[] { bRole.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() {
|
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");
|
User user = new User("all_access_user", "all_access");
|
||||||
roleMap.put("all_access", new RoleDescriptor("all access", new String[] { "all" },
|
roleMap.put("all_access", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("*").privileges("all").build() }, null));
|
|
||||||
ClusterState state = mock(ClusterState.class);
|
ClusterState state = mock(ClusterState.class);
|
||||||
when(clusterService.state()).thenReturn(state);
|
when(clusterService.state()).thenReturn(state);
|
||||||
when(state.metaData()).thenReturn(MetaData.builder()
|
when(state.metaData()).thenReturn(MetaData.builder()
|
||||||
|
@ -666,19 +696,19 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), action, request),
|
() -> authorize(createAuthentication(user), action, request),
|
||||||
action, "all_access_user");
|
action, "all_access_user");
|
||||||
verify(auditTrail).accessDenied(user, action, request);
|
verify(auditTrail).accessDenied(user, action, request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should allow waiting for the health of the index or any index if the user has this permission
|
// we should allow waiting for the health of the index or any index if the user has this permission
|
||||||
ClusterHealthRequest request = new ClusterHealthRequest(SecurityLifecycleService.SECURITY_INDEX_NAME);
|
ClusterHealthRequest request = new ClusterHealthRequest(SecurityLifecycleService.SECURITY_INDEX_NAME);
|
||||||
authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
|
authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
|
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||||
|
|
||||||
// multiple indices
|
// multiple indices
|
||||||
request = new ClusterHealthRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "foo", "bar");
|
request = new ClusterHealthRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "foo", "bar");
|
||||||
authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
|
authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
|
||||||
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
|
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request, new String[] { role.getName() });
|
||||||
|
|
||||||
SearchRequest searchRequest = new SearchRequest("_all");
|
SearchRequest searchRequest = new SearchRequest("_all");
|
||||||
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
authorize(createAuthentication(user), SearchAction.NAME, searchRequest);
|
||||||
|
@ -687,9 +717,10 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGrantedNonXPackUserCanExecuteMonitoringOperationsAgainstSecurityIndex() {
|
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");
|
User user = new User("all_access_user", "all_access");
|
||||||
roleMap.put("all_access", new RoleDescriptor("all access", new String[] { "all" },
|
roleMap.put("all_access", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("*").privileges("all").build() }, null));
|
|
||||||
ClusterState state = mock(ClusterState.class);
|
ClusterState state = mock(ClusterState.class);
|
||||||
when(clusterService.state()).thenReturn(state);
|
when(clusterService.state()).thenReturn(state);
|
||||||
when(state.metaData()).thenReturn(MetaData.builder()
|
when(state.metaData()).thenReturn(MetaData.builder()
|
||||||
|
@ -713,7 +744,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = requestTuple.v1();
|
String action = requestTuple.v1();
|
||||||
TransportRequest request = requestTuple.v2();
|
TransportRequest request = requestTuple.v2();
|
||||||
authorize(createAuthentication(user), action, request);
|
authorize(createAuthentication(user), action, request);
|
||||||
verify(auditTrail).accessGranted(user, action, request);
|
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +783,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = requestTuple.v1();
|
String action = requestTuple.v1();
|
||||||
TransportRequest request = requestTuple.v2();
|
TransportRequest request = requestTuple.v2();
|
||||||
authorize(createAuthentication(superuser), action, request);
|
authorize(createAuthentication(superuser), action, request);
|
||||||
verify(auditTrail).accessGranted(superuser, action, request);
|
verify(auditTrail).accessGranted(superuser, action, request, superuser.roles());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,7 +801,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = SearchAction.NAME;
|
String action = SearchAction.NAME;
|
||||||
SearchRequest request = new SearchRequest("_all");
|
SearchRequest request = new SearchRequest("_all");
|
||||||
authorize(createAuthentication(superuser), action, request);
|
authorize(createAuthentication(superuser), action, request);
|
||||||
verify(auditTrail).accessGranted(superuser, action, request);
|
verify(auditTrail).accessGranted(superuser, action, request, superuser.roles());
|
||||||
assertThat(request.indices(), arrayContaining(".security"));
|
assertThat(request.indices(), arrayContaining(".security"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,7 +843,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>();
|
PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>();
|
||||||
authorizationService.roles(new User("no role user"), rolesFuture);
|
authorizationService.roles(new User("no role user"), rolesFuture);
|
||||||
final Role roles = rolesFuture.actionGet();
|
final Role roles = rolesFuture.actionGet();
|
||||||
assertThat(roles.name(), containsString("anonymous_user_role"));
|
assertThat(Arrays.asList(roles.names()), hasItem("anonymous_user_role"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCompositeActionsAreImmediatelyRejected() {
|
public void testCompositeActionsAreImmediatelyRejected() {
|
||||||
|
@ -821,10 +852,11 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = compositeRequest.v1();
|
String action = compositeRequest.v1();
|
||||||
TransportRequest request = compositeRequest.v2();
|
TransportRequest request = compositeRequest.v2();
|
||||||
User user = new User("test user", "no_indices");
|
User user = new User("test user", "no_indices");
|
||||||
roleMap.put("no_indices", new RoleDescriptor("no_indices", null, null, null));
|
RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||||
|
roleMap.put("no_indices", role);
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), action, request), action, "test user");
|
() -> authorize(createAuthentication(user), action, request), action, "test user");
|
||||||
verify(auditTrail).accessDenied(user, action, request);
|
verify(auditTrail).accessDenied(user, action, request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,11 +866,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = compositeRequest.v1();
|
String action = compositeRequest.v1();
|
||||||
TransportRequest request = compositeRequest.v2();
|
TransportRequest request = compositeRequest.v2();
|
||||||
User user = new User("test user", "role");
|
User user = new User("test user", "role");
|
||||||
roleMap.put("role", new RoleDescriptor("role", null,
|
RoleDescriptor role = new RoleDescriptor("role", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices(randomBoolean() ? "a" : "index").privileges("all").build() },
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices(randomBoolean() ? "a" : "index").privileges("all").build() },
|
||||||
null));
|
null);
|
||||||
|
roleMap.put("role", role);
|
||||||
authorize(createAuthentication(user), action, request);
|
authorize(createAuthentication(user), action, request);
|
||||||
verify(auditTrail).accessGranted(user, action, request);
|
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,18 +944,19 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
||||||
|
|
||||||
User user = new User("user", "my-role");
|
User user = new User("user", "my-role");
|
||||||
roleMap.put("my-role", new RoleDescriptor("my-role", null, new IndicesPrivileges[] {
|
RoleDescriptor role = new RoleDescriptor("my-role", null, new IndicesPrivileges[] {
|
||||||
IndicesPrivileges.builder().indices("concrete-index").privileges("all").build(),
|
IndicesPrivileges.builder().indices("concrete-index").privileges("all").build(),
|
||||||
IndicesPrivileges.builder().indices("alias-1").privileges("index").build(),
|
IndicesPrivileges.builder().indices("alias-1").privileges("index").build(),
|
||||||
IndicesPrivileges.builder().indices("alias-2").privileges("delete").build()
|
IndicesPrivileges.builder().indices("alias-2").privileges("delete").build()
|
||||||
}, null));
|
}, null);
|
||||||
|
roleMap.put("my-role", role);
|
||||||
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
authorize(createAuthentication(user), action, request);
|
authorize(createAuthentication(user), action, request);
|
||||||
|
|
||||||
verify(auditTrail).accessDenied(user, DeleteAction.NAME, request); // alias-1 delete
|
verify(auditTrail).accessDenied(user, DeleteAction.NAME, request, new String[] { role.getName() }); // alias-1 delete
|
||||||
verify(auditTrail).accessDenied(user, IndexAction.NAME, request); // alias-2 index
|
verify(auditTrail).accessDenied(user, IndexAction.NAME, request, new String[] { role.getName() }); // alias-2 index
|
||||||
verify(auditTrail).accessGranted(user, action, request); // bulk request is allowed
|
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() }); // bulk request is allowed
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,15 +972,17 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
final TransportRequest request = new BulkShardRequest(shardId, WriteRequest.RefreshPolicy.IMMEDIATE, items);
|
||||||
|
|
||||||
User user = new User("user", "my-role");
|
User user = new User("user", "my-role");
|
||||||
roleMap.put("my-role", new RoleDescriptor("my-role", null, new IndicesPrivileges[] {
|
RoleDescriptor role = new RoleDescriptor("my-role", null,
|
||||||
IndicesPrivileges.builder().indices("datemath-*").privileges("index").build()
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("datemath-*").privileges("index").build() }, null);
|
||||||
}, null));
|
roleMap.put("my-role", role);
|
||||||
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
authorize(createAuthentication(user), action, request);
|
authorize(createAuthentication(user), action, request);
|
||||||
|
|
||||||
verify(auditTrail, Mockito.times(2)).accessDenied(user, DeleteAction.NAME, request); // both deletes should fail
|
verify(auditTrail, Mockito.times(2)).accessDenied(user, DeleteAction.NAME, request, new String[] { role.getName() }); // both
|
||||||
verify(auditTrail).accessGranted(user, action, request); // bulk request is allowed
|
// deletes
|
||||||
|
// should fail
|
||||||
|
verify(auditTrail).accessGranted(user, action, request, new String[] { role.getName() }); // bulk request is allowed
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,17 +1208,19 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, proxiedRequest);
|
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, proxiedRequest);
|
||||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.QUERY_ACTION_NAME);
|
String action = TransportActionProxy.getProxyAction(SearchTransportService.QUERY_ACTION_NAME);
|
||||||
User user = new User("test user", "no_indices");
|
User user = new User("test user", "no_indices");
|
||||||
roleMap.put("no_indices", new RoleDescriptor("no_indices", null, null, null));
|
RoleDescriptor role = new RoleDescriptor("no_indices", null, null, null);
|
||||||
|
roleMap.put("no_indices", role);
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
||||||
verify(auditTrail).accessDenied(user, action, proxiedRequest);
|
verify(auditTrail).accessDenied(user, action, proxiedRequest, new String[] { role.getName() });
|
||||||
verifyNoMoreInteractions(auditTrail);
|
verifyNoMoreInteractions(auditTrail);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testProxyRequestAuthenticationGrantedWithAllPrivileges() {
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null));
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||||
|
|
||||||
|
@ -1190,13 +1228,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||||
authorize(createAuthentication(user), action, transportRequest);
|
authorize(createAuthentication(user), action, transportRequest);
|
||||||
verify(auditTrail).accessGranted(user, action, clearScrollRequest);
|
verify(auditTrail).accessGranted(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testProxyRequestAuthenticationGranted() {
|
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");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
roleMap.put("a_all", role);
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("read_cross_cluster").build() }, null));
|
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||||
|
|
||||||
|
@ -1204,13 +1243,14 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
TransportRequest transportRequest = TransportActionProxy.wrapRequest(node, clearScrollRequest);
|
||||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||||
authorize(createAuthentication(user), action, transportRequest);
|
authorize(createAuthentication(user), action, transportRequest);
|
||||||
verify(auditTrail).accessGranted(user, action, clearScrollRequest);
|
verify(auditTrail).accessGranted(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testProxyRequestAuthenticationDeniedWithReadPrivileges() {
|
public void testProxyRequestAuthenticationDeniedWithReadPrivileges() {
|
||||||
User user = new User("test user", "a_all");
|
User user = new User("test user", "a_all");
|
||||||
roleMap.put("a_all", new RoleDescriptor("a_role", null,
|
RoleDescriptor role = new RoleDescriptor("a_role", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("read").build() }, null));
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("read").build() }, null);
|
||||||
|
roleMap.put("a_all", role);
|
||||||
mockEmptyMetaData();
|
mockEmptyMetaData();
|
||||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||||
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
|
||||||
|
@ -1218,6 +1258,6 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||||
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
String action = TransportActionProxy.getProxyAction(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME);
|
||||||
assertThrowsAuthorizationException(
|
assertThrowsAuthorizationException(
|
||||||
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
() -> authorize(createAuthentication(user), action, transportRequest), action, "test user");
|
||||||
verify(auditTrail).accessDenied(user, action, clearScrollRequest);
|
verify(auditTrail).accessDenied(user, action, clearScrollRequest, new String[] { role.getName() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.elasticsearch.xpack.security.user.User;
|
||||||
|
|
||||||
import static org.elasticsearch.mock.orig.Mockito.verifyNoMoreInteractions;
|
import static org.elasticsearch.mock.orig.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
||||||
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ROLE_NAMES_KEY;
|
||||||
import static org.elasticsearch.xpack.security.authz.SecuritySearchOperationListener.ensureAuthenticatedUserIsSame;
|
import static org.elasticsearch.xpack.security.authz.SecuritySearchOperationListener.ensureAuthenticatedUserIsSame;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
@ -110,13 +111,13 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||||
Authentication authentication = new Authentication(new User("test", "role"), new RealmRef(realmName, type, nodeName), null);
|
Authentication authentication = new Authentication(new User("test", "role"), new RealmRef(realmName, type, nodeName), null);
|
||||||
authentication.writeToContext(threadContext);
|
authentication.writeToContext(threadContext);
|
||||||
threadContext.putTransient(ORIGINATING_ACTION_KEY, "action");
|
threadContext.putTransient(ORIGINATING_ACTION_KEY, "action");
|
||||||
|
threadContext.putTransient(ROLE_NAMES_KEY, authentication.getUser().roles());
|
||||||
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
||||||
SearchContextMissingException expected =
|
SearchContextMissingException expected =
|
||||||
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
||||||
assertEquals(testSearchContext.id(), expected.id());
|
assertEquals(testSearchContext.id(), expected.id());
|
||||||
verify(licenseState, times(3)).isAuthAllowed();
|
verify(licenseState, times(3)).isAuthAllowed();
|
||||||
verify(auditTrailService)
|
verify(auditTrailService).accessDenied(authentication.getUser(), "action", request, authentication.getUser().roles());
|
||||||
.accessDenied(authentication.getUser(), "action", request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// another user running as the original user
|
// another user running as the original user
|
||||||
|
@ -144,13 +145,13 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||||
new Authentication(new User("authenticated", "runas"), new RealmRef(realmName, type, nodeName), null);
|
new Authentication(new User("authenticated", "runas"), new RealmRef(realmName, type, nodeName), null);
|
||||||
authentication.writeToContext(threadContext);
|
authentication.writeToContext(threadContext);
|
||||||
threadContext.putTransient(ORIGINATING_ACTION_KEY, "action");
|
threadContext.putTransient(ORIGINATING_ACTION_KEY, "action");
|
||||||
|
threadContext.putTransient(ROLE_NAMES_KEY, authentication.getUser().roles());
|
||||||
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
||||||
SearchContextMissingException expected =
|
SearchContextMissingException expected =
|
||||||
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
||||||
assertEquals(testSearchContext.id(), expected.id());
|
assertEquals(testSearchContext.id(), expected.id());
|
||||||
verify(licenseState, times(5)).isAuthAllowed();
|
verify(licenseState, times(5)).isAuthAllowed();
|
||||||
verify(auditTrailService)
|
verify(auditTrailService).accessDenied(authentication.getUser(), "action", request, authentication.getUser().roles());
|
||||||
.accessDenied(authentication.getUser(), "action", request);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,54 +164,55 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
||||||
TransportRequest request = Empty.INSTANCE;
|
TransportRequest request = Empty.INSTANCE;
|
||||||
AuditTrailService auditTrail = mock(AuditTrailService.class);
|
AuditTrailService auditTrail = mock(AuditTrailService.class);
|
||||||
|
|
||||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request);
|
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, original.getUser().roles());
|
||||||
verifyZeroInteractions(auditTrail);
|
verifyZeroInteractions(auditTrail);
|
||||||
|
|
||||||
// original user being run as
|
// original user being run as
|
||||||
User user = new User(new User("test", "role"), new User("authenticated", "runas"));
|
User user = new User(new User("test", "role"), new User("authenticated", "runas"));
|
||||||
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
||||||
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request);
|
ensureAuthenticatedUserIsSame(original, current, auditTrail, id, action, request, original.getUser().roles());
|
||||||
verifyZeroInteractions(auditTrail);
|
verifyZeroInteractions(auditTrail);
|
||||||
|
|
||||||
// both user are run as
|
// both user are run as
|
||||||
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
||||||
Authentication runAs = current;
|
Authentication runAs = current;
|
||||||
ensureAuthenticatedUserIsSame(runAs, current, auditTrail, id, action, request);
|
ensureAuthenticatedUserIsSame(runAs, current, auditTrail, id, action, request, original.getUser().roles());
|
||||||
verifyZeroInteractions(auditTrail);
|
verifyZeroInteractions(auditTrail);
|
||||||
|
|
||||||
// different authenticated by type
|
// different authenticated by type
|
||||||
Authentication differentRealmType =
|
Authentication differentRealmType =
|
||||||
new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null);
|
new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null);
|
||||||
SearchContextMissingException e = expectThrows(SearchContextMissingException.class,
|
SearchContextMissingException e = expectThrows(SearchContextMissingException.class,
|
||||||
() -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, id, action, request));
|
() -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, id, action, request,
|
||||||
|
original.getUser().roles()));
|
||||||
assertEquals(id, e.id());
|
assertEquals(id, e.id());
|
||||||
verify(auditTrail).accessDenied(differentRealmType.getUser(), action, request);
|
verify(auditTrail).accessDenied(differentRealmType.getUser(), action, request, original.getUser().roles());
|
||||||
|
|
||||||
// wrong user
|
// wrong user
|
||||||
Authentication differentUser =
|
Authentication differentUser =
|
||||||
new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null);
|
new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null);
|
||||||
e = expectThrows(SearchContextMissingException.class,
|
e = expectThrows(SearchContextMissingException.class,
|
||||||
() -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, id, action, request));
|
() -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, id, action, request, original.getUser().roles()));
|
||||||
assertEquals(id, e.id());
|
assertEquals(id, e.id());
|
||||||
verify(auditTrail).accessDenied(differentUser.getUser(), action, request);
|
verify(auditTrail).accessDenied(differentUser.getUser(), action, request, original.getUser().roles());
|
||||||
|
|
||||||
// run as different user
|
// run as different user
|
||||||
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
||||||
new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1"));
|
new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1"));
|
||||||
e = expectThrows(SearchContextMissingException.class,
|
e = expectThrows(SearchContextMissingException.class,
|
||||||
() -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, id, action, request));
|
() -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, id, action, request, original.getUser().roles()));
|
||||||
assertEquals(id, e.id());
|
assertEquals(id, e.id());
|
||||||
verify(auditTrail).accessDenied(diffRunAs.getUser(), action, request);
|
verify(auditTrail).accessDenied(diffRunAs.getUser(), action, request, original.getUser().roles());
|
||||||
|
|
||||||
// run as different looked up by type
|
// run as different looked up by type
|
||||||
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
||||||
new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node"));
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node"));
|
||||||
e = expectThrows(SearchContextMissingException.class,
|
e = expectThrows(SearchContextMissingException.class,
|
||||||
() -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, id, action, request));
|
() -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, id, action, request, original.getUser().roles()));
|
||||||
assertEquals(id, e.id());
|
assertEquals(id, e.id());
|
||||||
verify(auditTrail).accessDenied(runAsDiffType.getUser(), action, request);
|
verify(auditTrail).accessDenied(runAsDiffType.getUser(), action, request, original.getUser().roles());
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestScrollSearchContext extends TestSearchContext {
|
static class TestScrollSearchContext extends TestSearchContext {
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class PermissionTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBuildEmptyRole() {
|
public void testBuildEmptyRole() {
|
||||||
Role.Builder permission = Role.builder("some_role");
|
Role.Builder permission = Role.builder(new String[] { "some_role" });
|
||||||
Role role = permission.build();
|
Role role = permission.build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
|
|
|
@ -205,9 +205,10 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||||
verify(nativeRolesStore).getRoleDescriptors(isA(String[].class), any(ActionListener.class));
|
verify(nativeRolesStore).getRoleDescriptors(isA(String[].class), any(ActionListener.class));
|
||||||
|
|
||||||
final int numberOfTimesToCall = scaledRandomIntBetween(0, 32);
|
final int numberOfTimesToCall = scaledRandomIntBetween(0, 32);
|
||||||
final boolean getSuperuserRole = randomBoolean() && roleName.equals(ReservedRolesStore.SUPERUSER_ROLE.name()) == false;
|
final boolean getSuperuserRole = randomBoolean()
|
||||||
final Set<String> names = getSuperuserRole ? Sets.newHashSet(roleName, ReservedRolesStore.SUPERUSER_ROLE.name()) :
|
&& roleName.equals(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()) == false;
|
||||||
Collections.singleton(roleName);
|
final Set<String> names = getSuperuserRole ? Sets.newHashSet(roleName, ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName())
|
||||||
|
: Collections.singleton(roleName);
|
||||||
for (int i = 0; i < numberOfTimesToCall; i++) {
|
for (int i = 0; i < numberOfTimesToCall; i++) {
|
||||||
future = new PlainActionFuture<>();
|
future = new PlainActionFuture<>();
|
||||||
compositeRolesStore.roles(names, fieldPermissionsCache, future);
|
compositeRolesStore.roles(names, fieldPermissionsCache, future);
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
Role role = Role.builder(descriptor, null).build();
|
Role role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role1"));
|
assertThat(role.names(), equalTo(new String[] { "role1" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster().privilege(), is(ClusterPrivilege.ALL));
|
assertThat(role.cluster().privilege(), is(ClusterPrivilege.ALL));
|
||||||
assertThat(role.indices(), notNullValue());
|
assertThat(role.indices(), notNullValue());
|
||||||
|
@ -99,7 +99,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role1.ab"));
|
assertThat(role.names(), equalTo(new String[] { "role1.ab" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster().privilege(), is(ClusterPrivilege.ALL));
|
assertThat(role.cluster().privilege(), is(ClusterPrivilege.ALL));
|
||||||
assertThat(role.indices(), notNullValue());
|
assertThat(role.indices(), notNullValue());
|
||||||
|
@ -111,7 +111,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role2"));
|
assertThat(role.names(), equalTo(new String[] { "role2" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertTrue(Operations.sameLanguage(role.cluster().privilege().getAutomaton(), ClusterPrivilege.ALL.getAutomaton()));
|
assertTrue(Operations.sameLanguage(role.cluster().privilege().getAutomaton(), ClusterPrivilege.ALL.getAutomaton()));
|
||||||
assertThat(role.indices(), notNullValue());
|
assertThat(role.indices(), notNullValue());
|
||||||
|
@ -122,7 +122,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role3"));
|
assertThat(role.names(), equalTo(new String[] { "role3" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.indices(), notNullValue());
|
assertThat(role.indices(), notNullValue());
|
||||||
|
@ -146,7 +146,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role_run_as"));
|
assertThat(role.names(), equalTo(new String[] { "role_run_as" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.indices(), is(IndicesPermission.NONE));
|
assertThat(role.indices(), is(IndicesPermission.NONE));
|
||||||
|
@ -159,7 +159,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role_run_as1"));
|
assertThat(role.names(), equalTo(new String[] { "role_run_as1" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.indices(), is(IndicesPermission.NONE));
|
assertThat(role.indices(), is(IndicesPermission.NONE));
|
||||||
|
@ -172,7 +172,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role_fields"));
|
assertThat(role.names(), equalTo(new String[] { "role_fields" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
||||||
|
@ -194,7 +194,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role_query"));
|
assertThat(role.names(), equalTo(new String[] { "role_query" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
||||||
|
@ -215,7 +215,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
role = Role.builder(descriptor, null).build();
|
role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role_query_fields"));
|
assertThat(role.names(), equalTo(new String[] { "role_query_fields" }));
|
||||||
assertThat(role.cluster(), notNullValue());
|
assertThat(role.cluster(), notNullValue());
|
||||||
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
assertThat(role.cluster(), is(ClusterPermission.NONE));
|
||||||
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
assertThat(role.runAs(), is(RunAsPermission.NONE));
|
||||||
|
@ -346,7 +346,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertEquals(1, descriptors.size());
|
assertEquals(1, descriptors.size());
|
||||||
Role role = Role.builder(descriptors.iterator().next(), null).build();
|
Role role = Role.builder(descriptors.iterator().next(), null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("role5"));
|
assertThat(role.names(), equalTo(new String[] { "role5" }));
|
||||||
assertThat(role.cluster().check("cluster:monitor/foo/bar"), is(true));
|
assertThat(role.cluster().check("cluster:monitor/foo/bar"), is(true));
|
||||||
assertThat(role.cluster().check("cluster:admin/foo/bar"), is(false));
|
assertThat(role.cluster().check("cluster:admin/foo/bar"), is(false));
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ public class FileRolesStoreTests extends ESTestCase {
|
||||||
assertNotNull(descriptor);
|
assertNotNull(descriptor);
|
||||||
Role role = Role.builder(descriptor, null).build();
|
Role role = Role.builder(descriptor, null).build();
|
||||||
assertThat(role, notNullValue());
|
assertThat(role, notNullValue());
|
||||||
assertThat(role.name(), equalTo("valid_role"));
|
assertThat(role.names(), equalTo(new String[] { "valid_role" }));
|
||||||
|
|
||||||
List<String> entries = CapturingLogger.output(logger.getName(), Level.ERROR);
|
List<String> entries = CapturingLogger.output(logger.getName(), Level.ERROR);
|
||||||
assertThat(entries, hasSize(6));
|
assertThat(entries, hasSize(6));
|
||||||
|
|
Loading…
Reference in New Issue