Internal: Remove guice from authentication and authorization services

This change removes guice from most of the rest of security. It also
converts the last use of onModule in xpack extensions to a pull based
extension.

Original commit: elastic/x-pack-elasticsearch@9de072550e
This commit is contained in:
Ryan Ernst 2016-07-19 15:57:29 -07:00
parent 4b4e7158eb
commit f05005f667
22 changed files with 220 additions and 336 deletions

View File

@ -7,7 +7,7 @@ package org.elasticsearch.example;
import org.elasticsearch.example.realm.CustomAuthenticationFailureHandler; import org.elasticsearch.example.realm.CustomAuthenticationFailureHandler;
import org.elasticsearch.example.realm.CustomRealm; import org.elasticsearch.example.realm.CustomRealm;
import org.elasticsearch.xpack.security.authc.AuthenticationModule; import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.extensions.XPackExtension; import org.elasticsearch.xpack.extensions.XPackExtension;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
@ -38,15 +38,16 @@ public class ExampleRealmExtension extends XPackExtension {
return "a very basic implementation of a custom realm to validate it works"; return "a very basic implementation of a custom realm to validate it works";
} }
public void onModule(AuthenticationModule authenticationModule) {
authenticationModule.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler.class);
}
@Override @Override
public Map<String, Realm.Factory> getRealms() { public Map<String, Realm.Factory> getRealms() {
return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new); return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new);
} }
@Override
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
@Override @Override
public Collection<String> getRestHeaders() { public Collection<String> getRestHeaders() {
return Arrays.asList(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER); return Arrays.asList(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);

View File

@ -74,7 +74,8 @@ import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail; import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail;
import org.elasticsearch.xpack.security.authc.AuthenticationModule; import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.Realms;
@ -88,13 +89,14 @@ import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm; import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.SecuredString;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.security.authz.AuthorizationModule;
import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor; import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor;
import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache; import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache;
import org.elasticsearch.xpack.security.authz.accesscontrol.SecurityIndexSearcherWrapper; import org.elasticsearch.xpack.security.authz.accesscontrol.SecurityIndexSearcherWrapper;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.authz.store.FileRolesStore; import org.elasticsearch.xpack.security.authz.store.FileRolesStore;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.security.crypto.CryptoService; import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.security.rest.SecurityRestModule; import org.elasticsearch.xpack.security.rest.SecurityRestModule;
import org.elasticsearch.xpack.security.rest.action.RestAuthenticateAction; import org.elasticsearch.xpack.security.rest.action.RestAuthenticateAction;
@ -183,7 +185,6 @@ public class Security implements ActionPlugin, IngestPlugin {
if (enabled == false) { if (enabled == false) {
return modules; return modules;
} }
modules.add(new SecurityModule(settings));
modules.add(new SecurityTransportModule(settings)); modules.add(new SecurityTransportModule(settings));
modules.add(b -> { modules.add(b -> {
// for transport client we still must inject these ssl classes with guice // for transport client we still must inject these ssl classes with guice
@ -194,16 +195,16 @@ public class Security implements ActionPlugin, IngestPlugin {
return modules; return modules;
} }
modules.add(b -> XPackPlugin.bindFeatureSet(b, SecurityFeatureSet.class));
modules.add(new AuthenticationModule(settings));
modules.add(new AuthorizationModule(settings));
if (enabled == false) { if (enabled == false) {
modules.add(b -> { modules.add(b -> {
b.bind(CryptoService.class).toProvider(Providers.of(null)); b.bind(CryptoService.class).toProvider(Providers.of(null));
b.bind(Realms.class).toProvider(Providers.of(null)); // for SecurityFeatureSet
b.bind(CompositeRolesStore.class).toProvider(Providers.of(null)); // for SecurityFeatureSet
b.bind(AuditTrailService.class) b.bind(AuditTrailService.class)
.toInstance(new AuditTrailService(settings, Collections.emptyList(), securityLicenseState)); .toInstance(new AuditTrailService(settings, Collections.emptyList(), securityLicenseState));
}); });
modules.add(new SecurityModule(settings));
modules.add(new SecurityTransportModule(settings)); modules.add(new SecurityTransportModule(settings));
return modules; return modules;
} }
@ -216,32 +217,20 @@ public class Security implements ActionPlugin, IngestPlugin {
if (auditingEnabled(settings)) { if (auditingEnabled(settings)) {
b.bind(AuditTrail.class).to(AuditTrailService.class); // interface used by some actions... b.bind(AuditTrail.class).to(AuditTrailService.class); // interface used by some actions...
} }
if (indexAuditLoggingEnabled(settings) == false) {
// TODO: remove this once we can construct SecurityLifecycleService without guice
b.bind(IndexAuditTrail.class).toProvider(Providers.of(null));
}
}); });
modules.add(new SecurityModule(settings));
modules.add(new SecurityRestModule(settings)); modules.add(new SecurityRestModule(settings));
modules.add(new SecurityActionModule(settings)); modules.add(new SecurityActionModule(settings));
modules.add(new SecurityTransportModule(settings)); modules.add(new SecurityTransportModule(settings));
return modules; return modules;
} }
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
if (enabled == false || transportClientMode == true) {
return Collections.emptyList();
}
List<Class<? extends LifecycleComponent>> list = new ArrayList<>();
list.add(FileRolesStore.class);
return list;
}
public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, ClusterService clusterService, public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool, ClusterService clusterService,
ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) { ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) {
if (enabled == false) { if (enabled == false) {
return Collections.emptyList(); return Collections.emptyList();
} }
AnonymousUser.initialize(settings); // TODO: this is sketchy...testing is difficult b/c it is static....
List<Object> components = new ArrayList<>(); List<Object> components = new ArrayList<>();
final SecurityContext securityContext = new SecurityContext(settings, threadPool, cryptoService); final SecurityContext securityContext = new SecurityContext(settings, threadPool, cryptoService);
components.add(securityContext); components.add(securityContext);
@ -275,6 +264,7 @@ public class Security implements ActionPlugin, IngestPlugin {
components.add(realms); components.add(realms);
// audit trails construction // audit trails construction
IndexAuditTrail indexAuditTrail = null;
Set<AuditTrail> auditTrails = new LinkedHashSet<>(); Set<AuditTrail> auditTrails = new LinkedHashSet<>();
if (AUDIT_ENABLED_SETTING.get(settings)) { if (AUDIT_ENABLED_SETTING.get(settings)) {
List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings); List<String> outputs = AUDIT_OUTPUTS_SETTING.get(settings);
@ -289,16 +279,54 @@ public class Security implements ActionPlugin, IngestPlugin {
auditTrails.add(new LoggingAuditTrail(settings, clusterService, threadPool)); auditTrails.add(new LoggingAuditTrail(settings, clusterService, threadPool));
break; break;
case IndexAuditTrail.NAME: case IndexAuditTrail.NAME:
IndexAuditTrail indexAuditTrail = new IndexAuditTrail(settings, client, threadPool, clusterService); indexAuditTrail = new IndexAuditTrail(settings, client, threadPool, clusterService);
auditTrails.add(indexAuditTrail); auditTrails.add(indexAuditTrail);
components.add(indexAuditTrail); // SecurityLifecycleService needs this....
break; break;
default: default:
throw new IllegalArgumentException("Unknown audit trail output [" + output + "]"); throw new IllegalArgumentException("Unknown audit trail output [" + output + "]");
} }
} }
} }
components.add(new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), securityLicenseState)); final AuditTrailService auditTrailService =
new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), securityLicenseState);
components.add(auditTrailService);
AuthenticationFailureHandler failureHandler = null;
String extensionName = null;
for (XPackExtension extension : extensions) {
AuthenticationFailureHandler extensionFailureHandler = extension.getAuthenticationFailureHandler();
if (extensionFailureHandler != null && failureHandler != null) {
throw new IllegalStateException("Extensions [" + extensionName +"] and [" + extension.name() + "] " +
"both set an authentication failure handler");
}
failureHandler = extensionFailureHandler;
extensionName = extension.name();
}
if (failureHandler == null) {
logger.debug("Using default authentication failure handler");
failureHandler = new DefaultAuthenticationFailureHandler();
} else {
logger.debug("Using authentication failure handler from extension [" + extensionName + "]");
}
final AuthenticationService authcService = new AuthenticationService(settings, realms, auditTrailService,
cryptoService, failureHandler, threadPool);
components.add(authcService);
final FileRolesStore fileRolesStore = new FileRolesStore(settings, env, resourceWatcherService);
final NativeRolesStore nativeRolesStore = new NativeRolesStore(settings, client, threadPool);
final ReservedRolesStore reservedRolesStore = new ReservedRolesStore(securityContext);
final CompositeRolesStore allRolesStore = new CompositeRolesStore(fileRolesStore, nativeRolesStore, reservedRolesStore);
final AuthorizationService authzService = new AuthorizationService(settings, allRolesStore, clusterService,
auditTrailService, failureHandler, threadPool);
components.add(fileRolesStore); // has lifecycle
components.add(nativeRolesStore); // used by roles actions
components.add(reservedRolesStore); // used by roles actions
components.add(allRolesStore); // for SecurityFeatureSet
components.add(authzService);
components.add(new SecurityLifecycleService(settings, clusterService, threadPool, indexAuditTrail,
nativeUsersStore, nativeRolesStore, client));
return components; return components;
} }

