Add specific client and user for security index access (elastic/x-pack-elasticsearch#2492)

This change removes security index access from the xpack user by creating its own specific role
and adds a xpack security user that maintains the superuser role so that it can perform all
operations necessary for security.

Original commit: elastic/x-pack-elasticsearch@ad906bc913
This commit is contained in:
Jay Modi 2017-09-14 08:09:14 -06:00 committed by GitHub
parent 104a3a323f
commit 8d8baffe24
35 changed files with 197 additions and 82 deletions

View File

@ -283,7 +283,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
components.add(licenseState); components.add(licenseState);
try { try {
components.addAll(security.createComponents(internalClient, threadPool, clusterService, resourceWatcherService, components.addAll(security.createComponents(client, threadPool, clusterService, resourceWatcherService,
extensionsService.getExtensions())); extensionsService.getExtensions()));
} catch (final Exception e) { } catch (final Exception e) {
throw new IllegalStateException("security initialization failed", e); throw new IllegalStateException("security initialization failed", e);
@ -319,7 +319,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
components.addAll(logstash.createComponents(internalClient, clusterService)); components.addAll(logstash.createComponents(internalClient, clusterService));
components.addAll(upgrade.createComponents(internalClient, clusterService, threadPool, resourceWatcherService, components.addAll(upgrade.createComponents(client, clusterService, threadPool, resourceWatcherService,
scriptService, xContentRegistry)); scriptService, xContentRegistry));
// just create the reloader as it will pull all of the loaded ssl configurations and start watching them // just create the reloader as it will pull all of the loaded ssl configurations and start watching them

View File

@ -27,6 +27,7 @@ import org.elasticsearch.search.SearchHit;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser; import org.elasticsearch.xpack.security.user.XPackUser;
import java.io.IOException; import java.io.IOException;
@ -48,15 +49,21 @@ public class InternalClient extends FilterClient {
private final String nodeName; private final String nodeName;
private final boolean securityEnabled; private final boolean securityEnabled;
private final User user;
/** /**
* Constructs an InternalClient. * Constructs an InternalClient.
* If security is enabled the client is secure. Otherwise this client is a passthrough. * If security is enabled the client is secure. Otherwise this client is a passthrough.
*/ */
public InternalClient(Settings settings, ThreadPool threadPool, Client in) { public InternalClient(Settings settings, ThreadPool threadPool, Client in) {
this(settings, threadPool, in, XPackUser.INSTANCE);
}
InternalClient(Settings settings, ThreadPool threadPool, Client in, User user) {
super(settings, threadPool, in); super(settings, threadPool, in);
this.nodeName = Node.NODE_NAME_SETTING.get(settings); this.nodeName = Node.NODE_NAME_SETTING.get(settings);
this.securityEnabled = XPackSettings.SECURITY_ENABLED.get(settings); this.securityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
this.user = user;
} }
@Override @Override
@ -80,7 +87,7 @@ public class InternalClient extends FilterClient {
protected void processContext(ThreadContext threadContext) { protected void processContext(ThreadContext threadContext) {
try { try {
Authentication authentication = new Authentication(XPackUser.INSTANCE, Authentication authentication = new Authentication(user,
new Authentication.RealmRef("__attach", "__attach", nodeName), null); new Authentication.RealmRef("__attach", "__attach", nodeName), null);
authentication.writeToContext(threadContext); authentication.writeToContext(threadContext);
} catch (IOException ioe) { } catch (IOException ioe) {

View File

@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.user.XPackSecurityUser;
/**
* A special filter client for internal usage by security to modify the security index.
*
* The {@link XPackSecurityUser} user is added to the execution context before each action is executed.
*/
public class InternalSecurityClient extends InternalClient {
public InternalSecurityClient(Settings settings, ThreadPool threadPool, Client in) {
super(settings, threadPool, in, XPackSecurityUser.INSTANCE);
}
}

View File

@ -14,6 +14,7 @@ import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.ActionFilter; import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.action.support.DestructiveOperations; import org.elasticsearch.action.support.DestructiveOperations;
import org.elasticsearch.bootstrap.BootstrapCheck; import org.elasticsearch.bootstrap.BootstrapCheck;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.LocalNodeMasterListener; import org.elasticsearch.cluster.LocalNodeMasterListener;
import org.elasticsearch.cluster.NamedDiff; import org.elasticsearch.cluster.NamedDiff;
@ -295,12 +296,13 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin, Clus
return modules; return modules;
} }
public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, ClusterService clusterService, public Collection<Object> createComponents(Client nodeClient, ThreadPool threadPool, ClusterService clusterService,
ResourceWatcherService resourceWatcherService, ResourceWatcherService resourceWatcherService,
List<XPackExtension> extensions) throws Exception { List<XPackExtension> extensions) throws Exception {
if (enabled == false) { if (enabled == false) {
return Collections.emptyList(); return Collections.emptyList();
} }
final InternalSecurityClient client = new InternalSecurityClient(settings, threadPool, nodeClient);
threadContext.set(threadPool.getThreadContext()); threadContext.set(threadPool.getThreadContext());
List<Object> components = new ArrayList<>(); List<Object> components = new ArrayList<>();
securityContext.set(new SecurityContext(settings, threadPool.getThreadContext())); securityContext.set(new SecurityContext(settings, threadPool.getThreadContext()));

View File

@ -57,7 +57,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
private final IndexLifecycleManager securityIndex; private final IndexLifecycleManager securityIndex;
public SecurityLifecycleService(Settings settings, ClusterService clusterService, public SecurityLifecycleService(Settings settings, ClusterService clusterService,
ThreadPool threadPool, InternalClient client, ThreadPool threadPool, InternalSecurityClient client,
@Nullable IndexAuditTrail indexAuditTrail) { @Nullable IndexAuditTrail indexAuditTrail) {
super(settings); super(settings);
this.settings = settings; this.settings = settings;

View File

@ -48,6 +48,7 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportMessage; import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
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;
@ -177,7 +178,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl
return NAME; return NAME;
} }
public IndexAuditTrail(Settings settings, InternalClient client, ThreadPool threadPool, ClusterService clusterService) { public IndexAuditTrail(Settings settings, InternalSecurityClient client, ThreadPool threadPool, ClusterService clusterService) {
super(settings); super(settings);
this.threadPool = threadPool; this.threadPool = threadPool;
this.clusterService = clusterService; this.clusterService = clusterService;

View File

@ -18,6 +18,7 @@ import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.threadpool.ThreadPool.Names; import org.elasticsearch.threadpool.ThreadPool.Names;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import java.time.Instant; import java.time.Instant;
@ -30,12 +31,12 @@ import static org.elasticsearch.action.support.TransportActions.isShardNotAvaila
*/ */
final class ExpiredTokenRemover extends AbstractRunnable { final class ExpiredTokenRemover extends AbstractRunnable {
private final InternalClient client; private final InternalSecurityClient client;
private final AtomicBoolean inProgress = new AtomicBoolean(false); private final AtomicBoolean inProgress = new AtomicBoolean(false);
private final Logger logger; private final Logger logger;
private final TimeValue timeout; private final TimeValue timeout;
ExpiredTokenRemover(Settings settings, InternalClient internalClient) { ExpiredTokenRemover(Settings settings, InternalSecurityClient internalClient) {
this.client = internalClient; this.client = internalClient;
this.logger = Loggers.getLogger(getClass(), settings); this.logger = Loggers.getLogger(getClass(), settings);
this.timeout = TokenService.DELETE_TIMEOUT.get(settings); this.timeout = TokenService.DELETE_TIMEOUT.get(settings);

View File

@ -50,6 +50,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import javax.crypto.Cipher; import javax.crypto.Cipher;
@ -132,7 +133,7 @@ public final class TokenService extends AbstractComponent {
private final Clock clock; private final Clock clock;
private final TimeValue expirationDelay; private final TimeValue expirationDelay;
private final TimeValue deleteInterval; private final TimeValue deleteInterval;
private final InternalClient internalClient; private final InternalSecurityClient internalClient;
private final SecurityLifecycleService lifecycleService; private final SecurityLifecycleService lifecycleService;
private final ExpiredTokenRemover expiredTokenRemover; private final ExpiredTokenRemover expiredTokenRemover;
private final boolean enabled; private final boolean enabled;
@ -148,7 +149,7 @@ public final class TokenService extends AbstractComponent {
* @param clock the clock that will be used for comparing timestamps * @param clock the clock that will be used for comparing timestamps
* @param internalClient the client to use when checking for revocations * @param internalClient the client to use when checking for revocations
*/ */
public TokenService(Settings settings, Clock clock, InternalClient internalClient, public TokenService(Settings settings, Clock clock, InternalSecurityClient internalClient,
SecurityLifecycleService lifecycleService, ClusterService clusterService) throws GeneralSecurityException { SecurityLifecycleService lifecycleService, ClusterService clusterService) throws GeneralSecurityException {
super(settings); super(settings);
byte[] saltArr = new byte[SALT_BYTES]; byte[] saltArr = new byte[SALT_BYTES];

View File

@ -36,6 +36,7 @@ import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest;
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheResponse; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheResponse;
@ -73,12 +74,12 @@ public class NativeUsersStore extends AbstractComponent {
private final Hasher hasher = Hasher.BCRYPT; private final Hasher hasher = Hasher.BCRYPT;
private final InternalClient client; private final InternalSecurityClient client;
private final boolean isTribeNode; private final boolean isTribeNode;
private volatile SecurityLifecycleService securityLifecycleService; private volatile SecurityLifecycleService securityLifecycleService;
public NativeUsersStore(Settings settings, InternalClient client, SecurityLifecycleService securityLifecycleService) { public NativeUsersStore(Settings settings, InternalSecurityClient client, SecurityLifecycleService securityLifecycleService) {
super(settings); super(settings);
this.client = client; this.client = client;
this.isTribeNode = XPackPlugin.isTribeNode(settings); this.isTribeNode = XPackPlugin.isTribeNode(settings);

View File

@ -38,6 +38,7 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.action.rolemapping.DeleteRoleMappingRequest; import org.elasticsearch.xpack.security.action.rolemapping.DeleteRoleMappingRequest;
import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingRequest; import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingRequest;
@ -70,12 +71,12 @@ public class NativeRoleMappingStore extends AbstractComponent implements UserRol
private static final String SECURITY_GENERIC_TYPE = "doc"; private static final String SECURITY_GENERIC_TYPE = "doc";
private final InternalClient client; private final InternalSecurityClient client;
private final boolean isTribeNode; private final boolean isTribeNode;
private final SecurityLifecycleService securityLifecycleService; private final SecurityLifecycleService securityLifecycleService;
private final List<String> realmsToRefresh = new CopyOnWriteArrayList<>(); private final List<String> realmsToRefresh = new CopyOnWriteArrayList<>();
public NativeRoleMappingStore(Settings settings, InternalClient client, SecurityLifecycleService securityLifecycleService) { public NativeRoleMappingStore(Settings settings, InternalSecurityClient client, SecurityLifecycleService securityLifecycleService) {
super(settings); super(settings);
this.client = client; this.client = client;
this.isTribeNode = XPackPlugin.isTribeNode(settings); this.isTribeNode = XPackPlugin.isTribeNode(settings);

View File

@ -68,6 +68,7 @@ import org.elasticsearch.xpack.security.support.Automatons;
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;
import org.elasticsearch.xpack.security.user.XPackSecurityUser;
import org.elasticsearch.xpack.security.user.XPackUser; import org.elasticsearch.xpack.security.user.XPackUser;
import static org.elasticsearch.xpack.security.Security.setting; import static org.elasticsearch.xpack.security.Security.setting;
@ -290,7 +291,6 @@ public class AuthorizationService extends AbstractComponent {
throw denial(authentication, action, request); throw denial(authentication, action, request);
} else if (indicesAccessControl.getIndexPermissions(SecurityLifecycleService.SECURITY_INDEX_NAME) != null } else if (indicesAccessControl.getIndexPermissions(SecurityLifecycleService.SECURITY_INDEX_NAME) != null
&& indicesAccessControl.getIndexPermissions(SecurityLifecycleService.SECURITY_INDEX_NAME).isGranted() && indicesAccessControl.getIndexPermissions(SecurityLifecycleService.SECURITY_INDEX_NAME).isGranted()
&& XPackUser.is(authentication.getUser()) == false
&& MONITOR_INDEX_PREDICATE.test(action) == false && MONITOR_INDEX_PREDICATE.test(action) == false
&& isSuperuser(authentication.getUser()) == false) { && isSuperuser(authentication.getUser()) == false) {
// only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging // only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging
@ -392,7 +392,11 @@ public class AuthorizationService extends AbstractComponent {
" roles"); " roles");
} }
if (XPackUser.is(user)) { if (XPackUser.is(user)) {
assert XPackUser.INSTANCE.roles().length == 1 && ReservedRolesStore.SUPERUSER_ROLE.name().equals(XPackUser.INSTANCE.roles()[0]); assert XPackUser.INSTANCE.roles().length == 1;
roleActionListener.onResponse(XPackUser.ROLE);
return;
}
if (XPackSecurityUser.is(user)) {
roleActionListener.onResponse(ReservedRolesStore.SUPERUSER_ROLE); roleActionListener.onResponse(ReservedRolesStore.SUPERUSER_ROLE);
return; return;
} }

View File

@ -38,6 +38,7 @@ import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest; import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest;
import org.elasticsearch.xpack.security.action.role.ClearRolesCacheResponse; import org.elasticsearch.xpack.security.action.role.ClearRolesCacheResponse;
@ -79,14 +80,14 @@ public class NativeRolesStore extends AbstractComponent {
TimeValue.timeValueMinutes(20), Property.NodeScope, Property.Deprecated); TimeValue.timeValueMinutes(20), Property.NodeScope, Property.Deprecated);
private static final String ROLE_DOC_TYPE = "doc"; private static final String ROLE_DOC_TYPE = "doc";
private final InternalClient client; private final InternalSecurityClient client;
private final XPackLicenseState licenseState; private final XPackLicenseState licenseState;
private final boolean isTribeNode; private final boolean isTribeNode;
private SecurityClient securityClient; private SecurityClient securityClient;
private final SecurityLifecycleService securityLifecycleService; private final SecurityLifecycleService securityLifecycleService;
public NativeRolesStore(Settings settings, InternalClient client, XPackLicenseState licenseState, public NativeRolesStore(Settings settings, InternalSecurityClient client, XPackLicenseState licenseState,
SecurityLifecycleService securityLifecycleService) { SecurityLifecycleService securityLifecycleService) {
super(settings); super(settings);
this.client = client; this.client = client;

View File

@ -12,6 +12,7 @@ import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.support.MetadataUtils; import org.elasticsearch.xpack.security.support.MetadataUtils;
import org.elasticsearch.xpack.security.user.KibanaUser; import org.elasticsearch.xpack.security.user.KibanaUser;
import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.elasticsearch.xpack.watcher.execution.TriggeredWatchStore; import org.elasticsearch.xpack.watcher.execution.TriggeredWatchStore;
import org.elasticsearch.xpack.watcher.history.HistoryStore; import org.elasticsearch.xpack.watcher.history.HistoryStore;
import org.elasticsearch.xpack.watcher.watch.Watch; import org.elasticsearch.xpack.watcher.watch.Watch;
@ -126,7 +127,7 @@ public class ReservedRolesStore {
} }
public static boolean isReserved(String role) { public static boolean isReserved(String role) {
return RESERVED_ROLES.containsKey(role) || SystemUser.ROLE_NAME.equals(role); return RESERVED_ROLES.containsKey(role) || SystemUser.ROLE_NAME.equals(role) || XPackUser.ROLE_NAME.equals(role);
} }
} }

View File

@ -38,6 +38,7 @@ import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.template.TemplateUtils; import org.elasticsearch.xpack.template.TemplateUtils;
import org.elasticsearch.xpack.upgrade.IndexUpgradeCheck; import org.elasticsearch.xpack.upgrade.IndexUpgradeCheck;
@ -58,7 +59,7 @@ public class IndexLifecycleManager extends AbstractComponent {
private final String indexName; private final String indexName;
private final String templateName; private final String templateName;
private final InternalClient client; private final InternalSecurityClient client;
private final List<BiConsumer<ClusterIndexHealth, ClusterIndexHealth>> indexHealthChangeListeners = new CopyOnWriteArrayList<>(); private final List<BiConsumer<ClusterIndexHealth, ClusterIndexHealth>> indexHealthChangeListeners = new CopyOnWriteArrayList<>();
@ -70,7 +71,7 @@ public class IndexLifecycleManager extends AbstractComponent {
private volatile boolean mappingIsUpToDate; private volatile boolean mappingIsUpToDate;
private volatile Version mappingVersion; private volatile Version mappingVersion;
public IndexLifecycleManager(Settings settings, InternalClient client, String indexName, String templateName) { public IndexLifecycleManager(Settings settings, InternalSecurityClient client, String indexName, String templateName) {
super(settings); super(settings);
this.client = client; this.client = client;
this.indexName = indexName; this.indexName = indexName;

View File

@ -184,6 +184,8 @@ public class User implements ToXContentObject {
return SystemUser.INSTANCE; return SystemUser.INSTANCE;
} else if (XPackUser.is(username)) { } else if (XPackUser.is(username)) {
return XPackUser.INSTANCE; return XPackUser.INSTANCE;
} else if (XPackSecurityUser.is(username)) {
return XPackSecurityUser.INSTANCE;
} }
throw new IllegalStateException("user [" + username + "] is not an internal user"); throw new IllegalStateException("user [" + username + "] is not an internal user");
} }
@ -214,6 +216,9 @@ public class User implements ToXContentObject {
} else if (XPackUser.is(user)) { } else if (XPackUser.is(user)) {
output.writeBoolean(true); output.writeBoolean(true);
output.writeString(XPackUser.NAME); output.writeString(XPackUser.NAME);
} else if (XPackSecurityUser.is(user)) {
output.writeBoolean(true);
output.writeString(XPackSecurityUser.NAME);
} else { } else {
if (user.authenticatedUser == null) { if (user.authenticatedUser == null) {
// no backcompat necessary, since there is no inner user // no backcompat necessary, since there is no inner user

View File

@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security.user;
/**
* internal user that manages xpack security. Has all cluster/indices permissions.
*/
public class XPackSecurityUser extends User {
public static final String NAME = "_xpack_security";
public static final XPackSecurityUser INSTANCE = new XPackSecurityUser();
private static final String ROLE_NAME = "superuser";
private XPackSecurityUser() {
super(NAME, ROLE_NAME);
}
@Override
public boolean equals(Object o) {
return INSTANCE == o;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
public static boolean is(User user) {
return INSTANCE.equals(user);
}
public static boolean is(String principal) {
return NAME.equals(principal);
}
}

View File

@ -5,13 +5,22 @@
*/ */
package org.elasticsearch.xpack.security.user; package org.elasticsearch.xpack.security.user;
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.support.MetadataUtils;
/** /**
* XPack internal user that manages xpack. Has all cluster/indices permissions for x-pack to operate. * XPack internal user that manages xpack. Has all cluster/indices permissions for x-pack to operate excluding security permissions.
*/ */
public class XPackUser extends User { public class XPackUser extends User {
public static final String NAME = "_xpack"; public static final String NAME = "_xpack";
private static final String ROLE_NAME = "superuser"; public static final String ROLE_NAME = NAME;
public static final Role ROLE = Role.builder(new RoleDescriptor(ROLE_NAME, new String[] { "all" },
new RoleDescriptor.IndicesPrivileges[] {
RoleDescriptor.IndicesPrivileges.builder().indices("/@&~(\\.security*)/").privileges("all").build()},
new String[] { "*" },
MetadataUtils.DEFAULT_RESERVED_METADATA), null).build();
public static final XPackUser INSTANCE = new XPackUser(); public static final XPackUser INSTANCE = new XPackUser();
private XPackUser() { private XPackUser() {

View File

@ -8,6 +8,7 @@ package org.elasticsearch.xpack.upgrade;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.node.DiscoveryNodes;
@ -24,6 +25,7 @@ import org.elasticsearch.script.ScriptService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeAction; import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeAction;
import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeInfoAction; import org.elasticsearch.xpack.upgrade.actions.IndexUpgradeInfoAction;
import org.elasticsearch.xpack.upgrade.rest.RestIndexUpgradeAction; import org.elasticsearch.xpack.upgrade.rest.RestIndexUpgradeAction;
@ -53,12 +55,13 @@ public class Upgrade implements ActionPlugin {
this.upgradeCheckFactories = new ArrayList<>(); this.upgradeCheckFactories = new ArrayList<>();
} }
public Collection<Object> createComponents(InternalClient internalClient, ClusterService clusterService, ThreadPool threadPool, public Collection<Object> createComponents(Client client, ClusterService clusterService, ThreadPool threadPool,
ResourceWatcherService resourceWatcherService, ScriptService scriptService, ResourceWatcherService resourceWatcherService, ScriptService scriptService,
NamedXContentRegistry xContentRegistry) { NamedXContentRegistry xContentRegistry) {
final InternalSecurityClient internalSecurityClient = new InternalSecurityClient(settings, threadPool, client);
List<IndexUpgradeCheck> upgradeChecks = new ArrayList<>(upgradeCheckFactories.size()); List<IndexUpgradeCheck> upgradeChecks = new ArrayList<>(upgradeCheckFactories.size());
for (BiFunction<InternalClient, ClusterService, IndexUpgradeCheck> checkFactory : upgradeCheckFactories) { for (BiFunction<InternalClient, ClusterService, IndexUpgradeCheck> checkFactory : upgradeCheckFactories) {
upgradeChecks.add(checkFactory.apply(internalClient, clusterService)); upgradeChecks.add(checkFactory.apply(internalSecurityClient, clusterService));
} }
return Collections.singletonList(new IndexUpgradeService(settings, Collections.unmodifiableList(upgradeChecks))); return Collections.singletonList(new IndexUpgradeService(settings, Collections.unmodifiableList(upgradeChecks)));
} }

View File

@ -35,6 +35,7 @@ import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.ml.MachineLearning; import org.elasticsearch.xpack.ml.MachineLearning;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -438,6 +439,11 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
return internalCluster().getInstance(InternalClient.class); return internalCluster().getInstance(InternalClient.class);
} }
protected InternalSecurityClient internalSecurityClient() {
Client client = client();
return new InternalSecurityClient(client.settings(), client.threadPool(), client);
}
protected SecurityClient securityClient() { protected SecurityClient securityClient() {
return securityClient(client()); return securityClient(client());
} }

View File

@ -64,7 +64,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
threadPool = new TestThreadPool("security template service tests"); threadPool = new TestThreadPool("security template service tests");
transportClient = new MockTransportClient(Settings.EMPTY); transportClient = new MockTransportClient(Settings.EMPTY);
class IClient extends InternalClient { class IClient extends InternalSecurityClient {
IClient(Client transportClient) { IClient(Client transportClient) {
super(Settings.EMPTY, null, transportClient); super(Settings.EMPTY, null, transportClient);
} }
@ -79,7 +79,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase {
} }
} }
InternalClient client = new IClient(transportClient); InternalSecurityClient client = new IClient(transportClient);
securityLifecycleService = new SecurityLifecycleService(Settings.EMPTY, clusterService, securityLifecycleService = new SecurityLifecycleService(Settings.EMPTY, clusterService,
threadPool, client, mock(IndexAuditTrail.class)); threadPool, client, mock(IndexAuditTrail.class));
listeners = new CopyOnWriteArrayList<>(); listeners = new CopyOnWriteArrayList<>();

View File

@ -77,9 +77,9 @@ public class SecurityTests extends ESTestCase {
allowedSettings.addAll(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); allowedSettings.addAll(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
ClusterSettings clusterSettings = new ClusterSettings(settings, allowedSettings); ClusterSettings clusterSettings = new ClusterSettings(settings, allowedSettings);
when(clusterService.getClusterSettings()).thenReturn(clusterSettings); when(clusterService.getClusterSettings()).thenReturn(clusterSettings);
InternalClient client = new InternalClient(Settings.EMPTY, threadPool, mock(Client.class));
when(threadPool.relativeTimeInMillis()).thenReturn(1L); when(threadPool.relativeTimeInMillis()).thenReturn(1L);
return security.createComponents(client, threadPool, clusterService, mock(ResourceWatcherService.class), Arrays.asList(extensions)); return security.createComponents(mock(Client.class), threadPool, clusterService, mock(ResourceWatcherService.class),
Arrays.asList(extensions));
} }
private <T> T findComponent(Class<T> type, Collection<Object> components) { private <T> T findComponent(Class<T> type, Collection<Object> components) {

View File

@ -141,7 +141,7 @@ public class AuditTrailTests extends SecurityIntegTestCase {
return eventsRef.get(); return eventsRef.get();
} }
private Collection<Map<String, Object>> getAuditEvents() throws Exception { private Collection<Map<String, Object>> getAuditEvents() throws Exception {
final InternalClient client = internalClient(); final InternalClient client = internalSecurityClient();
DateTime now = new DateTime(DateTimeZone.UTC); DateTime now = new DateTime(DateTimeZone.UTC);
String indexName = IndexNameResolver.resolve(IndexAuditTrail.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY); String indexName = IndexNameResolver.resolve(IndexAuditTrail.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY);

View File

@ -27,6 +27,7 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.MockTransportClient; import org.elasticsearch.transport.MockTransportClient;
import org.elasticsearch.transport.TransportMessage; import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail.State; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail.State;
import org.elasticsearch.xpack.security.authc.AuthenticationToken; import org.elasticsearch.xpack.security.authc.AuthenticationToken;
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule; import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
@ -42,7 +43,7 @@ import static org.mockito.Mockito.when;
public class IndexAuditTrailMutedTests extends ESTestCase { public class IndexAuditTrailMutedTests extends ESTestCase {
private InternalClient client; private InternalSecurityClient client;
private TransportClient transportClient; private TransportClient transportClient;
private ThreadPool threadPool; private ThreadPool threadPool;
private ClusterService clusterService; private ClusterService clusterService;
@ -61,7 +62,7 @@ public class IndexAuditTrailMutedTests extends ESTestCase {
threadPool = new TestThreadPool("index audit trail tests"); threadPool = new TestThreadPool("index audit trail tests");
transportClient = new MockTransportClient(Settings.EMPTY); transportClient = new MockTransportClient(Settings.EMPTY);
clientCalled = new AtomicBoolean(false); clientCalled = new AtomicBoolean(false);
class IClient extends InternalClient { class IClient extends InternalSecurityClient {
IClient(Client transportClient){ IClient(Client transportClient){
super(Settings.EMPTY, threadPool, transportClient); super(Settings.EMPTY, threadPool, transportClient);
} }

View File

@ -295,7 +295,7 @@ public class IndexAuditTrailTests extends SecurityIntegTestCase {
when(nodes.isLocalNodeElectedMaster()).thenReturn(true); when(nodes.isLocalNodeElectedMaster()).thenReturn(true);
threadPool = new TestThreadPool("index audit trail tests"); threadPool = new TestThreadPool("index audit trail tests");
enqueuedMessage = new SetOnce<>(); enqueuedMessage = new SetOnce<>();
auditor = new IndexAuditTrail(settings, internalClient(), threadPool, clusterService) { auditor = new IndexAuditTrail(settings, internalSecurityClient(), threadPool, clusterService) {
@Override @Override
void enqueue(Message message, String type) { void enqueue(Message message, String type) {
enqueuedMessage.set(message); enqueuedMessage.set(message);

View File

@ -50,7 +50,7 @@ public class IndexAuditTrailUpdateMappingTests extends SecurityIntegTestCase {
when(localNode.getHostAddress()).thenReturn(buildNewFakeTransportAddress().toString()); when(localNode.getHostAddress()).thenReturn(buildNewFakeTransportAddress().toString());
ClusterService clusterService = mock(ClusterService.class); ClusterService clusterService = mock(ClusterService.class);
when(clusterService.localNode()).thenReturn(localNode); when(clusterService.localNode()).thenReturn(localNode);
auditor = new IndexAuditTrail(settings, internalClient(), threadPool, clusterService); auditor = new IndexAuditTrail(settings, internalSecurityClient(), threadPool, clusterService);
// before starting we add an event // before starting we add an event
auditor.authenticationFailed(new FakeRestRequest()); auditor.authenticationFailed(new FakeRestRequest());

View File

@ -48,6 +48,7 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportMessage; import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
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;
@ -135,7 +136,7 @@ public class AuthenticationServiceTests extends ESTestCase {
threadPool = new ThreadPool(settings, threadPool = new ThreadPool(settings,
new FixedExecutorBuilder(settings, TokenService.THREAD_POOL_NAME, 1, 1000, "xpack.security.authc.token.thread_pool")); new FixedExecutorBuilder(settings, TokenService.THREAD_POOL_NAME, 1, 1000, "xpack.security.authc.token.thread_pool"));
threadContext = threadPool.getThreadContext(); threadContext = threadPool.getThreadContext();
InternalClient internalClient = new InternalClient(Settings.EMPTY, threadPool, client); InternalSecurityClient internalClient = new InternalSecurityClient(Settings.EMPTY, threadPool, client);
lifecycleService = mock(SecurityLifecycleService.class); lifecycleService = mock(SecurityLifecycleService.class);
ClusterService clusterService = new ClusterService(settings, new ClusterSettings(settings, ClusterSettings ClusterService clusterService = new ClusterService(settings, new ClusterSettings(settings, ClusterSettings
.BUILT_IN_CLUSTER_SETTINGS), threadPool, Collections.emptyMap()); .BUILT_IN_CLUSTER_SETTINGS), threadPool, Collections.emptyMap());

View File

@ -56,7 +56,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
} }
public void testTokenServiceBootstrapOnNodeJoin() throws Exception { public void testTokenServiceBootstrapOnNodeJoin() throws Exception {
final Client client = internalClient(); final Client client = internalSecurityClient();
SecurityClient securityClient = new SecurityClient(client); SecurityClient securityClient = new SecurityClient(client);
CreateTokenResponse response = securityClient.prepareCreateToken() CreateTokenResponse response = securityClient.prepareCreateToken()
.setGrantType("password") .setGrantType("password")
@ -84,7 +84,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
public void testTokenServiceCanRotateKeys() throws Exception { public void testTokenServiceCanRotateKeys() throws Exception {
final Client client = internalClient(); final Client client = internalSecurityClient();
SecurityClient securityClient = new SecurityClient(client); SecurityClient securityClient = new SecurityClient(client);
CreateTokenResponse response = securityClient.prepareCreateToken() CreateTokenResponse response = securityClient.prepareCreateToken()
.setGrantType("password") .setGrantType("password")
@ -116,7 +116,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
} }
public void testExpiredTokensDeletedAfterExpiration() throws Exception { public void testExpiredTokensDeletedAfterExpiration() throws Exception {
final Client client = internalClient(); final Client client = internalSecurityClient();
SecurityClient securityClient = new SecurityClient(client); SecurityClient securityClient = new SecurityClient(client);
CreateTokenResponse response = securityClient.prepareCreateToken() CreateTokenResponse response = securityClient.prepareCreateToken()
.setGrantType("password") .setGrantType("password")

View File

@ -24,6 +24,7 @@ import org.elasticsearch.threadpool.FixedExecutorBuilder;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.security.authc.TokenService.BytesKey; import org.elasticsearch.xpack.security.authc.TokenService.BytesKey;
@ -49,7 +50,7 @@ import static org.mockito.Mockito.when;
public class TokenServiceTests extends ESTestCase { public class TokenServiceTests extends ESTestCase {
private InternalClient internalClient; private InternalSecurityClient internalClient;
private static ThreadPool threadPool; private static ThreadPool threadPool;
private static final Settings settings = Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "TokenServiceTests") private static final Settings settings = Settings.builder().put(Node.NODE_NAME_SETTING.getKey(), "TokenServiceTests")
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build(); .put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
@ -63,7 +64,7 @@ public class TokenServiceTests extends ESTestCase {
@Before @Before
public void setupClient() throws GeneralSecurityException { public void setupClient() throws GeneralSecurityException {
client = mock(Client.class); client = mock(Client.class);
internalClient = new InternalClient(settings, threadPool, client); internalClient = new InternalSecurityClient(settings, threadPool, client);
lifecycleService = mock(SecurityLifecycleService.class); lifecycleService = mock(SecurityLifecycleService.class);
when(lifecycleService.isSecurityIndexWriteable()).thenReturn(true); when(lifecycleService.isSecurityIndexWriteable()).thenReturn(true);
doAnswer(invocationOnMock -> { doAnswer(invocationOnMock -> {

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.authc.AuthenticationResult;
import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.Hasher;
@ -54,12 +55,12 @@ public class NativeUsersStoreTests extends ESTestCase {
private static final String PASSWORD_FIELD = User.Fields.PASSWORD.getPreferredName(); private static final String PASSWORD_FIELD = User.Fields.PASSWORD.getPreferredName();
private static final String BLANK_PASSWORD = ""; private static final String BLANK_PASSWORD = "";
private InternalClient internalClient; private InternalSecurityClient internalClient;
private final List<Tuple<ActionRequest, ActionListener<? extends ActionResponse>>> requests = new CopyOnWriteArrayList<>(); private final List<Tuple<ActionRequest, ActionListener<? extends ActionResponse>>> requests = new CopyOnWriteArrayList<>();
@Before @Before
public void setupMocks() { public void setupMocks() {
internalClient = new InternalClient(Settings.EMPTY, null, null) { internalClient = new InternalSecurityClient(Settings.EMPTY, null, null) {
@Override @Override
protected < protected <

View File

@ -17,6 +17,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.RealmConfig;
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
@ -53,7 +54,7 @@ public class NativeUserRoleMapperTests extends ESTestCase {
Collections.singletonList(FieldPredicate.create("cn=mutants,ou=groups,ou=dept_h,o=forces,dc=gc,dc=ca"))), Collections.singletonList(FieldPredicate.create("cn=mutants,ou=groups,ou=dept_h,o=forces,dc=gc,dc=ca"))),
Arrays.asList("mutants"), Collections.emptyMap(), false); Arrays.asList("mutants"), Collections.emptyMap(), false);
final InternalClient client = mock(InternalClient.class); final InternalSecurityClient client = mock(InternalSecurityClient.class);
final SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class); final SecurityLifecycleService lifecycleService = mock(SecurityLifecycleService.class);
when(lifecycleService.isSecurityIndexAvailable()).thenReturn(true); when(lifecycleService.isSecurityIndexAvailable()).thenReturn(true);

View File

@ -715,7 +715,7 @@ public class AuthorizationServiceTests extends ESTestCase {
} }
} }
public void testXPackUserAndSuperusersCanExecuteOperationAgainstSecurityIndex() { public void testSuperusersCanExecuteOperationAgainstSecurityIndex() {
final User superuser = new User("custom_admin", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()); final User superuser = new User("custom_admin", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName());
roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR); roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR);
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
@ -726,7 +726,6 @@ public class AuthorizationServiceTests extends ESTestCase {
.numberOfShards(1).numberOfReplicas(0).build(), true) .numberOfShards(1).numberOfReplicas(0).build(), true)
.build()); .build());
for (User user : Arrays.asList(XPackUser.INSTANCE, superuser)) {
List<Tuple<String, TransportRequest>> requests = new ArrayList<>(); List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(SecurityLifecycleService.SECURITY_INDEX_NAME, "type", "id")));
requests.add(new Tuple<>(BulkAction.NAME + "[s]", requests.add(new Tuple<>(BulkAction.NAME + "[s]",
@ -750,13 +749,12 @@ public class AuthorizationServiceTests extends ESTestCase {
for (Tuple<String, TransportRequest> requestTuple : requests) { for (Tuple<String, TransportRequest> requestTuple : requests) {
String action = requestTuple.v1(); String action = requestTuple.v1();
TransportRequest request = requestTuple.v2(); TransportRequest request = requestTuple.v2();
authorize(createAuthentication(user), action, request); authorize(createAuthentication(superuser), action, request);
verify(auditTrail).accessGranted(user, action, request); verify(auditTrail).accessGranted(superuser, action, request);
}
} }
} }
public void testXPackUserAndSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() { public void testSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() {
final User superuser = new User("custom_admin", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName()); final User superuser = new User("custom_admin", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName());
roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR); roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR);
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
@ -769,11 +767,6 @@ 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(XPackUser.INSTANCE), action, request);
verify(auditTrail).accessGranted(XPackUser.INSTANCE, action, request);
assertThat(request.indices(), arrayContaining(".security"));
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);
assertThat(request.indices(), arrayContaining(".security")); assertThat(request.indices(), arrayContaining(".security"));
@ -1073,7 +1066,7 @@ public class AuthorizationServiceTests extends ESTestCase {
PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>(); PlainActionFuture<Role> rolesFuture = new PlainActionFuture<>();
authorizationService.roles(XPackUser.INSTANCE, rolesFuture); authorizationService.roles(XPackUser.INSTANCE, rolesFuture);
final Role roles = rolesFuture.actionGet(); final Role roles = rolesFuture.actionGet();
assertThat(roles, equalTo(ReservedRolesStore.SUPERUSER_ROLE)); assertThat(roles, equalTo(XPackUser.ROLE));
verifyZeroInteractions(rolesStore); verifyZeroInteractions(rolesStore);
} }

View File

@ -69,6 +69,7 @@ import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.elasticsearch.xpack.security.test.SecurityTestUtils;
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;
import org.elasticsearch.xpack.security.user.XPackSecurityUser;
import org.elasticsearch.xpack.security.user.XPackUser; import org.elasticsearch.xpack.security.user.XPackUser;
import org.junit.Before; import org.junit.Before;
@ -1191,22 +1192,29 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
} }
} }
public void testXPackUserHasAccessToSecurityIndex() { public void testXPackSecurityUserHasAccessToSecurityIndex() {
SearchRequest request = new SearchRequest(); SearchRequest request = new SearchRequest();
{ {
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal(); List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME)); assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME));
} }
{ {
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest();
aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SecurityLifecycleService.SECURITY_INDEX_NAME)); aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SecurityLifecycleService.SECURITY_INDEX_NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, IndicesAliasesAction.NAME); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME)); assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME));
} }
} }
public void testXPackUserDoesNotHaveAccessToSecurityIndex() {
SearchRequest request = new SearchRequest();
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME)));
}
public void testNonXPackUserAccessingSecurityIndex() { public void testNonXPackUserAccessingSecurityIndex() {
User allAccessUser = new User("all_access", "all_access"); User allAccessUser = new User("all_access", "all_access");
roleMap.put("all_access", new RoleDescriptor("all_access", new String[] { "all" }, roleMap.put("all_access", new RoleDescriptor("all_access", new String[] { "all" },

View File

@ -38,6 +38,7 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.SecurityLifecycleService; import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.action.role.PutRoleRequest; import org.elasticsearch.xpack.security.action.role.PutRoleRequest;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
@ -184,7 +185,7 @@ public class NativeRolesStoreTests extends ESTestCase {
} }
public void testPutOfRoleWithFlsDlsUnlicensed() throws IOException { public void testPutOfRoleWithFlsDlsUnlicensed() throws IOException {
final InternalClient internalClient = mock(InternalClient.class); final InternalSecurityClient internalClient = mock(InternalSecurityClient.class);
final ClusterService clusterService = mock(ClusterService.class); final ClusterService clusterService = mock(ClusterService.class);
final XPackLicenseState licenseState = mock(XPackLicenseState.class); final XPackLicenseState licenseState = mock(XPackLicenseState.class);
final AtomicBoolean methodCalled = new AtomicBoolean(false); final AtomicBoolean methodCalled = new AtomicBoolean(false);

View File

@ -80,6 +80,7 @@ import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl
import org.elasticsearch.xpack.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.security.authz.permission.FieldPermissionsCache;
import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.elasticsearch.xpack.watcher.execution.TriggeredWatchStore; import org.elasticsearch.xpack.watcher.execution.TriggeredWatchStore;
import org.elasticsearch.xpack.watcher.history.HistoryStore; import org.elasticsearch.xpack.watcher.history.HistoryStore;
import org.elasticsearch.xpack.watcher.transport.actions.ack.AckWatchAction; import org.elasticsearch.xpack.watcher.transport.actions.ack.AckWatchAction;
@ -123,6 +124,7 @@ public class ReservedRolesStoreTests extends ESTestCase {
assertThat(ReservedRolesStore.isReserved("watcher_user"), is(true)); assertThat(ReservedRolesStore.isReserved("watcher_user"), is(true));
assertThat(ReservedRolesStore.isReserved("watcher_admin"), is(true)); assertThat(ReservedRolesStore.isReserved("watcher_admin"), is(true));
assertThat(ReservedRolesStore.isReserved("kibana_dashboard_only_user"), is(true)); assertThat(ReservedRolesStore.isReserved("kibana_dashboard_only_user"), is(true));
assertThat(ReservedRolesStore.isReserved(XPackUser.ROLE_NAME), is(true));
} }
public void testIngestAdminRole() { public void testIngestAdminRole() {

View File

@ -45,6 +45,7 @@ import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.InternalSecurityClient;
import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.elasticsearch.xpack.security.test.SecurityTestUtils;
import org.elasticsearch.xpack.template.TemplateUtils; import org.elasticsearch.xpack.template.TemplateUtils;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -71,7 +72,7 @@ public class IndexLifecycleManagerTests extends ESTestCase {
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY)); when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
actions = new LinkedHashMap<>(); actions = new LinkedHashMap<>();
final InternalClient client = new InternalClient(Settings.EMPTY, threadPool, mockClient) { final InternalSecurityClient client = new InternalSecurityClient(Settings.EMPTY, threadPool, mockClient) {
@Override @Override
protected <Request extends ActionRequest, protected <Request extends ActionRequest,
Response extends ActionResponse, Response extends ActionResponse,