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.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.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";
}
public void onModule(AuthenticationModule authenticationModule) {
authenticationModule.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler.class);
}
@Override
public Map<String, Realm.Factory> getRealms() {
return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new);
}
@Override
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
@Override
public Collection<String> getRestHeaders() {
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.IndexNameResolver;
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.Realm;
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.support.SecuredString;
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.accesscontrol.SetSecurityUserProcessor;
import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache;
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.NativeRolesStore;
import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.security.rest.SecurityRestModule;
import org.elasticsearch.xpack.security.rest.action.RestAuthenticateAction;
@ -183,7 +185,6 @@ public class Security implements ActionPlugin, IngestPlugin {
if (enabled == false) {
return modules;
}
modules.add(new SecurityModule(settings));
modules.add(new SecurityTransportModule(settings));
modules.add(b -> {
// for transport client we still must inject these ssl classes with guice
@ -194,16 +195,16 @@ public class Security implements ActionPlugin, IngestPlugin {
return modules;
}
modules.add(new AuthenticationModule(settings));
modules.add(new AuthorizationModule(settings));
modules.add(b -> XPackPlugin.bindFeatureSet(b, SecurityFeatureSet.class));
if (enabled == false) {
modules.add(b -> {
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)
.toInstance(new AuditTrailService(settings, Collections.emptyList(), securityLicenseState));
});
modules.add(new SecurityModule(settings));
modules.add(new SecurityTransportModule(settings));
return modules;
}
@ -216,32 +217,20 @@ public class Security implements ActionPlugin, IngestPlugin {
if (auditingEnabled(settings)) {
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 SecurityActionModule(settings));
modules.add(new SecurityTransportModule(settings));
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,
ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) {
if (enabled == false) {
return Collections.emptyList();
}
AnonymousUser.initialize(settings); // TODO: this is sketchy...testing is difficult b/c it is static....
List<Object> components = new ArrayList<>();
final SecurityContext securityContext = new SecurityContext(settings, threadPool, cryptoService);
components.add(securityContext);
@ -275,6 +264,7 @@ public class Security implements ActionPlugin, IngestPlugin {
components.add(realms);
// audit trails construction
IndexAuditTrail indexAuditTrail = null;
Set<AuditTrail> auditTrails = new LinkedHashSet<>();
if (AUDIT_ENABLED_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));
break;
case IndexAuditTrail.NAME:
IndexAuditTrail indexAuditTrail = new IndexAuditTrail(settings, client, threadPool, clusterService);
indexAuditTrail = new IndexAuditTrail(settings, client, threadPool, clusterService);
auditTrails.add(indexAuditTrail);
components.add(indexAuditTrail); // SecurityLifecycleService needs this....
break;
default:
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;
}

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

View File

@ -6,18 +6,17 @@
package org.elasticsearch.xpack.security;
import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.component.LifecycleListener;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.settings.Settings;
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.authc.esnative.NativeUsersStore;
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
@ -38,7 +37,6 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust
private final NativeUsersStore nativeUserStore;
private final NativeRolesStore nativeRolesStore;
@Inject
public SecurityLifecycleService(Settings settings, ClusterService clusterService, ThreadPool threadPool,
@Nullable IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore,
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;
import java.io.IOException;
import java.util.List;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.node.Node;
import org.elasticsearch.rest.RestRequest;
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.transport.TransportMessage;
import java.io.IOException;
import java.util.List;
import static org.elasticsearch.xpack.security.Security.setting;
/**
@ -53,7 +51,6 @@ public class AuthenticationService extends AbstractComponent {
private final boolean signUserHeader;
private final boolean runAsEnabled;
@Inject
public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, CryptoService cryptoService,
AuthenticationFailureHandler failureHandler, ThreadPool threadPool) {
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;
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.action.CompositeIndicesRequest;
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.search.ClearScrollAction;
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.metadata.AliasOrIndex;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.set.Sets;
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.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.authc.Authentication;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl;
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.privilege.ClusterPrivilege;
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.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.support.Exceptions.authorizationError;
@ -72,23 +72,22 @@ public class AuthorizationService extends AbstractComponent {
private static final Predicate<String> MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate();
private final ClusterService clusterService;
private final RolesStore rolesStore;
private final AuditTrail auditTrail;
private final CompositeRolesStore rolesStore;
private final AuditTrailService auditTrail;
private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers;
private final AuthenticationFailureHandler authcFailureHandler;
private final ThreadContext threadContext;
private final boolean anonymousAuthzExceptionEnabled;
@Inject
public AuthorizationService(Settings settings, RolesStore rolesStore, ClusterService clusterService,
public AuthorizationService(Settings settings, CompositeRolesStore rolesStore, ClusterService clusterService,
AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler,
ThreadPool threadPool, IndexNameExpressionResolver nameExpressionResolver) {
ThreadPool threadPool) {
super(settings);
this.rolesStore = rolesStore;
this.clusterService = clusterService;
this.auditTrail = auditTrail;
this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] {
new DefaultIndicesAndAliasesResolver(this, nameExpressionResolver)
new DefaultIndicesAndAliasesResolver(this, new IndexNameExpressionResolver(settings))
};
this.authcFailureHandler = authcFailureHandler;
this.threadContext = threadPool.getThreadContext();

View File

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

View File

@ -5,31 +5,6 @@
*/
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.nio.charset.StandardCharsets;
import java.nio.file.Files;
@ -41,6 +16,30 @@ import java.util.Map;
import java.util.Set;
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.emptySet;
import static java.util.Collections.unmodifiableMap;
@ -59,7 +58,6 @@ public class FileRolesStore extends AbstractLifecycleComponent implements RolesS
private volatile Map<String, Role> permissions;
@Inject
public FileRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService) {
this(settings, env, watcherService, RefreshListener.NOOP);
}

View File

@ -5,6 +5,21 @@
*/
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.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
@ -29,7 +44,6 @@ import org.elasticsearch.cluster.ClusterStateListener;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
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.QueryBuilders;
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.SecurityTemplateService;
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.Role;
import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.threadpool.ThreadPool;
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.xpack.security.Security.setting;
@ -116,7 +115,6 @@ public class NativeRolesStore extends AbstractComponent implements RolesStore, C
private volatile boolean securityIndexExists = false;
@Inject
public NativeRolesStore(Settings settings, InternalClient client, ThreadPool threadPool) {
super(settings);
this.client = client;

View File

@ -5,7 +5,12 @@
*/
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.xpack.security.SecurityContext;
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.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;
@Inject
public ReservedRolesStore(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.authc.Realm;
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.crypto.CryptoService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
@ -44,7 +45,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
private Realms realms;
private NamedWriteableRegistry namedWriteableRegistry;
private IPFilter ipFilter;
private RolesStore rolesStore;
private CompositeRolesStore rolesStore;
private AuditTrailService auditTrail;
private CryptoService cryptoService;
@ -55,7 +56,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
realms = mock(Realms.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
ipFilter = mock(IPFilter.class);
rolesStore = mock(RolesStore.class);
rolesStore = mock(CompositeRolesStore.class);
auditTrail = mock(AuditTrailService.class);
cryptoService = mock(CryptoService.class);
}

View File

@ -11,6 +11,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
@ -53,7 +54,8 @@ public class SecurityTests extends ESTestCase {
Environment env = new Environment(settings);
Security security = new Security(settings, env);
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) {
@ -90,7 +92,8 @@ public class SecurityTests extends ESTestCase {
public void testDisabledByDefault() throws Exception {
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 {

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.AuthenticationService;
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.User;
import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.junit.Before;
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.SecurityIntegTestCase;
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.Before;
@ -22,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -137,10 +140,13 @@ public class RemoteIndexAuditTrailStartingTests extends SecurityIntegTestCase {
}
public void testThatRemoteAuditInstancesAreStarted() throws Exception {
Iterable<IndexAuditTrail> auditTrails = remoteCluster.getInstances(IndexAuditTrail.class);
for (final IndexAuditTrail auditTrail : auditTrails) {
awaitBusy(() -> auditTrail.state() == IndexAuditTrail.State.STARTED, 2L, TimeUnit.SECONDS);
assertThat(auditTrail.state(), is(IndexAuditTrail.State.STARTED));
}
AuditTrailService auditTrailService = remoteCluster.getInstance(AuditTrailService.class);
Optional<AuditTrail> auditTrail = auditTrailService.getAuditTrails().stream()
.filter(t -> t.name().equals(IndexAuditTrail.NAME)).findFirst();
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.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
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.authc.Authentication;
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.authz.permission.Role;
import org.elasticsearch.xpack.security.authz.permission.SuperuserRole;
import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege;
import org.elasticsearch.xpack.security.authz.privilege.GeneralPrivilege;
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.Before;
@ -85,7 +84,6 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@ -95,25 +93,23 @@ import static org.mockito.Mockito.when;
public class AuthorizationServiceTests extends ESTestCase {
private AuditTrailService auditTrail;
private RolesStore rolesStore;
private CompositeRolesStore rolesStore;
private ClusterService clusterService;
private AuthorizationService internalAuthorizationService;
private AuthorizationService authorizationService;
private ThreadContext threadContext;
private ThreadPool threadPool;
@Before
public void setup() {
rolesStore = mock(RolesStore.class);
rolesStore = mock(CompositeRolesStore.class);
clusterService = mock(ClusterService.class);
auditTrail = mock(AuditTrailService.class);
threadContext = new ThreadContext(Settings.EMPTY);
threadPool = mock(ThreadPool.class);
when(threadPool.getThreadContext()).thenReturn(threadContext);
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class);
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg());
internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver);
authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(), threadPool);
}
@After
@ -125,10 +121,10 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = mock(TransportRequest.class);
// 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);
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "internal:whatever", request);
verify(auditTrail).accessGranted(SystemUser.INSTANCE, "internal:whatever", request);
verifyNoMoreInteractions(auditTrail);
}
@ -136,7 +132,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testIndicesActionsAreNotAuthorized() {
TransportRequest request = mock(TransportRequest.class);
try {
internalAuthorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request);
authorizationService.authorize(createAuthentication(SystemUser.INSTANCE), "indices:", request);
fail("action beginning with indices should have failed");
} catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e,
@ -149,7 +145,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testClusterAdminActionsAreNotAuthorized() {
TransportRequest request = mock(TransportRequest.class);
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");
} catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e,
@ -162,7 +158,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testClusterAdminSnapshotStatusActionIsNotAuthorized() {
TransportRequest request = mock(TransportRequest.class);
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");
} catch (ElasticsearchSecurityException e) {
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();
User user = new User("test user");
try {
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request);
authorizationService.authorize(createAuthentication(user), "indices:a", request);
fail("user without roles should be denied");
} catch (ElasticsearchSecurityException e) {
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();
User user = new User("test user", "non-existent-role");
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");
} catch (ElasticsearchSecurityException e) {
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());
try {
internalAuthorizationService.authorize(createAuthentication(user), "whatever", request);
authorizationService.authorize(createAuthentication(user), "whatever", request);
fail("non indices and non cluster requests should be denied");
} catch (ElasticsearchSecurityException e) {
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());
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");
} catch (ElasticsearchSecurityException e) {
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());
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);
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);
// 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);
internalAuthorizationService
authorizationService
.authorize(createAuthentication(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);
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);
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);
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);
verifyNoMoreInteractions(auditTrail);
}
@ -269,7 +265,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
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");
} catch (ElasticsearchSecurityException e) {
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);
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");
} catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e,
@ -311,7 +307,7 @@ public class AuthorizationServiceTests extends ESTestCase {
when(clusterService.state()).thenReturn(state);
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);
verifyNoMoreInteractions(auditTrail);
@ -322,7 +318,7 @@ public class AuthorizationServiceTests extends ESTestCase {
public void testIndicesAliasesWithNoRolesUser() {
User user = new User("test user");
List<String> list = internalAuthorizationService.authorizedIndicesAndAliases(user, "");
List<String> list = authorizationService.authorizedIndicesAndAliases(user, "");
assertThat(list.isEmpty(), is(true));
}
@ -347,7 +343,7 @@ public class AuthorizationServiceTests extends ESTestCase {
.build(), true)
.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.contains("bbbbb"), is(false));
assertThat(list.contains("ba"), is(false));
@ -357,17 +353,15 @@ public class AuthorizationServiceTests extends ESTestCase {
TransportRequest request = new IndicesExistsRequest("b");
ClusterState state = mock(ClusterState.class);
AnonymousUser.initialize(Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build());
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class);
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg());
internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail,
new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver);
authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail,
new DefaultAuthenticationFailureHandler(), threadPool);
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
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");
} catch (ElasticsearchSecurityException e) {
assertAuthorizationException(e,
@ -387,18 +381,16 @@ public class AuthorizationServiceTests extends ESTestCase {
.put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false)
.build());
User anonymousUser = AnonymousUser.INSTANCE;
IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class);
when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg());
internalAuthorizationService = new AuthorizationService(
authorizationService = new AuthorizationService(
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(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA);
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");
} catch (ElasticsearchSecurityException e) {
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" }));
assertThat(user.runAs(), is(notNullValue()));
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");
} catch (ElasticsearchSecurityException e) {
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());
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");
} catch (ElasticsearchSecurityException e) {
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 {
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");
} catch (ElasticsearchSecurityException e) {
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")
.build());
internalAuthorizationService.authorize(createAuthentication(user), "indices:a", request);
authorizationService.authorize(createAuthentication(user), "indices:a", request);
verify(auditTrail).runAsGranted(user, "indices:a", request);
verify(auditTrail).accessGranted(user, "indices:a", request);
verifyNoMoreInteractions(auditTrail);
@ -538,7 +530,7 @@ public class AuthorizationServiceTests extends ESTestCase {
String action = requestTuple.v1();
TransportRequest request = requestTuple.v2();
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");
} catch (ElasticsearchSecurityException e) {
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
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);
// multiple indices
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);
}
@ -586,7 +578,7 @@ public class AuthorizationServiceTests extends ESTestCase {
for (Tuple<String, ? extends TransportRequest> requestTuple : requests) {
String action = requestTuple.v1();
TransportRequest request = requestTuple.v2();
internalAuthorizationService.authorize(createAuthentication(user), action, request);
authorizationService.authorize(createAuthentication(user), action, request);
verify(auditTrail).accessGranted(user, action, request);
}
}
@ -620,7 +612,7 @@ public class AuthorizationServiceTests extends ESTestCase {
for (Tuple<String, TransportRequest> requestTuple : requests) {
String action = requestTuple.v1();
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);
}
}