View File

@ -18,6 +18,7 @@ import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.Realms;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.XPackFeatureSet; import org.elasticsearch.xpack.XPackFeatureSet;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.authz.store.RolesStore; import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.xpack.security.crypto.CryptoService; import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter; import org.elasticsearch.xpack.security.transport.filter.IPFilter;
@ -43,7 +44,7 @@ public class SecurityFeatureSet implements XPackFeatureSet {
@Nullable @Nullable
private final Realms realms; private final Realms realms;
@Nullable @Nullable
private final RolesStore rolesStore; private final CompositeRolesStore rolesStore;
@Nullable @Nullable
private final IPFilter ipFilter; private final IPFilter ipFilter;
@Nullable @Nullable
@ -52,8 +53,8 @@ public class SecurityFeatureSet implements XPackFeatureSet {
private final CryptoService cryptoService; private final CryptoService cryptoService;
@Inject @Inject
public SecurityFeatureSet(Settings settings, @Nullable SecurityLicenseState licenseState, public SecurityFeatureSet(Settings settings, @Nullable SecurityLicenseState licenseState, @Nullable Realms realms,
@Nullable Realms realms, NamedWriteableRegistry namedWriteableRegistry, @Nullable RolesStore rolesStore, NamedWriteableRegistry namedWriteableRegistry, @Nullable CompositeRolesStore rolesStore,
@Nullable IPFilter ipFilter, @Nullable AuditTrailService auditTrailService, @Nullable IPFilter ipFilter, @Nullable AuditTrailService auditTrailService,
@Nullable CryptoService cryptoService) { @Nullable CryptoService cryptoService) {
this.enabled = Security.enabled(settings); this.enabled = Security.enabled(settings);

View File

@ -6,18 +6,17 @@
package org.elasticsearch.xpack.security; package org.elasticsearch.xpack.security;
import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.component.LifecycleListener; import org.elasticsearch.common.component.LifecycleListener;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore; import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
import org.elasticsearch.threadpool.ThreadPool;
/** /**
* This class is used to provide a lifecycle for services that is based on the cluster's state * This class is used to provide a lifecycle for services that is based on the cluster's state
@ -38,7 +37,6 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
private final NativeUsersStore nativeUserStore; private final NativeUsersStore nativeUserStore;
private final NativeRolesStore nativeRolesStore; private final NativeRolesStore nativeRolesStore;
@Inject
public SecurityLifecycleService(Settings settings, ClusterService clusterService, ThreadPool threadPool, public SecurityLifecycleService(Settings settings, ClusterService clusterService, ThreadPool threadPool,
@Nullable IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore, @Nullable IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore,
NativeRolesStore nativeRolesStore, InternalClient client) { NativeRolesStore nativeRolesStore, InternalClient client) {

View File

@ -1,34 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
/**
*
*/
public class SecurityModule extends AbstractSecurityModule {
public SecurityModule(Settings settings) {
super(settings);
}
@Override
protected void configure(boolean clientMode) {
if (clientMode) {
return;
}
XPackPlugin.bindFeatureSet(binder(), SecurityFeatureSet.class);
if (securityEnabled) {
bind(SecurityLifecycleService.class).asEagerSingleton();
}
}
}

View File

@ -1,46 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security.authc;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
import org.elasticsearch.xpack.security.user.AnonymousUser;
/**
*
*/
public class AuthenticationModule extends AbstractSecurityModule.Node {
private Class<? extends AuthenticationFailureHandler> authcFailureHandler = null;
public AuthenticationModule(Settings settings) {
super(settings);
}
@Override
protected void configureNode() {
if (!securityEnabled) {
bind(Realms.class).toProvider(Providers.of(null));
return;
}
AnonymousUser.initialize(settings);
if (authcFailureHandler == null) {
bind(AuthenticationFailureHandler.class).to(DefaultAuthenticationFailureHandler.class).asEagerSingleton();
} else {
bind(AuthenticationFailureHandler.class).to(authcFailureHandler).asEagerSingleton();
}
bind(AuthenticationService.class).asEagerSingleton();
}
/**
* Sets the {@link AuthenticationFailureHandler} to the specified implementation
*/
public void setAuthenticationFailureHandler(Class<? extends AuthenticationFailureHandler> clazz) {
this.authcFailureHandler = clazz;
}
}

View File

@ -5,16 +5,17 @@
*/ */
package org.elasticsearch.xpack.security.authc; package org.elasticsearch.xpack.security.authc;
import java.io.IOException;
import java.util.List;
import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.node.Node; import org.elasticsearch.node.Node;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditTrailService;
@ -26,9 +27,6 @@ import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportMessage; import org.elasticsearch.transport.TransportMessage;
import java.io.IOException;
import java.util.List;
import static org.elasticsearch.xpack.security.Security.setting; import static org.elasticsearch.xpack.security.Security.setting;
/** /**
@ -53,7 +51,6 @@ public class AuthenticationService extends AbstractComponent {
private final boolean signUserHeader; private final boolean signUserHeader;
private final boolean runAsEnabled; private final boolean runAsEnabled;
@Inject
public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, CryptoService cryptoService, public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, CryptoService cryptoService,
AuthenticationFailureHandler failureHandler, ThreadPool threadPool) { AuthenticationFailureHandler failureHandler, ThreadPool threadPool) {
super(settings); super(settings);

View File

@ -1,42 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security.authz;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.authz.store.FileRolesStore;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
/**
* Module used to bind various classes necessary for authorization
*/
public class AuthorizationModule extends AbstractSecurityModule.Node {
public AuthorizationModule(Settings settings) {
super(settings);
}
@Override
protected void configureNode() {
if (securityEnabled == false) {
bind(RolesStore.class).toProvider(Providers.of(null));
return;
}
// First the file and native roles stores must be bound...
bind(ReservedRolesStore.class).asEagerSingleton();
bind(FileRolesStore.class).asEagerSingleton();
bind(NativeRolesStore.class).asEagerSingleton();
// Then the composite roles store (which combines both) can be bound
bind(RolesStore.class).to(CompositeRolesStore.class).asEagerSingleton();
bind(AuthorizationService.class).asEagerSingleton();
}
}

View File

@ -5,6 +5,13 @@
*/ */
package org.elasticsearch.xpack.security.authz; package org.elasticsearch.xpack.security.authz;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.action.CompositeIndicesRequest; import org.elasticsearch.action.CompositeIndicesRequest;
import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.IndicesRequest;
@ -12,28 +19,24 @@ import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.search.ClearScrollAction; import org.elasticsearch.action.search.ClearScrollAction;
import org.elasticsearch.action.search.SearchScrollAction; import org.elasticsearch.action.search.SearchScrollAction;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.AliasOrIndex;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.action.SearchTransportService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.SecurityTemplateService;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.user.AnonymousUser;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl;
import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver;
@ -45,16 +48,13 @@ import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.authz.permission.RunAsPermission; import org.elasticsearch.xpack.security.authz.permission.RunAsPermission;
import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege;
import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.user.AnonymousUser;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.elasticsearch.xpack.security.authz.store.RolesStore; import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import static org.elasticsearch.xpack.security.Security.setting; import static org.elasticsearch.xpack.security.Security.setting;
import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError; import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError;
@ -72,23 +72,22 @@ public class AuthorizationService extends AbstractComponent {
private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate(); private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate();
private final ClusterService clusterService; private final ClusterService clusterService;
private final RolesStore rolesStore; private final CompositeRolesStore rolesStore;
private final AuditTrail auditTrail; private final AuditTrailService auditTrail;
private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers; private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers;
private final AuthenticationFailureHandler authcFailureHandler; private final AuthenticationFailureHandler authcFailureHandler;
private final ThreadContext threadContext; private final ThreadContext threadContext;
private final boolean anonymousAuthzExceptionEnabled; private final boolean anonymousAuthzExceptionEnabled;
@Inject public AuthorizationService(Settings settings, CompositeRolesStore rolesStore, ClusterService clusterService,
public AuthorizationService(Settings settings, RolesStore rolesStore, ClusterService clusterService,
AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler, AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler,
ThreadPool threadPool, IndexNameExpressionResolver nameExpressionResolver) { ThreadPool threadPool) {
super(settings); super(settings);
this.rolesStore = rolesStore; this.rolesStore = rolesStore;
this.clusterService = clusterService; this.clusterService = clusterService;
this.auditTrail = auditTrail; this.auditTrail = auditTrail;
this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] { this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] {
new DefaultIndicesAndAliasesResolver(this, nameExpressionResolver) new DefaultIndicesAndAliasesResolver(this, new IndexNameExpressionResolver(settings))
}; };
this.authcFailureHandler = authcFailureHandler; this.authcFailureHandler = authcFailureHandler;
this.threadContext = threadPool.getThreadContext(); this.threadContext = threadPool.getThreadContext();

View File

@ -21,7 +21,6 @@ public class CompositeRolesStore implements RolesStore {
private final NativeRolesStore nativeRolesStore; private final NativeRolesStore nativeRolesStore;
private final ReservedRolesStore reservedRolesStore; private final ReservedRolesStore reservedRolesStore;
@Inject
public CompositeRolesStore(FileRolesStore fileRolesStore, NativeRolesStore nativeRolesStore, ReservedRolesStore reservedRolesStore) { public CompositeRolesStore(FileRolesStore fileRolesStore, NativeRolesStore nativeRolesStore, ReservedRolesStore reservedRolesStore) {
this.fileRolesStore = fileRolesStore; this.fileRolesStore = fileRolesStore;
this.nativeRolesStore = nativeRolesStore; this.nativeRolesStore = nativeRolesStore;

View File

@ -5,31 +5,6 @@
*/ */
package org.elasticsearch.xpack.security.authz.store; package org.elasticsearch.xpack.security.authz.store;
import com.fasterxml.jackson.dataformat.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.support.RefreshListener;
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.security.authz.permission.IndicesPermission.Group;
import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.support.NoOpLogger;
import org.elasticsearch.xpack.security.support.Validation;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.XPackPlugin;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
@ -41,6 +16,30 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.fasterxml.jackson.dataformat.yaml.snakeyaml.error.YAMLException;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.env.Environment;
import org.elasticsearch.watcher.FileChangesListener;
import org.elasticsearch.watcher.FileWatcher;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.support.RefreshListener;
import org.elasticsearch.xpack.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.security.authz.permission.IndicesPermission.Group;
import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.support.NoOpLogger;
import org.elasticsearch.xpack.security.support.Validation;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
@ -59,7 +58,6 @@ public class FileRolesStore extends AbstractLifecycleComponent implements RolesS
private volatile Map<String, Role> permissions; private volatile Map<String, Role> permissions;
@Inject
public FileRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService) { public FileRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService) {
this(settings, env, watcherService, RefreshListener.NOOP); this(settings, env, watcherService, RefreshListener.NOOP);
} }

View File

@ -5,6 +5,21 @@
*/ */
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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener; import org.elasticsearch.action.LatchedActionListener;
@ -29,7 +44,6 @@ import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -42,6 +56,8 @@ import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.threadpool.ThreadPool.Names;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.SecurityTemplateService;
import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest; import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest;
@ -52,24 +68,7 @@ import org.elasticsearch.xpack.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.security.authz.permission.IndicesPermission.Group; import org.elasticsearch.xpack.security.authz.permission.IndicesPermission.Group;
import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.threadpool.ThreadPool.Cancellable; import org.elasticsearch.threadpool.ThreadPool.Cancellable;
import org.elasticsearch.threadpool.ThreadPool.Names;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.xpack.security.Security.setting; import static org.elasticsearch.xpack.security.Security.setting;
@ -116,7 +115,6 @@ public class NativeRolesStore extends AbstractComponent implements RolesStore, C
private volatile boolean securityIndexExists = false; private volatile boolean securityIndexExists = false;
@Inject
public NativeRolesStore(Settings settings, InternalClient client, ThreadPool threadPool) { public NativeRolesStore(Settings settings, InternalClient client, ThreadPool threadPool) {
super(settings); super(settings);
this.client = client; this.client = client;

View File

@ -5,7 +5,12 @@
*/ */
package org.elasticsearch.xpack.security.authz.store; package org.elasticsearch.xpack.security.authz.store;
import org.elasticsearch.common.inject.Inject; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.xpack.security.SecurityContext; import org.elasticsearch.xpack.security.SecurityContext;
import org.elasticsearch.xpack.security.authz.RoleDescriptor; import org.elasticsearch.xpack.security.authz.RoleDescriptor;
@ -17,12 +22,6 @@ import org.elasticsearch.xpack.security.authz.permission.TransportClientRole;
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 java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/** /**
* *
*/ */
@ -30,7 +29,6 @@ public class ReservedRolesStore implements RolesStore {
private final SecurityContext securityContext; private final SecurityContext securityContext;
@Inject
public ReservedRolesStore(SecurityContext securityContext) { public ReservedRolesStore(SecurityContext securityContext) {
this.securityContext = securityContext; this.securityContext = securityContext;
} }

View File

@ -13,6 +13,7 @@ import org.elasticsearch.xpack.XPackFeatureSet;
import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.Realms;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.authz.store.RolesStore; import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.xpack.security.crypto.CryptoService; import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter; import org.elasticsearch.xpack.security.transport.filter.IPFilter;
@ -44,7 +45,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
private Realms realms; private Realms realms;
private NamedWriteableRegistry namedWriteableRegistry; private NamedWriteableRegistry namedWriteableRegistry;
private IPFilter ipFilter; private IPFilter ipFilter;
private RolesStore rolesStore; private CompositeRolesStore rolesStore;
private AuditTrailService auditTrail; private AuditTrailService auditTrail;
private CryptoService cryptoService; private CryptoService cryptoService;
@ -55,7 +56,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
realms = mock(Realms.class); realms = mock(Realms.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class); namedWriteableRegistry = mock(NamedWriteableRegistry.class);
ipFilter = mock(IPFilter.class); ipFilter = mock(IPFilter.class);
rolesStore = mock(RolesStore.class); rolesStore = mock(CompositeRolesStore.class);
auditTrail = mock(AuditTrailService.class); auditTrail = mock(AuditTrailService.class);
cryptoService = mock(CryptoService.class); cryptoService = mock(CryptoService.class);
} }

View File

@ -11,6 +11,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
@ -53,7 +54,8 @@ public class SecurityTests extends ESTestCase {
Environment env = new Environment(settings); Environment env = new Environment(settings);
Security security = new Security(settings, env); Security security = new Security(settings, env);
ThreadPool threadPool = mock(ThreadPool.class); ThreadPool threadPool = mock(ThreadPool.class);
return security.createComponents(null, threadPool, null, null, Arrays.asList(extensions)); ClusterService clusterService = mock(ClusterService.class);
return security.createComponents(null, threadPool, clusterService, null, Arrays.asList(extensions));
} }
private <T> T findComponent(Class<T> type, Collection<Object> components) { private <T> T findComponent(Class<T> type, Collection<Object> components) {
@ -90,7 +92,8 @@ public class SecurityTests extends ESTestCase {
public void testDisabledByDefault() throws Exception { public void testDisabledByDefault() throws Exception {
Collection<Object> components = createComponents(Settings.EMPTY); Collection<Object> components = createComponents(Settings.EMPTY);
assertNull(findComponent(AuthenticationService.class, components)); AuditTrailService auditTrailService = findComponent(AuditTrailService.class, components);
assertEquals(0, auditTrailService.getAuditTrails().size());
} }
public void testIndexAuditTrail() throws Exception { public void testIndexAuditTrail() throws Exception {

View File

@ -25,9 +25,9 @@ import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.crypto.CryptoService;
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.crypto.CryptoService;
import org.junit.Before; import org.junit.Before;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;

View File

@ -14,6 +14,8 @@ import org.elasticsearch.test.ESIntegTestCase.Scope;
import org.elasticsearch.test.InternalTestCluster; import org.elasticsearch.test.InternalTestCluster;
import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -22,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -137,10 +140,13 @@ public class RemoteIndexAuditTrailStartingTests extends SecurityIntegTestCase {
} }
public void testThatRemoteAuditInstancesAreStarted() throws Exception { public void testThatRemoteAuditInstancesAreStarted() throws Exception {
Iterable<IndexAuditTrail> auditTrails = remoteCluster.getInstances(IndexAuditTrail.class); AuditTrailService auditTrailService = remoteCluster.getInstance(AuditTrailService.class);
for (final IndexAuditTrail auditTrail : auditTrails) { Optional<AuditTrail> auditTrail = auditTrailService.getAuditTrails().stream()
awaitBusy(() -> auditTrail.state() == IndexAuditTrail.State.STARTED, 2L, TimeUnit.SECONDS); .filter(t -> t.name().equals(IndexAuditTrail.NAME)).findFirst();
assertThat(auditTrail.state(), is(IndexAuditTrail.State.STARTED)); assertTrue(auditTrail.isPresent());
} IndexAuditTrail indexAuditTrail = (IndexAuditTrail)auditTrail.get();
awaitBusy(() -> indexAuditTrail.state() == IndexAuditTrail.State.STARTED, 2L, TimeUnit.SECONDS);
assertThat(indexAuditTrail.state(), is(IndexAuditTrail.State.STARTED));
} }
} }

View File

@ -51,7 +51,6 @@ import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
@ -65,17 +64,17 @@ import org.elasticsearch.xpack.security.SecurityTemplateService;
import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.user.AnonymousUser;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler; import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; import org.elasticsearch.xpack.security.authz.permission.SuperuserRole;
import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege;
import org.elasticsearch.xpack.security.authz.privilege.GeneralPrivilege; import org.elasticsearch.xpack.security.authz.privilege.GeneralPrivilege;
import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege;
import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.xpack.security.user.AnonymousUser;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -85,7 +84,6 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@ -95,25 +93,23 @@ import static org.mockito.Mockito.when;
public class AuthorizationServiceTests extends ESTestCase { public class AuthorizationServiceTests extends ESTestCase {
private AuditTrailService auditTrail; private AuditTrailService auditTrail;
private RolesStore rolesStore; private CompositeRolesStore rolesStore;
private ClusterService clusterService; private ClusterService clusterService;
private AuthorizationService internalAuthorizationService; private AuthorizationService authorizationService;
private ThreadContext threadContext; private ThreadContext threadContext;
private ThreadPool threadPool; private ThreadPool threadPool;
@Before @Before
public void setup() { public void setup() {
rolesStore = mock(RolesStore.class); rolesStore = mock(CompositeRolesStore.class);
clusterService = mock(ClusterService.class); clusterService = mock(ClusterService.class);
auditTrail = mock(AuditTrailService.class); auditTrail = mock(AuditTrailService.class);
threadContext = new ThreadContext(Settings.EMPTY); threadContext = new ThreadContext(Settings.EMPTY);
threadPool = mock(ThreadPool.class); threadPool = mock(ThreadPool.class);
when(threadPool.getThreadContext()).thenReturn(threadContext); when(threadPool.getThreadContext()).thenReturn(threadContext);
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg()); auditTrail, new DefaultAuthenticationFailureHandler(), threadPool);
internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver);
} }
@After @After
@ -125,10 +121,10 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = mock(TransportRequest.class); TransportRequest request = mock(TransportRequest.class);
// A failure would throw an exception // A failure would throw an exception
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "indices:monitor/whatever", request); authorizationService.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);
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request); authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request); verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request);
verifyNoMoreInteractions(auditTrail); verifyNoMoreInteractions(auditTrail);
} }
@ -136,7 +132,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testIndicesActionsAreNotAuthorized() { public void testIndicesActionsAreNotAuthorized() {
TransportRequest request = mock(TransportRequest.class); TransportRequest request = mock(TransportRequest.class);
try { try {
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request); authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request);
fail("action beginning with indices should have failed"); fail("action beginning with indices should have failed");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, assertAuthorizationException(e,
@ -149,7 +145,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testClusterAdminActionsAreNotAuthorized() { public void testClusterAdminActionsAreNotAuthorized() {
TransportRequest request = mock(TransportRequest.class); TransportRequest request = mock(TransportRequest.class);
try { try {
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/whatever", request); authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/whatever", request);
fail("action beginning with cluster:admin/whatever should have failed"); fail("action beginning with cluster:admin/whatever should have failed");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, assertAuthorizationException(e,
@ -162,7 +158,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testClusterAdminSnapshotStatusActionIsNotAuthorized() { public void testClusterAdminSnapshotStatusActionIsNotAuthorized() {
TransportRequest request = mock(TransportRequest.class); TransportRequest request = mock(TransportRequest.class);
try { try {
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/snapshot/status", request); authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "cluster:admin/snapshot/status", request);
fail("action beginning with cluster:admin/snapshot/status should have failed"); fail("action beginning with cluster:admin/snapshot/status should have failed");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [cluster:admin/snapshot/status] is unauthorized for user [" + assertAuthorizationException(e, containsString("action [cluster:admin/snapshot/status] is unauthorized for user [" +
@ -176,7 +172,7 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = new SearchRequest(); TransportRequest request = new SearchRequest();
User user = new User("test user"); User user = new User("test user");
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user without roles should be denied"); fail("user without roles should be denied");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]"));
@ -189,7 +185,7 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = new SearchRequest(); TransportRequest request = new SearchRequest();
User user = new User("test user", "non-existent-role"); User user = new User("test user", "non-existent-role");
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user with unknown role only should have been denied"); fail("user with unknown role only should have been denied");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]"));
@ -204,7 +200,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build()); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build());
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "whatever", request); authorizationService.authorize(createAuthentication(user), "whatever", request);
fail("non indices and non cluster requests should be denied"); fail("non indices and non cluster requests should be denied");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [whatever] is unauthorized for user [test user]")); assertAuthorizationException(e, containsString("action [whatever] is unauthorized for user [test user]"));
@ -219,7 +215,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(rolesStore.role("no_indices")).thenReturn(Role.builder("no_indices").cluster(ClusterPrivilege.action("")).build()); when(rolesStore.role("no_indices")).thenReturn(Role.builder("no_indices").cluster(ClusterPrivilege.action("")).build());
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user only has cluster roles so indices requests should fail"); fail("user only has cluster roles so indices requests should fail");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]"));
@ -233,29 +229,29 @@ public class AuthorizationServiceTests extends ESTestCase {
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build()); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build());
ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
internalAuthorizationService.authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest); authorizationService.authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest);
verify(auditTrail).accessGranted(user, ClearScrollAction.NAME, clearScrollRequest); verify(auditTrail).accessGranted(user, ClearScrollAction.NAME, clearScrollRequest);
SearchScrollRequest searchScrollRequest = new SearchScrollRequest(); SearchScrollRequest searchScrollRequest = new SearchScrollRequest();
internalAuthorizationService.authorize(createAuthentication(user), SearchScrollAction.NAME, searchScrollRequest); authorizationService.authorize(createAuthentication(user), SearchScrollAction.NAME, searchScrollRequest);
verify(auditTrail).accessGranted(user, SearchScrollAction.NAME, searchScrollRequest); verify(auditTrail).accessGranted(user, SearchScrollAction.NAME, searchScrollRequest);
// 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);
internalAuthorizationService authorizationService
.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);
internalAuthorizationService.authorize(createAuthentication(user), SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME, request); authorizationService.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);
internalAuthorizationService.authorize(createAuthentication(user), SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME, request); authorizationService.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);
internalAuthorizationService.authorize(createAuthentication(user), SearchTransportService.QUERY_SCROLL_ACTION_NAME, request); authorizationService.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);
internalAuthorizationService.authorize(createAuthentication(user), SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME, request); authorizationService.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);
verifyNoMoreInteractions(auditTrail); verifyNoMoreInteractions(auditTrail);
} }
@ -269,7 +265,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("indices request for b should be denied since there is no such index"); fail("indices request for b should be denied since there is no such index");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user]"));
@ -290,7 +286,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
try { try {
internalAuthorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request); authorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request);
fail("indices creation request with alias should be denied since user does not have permission to alias"); fail("indices creation request with alias should be denied since user does not have permission to alias");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, assertAuthorizationException(e,
@ -311,7 +307,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
internalAuthorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request); authorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request);
verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request); verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request);
verifyNoMoreInteractions(auditTrail); verifyNoMoreInteractions(auditTrail);
@ -322,7 +318,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testIndicesAliasesWithNoRolesUser() { public void testIndicesAliasesWithNoRolesUser() {
User user = new User("test user"); User user = new User("test user");
List<String> list = internalAuthorizationService.authorizedIndicesAndAliases(user, ""); List<String> list = authorizationService.authorizedIndicesAndAliases(user, "");
assertThat(list.isEmpty(), is(true)); assertThat(list.isEmpty(), is(true));
} }
@ -347,7 +343,7 @@ public class AuthorizationServiceTests extends ESTestCase {
.build(), true) .build(), true)
.build()); .build());
List<String> list = internalAuthorizationService.authorizedIndicesAndAliases(user, SearchAction.NAME); List<String> list = authorizationService.authorizedIndicesAndAliases(user, SearchAction.NAME);
assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab")); assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab"));
assertThat(list.contains("bbbbb"), is(false)); assertThat(list.contains("bbbbb"), is(false));
assertThat(list.contains("ba"), is(false)); assertThat(list.contains("ba"), is(false));
@ -357,17 +353,15 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = new IndicesExistsRequest("b"); TransportRequest request = new IndicesExistsRequest("b");
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
AnonymousUser.initialize(Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build()); AnonymousUser.initialize(Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build());
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail,
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg()); new DefaultAuthenticationFailureHandler(), threadPool);
internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail,
new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver);
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
try { try {
internalAuthorizationService.authorize(createAuthentication(AnonymousUser.INSTANCE), "indices:a", request); authorizationService.authorize(createAuthentication(AnonymousUser.INSTANCE), "indices:a", request);
fail("indices request for b should be denied since there is no such index"); fail("indices request for b should be denied since there is no such index");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, assertAuthorizationException(e,
@ -387,18 +381,16 @@ public class AuthorizationServiceTests extends ESTestCase {
.put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false) .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false)
.build()); .build());
User anonymousUser = AnonymousUser.INSTANCE; User anonymousUser = AnonymousUser.INSTANCE;
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); authorizationService = new AuthorizationService(
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg());
internalAuthorizationService = new AuthorizationService(
Settings.builder().put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false).build(), Settings.builder().put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false).build(),
rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver); rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool);
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
try { try {
internalAuthorizationService.authorize(createAuthentication(anonymousUser), "indices:a", request); authorizationService.authorize(createAuthentication(anonymousUser), "indices:a", request);
fail("indices request for b should be denied since there is no such index"); fail("indices request for b should be denied since there is no such index");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthenticationException(e, containsString("action [indices:a] requires authentication")); assertAuthenticationException(e, containsString("action [indices:a] requires authentication"));
@ -414,7 +406,7 @@ public class AuthorizationServiceTests extends ESTestCase {
User user = new User("test user", null, new User("run as me", new String[] { "admin" })); User user = new User("test user", null, new User("run as me", new String[] { "admin" }));
assertThat(user.runAs(), is(notNullValue())); assertThat(user.runAs(), is(notNullValue()));
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user without roles should be denied for run as"); fail("user without roles should be denied for run as");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]"));
@ -434,7 +426,7 @@ public class AuthorizationServiceTests extends ESTestCase {
.build()); .build());
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user without roles should be denied for run as"); fail("user without roles should be denied for run as");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]"));
@ -468,7 +460,7 @@ public class AuthorizationServiceTests extends ESTestCase {
} }
try { try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("the run as user's role doesn't exist so they should not get authorized"); fail("the run as user's role doesn't exist so they should not get authorized");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]")); assertAuthorizationException(e, containsString("action [indices:a] is unauthorized for user [test user] run as [run as me]"));
@ -499,7 +491,7 @@ public class AuthorizationServiceTests extends ESTestCase {
.add(IndexPrivilege.ALL, "b") .add(IndexPrivilege.ALL, "b")
.build()); .build());
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request); authorizationService.authorize(createAuthentication(user), "indices:a", request);
verify(auditTrail).runAsGranted(user, "indices:a", request); verify(auditTrail).runAsGranted(user, "indices:a", request);
verify(auditTrail).accessGranted(user, "indices:a", request); verify(auditTrail).accessGranted(user, "indices:a", request);
verifyNoMoreInteractions(auditTrail); verifyNoMoreInteractions(auditTrail);
@ -538,7 +530,7 @@ public class AuthorizationServiceTests extends ESTestCase {
String action = requestTuple.v1(); String action = requestTuple.v1();
TransportRequest request = requestTuple.v2(); TransportRequest request = requestTuple.v2();
try { try {
internalAuthorizationService.authorize(createAuthentication(user), action, request); authorizationService.authorize(createAuthentication(user), action, request);
fail("only the xpack user can execute operation [" + action + "] against the internal index"); fail("only the xpack user can execute operation [" + action + "] against the internal index");
} catch (ElasticsearchSecurityException e) { } catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e, containsString("action [" + action + "] is unauthorized for user [all_access_user]")); assertAuthorizationException(e, containsString("action [" + action + "] is unauthorized for user [all_access_user]"));
@ -549,12 +541,12 @@ public class AuthorizationServiceTests extends ESTestCase {
// 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(SecurityTemplateService.SECURITY_INDEX_NAME); ClusterHealthRequest request = new ClusterHealthRequest(SecurityTemplateService.SECURITY_INDEX_NAME);
internalAuthorizationService.authorize(createAuthentication(user), ClusterHealthAction.NAME, request); authorizationService.authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
// multiple indices // multiple indices
request = new ClusterHealthRequest(SecurityTemplateService.SECURITY_INDEX_NAME, "foo", "bar"); request = new ClusterHealthRequest(SecurityTemplateService.SECURITY_INDEX_NAME, "foo", "bar");
internalAuthorizationService.authorize(createAuthentication(user), ClusterHealthAction.NAME, request); authorizationService.authorize(createAuthentication(user), ClusterHealthAction.NAME, request);
verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(user, ClusterHealthAction.NAME, request);
} }
@ -586,7 +578,7 @@ public class AuthorizationServiceTests extends ESTestCase {
for (Tuple<String, ? extends TransportRequest> requestTuple : requests) { for (Tuple<String, ? extends TransportRequest> requestTuple : requests) {
String action = requestTuple.v1(); String action = requestTuple.v1();
TransportRequest request = requestTuple.v2(); TransportRequest request = requestTuple.v2();
internalAuthorizationService.authorize(createAuthentication(user), action, request); authorizationService.authorize(createAuthentication(user), action, request);
verify(auditTrail).accessGranted(user, action, request); verify(auditTrail).accessGranted(user, action, request);
} }
} }
@ -620,7 +612,7 @@ 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();
internalAuthorizationService.authorize(createAuthentication(XPackUser.INSTANCE), action, request); authorizationService.authorize(createAuthentication(XPackUser.INSTANCE), action, request);
verify(auditTrail).accessGranted(XPackUser.INSTANCE, action, request); verify(auditTrail).accessGranted(XPackUser.INSTANCE, action, request);
} }
} }

