Merge pull request elastic/elasticsearch#2844 from rjernst/deguice8
Remove guice from realms construction Original commit: elastic/x-pack-elasticsearch@8bfeef931c
This commit is contained in:
commit
c3a3898da9
|
@ -7,16 +7,27 @@ package org.elasticsearch.example;
|
|||
|
||||
import org.elasticsearch.example.realm.CustomAuthenticationFailureHandler;
|
||||
import org.elasticsearch.example.realm.CustomRealm;
|
||||
import org.elasticsearch.example.realm.CustomRealmFactory;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExampleRealmExtension extends XPackExtension {
|
||||
|
||||
static {
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "custom realm example";
|
||||
|
@ -28,13 +39,12 @@ public class ExampleRealmExtension extends XPackExtension {
|
|||
}
|
||||
|
||||
public void onModule(AuthenticationModule authenticationModule) {
|
||||
authenticationModule.addCustomRealm(CustomRealm.TYPE, CustomRealmFactory.class);
|
||||
authenticationModule.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler.class);
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Realm.Factory> getRealms() {
|
||||
return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.elasticsearch.xpack.security.authc.RealmConfig;
|
|||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
||||
public class CustomRealm extends Realm<UsernamePasswordToken> {
|
||||
public class CustomRealm extends Realm {
|
||||
|
||||
public static final String TYPE = "custom";
|
||||
|
||||
|
@ -46,7 +46,8 @@ public class CustomRealm extends Realm<UsernamePasswordToken> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(UsernamePasswordToken token) {
|
||||
public User authenticate(AuthenticationToken authToken) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken)authToken;
|
||||
final String actualUser = token.principal();
|
||||
if (KNOWN_USER.equals(actualUser) && SecuredString.constantTimeEquals(token.credentials(), KNOWN_PW)) {
|
||||
return new User(actualUser, ROLES);
|
||||
|
|
|
@ -1,29 +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.example.realm;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
|
||||
public class CustomRealmFactory extends Realm.Factory<CustomRealm> {
|
||||
|
||||
@Inject
|
||||
public CustomRealmFactory() {
|
||||
super(CustomRealm.TYPE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm create(RealmConfig config) {
|
||||
return new CustomRealm(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm createDefault(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -36,8 +37,10 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.action.SecurityActionModule;
|
||||
import org.elasticsearch.xpack.security.action.filter.SecurityActionFilter;
|
||||
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheAction;
|
||||
|
@ -63,11 +66,20 @@ import org.elasticsearch.xpack.security.action.user.TransportPutUserAction;
|
|||
import org.elasticsearch.xpack.security.audit.AuditTrailModule;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
|
||||
import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
|
||||
import org.elasticsearch.xpack.security.authc.InternalAuthenticationService;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.Realms;
|
||||
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
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;
|
||||
|
@ -197,11 +209,11 @@ public class Security implements ActionPlugin {
|
|||
}
|
||||
List<Class<? extends LifecycleComponent>> list = new ArrayList<>();
|
||||
list.add(FileRolesStore.class);
|
||||
list.add(Realms.class);
|
||||
return list;
|
||||
}
|
||||
|
||||
public Collection<Object> createComponents(ResourceWatcherService resourceWatcherService) {
|
||||
public Collection<Object> createComponents(InternalClient client, ThreadPool threadPool,
|
||||
ResourceWatcherService resourceWatcherService, List<XPackExtension> extensions) {
|
||||
if (enabled == false) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
@ -210,7 +222,27 @@ public class Security implements ActionPlugin {
|
|||
final ClientSSLService clientSSLService = new ClientSSLService(settings, env, globalSslConfig, resourceWatcherService);
|
||||
final ServerSSLService serverSSLService = new ServerSSLService(settings, env, globalSslConfig, resourceWatcherService);
|
||||
|
||||
return Arrays.asList(clientSSLService, serverSSLService);
|
||||
// realms construction
|
||||
final NativeUsersStore nativeUsersStore = new NativeUsersStore(settings, client, threadPool);
|
||||
final ReservedRealm reservedRealm = new ReservedRealm(env, settings, nativeUsersStore);
|
||||
Map<String, Realm.Factory> realmFactories = new HashMap<>();
|
||||
realmFactories.put(FileRealm.TYPE, config -> new FileRealm(config, resourceWatcherService));
|
||||
realmFactories.put(NativeRealm.TYPE, config -> new NativeRealm(config, nativeUsersStore));
|
||||
realmFactories.put(ActiveDirectoryRealm.TYPE,
|
||||
config -> new ActiveDirectoryRealm(config, resourceWatcherService, clientSSLService));
|
||||
realmFactories.put(LdapRealm.TYPE, config -> new LdapRealm(config, resourceWatcherService, clientSSLService));
|
||||
realmFactories.put(PkiRealm.TYPE, config -> new PkiRealm(config, resourceWatcherService));
|
||||
for (XPackExtension extension : extensions) {
|
||||
Map<String, Realm.Factory> newRealms = extension.getRealms();
|
||||
for (Map.Entry<String, Realm.Factory> entry : newRealms.entrySet()) {
|
||||
if (realmFactories.put(entry.getKey(), entry.getValue()) != null) {
|
||||
throw new IllegalArgumentException("Realm type [" + entry.getKey() + "] is already registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
final Realms realms = new Realms(settings, env, realmFactories, securityLicenseState, reservedRealm);
|
||||
|
||||
return Arrays.asList(clientSSLService, serverSSLService, nativeUsersStore, realms);
|
||||
}
|
||||
|
||||
public Settings additionalSettings() {
|
||||
|
|
|
@ -5,36 +5,16 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc;
|
||||
|
||||
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
|
||||
import org.elasticsearch.xpack.security.support.AbstractSecurityModule;
|
||||
import org.elasticsearch.xpack.security.user.AnonymousUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class AuthenticationModule extends AbstractSecurityModule.Node {
|
||||
|
||||
static final List<String> INTERNAL_REALM_TYPES =
|
||||
Arrays.asList(ReservedRealm.TYPE, NativeRealm.TYPE, FileRealm.TYPE, ActiveDirectoryRealm.TYPE, LdapRealm.TYPE, PkiRealm.TYPE);
|
||||
|
||||
private final Map<String, Class<? extends Realm.Factory<? extends Realm<? extends AuthenticationToken>>>> customRealms =
|
||||
new HashMap<>();
|
||||
|
||||
private Class<? extends AuthenticationFailureHandler> authcFailureHandler = null;
|
||||
|
||||
public AuthenticationModule(Settings settings) {
|
||||
|
@ -49,45 +29,14 @@ public class AuthenticationModule extends AbstractSecurityModule.Node {
|
|||
}
|
||||
|
||||
AnonymousUser.initialize(settings);
|
||||
MapBinder<String, Realm.Factory> mapBinder = MapBinder.newMapBinder(binder(), String.class, Realm.Factory.class);
|
||||
mapBinder.addBinding(FileRealm.TYPE).to(FileRealm.Factory.class).asEagerSingleton();
|
||||
mapBinder.addBinding(NativeRealm.TYPE).to(NativeRealm.Factory.class).asEagerSingleton();
|
||||
mapBinder.addBinding(ActiveDirectoryRealm.TYPE).to(ActiveDirectoryRealm.Factory.class).asEagerSingleton();
|
||||
mapBinder.addBinding(LdapRealm.TYPE).to(LdapRealm.Factory.class).asEagerSingleton();
|
||||
mapBinder.addBinding(PkiRealm.TYPE).to(PkiRealm.Factory.class).asEagerSingleton();
|
||||
for (Entry<String, Class<? extends Realm.Factory<? extends Realm<? extends AuthenticationToken>>>> entry :
|
||||
customRealms.entrySet()) {
|
||||
mapBinder.addBinding(entry.getKey()).to(entry.getValue()).asEagerSingleton();
|
||||
}
|
||||
|
||||
bind(ReservedRealm.class).asEagerSingleton();
|
||||
bind(Realms.class).asEagerSingleton();
|
||||
if (authcFailureHandler == null) {
|
||||
bind(AuthenticationFailureHandler.class).to(DefaultAuthenticationFailureHandler.class).asEagerSingleton();
|
||||
} else {
|
||||
bind(AuthenticationFailureHandler.class).to(authcFailureHandler).asEagerSingleton();
|
||||
}
|
||||
bind(NativeUsersStore.class).asEagerSingleton();
|
||||
bind(AuthenticationService.class).to(InternalAuthenticationService.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom realm type and factory for use as a authentication realm
|
||||
*
|
||||
* @param type the type of the realm that identifies it. Must not be null, empty, or the same value as one of the built-in realms
|
||||
* @param clazz the factory class that is used to create this type of realm. Must not be null
|
||||
*/
|
||||
public void addCustomRealm(String type, Class<? extends Realm.Factory<? extends Realm<? extends AuthenticationToken>>> clazz) {
|
||||
if (type == null || type.isEmpty()) {
|
||||
throw new IllegalArgumentException("type must not be null or empty");
|
||||
} else if (clazz == null) {
|
||||
throw new IllegalArgumentException("realm factory class cannot be null");
|
||||
} else if (INTERNAL_REALM_TYPES.contains(type)) {
|
||||
throw new IllegalArgumentException("cannot redefine the type [" + type + "] with custom realm [" + clazz.getName() + "]");
|
||||
}
|
||||
customRealms.put(type, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationFailureHandler} to the specified implementation
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.util.Map;
|
|||
* service } delegates the authentication process. Different realms may be defined, each may be based on different
|
||||
* authentication mechanism supporting its own specific authentication token type.
|
||||
*/
|
||||
public abstract class Realm<T extends AuthenticationToken> implements Comparable<Realm> {
|
||||
public abstract class Realm implements Comparable<Realm> {
|
||||
|
||||
protected final ESLogger logger;
|
||||
protected final String type;
|
||||
|
@ -67,7 +67,7 @@ public abstract class Realm<T extends AuthenticationToken> implements Comparable
|
|||
* @param context The context that will provide information about the incoming request
|
||||
* @return The authentication token or {@code null} if not found
|
||||
*/
|
||||
public abstract T token(ThreadContext context);
|
||||
public abstract AuthenticationToken token(ThreadContext context);
|
||||
|
||||
/**
|
||||
* Authenticates the given token. A successful authentication will return the User associated
|
||||
|
@ -76,7 +76,7 @@ public abstract class Realm<T extends AuthenticationToken> implements Comparable
|
|||
* @param token The authentication token
|
||||
* @return The authenticated user or {@code null} if authentication failed.
|
||||
*/
|
||||
public abstract User authenticate(T token);
|
||||
public abstract User authenticate(AuthenticationToken token);
|
||||
|
||||
/**
|
||||
* Looks up the user identified the String identifier. A successful lookup will return the {@link User} identified
|
||||
|
@ -107,44 +107,14 @@ public abstract class Realm<T extends AuthenticationToken> implements Comparable
|
|||
}
|
||||
|
||||
/**
|
||||
* A factory for a specific realm type. Knows how to create a new realm given the appropriate
|
||||
* settings. The factory will be called when creating a realm during the parsing of realms defined in the
|
||||
* elasticsearch.yml file
|
||||
* A factory interface to construct a security realm.
|
||||
*/
|
||||
public abstract static class Factory<R extends Realm> {
|
||||
|
||||
private final String type;
|
||||
private final boolean internal;
|
||||
|
||||
public Factory(String type, boolean internal) {
|
||||
this.type = type;
|
||||
this.internal = internal;
|
||||
}
|
||||
public interface Factory {
|
||||
|
||||
/**
|
||||
* @return The type of the ream this factory creates
|
||||
* Constructs a realm which will be used for authentication.
|
||||
* @param config The configuration for the realm
|
||||
*/
|
||||
public String type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean internal() {
|
||||
return internal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new realm based on the given settigns.
|
||||
*
|
||||
* @param config The configuration for the realm
|
||||
* @return The new realm (this method never returns {@code null}).
|
||||
*/
|
||||
public abstract R create(RealmConfig config);
|
||||
|
||||
/**
|
||||
* Creates a default realm, one that has no custom settings. Some realms might require minimal
|
||||
* settings, in which case, this method will return {@code null}.
|
||||
*/
|
||||
public abstract R createDefault(String name);
|
||||
Realm create(RealmConfig config);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,13 @@ import org.elasticsearch.common.settings.Setting.Property;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType;
|
||||
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
|
||||
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.SecurityLicenseState;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -34,6 +37,9 @@ import static org.elasticsearch.xpack.security.Security.setting;
|
|||
*/
|
||||
public class Realms extends AbstractLifecycleComponent implements Iterable<Realm> {
|
||||
|
||||
static final List<String> INTERNAL_REALM_TYPES =
|
||||
Arrays.asList(ReservedRealm.TYPE, NativeRealm.TYPE, FileRealm.TYPE, ActiveDirectoryRealm.TYPE, LdapRealm.TYPE, PkiRealm.TYPE);
|
||||
|
||||
public static final Setting<Settings> REALMS_GROUPS_SETTINGS = Setting.groupSetting(setting("authc.realms."), Property.NodeScope);
|
||||
|
||||
private final Environment env;
|
||||
|
@ -47,7 +53,6 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
|
|||
// a list of realms that are considered native, that is they only interact with x-pack and no 3rd party auth sources
|
||||
protected List<Realm> nativeRealmsOnly = Collections.emptyList();
|
||||
|
||||
@Inject
|
||||
public Realms(Settings settings, Environment env, Map<String, Realm.Factory> factories, SecurityLicenseState securityLicenseState,
|
||||
ReservedRealm reservedRealm) {
|
||||
super(settings);
|
||||
|
@ -67,7 +72,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
|
|||
List<Realm> nativeRealms = new ArrayList<>();
|
||||
for (Realm realm : realms) {
|
||||
// don't add the reserved realm here otherwise we end up with only this realm...
|
||||
if (AuthenticationModule.INTERNAL_REALM_TYPES.contains(realm.type()) && ReservedRealm.TYPE.equals(realm.type()) == false) {
|
||||
if (INTERNAL_REALM_TYPES.contains(realm.type()) && ReservedRealm.TYPE.equals(realm.type()) == false) {
|
||||
internalRealms.add(realm);
|
||||
}
|
||||
|
||||
|
@ -151,7 +156,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (factory.internal()) {
|
||||
if (FileRealm.TYPE.equals(type) || NativeRealm.TYPE.equals(type)) {
|
||||
// this is an internal realm factory, let's make sure we didn't already registered one
|
||||
// (there can only be one instance of an internal realm)
|
||||
if (internalTypes.contains(type)) {
|
||||
|
@ -202,11 +207,12 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
|
|||
private void addNativeRealms(List<Realm> realms) {
|
||||
Realm.Factory fileRealm = factories.get(FileRealm.TYPE);
|
||||
if (fileRealm != null) {
|
||||
realms.add(fileRealm.createDefault("default_" + FileRealm.TYPE));
|
||||
|
||||
realms.add(fileRealm.create(new RealmConfig("default_" + FileRealm.TYPE, Settings.EMPTY, settings, env)));
|
||||
}
|
||||
Realm.Factory indexRealmFactory = factories.get(NativeRealm.TYPE);
|
||||
if (indexRealmFactory != null) {
|
||||
realms.add(indexRealmFactory.createDefault("default_" + NativeRealm.TYPE));
|
||||
realms.add(indexRealmFactory.create(new RealmConfig("default_" + NativeRealm.TYPE, Settings.EMPTY, settings, env)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.activedirectory;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.AbstractLdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
|
||||
import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
|
||||
import org.elasticsearch.xpack.security.ssl.ClientSSLService;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -20,30 +19,13 @@ public class ActiveDirectoryRealm extends AbstractLdapRealm {
|
|||
|
||||
public static final String TYPE = "active_directory";
|
||||
|
||||
public ActiveDirectoryRealm(RealmConfig config,
|
||||
ActiveDirectorySessionFactory connectionFactory,
|
||||
DnRoleMapper roleMapper) {
|
||||
|
||||
super(TYPE, config, connectionFactory, roleMapper);
|
||||
public ActiveDirectoryRealm(RealmConfig config, ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
this(config, new ActiveDirectorySessionFactory(config, clientSSLService),
|
||||
new DnRoleMapper(TYPE, config, watcherService, null));
|
||||
}
|
||||
|
||||
public static class Factory extends AbstractLdapRealm.Factory<ActiveDirectoryRealm> {
|
||||
|
||||
private final ResourceWatcherService watcherService;
|
||||
private final ClientSSLService clientSSLService;
|
||||
|
||||
@Inject
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
super(ActiveDirectoryRealm.TYPE);
|
||||
this.watcherService = watcherService;
|
||||
this.clientSSLService = clientSSLService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActiveDirectoryRealm create(RealmConfig config) {
|
||||
ActiveDirectorySessionFactory connectionFactory = new ActiveDirectorySessionFactory(config, clientSSLService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(TYPE, config, watcherService, null);
|
||||
return new ActiveDirectoryRealm(config, connectionFactory, roleMapper);
|
||||
}
|
||||
// pkg private for tests
|
||||
ActiveDirectoryRealm(RealmConfig config, SessionFactory sessionFactory, DnRoleMapper roleMapper) {
|
||||
super(TYPE, config, sessionFactory, roleMapper);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.esnative;
|
||||
|
||||
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.unit.TimeValue;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
||||
import java.util.List;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
/**
|
||||
* User/password realm that is backed by an Elasticsearch index
|
||||
|
@ -58,30 +51,4 @@ public class NativeRealm extends CachingUsernamePasswordRealm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory extends Realm.Factory<NativeRealm> {
|
||||
|
||||
private final Settings settings;
|
||||
private final Environment env;
|
||||
private final NativeUsersStore userStore;
|
||||
|
||||
@Inject
|
||||
public Factory(Settings settings, Environment env, NativeUsersStore userStore) {
|
||||
super(TYPE, true);
|
||||
this.settings = settings;
|
||||
this.env = env;
|
||||
this.userStore = userStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeRealm create(RealmConfig config) {
|
||||
return new NativeRealm(config, userStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeRealm createDefault(String name) {
|
||||
RealmConfig config = new RealmConfig(name, Settings.EMPTY, settings, env);
|
||||
return create(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,7 +123,6 @@ public class NativeUsersStore extends AbstractComponent implements ClusterStateL
|
|||
|
||||
private volatile boolean securityIndexExists = false;
|
||||
|
||||
@Inject
|
||||
public NativeUsersStore(Settings settings, InternalClient client, ThreadPool threadPool) {
|
||||
super(settings);
|
||||
this.client = client;
|
||||
|
|
|
@ -35,7 +35,6 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
|
|||
|
||||
private final NativeUsersStore nativeUsersStore;
|
||||
|
||||
@Inject
|
||||
public ReservedRealm(Environment env, Settings settings, NativeUsersStore nativeUsersStore) {
|
||||
super(TYPE, new RealmConfig(TYPE, Settings.EMPTY, settings, env));
|
||||
this.nativeUsersStore = nativeUsersStore;
|
||||
|
|
|
@ -5,19 +5,14 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.file;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.RefreshListener;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -29,7 +24,12 @@ public class FileRealm extends CachingUsernamePasswordRealm {
|
|||
final FileUserPasswdStore userPasswdStore;
|
||||
final FileUserRolesStore userRolesStore;
|
||||
|
||||
public FileRealm(RealmConfig config, FileUserPasswdStore userPasswdStore, FileUserRolesStore userRolesStore) {
|
||||
public FileRealm(RealmConfig config, ResourceWatcherService watcherService) {
|
||||
this(config, new FileUserPasswdStore(config, watcherService), new FileUserRolesStore(config, watcherService));
|
||||
}
|
||||
|
||||
// pkg private for testing
|
||||
FileRealm(RealmConfig config, FileUserPasswdStore userPasswdStore, FileUserRolesStore userRolesStore) {
|
||||
super(TYPE, config);
|
||||
Listener listener = new Listener();
|
||||
this.userPasswdStore = userPasswdStore;
|
||||
|
@ -76,31 +76,4 @@ public class FileRealm extends CachingUsernamePasswordRealm {
|
|||
expireAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory extends UsernamePasswordRealm.Factory<FileRealm> {
|
||||
|
||||
private final Settings settings;
|
||||
private final Environment env;
|
||||
private final ResourceWatcherService watcherService;
|
||||
|
||||
@Inject
|
||||
public Factory(Settings settings, Environment env, ResourceWatcherService watcherService) {
|
||||
super(TYPE, true);
|
||||
this.settings = settings;
|
||||
this.env = env;
|
||||
this.watcherService = watcherService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileRealm create(RealmConfig config) {
|
||||
return new FileRealm(config, new FileUserPasswdStore(config, watcherService),
|
||||
new FileUserRolesStore(config, watcherService));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileRealm createDefault(String name) {
|
||||
RealmConfig config = new RealmConfig(name, Settings.EMPTY, settings, env);
|
||||
return create(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,18 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.ldap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.AbstractLdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
|
||||
import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
|
||||
import org.elasticsearch.xpack.security.ssl.ClientSSLService;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Authenticates username/password tokens against ldap, locates groups and maps them to roles.
|
||||
|
@ -26,55 +25,40 @@ public class LdapRealm extends AbstractLdapRealm {
|
|||
|
||||
public static final String TYPE = "ldap";
|
||||
|
||||
public LdapRealm(RealmConfig config, SessionFactory ldap, DnRoleMapper roleMapper) {
|
||||
super(TYPE, config, ldap, roleMapper);
|
||||
public LdapRealm(RealmConfig config, ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
this(config, sessionFactory(config, clientSSLService), new DnRoleMapper(TYPE, config, watcherService, null));
|
||||
}
|
||||
|
||||
// pkg private for testing
|
||||
LdapRealm(RealmConfig config, SessionFactory sessionFactory, DnRoleMapper roleMapper) {
|
||||
super(TYPE, config, sessionFactory, roleMapper);
|
||||
}
|
||||
|
||||
static SessionFactory sessionFactory(RealmConfig config, ClientSSLService clientSSLService) {
|
||||
Settings searchSettings = userSearchSettings(config);
|
||||
try {
|
||||
if (!searchSettings.names().isEmpty()) {
|
||||
if (config.settings().getAsArray(LdapSessionFactory.USER_DN_TEMPLATES_SETTING).length > 0) {
|
||||
throw new IllegalArgumentException("settings were found for both user search and user template modes of operation. " +
|
||||
"Please remove the settings for the mode you do not wish to use. For more details refer to the ldap " +
|
||||
"authentication section of the X-Pack guide.");
|
||||
}
|
||||
return new LdapUserSearchSessionFactory(config, clientSSLService);
|
||||
}
|
||||
return new LdapSessionFactory(config, clientSSLService);
|
||||
} catch (LDAPException e) {
|
||||
throw new ElasticsearchException("failed to create realm [{}/{}]", e, LdapRealm.TYPE, config.name());
|
||||
}
|
||||
}
|
||||
|
||||
static Settings userSearchSettings(RealmConfig config) {
|
||||
return config.settings().getAsSettings("user_search");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> usageStats() {
|
||||
Map<String, Object> stats = super.usageStats();
|
||||
stats.put("user_search", Factory.userSearchSettings(config).isEmpty() == false);
|
||||
stats.put("user_search", userSearchSettings(config).isEmpty() == false);
|
||||
return stats;
|
||||
}
|
||||
|
||||
public static class Factory extends AbstractLdapRealm.Factory<LdapRealm> {
|
||||
|
||||
private final ResourceWatcherService watcherService;
|
||||
private final ClientSSLService clientSSLService;
|
||||
|
||||
@Inject
|
||||
public Factory(ResourceWatcherService watcherService, ClientSSLService clientSSLService) {
|
||||
super(TYPE);
|
||||
this.watcherService = watcherService;
|
||||
this.clientSSLService = clientSSLService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LdapRealm create(RealmConfig config) {
|
||||
try {
|
||||
SessionFactory sessionFactory = sessionFactory(config, clientSSLService);
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(TYPE, config, watcherService, null);
|
||||
return new LdapRealm(config, sessionFactory, roleMapper);
|
||||
} catch (LDAPException e) {
|
||||
throw new ElasticsearchException("failed to create realm [{}/{}]", e, LdapRealm.TYPE, config.name());
|
||||
}
|
||||
}
|
||||
|
||||
static SessionFactory sessionFactory(RealmConfig config, ClientSSLService clientSSLService) throws LDAPException {
|
||||
Settings searchSettings = userSearchSettings(config);
|
||||
if (!searchSettings.names().isEmpty()) {
|
||||
if (config.settings().getAsArray(LdapSessionFactory.USER_DN_TEMPLATES_SETTING).length > 0) {
|
||||
throw new IllegalArgumentException("settings were found for both user search and user template modes of operation. " +
|
||||
"Please remove the settings for the mode you do not wish to use. For more details refer to the ldap " +
|
||||
"authentication section of the X-Pack guide.");
|
||||
}
|
||||
return new LdapUserSearchSessionFactory(config, clientSSLService);
|
||||
}
|
||||
return new LdapSessionFactory(config, clientSSLService);
|
||||
}
|
||||
|
||||
static Settings userSearchSettings(RealmConfig config) {
|
||||
return config.settings().getAsSettings("user_search");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,18 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.authc.ldap.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.unboundid.ldap.sdk.LDAPException;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
|
||||
import org.elasticsearch.xpack.security.authc.support.RefreshListener;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordRealm;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Supporting class for LDAP realms
|
||||
*/
|
||||
|
@ -101,21 +99,4 @@ public abstract class AbstractLdapRealm extends CachingUsernamePasswordRealm {
|
|||
expireAll();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class Factory<R extends AbstractLdapRealm> extends UsernamePasswordRealm.Factory<R> {
|
||||
|
||||
public Factory(String type) {
|
||||
super(type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP realms require minimum settings (e.g. URL), therefore they'll never create a default.
|
||||
*
|
||||
* @return {@code null} always
|
||||
*/
|
||||
@Override
|
||||
public final R createDefault(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import java.util.Set;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PkiRealm extends Realm<X509AuthenticationToken> {
|
||||
public class PkiRealm extends Realm {
|
||||
|
||||
public static final String PKI_CERT_HEADER_NAME = "__SECURITY_CLIENT_CERTIFICATE";
|
||||
public static final String TYPE = "pki";
|
||||
|
@ -51,7 +51,13 @@ public class PkiRealm extends Realm<X509AuthenticationToken> {
|
|||
private final Pattern principalPattern;
|
||||
private final DnRoleMapper roleMapper;
|
||||
|
||||
public PkiRealm(RealmConfig config, DnRoleMapper roleMapper) {
|
||||
|
||||
public PkiRealm(RealmConfig config, ResourceWatcherService watcherService) {
|
||||
this(config, new DnRoleMapper(TYPE, config, watcherService, null));
|
||||
}
|
||||
|
||||
// pkg private for testing
|
||||
PkiRealm(RealmConfig config, DnRoleMapper roleMapper) {
|
||||
super(TYPE, config);
|
||||
this.trustManagers = trustManagers(config.settings(), config.env());
|
||||
this.principalPattern = Pattern.compile(config.settings().get("username_pattern", DEFAULT_USERNAME_PATTERN),
|
||||
|
@ -71,7 +77,8 @@ public class PkiRealm extends Realm<X509AuthenticationToken> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(X509AuthenticationToken token) {
|
||||
public User authenticate(AuthenticationToken authToken) {
|
||||
X509AuthenticationToken token = (X509AuthenticationToken)authToken;
|
||||
if (!isCertificateChainTrusted(trustManagers, token, logger)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -222,26 +229,4 @@ public class PkiRealm extends Realm<X509AuthenticationToken> {
|
|||
logger.error("PKI realm [{}] is enabled but cannot be used as neither HTTP or Transport have both SSL and client authentication " +
|
||||
"enabled", config.name());
|
||||
}
|
||||
|
||||
public static class Factory extends Realm.Factory<PkiRealm> {
|
||||
|
||||
private final ResourceWatcherService watcherService;
|
||||
|
||||
@Inject
|
||||
public Factory(ResourceWatcherService watcherService) {
|
||||
super(TYPE, false);
|
||||
this.watcherService = watcherService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PkiRealm create(RealmConfig config) {
|
||||
DnRoleMapper roleMapper = new DnRoleMapper(TYPE, config, watcherService, null);
|
||||
return new PkiRealm(config, roleMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PkiRealm createDefault(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.elasticsearch.common.cache.Cache;
|
|||
import org.elasticsearch.common.cache.CacheBuilder;
|
||||
import org.elasticsearch.common.cache.CacheLoader;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
import org.elasticsearch.xpack.security.support.Exceptions;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
@ -63,11 +65,12 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
|
|||
* against a hash also stored in the cache. Otherwise the subclass authenticates the user via
|
||||
* doAuthenticate
|
||||
*
|
||||
* @param token The authentication token
|
||||
* @param authToken The authentication token
|
||||
* @return an authenticated user with roles
|
||||
*/
|
||||
@Override
|
||||
public final User authenticate(final UsernamePasswordToken token) {
|
||||
public final User authenticate(AuthenticationToken authToken) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken)authToken;
|
||||
if (cache == null) {
|
||||
return doAuthenticate(token);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import java.util.Locale;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class UsernamePasswordRealm extends Realm<UsernamePasswordToken> {
|
||||
public abstract class UsernamePasswordRealm extends Realm {
|
||||
|
||||
public UsernamePasswordRealm(String type, RealmConfig config) {
|
||||
super(type, config);
|
||||
|
@ -31,13 +31,6 @@ public abstract class UsernamePasswordRealm extends Realm<UsernamePasswordToken>
|
|||
return token instanceof UsernamePasswordToken;
|
||||
}
|
||||
|
||||
public abstract static class Factory<R extends UsernamePasswordRealm> extends Realm.Factory<R> {
|
||||
|
||||
protected Factory(String type, boolean internal) {
|
||||
super(type, internal);
|
||||
}
|
||||
}
|
||||
|
||||
public enum UserbaseSize {
|
||||
|
||||
TINY,
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.Realms;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class SecurityTests extends ESTestCase {
|
||||
|
||||
public static class DummyExtension extends XPackExtension {
|
||||
private String realmType;
|
||||
DummyExtension(String realmType) {
|
||||
this.realmType = realmType;
|
||||
}
|
||||
@Override
|
||||
public String name() {
|
||||
return "dummy";
|
||||
}
|
||||
@Override
|
||||
public String description() {
|
||||
return "dummy";
|
||||
}
|
||||
@Override
|
||||
public Map<String, Realm.Factory> getRealms() {
|
||||
return Collections.singletonMap(realmType, config -> null);
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<Object> createComponents(Settings testSettings, XPackExtension... extensions) throws IOException {
|
||||
Settings settings = Settings.builder().put(testSettings)
|
||||
.put("path.home", createTempDir()).build();
|
||||
Environment env = new Environment(settings);
|
||||
Security security = new Security(settings, env);
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
return security.createComponents(null, threadPool, null, Arrays.asList(extensions));
|
||||
}
|
||||
|
||||
private <T> T findComponent(Class<T> type, Collection<Object> components) {
|
||||
for (Object obj : components) {
|
||||
if (type.isInstance(obj)) {
|
||||
return type.cast(obj);
|
||||
}
|
||||
}
|
||||
throw new AssertionError("Could not find component of type " + type + " in components");
|
||||
}
|
||||
|
||||
public void testCustomRealmExtension() throws Exception {
|
||||
Collection<Object> components = createComponents(Settings.EMPTY, new DummyExtension("myrealm"));
|
||||
Realms realms = findComponent(Realms.class, components);
|
||||
assertNotNull(realms.realmFactory("myrealm"));
|
||||
}
|
||||
|
||||
public void testCustomRealmExtensionConflict() throws Exception {
|
||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> createComponents(Settings.EMPTY, new DummyExtension(FileRealm.TYPE)));
|
||||
assertEquals("Realm type [" + FileRealm.TYPE + "] is already registered", e.getMessage());
|
||||
}
|
||||
}
|
|
@ -1,57 +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.settings.Settings;
|
||||
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
|
||||
import org.elasticsearch.xpack.security.authc.file.FileRealm;
|
||||
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
/**
|
||||
* Unit tests for the AuthenticationModule
|
||||
*/
|
||||
public class AuthenticationModuleTests extends ESTestCase {
|
||||
public void testAddingReservedRealmType() {
|
||||
Settings settings = Settings.EMPTY;
|
||||
AuthenticationModule module = new AuthenticationModule(settings);
|
||||
try {
|
||||
module.addCustomRealm(randomFrom(PkiRealm.TYPE, LdapRealm.TYPE, ActiveDirectoryRealm.TYPE, FileRealm.TYPE),
|
||||
randomFrom(PkiRealm.Factory.class, LdapRealm.Factory.class, ActiveDirectoryRealm.Factory.class,
|
||||
FileRealm.Factory.class));
|
||||
fail("overriding a built in realm type is not allowed!");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("cannot redefine"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddingNullOrEmptyType() {
|
||||
Settings settings = Settings.EMPTY;
|
||||
AuthenticationModule module = new AuthenticationModule(settings);
|
||||
try {
|
||||
module.addCustomRealm(randomBoolean() ? null : "",
|
||||
randomFrom(PkiRealm.Factory.class, LdapRealm.Factory.class, ActiveDirectoryRealm.Factory.class,
|
||||
FileRealm.Factory.class));
|
||||
fail("type must not be null");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("null or empty"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddingNullFactory() {
|
||||
Settings settings = Settings.EMPTY;
|
||||
AuthenticationModule module = new AuthenticationModule(settings);
|
||||
try {
|
||||
module.addCustomRealm(randomAsciiOfLength(7), null);
|
||||
fail("factory must not be null");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("null"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,9 +33,6 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class RealmsTests extends ESTestCase {
|
||||
private Map<String, Realm.Factory> factories;
|
||||
private SecurityLicenseState securityLicenseState;
|
||||
|
@ -44,11 +41,11 @@ public class RealmsTests extends ESTestCase {
|
|||
@Before
|
||||
public void init() throws Exception {
|
||||
factories = new HashMap<>();
|
||||
factories.put(FileRealm.TYPE, new DummyRealm.Factory(FileRealm.TYPE, true));
|
||||
factories.put(NativeRealm.TYPE, new DummyRealm.Factory(NativeRealm.TYPE, true));
|
||||
factories.put(FileRealm.TYPE, config -> new DummyRealm(FileRealm.TYPE, config));
|
||||
factories.put(NativeRealm.TYPE, config -> new DummyRealm(NativeRealm.TYPE, config));
|
||||
for (int i = 0; i < randomIntBetween(1, 5); i++) {
|
||||
DummyRealm.Factory factory = new DummyRealm.Factory("type_" + i, rarely());
|
||||
factories.put("type_" + i, factory);
|
||||
String name = "type_" + i;
|
||||
factories.put(name, config -> new DummyRealm(name, config));
|
||||
}
|
||||
securityLicenseState = mock(SecurityLicenseState.class);
|
||||
reservedRealm = mock(ReservedRealm.class);
|
||||
|
@ -195,7 +192,7 @@ public class RealmsTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testUnlicensedWithInternalRealms() throws Exception {
|
||||
factories.put(LdapRealm.TYPE, new DummyRealm.Factory(LdapRealm.TYPE, false));
|
||||
factories.put(LdapRealm.TYPE, config -> new DummyRealm(LdapRealm.TYPE, config));
|
||||
assertThat(factories.get("type_0"), notNullValue());
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put("path.home", createTempDir())
|
||||
|
@ -252,7 +249,7 @@ public class RealmsTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testUnlicensedWithNativeRealms() throws Exception {
|
||||
factories.put(LdapRealm.TYPE, new DummyRealm.Factory(LdapRealm.TYPE, false));
|
||||
factories.put(LdapRealm.TYPE, config -> new DummyRealm(LdapRealm.TYPE, config));
|
||||
final String type = randomFrom(FileRealm.TYPE, NativeRealm.TYPE);
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put("path.home", createTempDir())
|
||||
|
@ -385,26 +382,5 @@ public class RealmsTests extends ESTestCase {
|
|||
public boolean userLookupSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static class Factory extends Realm.Factory<DummyRealm> {
|
||||
|
||||
public Factory(String type, boolean internal) {
|
||||
super(type, internal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DummyRealm create(RealmConfig config) {
|
||||
return new DummyRealm(type(), config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DummyRealm createDefault(String name) {
|
||||
if (type().equals(NativeRealm.TYPE) || type().equals(FileRealm.TYPE)) {
|
||||
return new DummyRealm(type(), new RealmConfig(name, Settings.EMPTY,
|
||||
Settings.builder().put("path.home", createTempDir()).build()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
.put(HOSTNAME_VERIFICATION_SETTING, false)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings);
|
||||
SessionFactory sessionFactory = LdapRealm.Factory.sessionFactory(config, null);
|
||||
SessionFactory sessionFactory = LdapRealm.sessionFactory(config, null);
|
||||
assertThat(sessionFactory, is(instanceOf(LdapSessionFactory.class)));
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
.put(HOSTNAME_VERIFICATION_SETTING, false)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, globalSettings);
|
||||
SessionFactory sessionFactory = LdapRealm.Factory.sessionFactory(config, null);
|
||||
SessionFactory sessionFactory = LdapRealm.sessionFactory(config, null);
|
||||
try {
|
||||
assertThat(sessionFactory, is(instanceOf(LdapUserSearchSessionFactory.class)));
|
||||
} finally {
|
||||
|
@ -199,7 +199,7 @@ public class LdapRealmTests extends LdapTestCase {
|
|||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, globalSettings);
|
||||
try {
|
||||
LdapRealm.Factory.sessionFactory(config, null);
|
||||
LdapRealm.sessionFactory(config, null);
|
||||
fail("an exception should have been thrown because both user template and user search settings were specified");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("settings were found for both user search and user template"));
|
||||
|
|
|
@ -142,7 +142,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testAuthenticateContract() throws Exception {
|
||||
Realm<UsernamePasswordToken> realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
Realm realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
User user = realm.authenticate(new UsernamePasswordToken("user", SecuredStringTests.build("pass")));
|
||||
assertThat(user , nullValue());
|
||||
|
||||
|
@ -152,7 +152,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testLookupContract() throws Exception {
|
||||
Realm<UsernamePasswordToken> realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
Realm realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings);
|
||||
User user = realm.lookupUser("user");
|
||||
assertThat(user , nullValue());
|
||||
|
||||
|
|
|
@ -191,8 +191,8 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin {
|
|||
components.add(internalClient);
|
||||
|
||||
components.addAll(licensing.createComponents(clusterService, getClock(), env, resourceWatcherService,
|
||||
security.getSecurityLicenseState()));
|
||||
components.addAll(security.createComponents(resourceWatcherService));
|
||||
security.getSecurityLicenseState()));
|
||||
components.addAll(security.createComponents(internalClient, threadPool, resourceWatcherService, extensionsService.getExtensions()));
|
||||
|
||||
// watcher http stuff
|
||||
Map<String, HttpAuthFactory> httpAuthFactories = new HashMap<>();
|
||||
|
|
|
@ -7,8 +7,12 @@ package org.elasticsearch.xpack.extensions;
|
|||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -36,4 +40,16 @@ public abstract class XPackExtension {
|
|||
public Collection<String> getRestHeaders() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns authentication realm implementations added by this extension.
|
||||
*
|
||||
* The key of the returned {@link Map} is the type name of the realm, and the value
|
||||
* is a {@link org.elasticsearch.xpack.security.authc.Realm.Factory} which will construct
|
||||
* that realm for use in authentication when that realm type is configured.
|
||||
*/
|
||||
public Map<String, Realm.Factory> getRealms() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue