From 56957f98bc9efe54d648400d4000ac6cd9e04eed Mon Sep 17 00:00:00 2001 From: uboness Date: Fri, 16 Jan 2015 01:42:40 +0100 Subject: [PATCH] [Fix] All loggers are not contextual Meaning, all loggers are now settings aware, so all shield logs are now consistent with the rest of elasticsearch and will follow elasticsearch configuration and output format (printing out the node name by default). Also: - Changed the audit log to **not** be based on the elasticsearch settings as it needs to define its own format. - Added the node name as a prefix to the audit logs by default (can be disabled but setting `shield.audit.logfile.prefix.node_name` to `false` - As part of this change, the realms now changed and now created with a `RealmConfig`. This construct holds the realm settings, the environment and is served as a logger factory for all realm constructs. - The only exceptions to the logs are the ssl socket factories.. the logs there are only used for tests by calling `clear`. This behaviour will change in the future such that `clear` will be removed and then there'll be no need for loggers in there. Fixes elastic/elasticsearch#446 Original commit: elastic/x-pack-elasticsearch@7a1058a54e769d414baf2670398a413c8710d8ee --- .../shield/action/ShieldActionFilter.java | 11 +- .../audit/logfile/LoggingAuditTrail.java | 102 ++++++++++++------ .../org/elasticsearch/shield/authc/Realm.java | 26 ++--- .../shield/authc/RealmConfig.java | 67 ++++++++++++ .../elasticsearch/shield/authc/Realms.java | 13 ++- .../ActiveDirectoryConnection.java | 7 +- .../ActiveDirectoryConnectionFactory.java | 10 +- .../ActiveDirectoryGroupToRoleMapper.java | 7 +- .../ActiveDirectoryRealm.java | 26 ++--- .../shield/authc/esusers/ESUsersRealm.java | 20 ++-- .../authc/esusers/FileUserPasswdStore.java | 13 +-- .../authc/esusers/FileUserRolesStore.java | 17 +-- .../shield/authc/ldap/LdapConnection.java | 7 +- .../authc/ldap/LdapConnectionFactory.java | 11 +- .../authc/ldap/LdapGroupToRoleMapper.java | 7 +- .../shield/authc/ldap/LdapRealm.java | 24 ++--- .../support/CachingUsernamePasswordRealm.java | 12 +-- .../authc/support/UsernamePasswordRealm.java | 6 +- .../ldap/AbstractGroupToRoleMapper.java | 32 +++--- .../support/ldap/AbstractLdapConnection.java | 11 +- .../authc/support/ldap/AbstractLdapRealm.java | 6 +- .../ldap/AbstractLdapSslSocketFactory.java | 4 - .../ldap/ClosableNamingEnumeration.java | 1 + .../authc/support/ldap/ConnectionFactory.java | 20 ++-- ...HostnameVerifyingLdapSslSocketFactory.java | 6 ++ .../support/ldap/LdapSslSocketFactory.java | 5 + .../netty/HandshakeWaitingHandler.java | 11 +- .../netty/NettySecuredTransport.java | 3 +- .../action/ShieldActionFilterTests.java | 3 +- .../audit/logfile/LoggingAuditTrailTests.java | 92 +++++++++------- .../InternalAuthenticationServiceTests.java | 4 +- .../shield/authc/RealmsTests.java | 35 +++--- .../ActiveDirectoryFactoryTests.java | 32 +++--- .../authc/esusers/ESUsersRealmTests.java | 30 +++--- .../esusers/FileUserPasswdStoreTests.java | 5 +- .../esusers/FileUserRolesStoreTests.java | 8 +- .../authc/ldap/LdapConnectionTests.java | 23 ++-- .../authc/ldap/LdapGroupToRoleMapperTest.java | 14 +-- .../shield/authc/ldap/LdapRealmTest.java | 52 +++++---- .../shield/authc/ldap/OpenLdapTests.java | 22 ++-- .../CachingUsernamePasswordRealmTests.java | 7 +- .../support/ldap/ConnectionFactoryTests.java | 12 +-- .../shield/authc/support/ldap/LdapTest.java | 5 +- .../netty/HandshakeWaitingHandlerTests.java | 13 ++- 44 files changed, 513 insertions(+), 329 deletions(-) create mode 100644 src/main/java/org/elasticsearch/shield/authc/RealmConfig.java diff --git a/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java b/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java index 94c09c628e5..882b578b4e9 100644 --- a/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java +++ b/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java @@ -14,9 +14,9 @@ import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.support.ActionFilter; import org.elasticsearch.action.support.ActionFilterChain; import org.elasticsearch.common.base.Predicate; +import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.plugin.core.LicenseExpiredException; import org.elasticsearch.license.plugin.core.LicensesClientService; import org.elasticsearch.shield.User; @@ -36,12 +36,10 @@ import java.util.List; /** * */ -public class ShieldActionFilter implements ActionFilter { +public class ShieldActionFilter extends AbstractComponent implements ActionFilter { public static final String CLUSTER_PERMISSION_SCROLL_CLEAR_ALL_NAME = "cluster:admin/indices/scroll/clear_all"; - private static final ESLogger logger = Loggers.getLogger(ShieldActionFilter.class); - private static final Predicate READ_ACTION_MATCHER = Privilege.Index.READ.predicate(); private final AuthenticationService authcService; @@ -52,7 +50,8 @@ public class ShieldActionFilter implements ActionFilter { private volatile boolean licenseEnabled; @Inject - public ShieldActionFilter(AuthenticationService authcService, AuthorizationService authzService, SignatureService signatureService, AuditTrail auditTrail, LicenseEventsNotifier licenseEventsNotifier) { + public ShieldActionFilter(Settings settings, AuthenticationService authcService, AuthorizationService authzService, SignatureService signatureService, AuditTrail auditTrail, LicenseEventsNotifier licenseEventsNotifier) { + super(settings); this.authcService = authcService; this.authzService = authzService; this.signatureService = signatureService; diff --git a/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java b/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java index d0a7b512d34..0b8378b86bc 100644 --- a/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java +++ b/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java @@ -23,6 +23,7 @@ import org.elasticsearch.transport.TransportRequest; import java.io.IOException; import java.net.InetAddress; +import java.net.UnknownHostException; /** * @@ -31,6 +32,7 @@ public class LoggingAuditTrail implements AuditTrail { public static final String NAME = "logfile"; + private final String prefix; private final ESLogger logger; @Override @@ -40,11 +42,20 @@ public class LoggingAuditTrail implements AuditTrail { @Inject public LoggingAuditTrail(Settings settings) { - this(Loggers.getLogger(LoggingAuditTrail.class, settings)); + this(resolvePrefix(settings), Loggers.getLogger(LoggingAuditTrail.class)); + } + + LoggingAuditTrail(Settings settings, ESLogger logger) { + this(resolvePrefix(settings), logger); } LoggingAuditTrail(ESLogger logger) { + this("", logger); + } + + LoggingAuditTrail(String prefix, ESLogger logger) { this.logger = logger; + this.prefix = prefix; } @Override @@ -52,15 +63,15 @@ public class LoggingAuditTrail implements AuditTrail { String indices = indices(message); if (indices != null) { if (logger.isDebugEnabled()) { - logger.debug("ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}], request=[{}]", message.remoteAddress(), action, indices, message.getClass().getSimpleName()); + logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), action, indices, message.getClass().getSimpleName()); } else { - logger.warn("ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}]", message.remoteAddress(), action, indices); + logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), action, indices); } } else { if (logger.isDebugEnabled()) { - logger.debug("ANONYMOUS_ACCESS\thost=[{}], action=[{}], request=[{}]", message.remoteAddress(), action, message.getClass().getSimpleName()); + logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), action, message.getClass().getSimpleName()); } else { - logger.warn("ANONYMOUS_ACCESS\thost=[{}], action=[{}]", message.remoteAddress(), action); + logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], action=[{}]", prefix, message.remoteAddress(), action); } } } @@ -68,9 +79,9 @@ public class LoggingAuditTrail implements AuditTrail { @Override public void anonymousAccess(RestRequest request) { if (logger.isDebugEnabled()) { - logger.debug("ANONYMOUS_ACCESS\thost=[{}], URI=[{}], request=[{}]", request.getRemoteAddress(), request.uri(), restRequestContent(request)); + logger.debug("{}ANONYMOUS_ACCESS\thost=[{}], URI=[{}], request=[{}]", prefix, request.getRemoteAddress(), request.uri(), restRequestContent(request)); } else { - logger.warn("ANONYMOUS_ACCESS\thost=[{}], URI=[{}]", request.getRemoteAddress(), request.uri()); + logger.warn("{}ANONYMOUS_ACCESS\thost=[{}], URI=[{}]", prefix, request.getRemoteAddress(), request.uri()); } } @@ -79,15 +90,15 @@ public class LoggingAuditTrail implements AuditTrail { String indices = indices(message); if (indices != null) { if (logger.isDebugEnabled()) { - logger.debug("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName()); + logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName()); } else { - logger.error("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", message.remoteAddress(), token.principal(), action, indices); + logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), token.principal(), action, indices); } } else { if (logger.isDebugEnabled()) { - logger.debug("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], request=[{}]", message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName()); + logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName()); } else { - logger.error("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}]", message.remoteAddress(), token.principal(), action); + logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), token.principal(), action); } } } @@ -95,9 +106,9 @@ public class LoggingAuditTrail implements AuditTrail { @Override public void authenticationFailed(AuthenticationToken token, RestRequest request) { if (logger.isDebugEnabled()) { - logger.debug("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}], request=[{}]", request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request)); + logger.debug("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}], request=[{}]", prefix, request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request)); } else { - logger.error("AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}]", request.getRemoteAddress(), token.principal(), request.uri()); + logger.error("{}AUTHENTICATION_FAILED\thost=[{}], principal=[{}], URI=[{}]", prefix, request.getRemoteAddress(), token.principal(), request.uri()); } } @@ -106,9 +117,9 @@ public class LoggingAuditTrail implements AuditTrail { if (logger.isTraceEnabled()) { String indices = indices(message); if (indices != null) { - logger.trace("AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", realm, message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName()); + logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, realm, message.remoteAddress(), token.principal(), action, indices, message.getClass().getSimpleName()); } else { - logger.trace("AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], request=[{}]", realm, message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName()); + logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, realm, message.remoteAddress(), token.principal(), action, message.getClass().getSimpleName()); } } } @@ -116,7 +127,7 @@ public class LoggingAuditTrail implements AuditTrail { @Override public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) { if (logger.isTraceEnabled()) { - logger.trace("AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], URI=[{}], request=[{}]", realm, request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request)); + logger.trace("{}AUTHENTICATION_FAILED[{}]\thost=[{}], principal=[{}], URI=[{}], request=[{}]", prefix, realm, request.getRemoteAddress(), token.principal(), request.uri(), restRequestContent(request)); } } @@ -128,9 +139,9 @@ public class LoggingAuditTrail implements AuditTrail { if (Privilege.SYSTEM.internalActionPredicate().apply(action)) { if (logger.isTraceEnabled()) { if (indices != null) { - logger.trace("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); + logger.trace("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); } else { - logger.trace("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); + logger.trace("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); } } return; @@ -138,15 +149,15 @@ public class LoggingAuditTrail implements AuditTrail { if (indices != null) { if (logger.isDebugEnabled()) { - logger.debug("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); + logger.debug("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); } else { - logger.info("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", message.remoteAddress(), user.principal(), action, indices); + logger.info("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices); } } else { if (logger.isDebugEnabled()) { - logger.debug("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); + logger.debug("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); } else { - logger.info("ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}]", message.remoteAddress(), user.principal(), action); + logger.info("{}ACCESS_GRANTED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), user.principal(), action); } } } @@ -156,15 +167,15 @@ public class LoggingAuditTrail implements AuditTrail { String indices = indices(message); if (indices != null) { if (logger.isDebugEnabled()) { - logger.debug("ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); + logger.debug("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices, message.getClass().getSimpleName()); } else { - logger.error("ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", message.remoteAddress(), user.principal(), action, indices); + logger.error("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, message.remoteAddress(), user.principal(), action, indices); } } else { if (logger.isDebugEnabled()) { - logger.debug("ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], request=[{}]", message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); + logger.debug("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, message.remoteAddress(), user.principal(), action, message.getClass().getSimpleName()); } else { - logger.error("ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}]", message.remoteAddress(), user.principal(), action); + logger.error("{}ACCESS_DENIED\thost=[{}], principal=[{}], action=[{}]", prefix, message.remoteAddress(), user.principal(), action); } } } @@ -174,15 +185,15 @@ public class LoggingAuditTrail implements AuditTrail { String indices = indices(request); if (indices != null) { if (logger.isDebugEnabled()) { - logger.debug("TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", request.remoteAddress(), user.principal(), action, indices, request.getClass().getSimpleName()); + logger.debug("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices, request.getClass().getSimpleName()); } else { - logger.error("TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}]", request.remoteAddress(), user.principal(), action, indices); + logger.error("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], indices=[{}]", prefix, request.remoteAddress(), user.principal(), action, indices); } } else { if (logger.isDebugEnabled()) { - logger.debug("TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], request=[{}]", request.remoteAddress(), user.principal(), action, request.getClass().getSimpleName()); + logger.debug("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}], request=[{}]", prefix, request.remoteAddress(), user.principal(), action, request.getClass().getSimpleName()); } else { - logger.error("TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}]", request.remoteAddress(), user.principal(), action); + logger.error("{}TAMPERED REQUEST\thost=[{}], principal=[{}], action=[{}]", prefix, request.remoteAddress(), user.principal(), action); } } } @@ -190,13 +201,13 @@ public class LoggingAuditTrail implements AuditTrail { @Override public void connectionGranted(InetAddress inetAddress, String profile, ShieldIpFilterRule rule) { if (logger.isTraceEnabled()) { - logger.trace("CONNECTION_GRANTED\thost=[{}], profile=[{}], rule=[{}]", inetAddress.getHostAddress(), profile, rule); + logger.trace("{}CONNECTION_GRANTED\thost=[{}], profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule); } } @Override public void connectionDenied(InetAddress inetAddress, String profile, ShieldIpFilterRule rule) { - logger.error("CONNECTION_DENIED\thost=[{}], profile=[{}], rule=[{}]", inetAddress.getHostAddress(), profile, rule); + logger.error("{}CONNECTION_DENIED\thost=[{}], profile=[{}], rule=[{}]", prefix, inetAddress.getHostAddress(), profile, rule); } private static String indices(TransportMessage message) { @@ -216,4 +227,31 @@ public class LoggingAuditTrail implements AuditTrail { } return ""; } + + static String resolvePrefix(Settings settings) { + StringBuilder builder = new StringBuilder(); + if (settings.getAsBoolean("shield.audit.logfile.prefix.node_host_address", false)) { + try { + String address = InetAddress.getLocalHost().getHostAddress(); + builder.append("[").append(address).append("] "); + } catch (UnknownHostException e) { + // ignore + } + } + if (settings.getAsBoolean("shield.audit.logfile.prefix.node_host_name", false)) { + try { + String hostName = InetAddress.getLocalHost().getHostName(); + builder.append("[").append(hostName).append("] "); + } catch (UnknownHostException e) { + // ignore + } + } + if (settings.getAsBoolean("shield.audit.logfile.prefix.node_name", true)) { + String name = settings.get("name"); + if (name != null) { + builder.append("[").append(name).append("] "); + } + } + return builder.toString(); + } } diff --git a/src/main/java/org/elasticsearch/shield/authc/Realm.java b/src/main/java/org/elasticsearch/shield/authc/Realm.java index ce8bb32acef..1cce4d0d607 100644 --- a/src/main/java/org/elasticsearch/shield/authc/Realm.java +++ b/src/main/java/org/elasticsearch/shield/authc/Realm.java @@ -6,8 +6,6 @@ package org.elasticsearch.shield.authc; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.User; import org.elasticsearch.transport.TransportMessage; @@ -19,18 +17,14 @@ import org.elasticsearch.transport.TransportMessage; */ public abstract class Realm implements Comparable { - protected final ESLogger logger = Loggers.getLogger(getClass()); - + protected final ESLogger logger; protected final String type; - protected final String name; - protected final Settings settings; - protected final int order; + protected RealmConfig config; - public Realm(String type, String name, Settings settings) { + public Realm(String type, RealmConfig config) { this.type = type; - this.name = name; - this.settings = settings; - this.order = settings.getAsInt("order", Integer.MAX_VALUE); + this.config = config; + this.logger = config.logger(getClass()); } /** @@ -44,19 +38,19 @@ public abstract class Realm implements Comparable * @return The name of this realm. */ public String name() { - return name; + return config.name; } /** * @return The order of this realm within the executing realm chain. */ public int order() { - return order; + return config.order; } @Override public int compareTo(Realm other) { - return Integer.compare(order, other.order); + return Integer.compare(config.order, other.config.order); } /** @@ -120,10 +114,10 @@ public abstract class Realm implements Comparable /** * Creates a new realm based on the given settigns. * - * @param settings The settings for the realm. + * @param config The configuration for the realm * @return The new realm (this method never returns {@code null}). */ - public abstract R create(String name, Settings settings); + public abstract R create(RealmConfig config); /** * Creates a default realm, one that has no custom settings. Some realms might require minimal diff --git a/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java b/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java new file mode 100644 index 00000000000..3680a4a9258 --- /dev/null +++ b/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java @@ -0,0 +1,67 @@ +/* + * 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.shield.authc; + +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; + +/** + * + */ +public class RealmConfig { + + final String name; + final boolean enabled; + final int order; + final Settings settings; + + private final Environment env; + private final Settings globalSettings; + + public RealmConfig(String name) { + this(name, ImmutableSettings.EMPTY); + } + + public RealmConfig(String name, Settings settings) { + this(name, settings, ImmutableSettings.EMPTY, new Environment(ImmutableSettings.EMPTY)); + } + + public RealmConfig(String name, Settings settings, Settings globalSettings, Environment env) { + this.name = name; + this.settings = settings; + this.globalSettings = globalSettings; + this.env = env; + enabled = settings.getAsBoolean("enabled", true); + order = settings.getAsInt("order", Integer.MAX_VALUE); + } + + public String name() { + return name; + } + + public boolean enabled() { + return enabled; + } + + public int order() { + return order; + } + + public Settings settings() { + return settings; + } + + public ESLogger logger(Class clazz) { + return Loggers.getLogger(clazz, globalSettings); + } + + public Environment env() { + return env; + } +} diff --git a/src/main/java/org/elasticsearch/shield/authc/Realms.java b/src/main/java/org/elasticsearch/shield/authc/Realms.java index b1317716f22..14463da0a50 100644 --- a/src/main/java/org/elasticsearch/shield/authc/Realms.java +++ b/src/main/java/org/elasticsearch/shield/authc/Realms.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldSettingsException; import org.elasticsearch.shield.authc.esusers.ESUsersRealm; @@ -24,12 +25,15 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class Realms extends AbstractLifecycleComponent implements Iterable { + private final Environment env; private final Map factories; + private List realms = Collections.emptyList(); @Inject - public Realms(Settings settings, Map factories) { + public Realms(Settings settings, Environment env, Map factories) { super(settings); + this.env = env; this.factories = factories; } @@ -51,7 +55,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterab public Realm realm(String name) { for (Realm realm : realms) { - if (name.equals(realm.name)) { + if (name.equals(realm.config.name)) { return realm; } } @@ -76,7 +80,8 @@ public class Realms extends AbstractLifecycleComponent implements Iterab if (factory == null) { throw new ShieldSettingsException("Unknown realm type [" + type + "] set for realm [" + name + "]"); } - if (!realmSettings.getAsBoolean("enabled", true)) { + RealmConfig config = new RealmConfig(name, realmSettings, settings, env); + if (!config.enabled()) { if (logger.isDebugEnabled()) { logger.debug("realm [{}] type [{}] is disabled", name, type); } @@ -91,7 +96,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterab } internalTypes.add(type); } - realms.add(factory.create(name, realmSettings)); + realms.add(factory.create(config)); } if (!realms.isEmpty()) { diff --git a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnection.java b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnection.java index 49b548bfac0..7e5b69557fd 100644 --- a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnection.java +++ b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnection.java @@ -8,7 +8,6 @@ package org.elasticsearch.shield.authc.active_directory; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.shield.authc.ldap.LdapException; import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection; import org.elasticsearch.shield.authc.support.ldap.ClosableNamingEnumeration; @@ -23,16 +22,14 @@ import java.util.List; */ public class ActiveDirectoryConnection extends AbstractLdapConnection { - private static final ESLogger logger = Loggers.getLogger(ActiveDirectoryConnection.class); - private final String groupSearchDN; private final int timeoutMilliseconds; /** * This object is intended to be constructed by the LdapConnectionFactory */ - ActiveDirectoryConnection(DirContext ctx, String boundName, String groupSearchDN, int timeoutMilliseconds) { - super(ctx, boundName); + ActiveDirectoryConnection(ESLogger logger, DirContext ctx, String boundName, String groupSearchDN, int timeoutMilliseconds) { + super(logger, ctx, boundName); this.groupSearchDN = groupSearchDN; this.timeoutMilliseconds = timeoutMilliseconds; } diff --git a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnectionFactory.java b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnectionFactory.java index 725699af110..7dc5b8b7b6a 100644 --- a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnectionFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryConnectionFactory.java @@ -10,6 +10,7 @@ import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldSettingsException; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.ldap.LdapException; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.ldap.ClosableNamingEnumeration; @@ -30,7 +31,7 @@ import java.util.Hashtable; * user entry in Active Directory that matches the user name). This eliminates the need for user templates, and simplifies * the configuration for windows admins that may not be familiar with LDAP concepts. */ -public class ActiveDirectoryConnectionFactory extends ConnectionFactory { +public class ActiveDirectoryConnectionFactory extends ConnectionFactory { public static final String AD_DOMAIN_NAME_SETTING = "domain_name"; public static final String AD_USER_SEARCH_BASEDN_SETTING = "user_search_dn"; @@ -41,8 +42,9 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory { private final int timeoutMilliseconds; @Inject - public ActiveDirectoryConnectionFactory(Settings settings) { - super(settings); + public ActiveDirectoryConnectionFactory(RealmConfig config) { + super(ActiveDirectoryConnection.class, config); + Settings settings = config.settings(); domainName = settings.get(AD_DOMAIN_NAME_SETTING); if (domainName == null) { throw new ShieldSettingsException("Missing [" + AD_DOMAIN_NAME_SETTING + "] setting for active directory"); @@ -94,7 +96,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory { String name = entry.getNameInNamespace(); if (!results.hasMore()) { - return new ActiveDirectoryConnection(ctx, name, userSearchDN, timeoutMilliseconds); + return new ActiveDirectoryConnection(connectionLogger, ctx, name, userSearchDN, timeoutMilliseconds); } throw new ActiveDirectoryException("Search for user [" + userName + "] by principle name yielded multiple results"); } diff --git a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryGroupToRoleMapper.java b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryGroupToRoleMapper.java index d1e85b44e98..52a45b143a9 100644 --- a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryGroupToRoleMapper.java +++ b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryGroupToRoleMapper.java @@ -5,8 +5,7 @@ */ package org.elasticsearch.shield.authc.active_directory; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.ldap.AbstractGroupToRoleMapper; import org.elasticsearch.watcher.ResourceWatcherService; @@ -15,7 +14,7 @@ import org.elasticsearch.watcher.ResourceWatcherService; */ public class ActiveDirectoryGroupToRoleMapper extends AbstractGroupToRoleMapper { - public ActiveDirectoryGroupToRoleMapper(Settings settings, String realmName, Environment env, ResourceWatcherService watcherService) { - super(settings, ActiveDirectoryRealm.TYPE, realmName, env, watcherService, null); + public ActiveDirectoryGroupToRoleMapper(RealmConfig config, ResourceWatcherService watcherService) { + super(ActiveDirectoryRealm.TYPE, config, watcherService, null); } } diff --git a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryRealm.java b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryRealm.java index e15abc124a9..7c639233151 100644 --- a/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryRealm.java @@ -6,9 +6,8 @@ package org.elasticsearch.shield.authc.active_directory; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestController; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.ldap.AbstractLdapRealm; import org.elasticsearch.watcher.ResourceWatcherService; @@ -20,35 +19,28 @@ public class ActiveDirectoryRealm extends AbstractLdapRealm { public static final String TYPE = "active_directory"; @Inject - public ActiveDirectoryRealm(String name, Settings settings, ActiveDirectoryConnectionFactory connectionFactory, + public ActiveDirectoryRealm(RealmConfig config, + ActiveDirectoryConnectionFactory connectionFactory, ActiveDirectoryGroupToRoleMapper roleMapper) { - super(name, TYPE, settings, connectionFactory, roleMapper); + super(TYPE, config, connectionFactory, roleMapper); } - @Override - public String type() { - return TYPE; - } - - public static class Factory extends AbstractLdapRealm.Factory { - private final Environment env; private final ResourceWatcherService watcherService; @Inject - public Factory(Environment env, ResourceWatcherService watcherService, RestController restController) { + public Factory(ResourceWatcherService watcherService, RestController restController) { super(ActiveDirectoryRealm.TYPE, restController); - this.env = env; this.watcherService = watcherService; } @Override - public ActiveDirectoryRealm create(String name, Settings settings) { - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(settings); - ActiveDirectoryGroupToRoleMapper roleMapper = new ActiveDirectoryGroupToRoleMapper(settings, name, env, watcherService); - return new ActiveDirectoryRealm(name, settings, connectionFactory, roleMapper); + public ActiveDirectoryRealm create(RealmConfig config) { + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); + ActiveDirectoryGroupToRoleMapper roleMapper = new ActiveDirectoryGroupToRoleMapper(config, watcherService); + return new ActiveDirectoryRealm(config, connectionFactory, roleMapper); } } } diff --git a/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java b/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java index 8dbce2d27af..81fc4692fba 100644 --- a/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java @@ -12,6 +12,7 @@ import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestController; import org.elasticsearch.shield.User; import org.elasticsearch.shield.authc.Realm; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; @@ -27,8 +28,8 @@ public class ESUsersRealm extends CachingUsernamePasswordRealm { final FileUserPasswdStore userPasswdStore; final FileUserRolesStore userRolesStore; - public ESUsersRealm(String name, Settings settings, FileUserPasswdStore userPasswdStore, FileUserRolesStore userRolesStore) { - super(name, TYPE, settings); + public ESUsersRealm(RealmConfig config, FileUserPasswdStore userPasswdStore, FileUserRolesStore userRolesStore) { + super(TYPE, config); Listener listener = new Listener(); this.userPasswdStore = userPasswdStore; userPasswdStore.addListener(listener); @@ -54,27 +55,30 @@ public class ESUsersRealm extends CachingUsernamePasswordRealm { public static class Factory extends Realm.Factory { + private final Settings settings; private final Environment env; private final ResourceWatcherService watcherService; @Inject - public Factory(Environment env, ResourceWatcherService watcherService, RestController restController) { + public Factory(Settings settings, Environment env, ResourceWatcherService watcherService, RestController restController) { super(TYPE, true); + this.settings = settings; this.env = env; this.watcherService = watcherService; restController.registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER); } @Override - public ESUsersRealm create(String name, Settings settings) { - FileUserPasswdStore userPasswdStore = new FileUserPasswdStore(settings, env, watcherService); - FileUserRolesStore userRolesStore = new FileUserRolesStore(settings, env, watcherService); - return new ESUsersRealm(name, settings, userPasswdStore, userRolesStore); + public ESUsersRealm create(RealmConfig config) { + FileUserPasswdStore userPasswdStore = new FileUserPasswdStore(config, watcherService); + FileUserRolesStore userRolesStore = new FileUserRolesStore(config, watcherService); + return new ESUsersRealm(config, userPasswdStore, userRolesStore); } @Override public ESUsersRealm createDefault(String name) { - return create(name, ImmutableSettings.EMPTY); + RealmConfig config = new RealmConfig(name, ImmutableSettings.EMPTY, settings, env); + return create(config); } } } diff --git a/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java b/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java index a3b17acb687..b036046353b 100644 --- a/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java +++ b/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java @@ -10,11 +10,11 @@ import org.elasticsearch.common.base.Charsets; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldException; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authc.support.SecuredString; @@ -41,7 +41,7 @@ import static org.elasticsearch.shield.support.ShieldFiles.openAtomicMoveWriter; */ public class FileUserPasswdStore { - private static final ESLogger logger = Loggers.getLogger(FileUserPasswdStore.class); + private final ESLogger logger; private final Path file; final Hasher hasher = Hasher.HTPASSWD; @@ -50,12 +50,13 @@ public class FileUserPasswdStore { private CopyOnWriteArrayList listeners; - public FileUserPasswdStore(Settings settings, Environment env, ResourceWatcherService watcherService) { - this(settings, env, watcherService, null); + public FileUserPasswdStore(RealmConfig config, ResourceWatcherService watcherService) { + this(config, watcherService, null); } - FileUserPasswdStore(Settings settings, Environment env, ResourceWatcherService watcherService, RefreshListener listener) { - file = resolveFile(settings, env); + FileUserPasswdStore(RealmConfig config, ResourceWatcherService watcherService, RefreshListener listener) { + logger = config.logger(FileUserPasswdStore.class); + file = resolveFile(config.settings(), config.env()); esUsers = parseFile(file, logger); if (esUsers.isEmpty() && logger.isDebugEnabled()) { logger.debug("Realm [esusers] has no users"); diff --git a/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java b/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java index ea77d226ff2..1fc684becb3 100644 --- a/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java +++ b/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java @@ -11,10 +11,10 @@ import org.elasticsearch.common.base.Charsets; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.support.Validation; import org.elasticsearch.watcher.FileChangesListener; @@ -38,20 +38,21 @@ import static org.elasticsearch.shield.support.ShieldFiles.openAtomicMoveWriter; */ public class FileUserRolesStore { - private static final ESLogger logger = Loggers.getLogger(FileUserPasswdStore.class); - private static final Pattern USERS_DELIM = Pattern.compile("\\s*,\\s*"); + private final ESLogger logger; + private final Path file; private CopyOnWriteArrayList listeners; private volatile ImmutableMap userRoles; - public FileUserRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService) { - this(settings, env, watcherService, null); + public FileUserRolesStore(RealmConfig config, ResourceWatcherService watcherService) { + this(config, watcherService, null); } - FileUserRolesStore(Settings settings, Environment env, ResourceWatcherService watcherService, RefreshListener listener) { - file = resolveFile(settings, env); + FileUserRolesStore(RealmConfig config, ResourceWatcherService watcherService, RefreshListener listener) { + logger = config.logger(FileUserRolesStore.class); + file = resolveFile(config.settings(), config.env()); userRoles = parseFile(file, logger); FileWatcher watcher = new FileWatcher(file.getParent().toFile()); watcher.addListener(new FileListener()); @@ -89,7 +90,7 @@ public class FileUserRolesStore { */ public static ImmutableMap parseFile(Path path, @Nullable ESLogger logger) { if (logger != null) { - logger.trace("Reading users roles file located at [{}]", path); + logger.trace("reading users roles file located at [{}]", path); } if (!Files.exists(path)) { diff --git a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnection.java b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnection.java index 840823628b7..dee73640fc7 100644 --- a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnection.java +++ b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnection.java @@ -7,7 +7,6 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.Strings; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection; import org.elasticsearch.shield.authc.support.ldap.ClosableNamingEnumeration; @@ -30,8 +29,6 @@ import java.util.List; */ public class LdapConnection extends AbstractLdapConnection { - private static final ESLogger logger = Loggers.getLogger(LdapConnection.class); - private final String groupSearchDN; private final boolean isGroupSubTreeSearch; private final boolean isFindGroupsByAttribute; @@ -41,8 +38,8 @@ public class LdapConnection extends AbstractLdapConnection { /** * This object is intended to be constructed by the LdapConnectionFactory */ - LdapConnection(DirContext ctx, String boundName, boolean isFindGroupsByAttribute, boolean isGroupSubTreeSearch, String groupSearchDN, int timeoutMilliseconds) { - super(ctx, boundName); + LdapConnection(ESLogger logger, DirContext ctx, String boundName, boolean isFindGroupsByAttribute, boolean isGroupSubTreeSearch, String groupSearchDN, int timeoutMilliseconds) { + super(logger, ctx, boundName); this.isGroupSubTreeSearch = isGroupSubTreeSearch; this.groupSearchDN = groupSearchDN; this.isFindGroupsByAttribute = isFindGroupsByAttribute; diff --git a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java index 27dac39c8f5..7e1d82466f6 100644 --- a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java @@ -10,9 +10,9 @@ import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldSettingsException; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory; -import org.elasticsearch.shield.authc.support.ldap.AbstractLdapSslSocketFactory; import javax.naming.Context; import javax.naming.NamingException; @@ -29,7 +29,7 @@ import java.util.Hashtable; * Note that even though there is a separate factory for Active Directory, this factory would work against AD. A template * for each user context would need to be supplied. */ -public class LdapConnectionFactory extends ConnectionFactory { +public class LdapConnectionFactory extends ConnectionFactory { public static final String USER_DN_TEMPLATES_SETTING = "user_dn_templates"; public static final String GROUP_SEARCH_SUBTREE_SETTING = "group_search.subtree_search"; @@ -43,8 +43,9 @@ public class LdapConnectionFactory extends ConnectionFactory { private final int timeoutMilliseconds; @Inject() - public LdapConnectionFactory(Settings settings) { - super(settings); + public LdapConnectionFactory(RealmConfig config) { + super(LdapConnection.class, config); + Settings settings = config.settings(); userDnTemplates = settings.getAsArray(USER_DN_TEMPLATES_SETTING); if (userDnTemplates == null) { throw new ShieldSettingsException("Missing required ldap setting [" + USER_DN_TEMPLATES_SETTING + "]"); @@ -92,7 +93,7 @@ public class LdapConnectionFactory extends ConnectionFactory { DirContext ctx = new InitialDirContext(ldapEnv); //return the first good connection - return new LdapConnection(ctx, dn, findGroupsByAttribute, groupSubTreeSearch, groupSearchDN, timeoutMilliseconds); + return new LdapConnection(connectionLogger, ctx, dn, findGroupsByAttribute, groupSubTreeSearch, groupSearchDN, timeoutMilliseconds); } catch (NamingException e) { logger.warn("Failed ldap authentication with user template [{}], dn [{}]", e, template, dn); diff --git a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapper.java b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapper.java index 47844be8f3c..80f6f48edfa 100644 --- a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapper.java +++ b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapper.java @@ -5,8 +5,7 @@ */ package org.elasticsearch.shield.authc.ldap; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.ldap.AbstractGroupToRoleMapper; import org.elasticsearch.watcher.ResourceWatcherService; @@ -15,7 +14,7 @@ import org.elasticsearch.watcher.ResourceWatcherService; */ public class LdapGroupToRoleMapper extends AbstractGroupToRoleMapper { - public LdapGroupToRoleMapper(Settings settings, String realmName, Environment env, ResourceWatcherService watcherService) { - super(settings, LdapRealm.TYPE, realmName, env, watcherService, null); + public LdapGroupToRoleMapper(RealmConfig config, ResourceWatcherService watcherService) { + super(LdapRealm.TYPE, config, watcherService, null); } } diff --git a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java index f4e13956c8f..f5e22156ab1 100644 --- a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java @@ -6,9 +6,8 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestController; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.ldap.AbstractLdapRealm; import org.elasticsearch.watcher.ResourceWatcherService; @@ -20,32 +19,25 @@ public class LdapRealm extends AbstractLdapRealm { public static final String TYPE = "ldap"; @Inject - public LdapRealm(String name, Settings settings, LdapConnectionFactory ldap, LdapGroupToRoleMapper roleMapper) { - super(name, TYPE, settings, ldap, roleMapper); - } - - @Override - public String type() { - return TYPE; + public LdapRealm(RealmConfig config, LdapConnectionFactory ldap, LdapGroupToRoleMapper roleMapper) { + super(TYPE, config, ldap, roleMapper); } public static class Factory extends AbstractLdapRealm.Factory { - private final Environment env; private final ResourceWatcherService watcherService; @Inject - public Factory(Environment env, ResourceWatcherService watcherService, RestController restController) { + public Factory(ResourceWatcherService watcherService, RestController restController) { super(TYPE, restController); - this.env = env; this.watcherService = watcherService; } @Override - public LdapRealm create(String name, Settings settings) { - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); - LdapGroupToRoleMapper roleMapper = new LdapGroupToRoleMapper(settings, name, env, watcherService); - return new LdapRealm(name, settings, connectionFactory, roleMapper); + public LdapRealm create(RealmConfig config) { + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); + LdapGroupToRoleMapper roleMapper = new LdapGroupToRoleMapper(config, watcherService); + return new LdapRealm(config, connectionFactory, roleMapper); } } } diff --git a/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java b/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java index a20fc8d0f7d..13179ae354b 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java @@ -7,11 +7,11 @@ package org.elasticsearch.shield.authc.support; import org.elasticsearch.common.cache.Cache; import org.elasticsearch.common.cache.CacheBuilder; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.UncheckedExecutionException; import org.elasticsearch.shield.User; import org.elasticsearch.shield.authc.AuthenticationException; +import org.elasticsearch.shield.authc.RealmConfig; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -27,14 +27,14 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm private final Cache cache; private final Hasher hasher; - protected CachingUsernamePasswordRealm(String type, String name, Settings settings) { - super(type, name, settings); - hasher = Hasher.resolve(settings.get("cache.hash_algo", null), Hasher.SHA2); - TimeValue ttl = settings.getAsTime(CACHE_TTL, DEFAULT_TTL); + protected CachingUsernamePasswordRealm(String type, RealmConfig config) { + super(type, config); + hasher = Hasher.resolve(config.settings().get("cache.hash_algo", null), Hasher.SHA2); + TimeValue ttl = config.settings().getAsTime(CACHE_TTL, DEFAULT_TTL); if (ttl.millis() > 0) { cache = CacheBuilder.newBuilder() .expireAfterWrite(ttl.getMillis(), TimeUnit.MILLISECONDS) - .maximumSize(settings.getAsInt(CACHE_MAX_USERS, DEFAULT_MAX_USERS)) + .maximumSize(config.settings().getAsInt(CACHE_MAX_USERS, DEFAULT_MAX_USERS)) .build(); } else { cache = null; diff --git a/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java b/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java index 5b0b0c8e9f1..2d13b424776 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java @@ -5,11 +5,11 @@ */ package org.elasticsearch.shield.authc.support; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.authc.AuthenticationToken; import org.elasticsearch.shield.authc.Realm; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.transport.TransportMessage; import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER; @@ -19,8 +19,8 @@ import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC */ public abstract class UsernamePasswordRealm extends Realm { - public UsernamePasswordRealm(String type, String name, Settings settings) { - super(type, name, settings); + public UsernamePasswordRealm(String type, RealmConfig config) { + super(type, config); } @Override diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractGroupToRoleMapper.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractGroupToRoleMapper.java index b43a25704b0..572bf4c3de9 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractGroupToRoleMapper.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractGroupToRoleMapper.java @@ -9,11 +9,11 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.watcher.FileChangesListener; import org.elasticsearch.watcher.FileWatcher; @@ -39,24 +39,24 @@ public abstract class AbstractGroupToRoleMapper { public static final String ROLE_MAPPING_FILE_SETTING = "files.role_mapping"; public static final String USE_UNMAPPED_GROUPS_AS_ROLES_SETTING = "unmapped_groups_as_roles"; - protected final ESLogger logger = Loggers.getLogger(getClass()); - protected final Settings settings; + protected final ESLogger logger; + protected final RealmConfig config; + + private final String realmType; private final Path file; private final boolean useUnmappedGroupsAsRoles; - private final String realmName; - private final String realmType; private volatile ImmutableMap> groupRoles; private CopyOnWriteArrayList listeners; - protected AbstractGroupToRoleMapper(Settings settings, String realmType, String realmName, Environment env, - ResourceWatcherService watcherService, @Nullable RefreshListener listener) { - this.settings = settings; + protected AbstractGroupToRoleMapper(String realmType, RealmConfig config, ResourceWatcherService watcherService, @Nullable RefreshListener listener) { this.realmType = realmType; - this.realmName = realmName; - useUnmappedGroupsAsRoles = settings.getAsBoolean(USE_UNMAPPED_GROUPS_AS_ROLES_SETTING, false); - file = resolveFile(settings, env); - groupRoles = parseFile(file, logger, realmType, realmName); + this.config = config; + this.logger = config.logger(getClass()); + + useUnmappedGroupsAsRoles = config.settings().getAsBoolean(USE_UNMAPPED_GROUPS_AS_ROLES_SETTING, false); + file = resolveFile(config.settings(), config.env()); + groupRoles = parseFile(file, logger, realmType, config.name()); FileWatcher watcher = new FileWatcher(file.getParent().toFile()); watcher.addListener(new FileListener()); watcherService.add(watcher, ResourceWatcherService.Frequency.HIGH); @@ -127,7 +127,7 @@ public abstract class AbstractGroupToRoleMapper { } } if (logger.isDebugEnabled()) { - logger.debug("The roles [{}], are mapped from these [{}] groups [{}] for realm [{}]", roles, realmType, groupDns, realmName); + logger.debug("The roles [{}], are mapped from these [{}] groups [{}] for realm [{}]", roles, realmType, groupDns, config.name()); } return roles; } @@ -157,10 +157,10 @@ public abstract class AbstractGroupToRoleMapper { public void onFileChanged(File file) { if (file.equals(AbstractGroupToRoleMapper.this.file.toFile())) { try { - groupRoles = parseFile(file.toPath(), logger, realmType, realmName); - logger.info("updated role mappings (role mappings file [{}] changed) for realm [{}]", file.getAbsolutePath(), realmName); + groupRoles = parseFile(file.toPath(), logger, realmType, config.name()); + logger.info("updated role mappings (role mappings file [{}] changed) for realm [{}]", file.getAbsolutePath(), config.name()); } catch (Throwable t) { - logger.error("could not reload role mappings file [{}] for realm [{}]. Current role mappings remain unmodified", t, file.getAbsolutePath(), realmName); + logger.error("could not reload role mappings file [{}] for realm [{}]. Current role mappings remain unmodified", t, file.getAbsolutePath(), config.name()); return; } notifyRefresh(); diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapConnection.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapConnection.java index 30db9047dac..84fc08ce817 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapConnection.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapConnection.java @@ -5,6 +5,8 @@ */ package org.elasticsearch.shield.authc.support.ldap; +import org.elasticsearch.common.logging.ESLogger; + import javax.naming.NamingException; import javax.naming.directory.DirContext; import java.io.Closeable; @@ -15,13 +17,20 @@ import java.util.List; */ public abstract class AbstractLdapConnection implements Closeable { + protected final ESLogger logger; protected final DirContext jndiContext; protected final String bindDn; /** * This object is intended to be constructed by the LdapConnectionFactory + * + * This constructor accepts a logger with wich the connection can log. Since this connection + * can be instantiated very frequently, it's best to have the logger for this connection created + * outside of and be reused across all connections. We can't keep a static logger in this class + * since we want the logger to be contextual (i.e. aware of the settings and its enviorment). */ - public AbstractLdapConnection(DirContext ctx, String boundName) { + public AbstractLdapConnection(ESLogger logger, DirContext ctx, String boundName) { + this.logger = logger; this.jndiContext = ctx; this.bindDn = boundName; } diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapRealm.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapRealm.java index 4d87e3b4b3e..d59c40bd06c 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapRealm.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapRealm.java @@ -5,9 +5,9 @@ */ package org.elasticsearch.shield.authc.support.ldap; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.RestController; import org.elasticsearch.shield.User; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.CachingUsernamePasswordRealm; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authc.support.UsernamePasswordRealm; @@ -24,9 +24,9 @@ public abstract class AbstractLdapRealm extends CachingUsernamePasswordRealm { protected final ConnectionFactory connectionFactory; protected final AbstractGroupToRoleMapper roleMapper; - protected AbstractLdapRealm(String type, String name, Settings settings, + protected AbstractLdapRealm(String type, RealmConfig config, ConnectionFactory connectionFactory, AbstractGroupToRoleMapper roleMapper) { - super(type, name, settings); + super(type, config); this.connectionFactory = connectionFactory; this.roleMapper = roleMapper; roleMapper.addListener(new Listener()); diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapSslSocketFactory.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapSslSocketFactory.java index 6d8adf7cdce..ab56cd8d55c 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapSslSocketFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/AbstractLdapSslSocketFactory.java @@ -6,8 +6,6 @@ package org.elasticsearch.shield.authc.support.ldap; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.shield.ssl.SSLService; import javax.net.SocketFactory; @@ -21,7 +19,6 @@ import java.net.InetAddress; */ public abstract class AbstractLdapSslSocketFactory extends SocketFactory { - protected static ESLogger logger = Loggers.getLogger(AbstractLdapSslSocketFactory.class); protected static SSLService sslService; private final SSLSocketFactory socketFactory; @@ -81,6 +78,5 @@ public abstract class AbstractLdapSslSocketFactory extends SocketFactory { * @param sslSocket */ protected void configureSSLSocket(SSLSocket sslSocket) { - } } diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/ClosableNamingEnumeration.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/ClosableNamingEnumeration.java index 80c6b31f279..18a6b310ca6 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/ClosableNamingEnumeration.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/ClosableNamingEnumeration.java @@ -15,6 +15,7 @@ import java.io.Closeable; * ClosableNamingEnumeration wraps a NamingEnumeration so it can be used in a try with resources block and auto-closed. */ public class ClosableNamingEnumeration implements Closeable, NamingEnumeration { + private final NamingEnumeration namingEnumeration; public ClosableNamingEnumeration(NamingEnumeration namingEnumeration) { diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactory.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactory.java index e8ceff94f74..2ff02e3acd6 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactory.java @@ -8,10 +8,9 @@ package org.elasticsearch.shield.authc.support.ldap; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.shield.ShieldSettingsException; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredString; import java.io.Serializable; @@ -33,7 +32,7 @@ import static org.elasticsearch.common.collect.Iterables.all; } */ -public abstract class ConnectionFactory { +public abstract class ConnectionFactory { public static final String URLS_SETTING = "url"; public static final String JNDI_LDAP_READ_TIMEOUT = "com.sun.jndi.ldap.read.timeout"; @@ -47,11 +46,14 @@ public abstract class ConnectionFactory { private static final Pattern STARTS_WITH_LDAPS = Pattern.compile("^ldaps:.*", Pattern.CASE_INSENSITIVE); private static final Pattern STARTS_WITH_LDAP = Pattern.compile("^ldap:.*", Pattern.CASE_INSENSITIVE); - protected final ESLogger logger = Loggers.getLogger(getClass()); - private final Settings settings; + protected final ESLogger logger; + protected final ESLogger connectionLogger; + protected final RealmConfig config; - protected ConnectionFactory(Settings settings) { - this.settings = settings; + protected ConnectionFactory(Class connectionClass, RealmConfig config) { + this.config = config; + this.logger = config.logger(getClass()); + this.connectionLogger = config.logger(connectionClass); } /** @@ -61,7 +63,7 @@ public abstract class ConnectionFactory { * @param user The name of the user to authenticate the connection with. * @param password The password of the user */ - public abstract AbstractLdapConnection open(String user, SecuredString password) ; + public abstract Connection open(String user, SecuredString password) ; /** * If one of the ldapUrls are SSL this will set the LdapSslSocketFactory as a socket provider on the builder @@ -73,7 +75,7 @@ public abstract class ConnectionFactory { protected void configureJndiSSL(String[] ldapUrls, ImmutableMap.Builder builder) { boolean secureProtocol = secureUrls(ldapUrls); if (secureProtocol) { - if (settings.getAsBoolean(HOSTNAME_VERIFICATION_SETTING, true)) { + if (config.settings().getAsBoolean(HOSTNAME_VERIFICATION_SETTING, true)) { builder.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, HostnameVerifyingLdapSslSocketFactory.class.getName()); logger.debug("using encryption for LDAP connections with hostname verification"); } else { diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/HostnameVerifyingLdapSslSocketFactory.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/HostnameVerifyingLdapSslSocketFactory.java index d1b04cd3419..8c4dd37a4a3 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/HostnameVerifyingLdapSslSocketFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/HostnameVerifyingLdapSslSocketFactory.java @@ -5,6 +5,9 @@ */ package org.elasticsearch.shield.authc.support.ldap; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; + import javax.net.SocketFactory; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; @@ -17,6 +20,9 @@ import java.net.InetAddress; * have the appropriate SSLParameters set to indicate that hostname verification is required */ public class HostnameVerifyingLdapSslSocketFactory extends AbstractLdapSslSocketFactory { + + private static final ESLogger logger = Loggers.getLogger(HostnameVerifyingLdapSslSocketFactory.class); + private static HostnameVerifyingLdapSslSocketFactory instance; private final SSLParameters sslParameters; diff --git a/src/main/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactory.java b/src/main/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactory.java index b761ade72e7..1679e231437 100644 --- a/src/main/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactory.java @@ -5,6 +5,9 @@ */ package org.elasticsearch.shield.authc.support.ldap; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; + import javax.net.SocketFactory; import javax.net.ssl.SSLSocketFactory; @@ -18,6 +21,8 @@ import javax.net.ssl.SSLSocketFactory; */ public class LdapSslSocketFactory extends AbstractLdapSslSocketFactory { + private static final ESLogger logger = Loggers.getLogger(LdapSslSocketFactory.class); + private static LdapSslSocketFactory instance; public LdapSslSocketFactory(SSLSocketFactory socketFactory) { diff --git a/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java b/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java index 21d1fcb4619..8d003ca46dc 100644 --- a/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java +++ b/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java @@ -6,7 +6,6 @@ package org.elasticsearch.shield.transport.netty; import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.netty.channel.*; import org.elasticsearch.common.netty.handler.ssl.SslHandler; @@ -25,11 +24,19 @@ import java.util.Queue; * is the way that NettyTransport currently works */ public class HandshakeWaitingHandler extends SimpleChannelHandler { - private static final ESLogger logger = Loggers.getLogger(HandshakeWaitingHandler.class); + + private final ESLogger logger; private boolean handshaken = false; private Queue pendingWrites = new LinkedList<>(); + /** + * @param logger We pass a context aware logger here (logger that is aware of the node name & env) + */ + public HandshakeWaitingHandler(ESLogger logger) { + this.logger = logger; + } + @Override public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class); diff --git a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java index b0559149608..55859649986 100644 --- a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java +++ b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java @@ -27,6 +27,7 @@ import java.net.InetSocketAddress; * */ public class NettySecuredTransport extends NettyTransport { + public static final String HOSTNAME_VERIFICATION_SETTING = "shield.ssl.hostname_verification"; private final SSLService sslService; @@ -123,7 +124,7 @@ public class NettySecuredTransport extends NettyTransport { sslEngine.setUseClientMode(true); ctx.getPipeline().replace(this, "ssl", new SslHandler(sslEngine)); - ctx.getPipeline().addAfter("ssl", "handshake", new HandshakeWaitingHandler()); + ctx.getPipeline().addAfter("ssl", "handshake", new HandshakeWaitingHandler(logger)); ctx.sendDownstream(e); } diff --git a/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java b/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java index 136d06a4842..7c74923db75 100644 --- a/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java +++ b/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.support.ActionFilterChain; +import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.license.plugin.core.LicensesClientService; import org.elasticsearch.shield.User; import org.elasticsearch.shield.audit.AuditTrail; @@ -46,7 +47,7 @@ public class ShieldActionFilterTests extends ElasticsearchTestCase { signatureService = mock(SignatureService.class); auditTrail = mock(AuditTrail.class); licenseEventsNotifier = new MockLicenseEventsNotifier(); - filter = new ShieldActionFilter(authcService, authzService, signatureService, auditTrail, licenseEventsNotifier); + filter = new ShieldActionFilter(ImmutableSettings.EMPTY, authcService, authzService, signatureService, auditTrail, licenseEventsNotifier); } @Test diff --git a/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java b/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java index 896aca2aa1d..1ef2aaa3d8e 100644 --- a/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java +++ b/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java @@ -10,6 +10,8 @@ import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.LocalTransportAddress; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.User; @@ -18,6 +20,7 @@ import org.elasticsearch.shield.transport.filter.IPFilter; import org.elasticsearch.shield.transport.filter.ShieldIpFilterRule; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.transport.TransportMessage; +import org.junit.Before; import org.junit.Test; import java.net.InetAddress; @@ -93,11 +96,24 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { protected abstract String expectedMessage(); } + private String prefix; + private Settings settings; + + @Before + public void init() throws Exception { + settings = ImmutableSettings.builder() + .put("shield.audit.logfile.prefix.node_host_address", randomBoolean()) + .put("shield.audit.logfile.prefix.node_host_name", randomBoolean()) + .put("shield.audit.logfile.prefix.node_name", randomBoolean()) + .build(); + prefix = LoggingAuditTrail.resolvePrefix(settings); + } + @Test public void testAnonymousAccess_Transport() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.anonymousAccess("_action", message); switch (level) { @@ -107,17 +123,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { case WARN: case INFO: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.WARN, "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2]"); + assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2]"); } else { - assertMsg(logger, Level.WARN, "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action]"); + assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action]"); } break; case DEBUG: case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.DEBUG, "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.DEBUG, "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], request=[MockMessage]"); + assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[local[_host]], action=[_action], request=[MockMessage]"); } } } @@ -132,7 +148,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); auditTrail.anonymousAccess(request); switch (level) { case ERROR: @@ -140,11 +156,11 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { break; case WARN: case INFO: - assertMsg(logger, Level.WARN, "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri]"); + assertMsg(logger, Level.WARN, prefix + "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri]"); break; case DEBUG: case TRACE: - assertMsg(logger, Level.DEBUG, "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri], request=[" + expectedMessage + "]"); + assertMsg(logger, Level.DEBUG, prefix + "ANONYMOUS_ACCESS\thost=[_hostname:9200], URI=[_uri], request=[" + expectedMessage + "]"); } } } @@ -153,7 +169,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testAuthenticationFailed() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.authenticationFailed(new MockToken(), "_action", message); switch (level) { @@ -161,17 +177,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { case WARN: case INFO: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.ERROR, "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2]"); + assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2]"); } else { - assertMsg(logger, Level.ERROR, "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action]"); + assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action]"); } break; case DEBUG: case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.DEBUG, "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.DEBUG, "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]"); + assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]"); } } } @@ -185,17 +201,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { when(request.uri()).thenReturn("_uri"); String expectedMessage = prepareRestContent(request); CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); auditTrail.authenticationFailed(new MockToken(), request); switch (level) { case ERROR: case WARN: case INFO: - assertMsg(logger, Level.ERROR, "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri]"); + assertMsg(logger, Level.ERROR, prefix + "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri]"); break; case DEBUG: case TRACE: - assertMsg(logger, Level.DEBUG, "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]"); + assertMsg(logger, Level.DEBUG, prefix + "AUTHENTICATION_FAILED\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]"); } } } @@ -204,7 +220,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testAuthenticationFailed_Realm() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.authenticationFailed("_realm", new MockToken(), "_action", message); switch (level) { @@ -216,9 +232,9 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { break; case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.TRACE, "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.TRACE, "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]"); + assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[local[_host]], principal=[_principal], action=[_action], request=[MockMessage]"); } } } @@ -232,7 +248,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { when(request.uri()).thenReturn("_uri"); String expectedMessage = prepareRestContent(request); CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); auditTrail.authenticationFailed("_realm", new MockToken(), request); switch (level) { case ERROR: @@ -242,7 +258,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { assertEmptyLog(logger); break; case TRACE: - assertMsg(logger, Level.TRACE, "AUTHENTICATION_FAILED[_realm]\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]"); + assertMsg(logger, Level.TRACE, prefix + "AUTHENTICATION_FAILED[_realm]\thost=[_hostname:9200], principal=[_principal], URI=[_uri], request=[" + expectedMessage + "]"); } } } @@ -251,7 +267,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testAccessGranted() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.accessGranted(new User.Simple("_username", "r1"), "_action", message); switch (level) { @@ -261,17 +277,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { break; case INFO: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.INFO, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]"); + assertMsg(logger, Level.INFO, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]"); } else { - assertMsg(logger, Level.INFO, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action]"); + assertMsg(logger, Level.INFO, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action]"); } break; case DEBUG: case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.DEBUG, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.DEBUG, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.DEBUG, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]"); + assertMsg(logger, Level.DEBUG, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]"); } } } @@ -281,7 +297,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testAccessGranted_InternalSystemAction() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.accessGranted(new User.Simple("_username", "r1"), "internal:_action", message); switch (level) { @@ -293,9 +309,9 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { break; case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.TRACE, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.TRACE, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.TRACE, "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], request=[MockMessage]"); + assertMsg(logger, Level.TRACE, prefix + "ACCESS_GRANTED\thost=[local[_host]], principal=[_username], action=[internal:_action], request=[MockMessage]"); } } } @@ -305,7 +321,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testAccessDenied() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); TransportMessage message = randomBoolean() ? new MockMessage() : new MockIndicesRequest(); auditTrail.accessDenied(new User.Simple("_username", "r1"), "_action", message); switch (level) { @@ -313,17 +329,17 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { case WARN: case INFO: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.ERROR, "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]"); + assertMsg(logger, Level.ERROR, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2]"); } else { - assertMsg(logger, Level.ERROR, "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action]"); + assertMsg(logger, Level.ERROR, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action]"); } break; case DEBUG: case TRACE: if (message instanceof IndicesRequest) { - assertMsg(logger, Level.DEBUG, "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); + assertMsg(logger, Level.DEBUG, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], indices=[idx1,idx2], request=[MockIndicesRequest]"); } else { - assertMsg(logger, Level.DEBUG, "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]"); + assertMsg(logger, Level.DEBUG, prefix + "ACCESS_DENIED\thost=[local[_host]], principal=[_username], action=[_action], request=[MockMessage]"); } } } @@ -333,13 +349,13 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testConnectionDenied() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); InetAddress inetAddress = InetAddress.getLocalHost(); ShieldIpFilterRule rule = new ShieldIpFilterRule(false, "_all"); auditTrail.connectionDenied(inetAddress, "default", rule); switch (level) { case ERROR: - assertMsg(logger, Level.ERROR, String.format(Locale.ROOT, "CONNECTION_DENIED\thost=[%s], profile=[%s], rule=[deny %s]", + assertMsg(logger, Level.ERROR, String.format(Locale.ROOT, prefix + "CONNECTION_DENIED\thost=[%s], profile=[%s], rule=[deny %s]", inetAddress.getHostAddress(), "default", "_all")); break; case WARN: @@ -354,7 +370,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { public void testConnectionGranted() throws Exception { for (Level level : Level.values()) { CapturingLogger logger = new CapturingLogger(level); - LoggingAuditTrail auditTrail = new LoggingAuditTrail(logger); + LoggingAuditTrail auditTrail = new LoggingAuditTrail(settings, logger); InetAddress inetAddress = InetAddress.getLocalHost(); ShieldIpFilterRule rule = IPFilter.DEFAULT_PROFILE_ACCEPT_ALL; auditTrail.connectionGranted(inetAddress, "default", rule); @@ -367,7 +383,7 @@ public class LoggingAuditTrailTests extends ElasticsearchTestCase { break; case TRACE: assertMsg(logger, Level.TRACE, String.format(Locale.ROOT, - "CONNECTION_GRANTED\thost=[%s], profile=[default], rule=[allow default:accept_all]", + prefix + "CONNECTION_GRANTED\thost=[%s], profile=[default], rule=[allow default:accept_all]", inetAddress.getHostAddress())); } } diff --git a/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java b/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java index c383afda171..a95ddab8c56 100644 --- a/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.io.stream.BytesStreamInput; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.User; import org.elasticsearch.shield.audit.AuditTrail; @@ -22,7 +23,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Mockito; import java.util.Collections; import java.util.List; @@ -59,7 +59,7 @@ public class InternalAuthenticationServiceTests extends ElasticsearchTestCase { when(firstRealm.type()).thenReturn("first"); secondRealm = mock(Realm.class); when(secondRealm.type()).thenReturn("second"); - realms = new Realms(ImmutableSettings.EMPTY, Collections.emptyMap()) { + realms = new Realms(ImmutableSettings.EMPTY, new Environment(ImmutableSettings.EMPTY), Collections.emptyMap()) { @Override protected List initRealms() { return ImmutableList.of(firstRealm, secondRealm); diff --git a/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java b/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java index a7235eeb1f6..01962ce43b2 100644 --- a/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.shield.authc; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.ShieldSettingsException; import org.elasticsearch.shield.User; @@ -51,7 +52,9 @@ public class RealmsTests extends ElasticsearchTestCase { builder.put("shield.authc.realms.realm_" + i + ".order", orders.get(i)); orderToIndex.put(orders.get(i), i); } - Realms realms = new Realms(builder.build(), factories); + Settings settings = builder.build(); + Environment env = new Environment(settings); + Realms realms = new Realms(settings, env, factories); realms.start(); int i = 0; for (Realm realm : realms) { @@ -65,17 +68,19 @@ public class RealmsTests extends ElasticsearchTestCase { @Test(expected = ShieldSettingsException.class) public void testWithSettings_WithMultipleInternalRealmsOfSameType() throws Exception { - ImmutableSettings.Builder builder = ImmutableSettings.builder(); - builder.put("shield.authc.realms.realm_1.type", ESUsersRealm.TYPE); - builder.put("shield.authc.realms.realm_1.order", 0); - builder.put("shield.authc.realms.realm_2.type", ESUsersRealm.TYPE); - builder.put("shield.authc.realms.realm_2.order", 1); - new Realms(builder.build(), factories).start(); + Settings settings = ImmutableSettings.builder() + .put("shield.authc.realms.realm_1.type", ESUsersRealm.TYPE) + .put("shield.authc.realms.realm_1.order", 0) + .put("shield.authc.realms.realm_2.type", ESUsersRealm.TYPE) + .put("shield.authc.realms.realm_2.order", 1) + .build(); + Environment env = new Environment(settings); + new Realms(settings, env, factories).start(); } @Test public void testWithEmptySettings() throws Exception { - Realms realms = new Realms(ImmutableSettings.EMPTY, factories); + Realms realms = new Realms(ImmutableSettings.EMPTY, new Environment(ImmutableSettings.EMPTY), factories); realms.start(); Iterator iter = realms.iterator(); assertThat(iter.hasNext(), is(true)); @@ -105,9 +110,9 @@ public class RealmsTests extends ElasticsearchTestCase { logger.error("put [{}] -> [{}]", orders.get(i), i); } } - Settings settings = builder.build(); - Realms realms = new Realms(settings, factories); + Environment env = new Environment(settings); + Realms realms = new Realms(settings, env, factories); realms.start(); Iterator iterator = realms.iterator(); @@ -133,8 +138,8 @@ public class RealmsTests extends ElasticsearchTestCase { static class DummyRealm extends Realm { - public DummyRealm(String type, String name, Settings settings) { - super(type, name, settings); + public DummyRealm(String type, RealmConfig config) { + super(type, config); } @Override @@ -164,13 +169,13 @@ public class RealmsTests extends ElasticsearchTestCase { } @Override - public DummyRealm create(String name, Settings settings) { - return new DummyRealm(type(), name, settings); + public DummyRealm create(RealmConfig config) { + return new DummyRealm(type(), config); } @Override public DummyRealm createDefault(String name) { - return type().equals("esusers") ? new DummyRealm("esusers", name, ImmutableSettings.EMPTY) : null; + return type().equals("esusers") ? new DummyRealm("esusers", new RealmConfig(name)) : null; } } } diff --git a/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java b/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java index 65ceb6d367a..f8c0d19458f 100644 --- a/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java @@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.active_directory; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.ldap.LdapConnection; import org.elasticsearch.shield.authc.ldap.LdapConnectionFactory; import org.elasticsearch.shield.authc.ldap.LdapConnectionTests; @@ -18,7 +19,9 @@ import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.junit.annotations.Network; import org.hamcrest.Matchers; -import org.junit.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; import java.nio.file.Path; import java.nio.file.Paths; @@ -56,8 +59,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { @Test @SuppressWarnings("unchecked") public void testAdAuth() { - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory( - buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false)); + RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false)); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); String userName = "ironman"; try (AbstractLdapConnection ldap = connectionFactory.open(userName, SecuredStringTests.build(PASSWORD))) { @@ -82,7 +85,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { .put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false) .put(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms") .build(); - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(settings); + RealmConfig config = new RealmConfig("ad-test", settings); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); try (AbstractLdapConnection ldap = connectionFactory.open("ironman", SecuredStringTests.build(PASSWORD))) { fail("The TCP connection should timeout before getting groups back"); @@ -93,8 +97,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { @Test public void testAdAuth_avengers() { - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory( - buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false)); + RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false)); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); String[] users = new String[]{"cap", "hawkeye", "hulk", "ironman", "thor", "blackwidow", }; for(String user: users) { @@ -107,7 +111,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { @Test @SuppressWarnings("unchecked") public void testAdAuth_specificUserSearch() { Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", false); - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(settings); + RealmConfig config = new RealmConfig("ad-test", settings); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); String userName = "hulk"; try (AbstractLdapConnection ldap = connectionFactory.open(userName, SecuredStringTests.build(PASSWORD))) { @@ -127,7 +132,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { @Test @SuppressWarnings("unchecked") public void testAdUpnLogin() { Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", false); - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(settings); + RealmConfig config = new RealmConfig("ad-test", settings); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); //Login with the UserPrincipalName String userDN; @@ -154,7 +160,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com"; String userTemplate = "CN={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; Settings settings = LdapTest.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, true, false); - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); + RealmConfig config = new RealmConfig("ad-test", settings); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String user = "Bruce Banner"; try (LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD))) { @@ -177,8 +184,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { @Test(expected = ActiveDirectoryException.class) public void testAdAuthWithHostnameVerification() { - ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory( - buildAdSettings(AD_LDAP_URL, AD_DOMAIN)); + RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN)); + ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config); String userName = "ironman"; try (AbstractLdapConnection ldap = connectionFactory.open(userName, SecuredStringTests.build(PASSWORD))) { @@ -191,7 +198,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com"; String userTemplate = "CN={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; Settings settings = LdapTest.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, true); - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); + RealmConfig config = new RealmConfig("ad-test", settings); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String user = "Bruce Banner"; try (LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD))) { diff --git a/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java b/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java index 98f1c31ef8b..46bb484b64a 100644 --- a/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.shield.User; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredStringTests; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; @@ -60,7 +61,7 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { @Test public void testRestHeaderRegistration() { - new ESUsersRealm.Factory(mock(Environment.class), mock(ResourceWatcherService.class), restController); + new ESUsersRealm.Factory(ImmutableSettings.EMPTY, mock(Environment.class), mock(ResourceWatcherService.class), restController); verify(restController).registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER); } @@ -68,7 +69,8 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { public void testAuthenticate() throws Exception { when(userPasswdStore.verifyPassword("user1", SecuredStringTests.build("test123"))).thenReturn(true); when(userRolesStore.roles("user1")).thenReturn(new String[] { "role1", "role2" }); - ESUsersRealm realm = new ESUsersRealm("esusers-test", ImmutableSettings.EMPTY, userPasswdStore, userRolesStore); + RealmConfig config = new RealmConfig("esusers-test"); + ESUsersRealm realm = new ESUsersRealm(config, userPasswdStore, userRolesStore); User user = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); assertThat(user, notNullValue()); assertThat(user.principal(), equalTo("user1")); @@ -82,20 +84,22 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { Settings settings = ImmutableSettings.builder() .put("cache.hash_algo", Hasher.values()[randomIntBetween(0, Hasher.values().length - 1)].name().toLowerCase(Locale.ROOT)) .build(); + RealmConfig config = new RealmConfig("esusers-test", settings); when(userPasswdStore.verifyPassword("user1", SecuredStringTests.build("test123"))).thenReturn(true); when(userRolesStore.roles("user1")).thenReturn(new String[] { "role1", "role2" }); - ESUsersRealm realm = new ESUsersRealm("esusers-test", settings, userPasswdStore, userRolesStore); + ESUsersRealm realm = new ESUsersRealm(config, userPasswdStore, userRolesStore); User user1 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); User user2 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); assertThat(user1, sameInstance(user2)); } public void testAuthenticate_Caching_Refresh() throws Exception { - userPasswdStore = spy(new UserPasswdStore()); - userRolesStore = spy(new UserRolesStore()); + RealmConfig config = new RealmConfig("esusers-test", ImmutableSettings.EMPTY); + userPasswdStore = spy(new UserPasswdStore(config)); + userRolesStore = spy(new UserRolesStore(config)); doReturn(true).when(userPasswdStore).verifyPassword("user1", SecuredStringTests.build("test123")); doReturn(new String[] { "role1", "role2" }).when(userRolesStore).roles("user1"); - ESUsersRealm realm = new ESUsersRealm("esusers-test", ImmutableSettings.EMPTY, userPasswdStore, userRolesStore); + ESUsersRealm realm = new ESUsersRealm(config, userPasswdStore, userRolesStore); User user1 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); User user2 = realm.authenticate(new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); assertThat(user1, sameInstance(user2)); @@ -113,9 +117,10 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { @Test public void testToken() throws Exception { + RealmConfig config = new RealmConfig("esusers-test", ImmutableSettings.EMPTY); when(userPasswdStore.verifyPassword("user1", SecuredStringTests.build("test123"))).thenReturn(true); when(userRolesStore.roles("user1")).thenReturn(new String[] { "role1", "role2" }); - ESUsersRealm realm = new ESUsersRealm("esusers-test", ImmutableSettings.EMPTY, userPasswdStore, userRolesStore); + ESUsersRealm realm = new ESUsersRealm(config, userPasswdStore, userRolesStore); TransportRequest request = new TransportRequest() {}; UsernamePasswordToken.putTokenHeader(request, new UsernamePasswordToken("user1", SecuredStringTests.build("test123"))); @@ -129,8 +134,9 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { @Test @SuppressWarnings("unchecked") public void testRestHeadersAreCopied() throws Exception { + RealmConfig config = new RealmConfig("esusers-test", ImmutableSettings.EMPTY); // the required header will be registered only if ESUsersRealm is actually used. - new ESUsersRealm("esusers-test", ImmutableSettings.EMPTY, new UserPasswdStore(), new UserRolesStore()); + new ESUsersRealm(config, new UserPasswdStore(config), new UserRolesStore(config)); when(restController.relevantHeaders()).thenReturn(ImmutableSet.of(UsernamePasswordToken.BASIC_AUTH_HEADER)); when(client.admin()).thenReturn(adminClient); when(adminClient.cluster()).thenReturn(mock(ClusterAdminClient.class)); @@ -159,15 +165,15 @@ public class ESUsersRealmTests extends ElasticsearchTestCase { static class UserPasswdStore extends FileUserPasswdStore { - public UserPasswdStore() { - super(ImmutableSettings.EMPTY, new Environment(ImmutableSettings.EMPTY), mock(ResourceWatcherService.class)); + public UserPasswdStore(RealmConfig config) { + super(config, mock(ResourceWatcherService.class)); } } static class UserRolesStore extends FileUserRolesStore { - public UserRolesStore() { - super(ImmutableSettings.EMPTY, new Environment(ImmutableSettings.EMPTY), mock(ResourceWatcherService.class)); + public UserRolesStore(RealmConfig config) { + super(config, mock(ResourceWatcherService.class)); } } } diff --git a/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java b/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java index 2f2c9283220..67f7f58fc49 100644 --- a/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authc.support.SecuredStringTests; @@ -77,10 +78,12 @@ public class FileUserPasswdStoreTests extends ElasticsearchTestCase { Environment env = new Environment(settings); + RealmConfig config = new RealmConfig("esusers-test", esusersSettings, settings, env); threadPool = new ThreadPool("test"); watcherService = new ResourceWatcherService(settings, threadPool); final CountDownLatch latch = new CountDownLatch(1); - FileUserPasswdStore store = new FileUserPasswdStore(esusersSettings, env, watcherService, new RefreshListener() { + + FileUserPasswdStore store = new FileUserPasswdStore(config, watcherService, new RefreshListener() { @Override public void onRefresh() { latch.countDown(); diff --git a/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java b/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java index 613f102989b..2756feab38d 100644 --- a/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.threadpool.ThreadPool; @@ -69,10 +70,12 @@ public class FileUserRolesStoreTests extends ElasticsearchTestCase { .build(); Environment env = new Environment(settings); + RealmConfig config = new RealmConfig("esusers-test", esusersSettings, settings, env); threadPool = new ThreadPool("test"); watcherService = new ResourceWatcherService(settings, threadPool); final CountDownLatch latch = new CountDownLatch(1); - FileUserRolesStore store = new FileUserRolesStore(esusersSettings, env, watcherService, new RefreshListener() { + + FileUserRolesStore store = new FileUserRolesStore(config, watcherService, new RefreshListener() { @Override public void onRefresh() { latch.countDown(); @@ -127,8 +130,9 @@ public class FileUserRolesStoreTests extends ElasticsearchTestCase { .build(); Environment env = new Environment(settings); + RealmConfig config = new RealmConfig("esusers-test", ImmutableSettings.EMPTY, settings, env); ResourceWatcherService watcherService = new ResourceWatcherService(settings, threadPool); - FileUserRolesStore store = new FileUserRolesStore(esusersSettings, env, watcherService); + FileUserRolesStore store = new FileUserRolesStore(config, watcherService); assertThat(store.roles("user"), equalTo(Strings.EMPTY_ARRAY)); } finally { if (threadPool != null) { diff --git a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java index c53b8a5f9fc..684b03d0ae0 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredStringTests; import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory; @@ -40,7 +41,8 @@ public class LdapConnectionTests extends LdapTest { .put(buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true)) .put(ConnectionFactory.TIMEOUT_TCP_CONNECTION_SETTING, "1ms") //1 millisecond .build(); - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); + RealmConfig config = new RealmConfig("ldap_realm", settings); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String user = "Horatio Hornblower"; SecuredString userPass = SecuredStringTests.build("pass"); @@ -65,8 +67,9 @@ public class LdapConnectionTests extends LdapTest { "wrongname={0},ou=people,o=sevenSeas", "cn={0},ou=people,o=sevenSeas", //this last one should work }; - LdapConnectionFactory connectionFactory = new LdapConnectionFactory( - buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true)); + RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true)); + + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String user = "Horatio Hornblower"; SecuredString userPass = SecuredStringTests.build("pass"); @@ -89,8 +92,9 @@ public class LdapConnectionTests extends LdapTest { "wrongname={0},ou=people,o=sevenSeas", "asdf={0},ou=people,o=sevenSeas", //none of these should work }; - LdapConnectionFactory ldapFac = new LdapConnectionFactory( - buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, isSubTreeSearch)); + RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, isSubTreeSearch)); + + LdapConnectionFactory ldapFac = new LdapConnectionFactory(config); String user = "Horatio Hornblower"; SecuredString userPass = SecuredStringTests.build("pass"); @@ -102,9 +106,9 @@ public class LdapConnectionTests extends LdapTest { public void testGroupLookup_Subtree() { String groupSearchBase = "o=sevenSeas"; String userTemplate = "cn={0},ou=people,o=sevenSeas"; + RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, true)); - LdapConnectionFactory ldapFac = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, true)); + LdapConnectionFactory ldapFac = new LdapConnectionFactory(config); String user = "Horatio Hornblower"; SecuredString userPass = SecuredStringTests.build("pass"); @@ -119,8 +123,9 @@ public class LdapConnectionTests extends LdapTest { public void testGroupLookup_OneLevel() { String groupSearchBase = "ou=crews,ou=groups,o=sevenSeas"; String userTemplate = "cn={0},ou=people,o=sevenSeas"; - LdapConnectionFactory ldapFac = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, false)); + RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, false)); + + LdapConnectionFactory ldapFac = new LdapConnectionFactory(config); String user = "Horatio Hornblower"; try (LdapConnection ldap = ldapFac.open(user, SecuredStringTests.build("pass"))) { diff --git a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapperTest.java b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapperTest.java index 20bb41a8137..1aaec678232 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapperTest.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapGroupToRoleMapperTest.java @@ -7,7 +7,7 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.ldap.AbstractGroupToRoleMapper; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.threadpool.ThreadPool; @@ -57,11 +57,9 @@ public class LdapGroupToRoleMapperTest extends ElasticsearchTestCase { Settings settings = ImmutableSettings.settingsBuilder() .put(LdapGroupToRoleMapper.ROLE_MAPPING_FILE_SETTING, file.getCanonicalPath()) .build(); + RealmConfig config = new RealmConfig("ldap1", settings); - AbstractGroupToRoleMapper mapper = new LdapGroupToRoleMapper(settings, - "ldap1", - new Environment(settings), - new ResourceWatcherService(settings, threadPool)); + AbstractGroupToRoleMapper mapper = new LdapGroupToRoleMapper(config, new ResourceWatcherService(settings, threadPool)); Set roles = mapper.mapRoles( Arrays.asList(starkGroupDns) ); @@ -74,11 +72,9 @@ public class LdapGroupToRoleMapperTest extends ElasticsearchTestCase { Settings settings = ImmutableSettings.builder() .put(AbstractGroupToRoleMapper.USE_UNMAPPED_GROUPS_AS_ROLES_SETTING, true) .build(); + RealmConfig config = new RealmConfig("ldap1", settings); - AbstractGroupToRoleMapper mapper = new LdapGroupToRoleMapper(settings, - "ldap1", - new Environment(settings), - new ResourceWatcherService(settings, threadPool)); + AbstractGroupToRoleMapper mapper = new LdapGroupToRoleMapper(config, new ResourceWatcherService(settings, threadPool)); Set roles = mapper.mapRoles(Arrays.asList(starkGroupDns)); assertThat(roles, hasItems("genius", "billionaire", "playboy", "philanthropist", "shield", "avengers")); diff --git a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTest.java b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTest.java index 9ccb2855f37..13b3f6bf46d 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTest.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTest.java @@ -7,9 +7,9 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; import org.elasticsearch.rest.RestController; import org.elasticsearch.shield.User; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredStringTests; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; @@ -51,7 +51,7 @@ public class LdapRealmTest extends LdapTest { @Test public void testRestHeaderRegistration() { - new LdapRealm.Factory(mock(Environment.class), resourceWatcherService, restController); + new LdapRealm.Factory(resourceWatcherService, restController); verify(restController).registerRelevantHeaders(UsernamePasswordToken.BASIC_AUTH_HEADER); } @@ -61,9 +61,10 @@ public class LdapRealmTest extends LdapTest { boolean isSubTreeSearch = true; String userTemplate = VALID_USER_TEMPLATE; Settings settings = buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch); - LdapConnectionFactory ldapFactory = new LdapConnectionFactory(settings); - - LdapRealm ldap = new LdapRealm("test-ldap-realm", buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings); + LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config); + config = new RealmConfig("test-ldap-realm", buildNonCachingSettings()); + LdapRealm ldap = new LdapRealm(config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); User user = ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); assertThat( user, notNullValue()); @@ -75,10 +76,14 @@ public class LdapRealmTest extends LdapTest { String groupSearchBase = "ou=crews,ou=groups,o=sevenSeas"; boolean isSubTreeSearch = false; String userTemplate = VALID_USER_TEMPLATE; - LdapConnectionFactory ldapFactory = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)); + Settings settings = ImmutableSettings.builder() + .put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)) + .put(buildNonCachingSettings()) + .build(); + RealmConfig config = new RealmConfig("test-ldap-realm", settings); - LdapRealm ldap = new LdapRealm("test-ldap-realm", buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); + LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config); + LdapRealm ldap = new LdapRealm(config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); User user = ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); assertThat( user, notNullValue()); @@ -90,11 +95,15 @@ public class LdapRealmTest extends LdapTest { String groupSearchBase = "o=sevenSeas"; boolean isSubTreeSearch = true; String userTemplate = VALID_USER_TEMPLATE; - LdapConnectionFactory ldapFactory = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch) ); + Settings settings = ImmutableSettings.builder() + .put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)) + .put(buildCachingSettings()) + .build(); + RealmConfig config = new RealmConfig("test-ldap-realm", settings); + LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config); ldapFactory = spy(ldapFactory); - LdapRealm ldap = new LdapRealm("test-ldap-realm", buildCachingSettings(), ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); + LdapRealm ldap = new LdapRealm(config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); User user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); @@ -107,13 +116,16 @@ public class LdapRealmTest extends LdapTest { String groupSearchBase = "o=sevenSeas"; boolean isSubTreeSearch = true; String userTemplate = VALID_USER_TEMPLATE; - LdapConnectionFactory ldapFactory = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch) ); + Settings settings = ImmutableSettings.builder() + .put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)) + .put(buildCachingSettings()) + .build(); + RealmConfig config = new RealmConfig("test-ldap-realm", settings); + LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config); LdapGroupToRoleMapper roleMapper = buildGroupAsRoleMapper(resourceWatcherService); - ldapFactory = spy(ldapFactory); - LdapRealm ldap = new LdapRealm("test-ldap-realm", buildCachingSettings(), ldapFactory, roleMapper); + LdapRealm ldap = new LdapRealm(config, ldapFactory, roleMapper); User user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); @@ -133,11 +145,15 @@ public class LdapRealmTest extends LdapTest { String groupSearchBase = "o=sevenSeas"; boolean isSubTreeSearch = true; String userTemplate = VALID_USER_TEMPLATE; - LdapConnectionFactory ldapFactory = new LdapConnectionFactory( - buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)); + Settings settings = ImmutableSettings.builder() + .put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch)) + .put(buildNonCachingSettings()) + .build(); + RealmConfig config = new RealmConfig("test-ldap-realm", settings); + LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config); ldapFactory = spy(ldapFactory); - LdapRealm ldap = new LdapRealm("test-ldap-realm", buildNonCachingSettings(), ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); + LdapRealm ldap = new LdapRealm(config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService)); User user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD))); diff --git a/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java b/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java index 8bd668ac0f2..5100b6371d3 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java @@ -8,15 +8,18 @@ package org.elasticsearch.shield.authc.ldap; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredStringTests; -import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory; import org.elasticsearch.shield.authc.support.ldap.AbstractLdapSslSocketFactory; +import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory; import org.elasticsearch.shield.authc.support.ldap.HostnameVerifyingLdapSslSocketFactory; import org.elasticsearch.shield.authc.support.ldap.LdapSslSocketFactory; import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.junit.annotations.Network; -import org.junit.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; import java.nio.file.Path; import java.nio.file.Paths; @@ -57,8 +60,8 @@ public class OpenLdapTests extends ElasticsearchTestCase { String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; - LdapConnectionFactory connectionFactory = new LdapConnectionFactory( - LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true, false)); + RealmConfig config = new RealmConfig("oldap-test", LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true, false)); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" }; for (String user : users) { @@ -77,8 +80,8 @@ public class OpenLdapTests extends ElasticsearchTestCase { .put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false) .put(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms") //1 millisecond .build(); - - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); + RealmConfig config = new RealmConfig("oldap-test", settings); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); try (LdapConnection ldap = connectionFactory.open("thor", SecuredStringTests.build(PASSWORD))){ ldap.groups(); @@ -97,8 +100,9 @@ public class OpenLdapTests extends ElasticsearchTestCase { .put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false) .put(ConnectionFactory.TIMEOUT_LDAP_SETTING, "1ms") //1 millisecond .build(); + RealmConfig config = new RealmConfig("oldap-test", settings); - LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); try (LdapConnection ldap = connectionFactory.open("thor", SecuredStringTests.build(PASSWORD))) { ldap.groups(); @@ -113,8 +117,8 @@ public class OpenLdapTests extends ElasticsearchTestCase { //openldap does not use cn as naming attributes by default String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; - LdapConnectionFactory connectionFactory = new LdapConnectionFactory( - LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true)); + RealmConfig config = new RealmConfig("oldap-test", LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true)); + LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config); String user = "blackwidow"; try (LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD))) { diff --git a/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java b/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java index 21258162dec..352e94f2ade 100644 --- a/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.User; import org.elasticsearch.shield.authc.Realm; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.test.ElasticsearchTestCase; import org.junit.Test; @@ -68,7 +69,7 @@ public class CachingUsernamePasswordRealmTests extends ElasticsearchTestCase { static class FailingAuthenticationRealm extends CachingUsernamePasswordRealm { FailingAuthenticationRealm(Settings settings) { - super("failing", "failing-test", settings); + super("failing", new RealmConfig("failing-test", settings)); } @Override @@ -80,7 +81,7 @@ public class CachingUsernamePasswordRealmTests extends ElasticsearchTestCase { static class ThrowingAuthenticationRealm extends CachingUsernamePasswordRealm { ThrowingAuthenticationRealm(Settings settings) { - super("throwing", "throwing-test", settings); + super("throwing", new RealmConfig("throwing-test", settings)); } @Override @@ -95,7 +96,7 @@ public class CachingUsernamePasswordRealmTests extends ElasticsearchTestCase { public final AtomicInteger INVOCATION_COUNTER = new AtomicInteger(0); AlwaysAuthenticateCachingRealm() { - super("always", "always-test", ImmutableSettings.EMPTY); + super("always", new RealmConfig("always-test", ImmutableSettings.EMPTY)); } @Override diff --git a/src/test/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactoryTests.java b/src/test/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactoryTests.java index 4569f0c1ae0..64aa35b8ff0 100644 --- a/src/test/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactoryTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/support/ldap/ConnectionFactoryTests.java @@ -8,18 +8,13 @@ package org.elasticsearch.shield.authc.support.ldap; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.shield.ShieldSettingsException; -import org.elasticsearch.shield.authc.ldap.LdapConnectionTests; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.SecuredString; -import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.test.ElasticsearchTestCase; import org.hamcrest.Matchers; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.Test; -import java.io.File; import java.io.Serializable; -import java.net.URISyntaxException; import static org.hamcrest.Matchers.equalTo; @@ -104,7 +99,8 @@ public class ConnectionFactoryTests extends ElasticsearchTestCase { } private ConnectionFactory createConnectionFactoryWithoutHostnameVerification() { - return new ConnectionFactory(ImmutableSettings.builder().put("hostname_verification", false).build()) { + RealmConfig config = new RealmConfig("_name", ImmutableSettings.builder().put("hostname_verification", false).build()); + return new ConnectionFactory(AbstractLdapConnection.class, config) { @Override public AbstractLdapConnection open(String user, SecuredString password) { return null; @@ -113,7 +109,7 @@ public class ConnectionFactoryTests extends ElasticsearchTestCase { } private ConnectionFactory createConnectionFactoryWithHostnameVerification() { - return new ConnectionFactory(ImmutableSettings.EMPTY) { + return new ConnectionFactory(AbstractLdapConnection.class, new RealmConfig("_name")) { @Override public AbstractLdapConnection open(String user, SecuredString password) { return null; diff --git a/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapTest.java b/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapTest.java index 50ed8480bb8..a8a284b4f28 100644 --- a/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapTest.java +++ b/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapTest.java @@ -10,7 +10,7 @@ import com.carrotsearch.randomizedtesting.ThreadFilter; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.ldap.LdapConnectionFactory; import org.elasticsearch.shield.authc.ldap.LdapGroupToRoleMapper; import org.elasticsearch.shield.authc.ldap.LdapRealm; @@ -78,8 +78,9 @@ public abstract class LdapTest extends ElasticsearchTestCase { Settings settings = ImmutableSettings.builder() .put(AbstractGroupToRoleMapper.USE_UNMAPPED_GROUPS_AS_ROLES_SETTING, true) .build(); + RealmConfig config = new RealmConfig("ldap1", settings); - return new LdapGroupToRoleMapper(settings, "ldap1", new Environment(settings), resourceWatcherService); + return new LdapGroupToRoleMapper(config, resourceWatcherService); } /** diff --git a/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java b/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java index eb215d6f621..186550a3809 100644 --- a/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java +++ b/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java @@ -6,6 +6,7 @@ package org.elasticsearch.shield.transport.netty; import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.netty.bootstrap.ClientBootstrap; import org.elasticsearch.common.netty.bootstrap.ServerBootstrap; import org.elasticsearch.common.netty.buffer.ChannelBuffer; @@ -16,7 +17,10 @@ import org.elasticsearch.common.netty.channel.socket.nio.NioServerSocketChannelF import org.elasticsearch.common.netty.handler.ssl.SslHandler; import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.*; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -28,7 +32,10 @@ import java.nio.file.Paths; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; @@ -133,7 +140,7 @@ public class HandshakeWaitingHandlerTests extends ElasticsearchTestCase { engine.setUseClientMode(true); return Channels.pipeline( new SslHandler(engine), - new HandshakeWaitingHandler()); + new HandshakeWaitingHandler(Loggers.getLogger(HandshakeWaitingHandler.class))); } });