View File

@ -34,6 +34,10 @@ import org.elasticsearch.index.IndexNotFoundException;
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.SecurityTemplateService; import org.elasticsearch.xpack.security.SecurityTemplateService;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
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.DefaultAuthenticationFailureHandler; import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.AuthorizationService;
@ -41,9 +45,6 @@ import org.elasticsearch.xpack.security.authz.permission.Role;
import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; import org.elasticsearch.xpack.security.authz.permission.SuperuserRole;
import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege;
import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege;
import org.elasticsearch.xpack.security.authz.store.RolesStore;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.junit.Before; import org.junit.Before;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
@ -60,7 +61,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
private User user; private User user;
private User userNoIndices; private User userNoIndices;
private RolesStore rolesStore; private CompositeRolesStore rolesStore;
private MetaData metaData; private MetaData metaData;
private DefaultIndicesAndAliasesResolver defaultIndicesResolver; private DefaultIndicesAndAliasesResolver defaultIndicesResolver;
private IndexNameExpressionResolver indexNameExpressionResolver; private IndexNameExpressionResolver indexNameExpressionResolver;
@ -91,7 +92,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
user = new User("user", "role"); user = new User("user", "role");
userNoIndices = new User("test", "test"); userNoIndices = new User("test", "test");
rolesStore = mock(RolesStore.class); rolesStore = mock(CompositeRolesStore.class);
String[] authorizedIndices = new String[] { "bar", "bar-closed", "foofoobar", "foofoo", "missing", "foofoo-closed" }; String[] authorizedIndices = new String[] { "bar", "bar-closed", "foofoobar", "foofoo", "missing", "foofoo-closed" };
when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build()); when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build());
when(rolesStore.role("test")).thenReturn(Role.builder("test").cluster(ClusterPrivilege.MONITOR).build()); when(rolesStore.role("test")).thenReturn(Role.builder("test").cluster(ClusterPrivilege.MONITOR).build());
@ -102,8 +103,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
when(state.metaData()).thenReturn(metaData); when(state.metaData()).thenReturn(metaData);
AuthorizationService authzService = new AuthorizationService(settings, rolesStore, clusterService, AuthorizationService authzService = new AuthorizationService(settings, rolesStore, clusterService,
mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class), mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class));
indexNameExpressionResolver);
defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService, indexNameExpressionResolver); defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService, indexNameExpressionResolver);
} }

