From 9df99573070017534b0400edef21819ea037455a Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 15 Jul 2016 13:01:02 -0700 Subject: [PATCH] Remove guice from realms construction This change makes the internal realms factories, as well as those added by extensions, constructed directly instead of via guice. Adding realms in extensions is now pull based. Finally, all of the generics for realms and realm factories have been removed. Original commit: elastic/x-pack-elasticsearch@f0de9d2340e60b588be8660920d39fd8ef380058 --- .../example/ExampleRealmExtension.java | 24 ++++-- .../example/realm/CustomRealm.java | 5 +- .../example/realm/CustomRealmFactory.java | 29 ------- .../xpack/security/Security.java | 38 ++++++++- .../security/authc/AuthenticationModule.java | 51 ------------ .../xpack/security/authc/Realm.java | 46 ++--------- .../xpack/security/authc/Realms.java | 16 ++-- .../activedirectory/ActiveDirectoryRealm.java | 34 ++------ .../security/authc/esnative/NativeRealm.java | 39 +-------- .../authc/esnative/NativeUsersStore.java | 1 - .../authc/esnative/ReservedRealm.java | 1 - .../xpack/security/authc/file/FileRealm.java | 45 +++-------- .../xpack/security/authc/ldap/LdapRealm.java | 79 +++++++------------ .../authc/ldap/support/AbstractLdapRealm.java | 29 ++----- .../xpack/security/authc/pki/PkiRealm.java | 35 +++----- .../support/CachingUsernamePasswordRealm.java | 7 +- .../authc/support/UsernamePasswordRealm.java | 9 +-- .../xpack/security/SecurityTests.java | 33 ++++++++ .../authc/AuthenticationModuleTests.java | 57 ------------- .../xpack/security/authc/RealmsTests.java | 36 ++------- .../security/authc/ldap/LdapRealmTests.java | 6 +- .../CachingUsernamePasswordRealmTests.java | 4 +- .../org/elasticsearch/xpack/XPackPlugin.java | 4 +- .../xpack/extensions/XPackExtension.java | 16 ++++ 24 files changed, 205 insertions(+), 439 deletions(-) delete mode 100644 elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java create mode 100644 elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java delete mode 100644 elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationModuleTests.java diff --git a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmExtension.java b/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmExtension.java index c859489e5ee..86d4091a08e 100644 --- a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmExtension.java +++ b/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmExtension.java @@ -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) () -> { + 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) () -> { - System.getSecurityManager().checkPrintJobAccess(); - return null; - }); + } + + @Override + public Map getRealms() { + return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new); } @Override diff --git a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java b/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java index f1cc2dc9a80..aee93517fdd 100644 --- a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java +++ b/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java @@ -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 { +public class CustomRealm extends Realm { public static final String TYPE = "custom"; @@ -46,7 +46,8 @@ public class CustomRealm extends Realm { } @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); diff --git a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java b/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java deleted file mode 100644 index b1f65bbeccf..00000000000 --- a/elasticsearch/qa/security-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java +++ /dev/null @@ -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 { - - @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; - } -} diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java index aa0764b9458..faeaeebfee5 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -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> list = new ArrayList<>(); list.add(FileRolesStore.class); - list.add(Realms.class); return list; } - public Collection createComponents(ResourceWatcherService resourceWatcherService) { + public Collection createComponents(InternalClient client, ThreadPool threadPool, + ResourceWatcherService resourceWatcherService, List 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 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 newRealms = extension.getRealms(); + for (Map.Entry 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() { diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java index afdf6f563c2..57491d0c12e 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java @@ -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 INTERNAL_REALM_TYPES = - Arrays.asList(ReservedRealm.TYPE, NativeRealm.TYPE, FileRealm.TYPE, ActiveDirectoryRealm.TYPE, LdapRealm.TYPE, PkiRealm.TYPE); - - private final Map>>> customRealms = - new HashMap<>(); - private Class authcFailureHandler = null; public AuthenticationModule(Settings settings) { @@ -49,45 +29,14 @@ public class AuthenticationModule extends AbstractSecurityModule.Node { } AnonymousUser.initialize(settings); - MapBinder 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>>> 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>> 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 */ diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java index dd5a9f404c3..078ff26c76e 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java @@ -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 implements Comparable { +public abstract class Realm implements Comparable { protected final ESLogger logger; protected final String type; @@ -67,7 +67,7 @@ public abstract class Realm 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 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 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 { - - 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); } - } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java index 470c664f2e1..2fda12f8b42 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/Realms.java @@ -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 { + static final List INTERNAL_REALM_TYPES = + Arrays.asList(ReservedRealm.TYPE, NativeRealm.TYPE, FileRealm.TYPE, ActiveDirectoryRealm.TYPE, LdapRealm.TYPE, PkiRealm.TYPE); + public static final Setting 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 nativeRealmsOnly = Collections.emptyList(); - @Inject public Realms(Settings settings, Environment env, Map factories, SecurityLicenseState securityLicenseState, ReservedRealm reservedRealm) { super(settings); @@ -67,7 +72,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterable 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 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))); } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/activedirectory/ActiveDirectoryRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/activedirectory/ActiveDirectoryRealm.java index 1596ba47d53..19a72fe90d5 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/activedirectory/ActiveDirectoryRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/activedirectory/ActiveDirectoryRealm.java @@ -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).init(), + new DnRoleMapper(TYPE, config, watcherService, null)); } - public static class Factory extends AbstractLdapRealm.Factory { - - 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).init(); - 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); } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java index be8b2a65250..e018c5e3ac8 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java @@ -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 { - - 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); - } - } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java index 78af963ca9c..e8e3ea3e08b 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java @@ -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; diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java index 52aa20550af..4dbafd1b39d 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java @@ -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; diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java index a582f76931f..bd17724107c 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java @@ -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 { - - 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); - } - } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java index cc1a739f36d..4f0fc570592 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java @@ -5,19 +5,15 @@ */ package org.elasticsearch.xpack.security.authc.ldap; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.inject.Inject; +import java.util.Map; + 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.io.IOException; -import java.util.Map; /** * Authenticates username/password tokens against ldap, locates groups and maps them to roles. @@ -26,55 +22,36 @@ 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); + 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).init(); + } + return new LdapSessionFactory(config, clientSSLService).init(); + } + + static Settings userSearchSettings(RealmConfig config) { + return config.settings().getAsSettings("user_search"); } @Override public Map usageStats() { Map 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 { - - 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 (IOException e) { - throw new ElasticsearchException("failed to create realm [{}/{}]", e, LdapRealm.TYPE, config.name()); - } - } - - static SessionFactory sessionFactory(RealmConfig config, ClientSSLService clientSSLService) throws IOException { - 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).init(); - } - return new LdapSessionFactory(config, clientSSLService).init(); - } - - static Settings userSearchSettings(RealmConfig config) { - return config.settings().getAsSettings("user_search"); - } - } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/AbstractLdapRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/AbstractLdapRealm.java index 68ef7ea0e7f..4c542f44e8b 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/AbstractLdapRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/AbstractLdapRealm.java @@ -5,18 +5,16 @@ */ package org.elasticsearch.xpack.security.authc.ldap.support; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.xpack.security.user.User; +import java.util.List; +import java.util.Map; +import java.util.Set; + 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; +import org.elasticsearch.xpack.security.user.User; /** * Supporting class for LDAP realms @@ -100,21 +98,4 @@ public abstract class AbstractLdapRealm extends CachingUsernamePasswordRealm { expireAll(); } } - - public abstract static class Factory extends UsernamePasswordRealm.Factory { - - 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; - } - } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java index 9d129799612..d128d25f092 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java @@ -38,7 +38,7 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class PkiRealm extends Realm { +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 { 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 { } @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 { 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 { - - 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; - } - } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java index 5cd1e69288d..54e5b59b1d6 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java @@ -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); } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/UsernamePasswordRealm.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/UsernamePasswordRealm.java index 24d08517c26..1bac5a68aab 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/UsernamePasswordRealm.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/support/UsernamePasswordRealm.java @@ -16,7 +16,7 @@ import java.util.Locale; /** * */ -public abstract class UsernamePasswordRealm extends Realm { +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 return token instanceof UsernamePasswordToken; } - public abstract static class Factory extends Realm.Factory { - - protected Factory(String type, boolean internal) { - super(type, internal); - } - } - public enum UserbaseSize { TINY, diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java new file mode 100644 index 00000000000..a04880ebb12 --- /dev/null +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java @@ -0,0 +1,33 @@ +/* + * 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.env.Environment; +import org.elasticsearch.test.ESTestCase; +import org.junit.Before; + +public class SecurityTests extends ESTestCase { + + private Environment env; + + @Before + public void setupEnv() { + Settings settings = Settings.builder() + .put("path.home", createTempDir()).build(); + env = new Environment(settings); + } + + public void testCustomRealmExtension() throws Exception { + Security security = new Security(Settings.EMPTY, env); + + //security.createComponents(null, null, null, ) + } + + public void testCustomRealmExtensionConflict() throws Exception { + + } +} diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationModuleTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationModuleTests.java deleted file mode 100644 index aedd3a25917..00000000000 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationModuleTests.java +++ /dev/null @@ -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")); - } - } -} diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java index f58558aec77..2102a461789 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java @@ -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 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 { - - 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; - } - } } } diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java index 56588941cfe..1f90bc69610 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java @@ -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")); diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java index 09b1e12852b..bd45c406c46 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java @@ -142,7 +142,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { } public void testAuthenticateContract() throws Exception { - Realm 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 realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings); + Realm realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings); User user = realm.lookupUser("user"); assertThat(user , nullValue()); diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index 63322c8aba3..1203ccb16a1 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -192,8 +192,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 httpAuthFactories = new HashMap<>(); diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/extensions/XPackExtension.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/extensions/XPackExtension.java index 11459645663..be819449dc7 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/extensions/XPackExtension.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/extensions/XPackExtension.java @@ -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 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 getRealms() { + return Collections.emptyMap(); + } }