View File

@ -34,6 +34,10 @@ import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
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.authc.DefaultAuthenticationFailureHandler;
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.privilege.ClusterPrivilege;
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 static org.hamcrest.Matchers.arrayContaining;
@ -60,7 +61,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
private User user;
private User userNoIndices;
private RolesStore rolesStore;
private CompositeRolesStore rolesStore;
private MetaData metaData;
private DefaultIndicesAndAliasesResolver defaultIndicesResolver;
private IndexNameExpressionResolver indexNameExpressionResolver;
@ -91,7 +92,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
user = new User("user", "role");
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" };
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());
@ -102,8 +103,7 @@ public class DefaultIndicesResolverTests extends ESTestCase {
when(state.metaData()).thenReturn(metaData);
AuthorizationService authzService = new AuthorizationService(settings, rolesStore, clusterService,
mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class),
indexNameExpressionResolver);
mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class));
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.security.InternalClient;
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.support.UsernamePasswordToken;
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() {
ArrayList<Class<? extends LifecycleComponent>> services = new ArrayList<>();
services.addAll(notification.nodeServices());
services.addAll(security.nodeServices());
services.addAll(monitoring.nodeServices());
return services;
}
@ -315,12 +313,6 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
return security.getProcessors(parameters);
}
public void onModule(AuthenticationModule module) {
if (extensionsService != null) {
extensionsService.onModule(module);
}
}
public void onIndexModule(IndexModule module) {
security.onIndexModule(module);
}

View File

@ -9,9 +9,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import org.elasticsearch.xpack.security.authc.Realm;
@ -29,11 +27,6 @@ public abstract class XPackExtension {
*/
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.
*/
@ -41,7 +34,6 @@ public abstract class XPackExtension {
return Collections.emptyList();
}
/**
* Returns authentication realm implementations added by this extension.
*
@ -52,4 +44,14 @@ public abstract class XPackExtension {
public Map<String, Realm.Factory> getRealms() {
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.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
import java.io.IOException;
import java.net.URL;
@ -74,12 +73,6 @@ public class XPackExtensionsService {
extensions = Collections.unmodifiableList(extensionsLoaded);
}
public void onModule(AuthenticationModule module) {
for (Tuple<XPackExtensionInfo, XPackExtension> tuple : extensions) {
tuple.v2().onModule(module);
}
}
public List<XPackExtension> getExtensions() {
return extensions.stream().map(Tuple::v2).collect(Collectors.toList());
}