View File

@ -69,7 +69,6 @@ import org.elasticsearch.xpack.rest.action.RestXPackInfoAction;
import org.elasticsearch.xpack.rest.action.RestXPackUsageAction; import org.elasticsearch.xpack.rest.action.RestXPackUsageAction;
import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.support.clock.Clock; import org.elasticsearch.xpack.support.clock.Clock;
@ -180,7 +179,6 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() { public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
ArrayList<Class<? extends LifecycleComponent>> services = new ArrayList<>(); ArrayList<Class<? extends LifecycleComponent>> services = new ArrayList<>();
services.addAll(notification.nodeServices()); services.addAll(notification.nodeServices());
services.addAll(security.nodeServices());
services.addAll(monitoring.nodeServices()); services.addAll(monitoring.nodeServices());
return services; return services;
} }
@ -315,12 +313,6 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
return security.getProcessors(parameters); return security.getProcessors(parameters);
} }
public void onModule(AuthenticationModule module) {
if (extensionsService != null) {
extensionsService.onModule(module);
}
}
public void onIndexModule(IndexModule module) { public void onIndexModule(IndexModule module) {
security.onIndexModule(module); security.onIndexModule(module);
} }

View File

@ -9,9 +9,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realm;
@ -29,11 +27,6 @@ public abstract class XPackExtension {
*/ */
public abstract String description(); public abstract String description();
/**
* Implement this function to register custom extensions in the authentication module.
*/
public void onModule(AuthenticationModule module) {}
/** /**
* Returns headers which should be copied from REST requests to internal cluster requests. * Returns headers which should be copied from REST requests to internal cluster requests.
*/ */
@ -41,7 +34,6 @@ public abstract class XPackExtension {
return Collections.emptyList(); return Collections.emptyList();
} }
/** /**
* Returns authentication realm implementations added by this extension. * Returns authentication realm implementations added by this extension.
* *
@ -52,4 +44,14 @@ public abstract class XPackExtension {
public Map<String, Realm.Factory> getRealms() { public Map<String, Realm.Factory> getRealms() {
return Collections.emptyMap(); return Collections.emptyMap();
} }
/**
* Returns a handler for authentication failures, or null to use the default handler.
*
* Only one installed extension may have an authentication failure handler. If more than
* one extension returns a non-null handler, an error is raised.
*/
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return null;
}
} }

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
@ -74,12 +73,6 @@ public class XPackExtensionsService {
extensions = Collections.unmodifiableList(extensionsLoaded); extensions = Collections.unmodifiableList(extensionsLoaded);
} }
public void onModule(AuthenticationModule module) {
for (Tuple<XPackExtensionInfo, XPackExtension> tuple : extensions) {
tuple.v2().onModule(module);
}
}
public List<XPackExtension> getExtensions() { public List<XPackExtension> getExtensions() {
return extensions.stream().map(Tuple::v2).collect(Collectors.toList()); return extensions.stream().map(Tuple::v2).collect(Collectors.toList());
} }