LDAP: Adds SearchScope.Base tests and group.search settings for AD
Previously, AD group search used the user search dn so this adds configuration to separate the group search from the user search This adds tests for the newly introduced SearchScope.Base and includes general test cleanup. Original commit: elastic/x-pack-elasticsearch@6ed1114b29
This commit is contained in:
parent
da5299e4c5
commit
1f8189fa12
|
@ -19,8 +19,8 @@ public class ActiveDirectoryConnection extends AbstractLdapConnection {
|
|||
/**
|
||||
* This object is intended to be constructed by the LdapConnectionFactory
|
||||
*/
|
||||
ActiveDirectoryConnection(ESLogger logger, DirContext ctx, String boundName, String groupSearchDN, TimeValue timeout) {
|
||||
super(logger, ctx, boundName, new ActiveDirectoryGroupsResolver(logger, groupSearchDN), timeout);
|
||||
ActiveDirectoryConnection(ESLogger logger, DirContext ctx, String boundName, GroupsResolver resolver, TimeValue timeout) {
|
||||
super(logger, ctx, boundName, resolver, timeout);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ 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.ldap.LdapException;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection;
|
||||
import org.elasticsearch.shield.authc.support.ldap.ClosableNamingEnumeration;
|
||||
import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory;
|
||||
import org.elasticsearch.shield.authc.support.ldap.SearchScope;
|
||||
|
@ -36,6 +36,9 @@ import java.util.Hashtable;
|
|||
public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDirectoryConnection> {
|
||||
|
||||
public static final String AD_DOMAIN_NAME_SETTING = "domain_name";
|
||||
|
||||
public static final String AD_GROUP_SEARCH_BASEDN_SETTING = "group_search.base_dn";
|
||||
public static final String AD_GROUP_SEARCH_SCOPE_SETTING = "group_search.scope";
|
||||
public static final String AD_USER_SEARCH_BASEDN_SETTING = "user_search.base_dn";
|
||||
public static final String AD_USER_SEARCH_FILTER_SETTING = "user_search.filter";
|
||||
public static final String AD_USER_SEARCH_SCOPE_SETTING = "user_search.scope";
|
||||
|
@ -46,6 +49,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDi
|
|||
private final String userSearchFilter;
|
||||
private final SearchScope userSearchScope;
|
||||
private final TimeValue timeout;
|
||||
private final AbstractLdapConnection.GroupsResolver groupResolver;
|
||||
|
||||
@Inject
|
||||
public ActiveDirectoryConnectionFactory(RealmConfig config) {
|
||||
|
@ -55,9 +59,10 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDi
|
|||
if (domainName == null) {
|
||||
throw new ShieldSettingsException("missing [" + AD_DOMAIN_NAME_SETTING + "] setting for active directory");
|
||||
}
|
||||
userSearchDN = settings.get(AD_USER_SEARCH_BASEDN_SETTING, buildDnFromDomain(domainName));
|
||||
userSearchFilter = settings.get(AD_USER_SEARCH_FILTER_SETTING, "(&(objectClass=user)(|(sAMAccountName={0})(userPrincipalName={0}@" + domainName + ")))");
|
||||
String domainDN = buildDnFromDomain(domainName);
|
||||
userSearchDN = settings.get(AD_USER_SEARCH_BASEDN_SETTING, domainDN);
|
||||
userSearchScope = SearchScope.resolve(settings.get(AD_USER_SEARCH_SCOPE_SETTING), SearchScope.SUB_TREE);
|
||||
userSearchFilter = settings.get(AD_USER_SEARCH_FILTER_SETTING, "(&(objectClass=user)(|(sAMAccountName={0})(userPrincipalName={0}@" + domainName + ")))");
|
||||
timeout = settings.getAsTime(TIMEOUT_LDAP_SETTING, TIMEOUT_DEFAULT);
|
||||
String[] ldapUrls = settings.getAsArray(URLS_SETTING, new String[] { "ldaps://" + domainName + ":636" });
|
||||
|
||||
|
@ -72,6 +77,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDi
|
|||
configureJndiSSL(ldapUrls, builder);
|
||||
|
||||
sharedLdapEnv = builder.build();
|
||||
groupResolver = new ActiveDirectoryGroupsResolver(settings.getAsSettings("group_search"), domainDN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,16 +109,14 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDi
|
|||
String name = entry.getNameInNamespace();
|
||||
|
||||
if (!results.hasMore()) {
|
||||
return new ActiveDirectoryConnection(connectionLogger, ctx, name, userSearchDN, timeout);
|
||||
return new ActiveDirectoryConnection(connectionLogger, ctx, name, groupResolver, timeout);
|
||||
}
|
||||
throw new ActiveDirectoryException("search for user [" + userName + "] by principle name yielded multiple results");
|
||||
} else {
|
||||
throw new ActiveDirectoryException("search for user [" + userName + "] by principle name yielded no results");
|
||||
}
|
||||
}
|
||||
} catch (NamingException | LdapException e) {
|
||||
throw new ActiveDirectoryException("unable to authenticate user [" + userName + "] to active directory domain [" + domainName + "]", e);
|
||||
} finally {
|
||||
} catch (Throwable e) {
|
||||
if (ctx != null) {
|
||||
try {
|
||||
ctx.close();
|
||||
|
@ -120,6 +124,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory<ActiveDi
|
|||
logger.trace("an unexpected error occurred closing an LDAP context", ne);
|
||||
}
|
||||
}
|
||||
throw new ActiveDirectoryException("unable to authenticate user [" + userName + "] to active directory domain [" + domainName + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ 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.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.shield.authc.ldap.LdapException;
|
||||
import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection;
|
||||
|
@ -24,15 +25,15 @@ import java.util.List;
|
|||
*/
|
||||
public class ActiveDirectoryGroupsResolver implements AbstractLdapConnection.GroupsResolver {
|
||||
|
||||
private final ESLogger logger;
|
||||
private final String baseDn;
|
||||
private final SearchScope scope;
|
||||
|
||||
public ActiveDirectoryGroupsResolver(ESLogger logger, String baseDn) {
|
||||
this.logger = logger;
|
||||
this.baseDn = baseDn;
|
||||
public ActiveDirectoryGroupsResolver(Settings settings, String baseDnDefault) {
|
||||
this.baseDn = settings.get("base_dn", baseDnDefault);
|
||||
this.scope = SearchScope.resolve(settings.get("scope"), SearchScope.SUB_TREE);
|
||||
}
|
||||
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout) {
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout, ESLogger logger) {
|
||||
|
||||
String groupsSearchFilter = buildGroupQuery(ctx, userDn, timeout);
|
||||
logger.debug("group SID to DN search filter: [{}]", groupsSearchFilter);
|
||||
|
@ -42,7 +43,7 @@ public class ActiveDirectoryGroupsResolver implements AbstractLdapConnection.Gro
|
|||
SearchControls groupsSearchCtls = new SearchControls();
|
||||
|
||||
//Specify the search scope
|
||||
groupsSearchCtls.setSearchScope(SearchScope.SUB_TREE.scope());
|
||||
groupsSearchCtls.setSearchScope(scope.scope());
|
||||
groupsSearchCtls.setReturningAttributes(Strings.EMPTY_ARRAY); //we only need the entry DN
|
||||
groupsSearchCtls.setTimeLimit((int) timeout.millis());
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.shield.authc.ldap;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection;
|
||||
|
@ -38,18 +39,11 @@ class SearchGroupsResolver implements AbstractLdapConnection.GroupsResolver {
|
|||
scope = SearchScope.resolve(settings.get("scope"), SearchScope.SUB_TREE);
|
||||
}
|
||||
|
||||
public SearchGroupsResolver(String baseDn, String filter, String userAttribute, SearchScope scope) {
|
||||
this.baseDn = baseDn;
|
||||
this.filter = filter;
|
||||
this.userAttribute = userAttribute;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout) {
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout, ESLogger logger) {
|
||||
List<String> groups = new LinkedList<>();
|
||||
|
||||
String userId = userAttribute != null ? readUserAttribute(ctx, userDn, userDn) : userDn;
|
||||
String userId = userAttribute != null ? readUserAttribute(ctx, userDn) : userDn;
|
||||
SearchControls search = new SearchControls();
|
||||
search.setReturningAttributes(Strings.EMPTY_ARRAY);
|
||||
search.setSearchScope(scope.scope());
|
||||
|
@ -66,7 +60,7 @@ class SearchGroupsResolver implements AbstractLdapConnection.GroupsResolver {
|
|||
return groups;
|
||||
}
|
||||
|
||||
String readUserAttribute(DirContext ctx, String userDn, String userAttribute) {
|
||||
String readUserAttribute(DirContext ctx, String userDn) {
|
||||
try {
|
||||
Attributes results = ctx.getAttributes(userDn, new String[]{userAttribute});
|
||||
Attribute attribute = results.get(userAttribute);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.authc.ldap;
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection;
|
||||
|
@ -34,7 +35,7 @@ class UserAttributeGroupsResolver implements AbstractLdapConnection.GroupsResolv
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout) {
|
||||
public List<String> resolve(DirContext ctx, String userDn, TimeValue timeout, ESLogger logger) {
|
||||
List<String> groupDns = new LinkedList<>();
|
||||
try {
|
||||
Attributes results = ctx.getAttributes(userDn, new String[] { attribute });
|
||||
|
|
|
@ -27,10 +27,10 @@ public abstract class AbstractLdapConnection implements Closeable {
|
|||
/**
|
||||
* This object is intended to be constructed by the LdapConnectionFactory
|
||||
*
|
||||
* This constructor accepts a logger with wich the connection can log. Since this connection
|
||||
* This constructor accepts a logger with which 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).
|
||||
* since we want the logger to be contextual (i.e. aware of the settings and its environment).
|
||||
*/
|
||||
public AbstractLdapConnection(ESLogger logger, DirContext ctx, String boundName, GroupsResolver groupsResolver, TimeValue timeout) {
|
||||
this.logger = logger;
|
||||
|
@ -64,12 +64,12 @@ public abstract class AbstractLdapConnection implements Closeable {
|
|||
* @return List of fully distinguished group names
|
||||
*/
|
||||
public List<String> groups() {
|
||||
return groupsResolver.resolve(jndiContext, bindDn, timeout);
|
||||
return groupsResolver.resolve(jndiContext, bindDn, timeout, logger);
|
||||
}
|
||||
|
||||
public static interface GroupsResolver {
|
||||
|
||||
List<String> resolve(DirContext ctx, String userDn, TimeValue timeout);
|
||||
List<String> resolve(DirContext ctx, String userDn, TimeValue timeout, ESLogger logger);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.support.ldap;
|
|||
import org.elasticsearch.shield.authc.ldap.LdapException;
|
||||
|
||||
import javax.naming.directory.SearchControls;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -32,7 +33,7 @@ public enum SearchScope {
|
|||
if (scope == null) {
|
||||
return defaultScope;
|
||||
}
|
||||
switch (scope.toLowerCase()) {
|
||||
switch (scope.toLowerCase(Locale.ENGLISH)) {
|
||||
case "base":
|
||||
case "object": return BASE;
|
||||
case "one_level" : return ONE_LEVEL;
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.shield.authc.active_directory.ActiveDirectoryRealm;
|
|||
import org.elasticsearch.shield.authc.ldap.LdapRealm;
|
||||
import org.elasticsearch.shield.authc.support.SecuredString;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.authc.support.ldap.SearchScope;
|
||||
import org.elasticsearch.shield.authz.AuthorizationException;
|
||||
import org.elasticsearch.shield.transport.netty.NettySecuredTransport;
|
||||
import org.elasticsearch.test.ShieldIntegrationTest;
|
||||
|
@ -173,6 +174,8 @@ abstract public class AbstractAdLdapRealmTests extends ShieldIntegrationTest {
|
|||
ImmutableSettings.builder()
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".type", ActiveDirectoryRealm.TYPE)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".domain_name", "ad.test.elasticsearch.com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.base_dn", "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.scope", randomBoolean() ? SearchScope.SUB_TREE : SearchScope.ONE_LEVEL)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://ad.test.elasticsearch.com:636")
|
||||
.build()),
|
||||
|
||||
|
@ -180,7 +183,8 @@ abstract public class AbstractAdLdapRealmTests extends ShieldIntegrationTest {
|
|||
ImmutableSettings.builder()
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".type", LdapRealm.TYPE)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://ad.test.elasticsearch.com:636")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.group_search_dn", "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.base_dn", "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.scope", randomBoolean() ? SearchScope.SUB_TREE : SearchScope.ONE_LEVEL)
|
||||
.putArray(SHIELD_AUTHC_REALMS_EXTERNAL + ".user_dn_templates", "cn={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
|
||||
.build()),
|
||||
|
||||
|
@ -195,7 +199,8 @@ abstract public class AbstractAdLdapRealmTests extends ShieldIntegrationTest {
|
|||
ImmutableSettings.builder()
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".type", LdapRealm.TYPE)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".url", "ldaps://54.200.235.244:636")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.group_search_dn", "ou=people, dc=oldap, dc=test, dc=elasticsearch, dc=com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.base_dn", "ou=people, dc=oldap, dc=test, dc=elasticsearch, dc=com")
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.scope", randomBoolean() ? SearchScope.SUB_TREE : SearchScope.ONE_LEVEL)
|
||||
.putArray(SHIELD_AUTHC_REALMS_EXTERNAL + ".user_dn_templates", "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com")
|
||||
.build());
|
||||
|
||||
|
@ -215,7 +220,6 @@ abstract public class AbstractAdLdapRealmTests extends ShieldIntegrationTest {
|
|||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".order", 1)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".hostname_verification", false)
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".group_search.subtree_search", randomBoolean())
|
||||
.put(SHIELD_AUTHC_REALMS_EXTERNAL + ".unmapped_groups_as_roles", mapGroupsAsRoles)
|
||||
.put(sslSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode")) //we need ssl to the LDAP server
|
||||
.put(this.settings);
|
||||
|
|
|
@ -11,7 +11,6 @@ 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;
|
||||
import org.elasticsearch.shield.authc.ldap.LdapException;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.ldap.*;
|
||||
|
@ -38,7 +37,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
|
||||
@Before
|
||||
public void initializeSslSocketFactory() throws Exception {
|
||||
Path keystore = Paths.get(LdapConnectionTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).toAbsolutePath();
|
||||
Path keystore = Paths.get(ActiveDirectoryFactoryTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).toAbsolutePath();
|
||||
|
||||
/*
|
||||
* Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext.
|
||||
|
@ -81,7 +80,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
@Test @LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch-shield/issues/499")
|
||||
public void testTcpReadTimeout() {
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN))
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false))
|
||||
.put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false)
|
||||
.put(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms")
|
||||
.build();
|
||||
|
@ -109,8 +108,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
}
|
||||
|
||||
@Test @SuppressWarnings("unchecked")
|
||||
public void testAuthenticate_specificUserSearch() {
|
||||
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", false);
|
||||
public void testAuthenticate() {
|
||||
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", SearchScope.ONE_LEVEL, false);
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config);
|
||||
|
||||
|
@ -123,15 +122,54 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
containsString("SHIELD"),
|
||||
containsString("Geniuses"),
|
||||
containsString("Philanthropists"),
|
||||
//containsString("Users"), Users group is in a different user context
|
||||
containsString("Users"),
|
||||
containsString("Domain Users"),
|
||||
containsString("Supers")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test @SuppressWarnings("unchecked")
|
||||
public void testAuthenticate_baseUserSearch() {
|
||||
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Bruce Banner, CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", SearchScope.BASE, false);
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config);
|
||||
|
||||
String userName = "hulk";
|
||||
try (AbstractLdapConnection ldap = connectionFactory.open(userName, SecuredStringTests.build(PASSWORD))) {
|
||||
List<String> groups = ldap.groups();
|
||||
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Avengers"),
|
||||
containsString("SHIELD"),
|
||||
containsString("Geniuses"),
|
||||
containsString("Philanthropists"),
|
||||
containsString("Users"),
|
||||
containsString("Domain Users"),
|
||||
containsString("Supers")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test @SuppressWarnings("unchecked")
|
||||
public void testAuthenticate_baseGroupSearch() {
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", SearchScope.ONE_LEVEL, false))
|
||||
.put(ActiveDirectoryConnectionFactory.AD_GROUP_SEARCH_BASEDN_SETTING, "CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
|
||||
.put(ActiveDirectoryConnectionFactory.AD_GROUP_SEARCH_SCOPE_SETTING, SearchScope.BASE)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config);
|
||||
|
||||
String userName = "hulk";
|
||||
try (AbstractLdapConnection ldap = connectionFactory.open(userName, SecuredStringTests.build(PASSWORD))) {
|
||||
List<String> groups = ldap.groups();
|
||||
|
||||
assertThat(groups, hasItem(containsString("Avengers")));
|
||||
}
|
||||
}
|
||||
|
||||
@Test @SuppressWarnings("unchecked")
|
||||
public void testAuthenticate_UserPrincipalName() {
|
||||
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", false);
|
||||
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", SearchScope.ONE_LEVEL, false);
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config);
|
||||
|
||||
|
@ -142,6 +180,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
userDN = ldap.authenticatedUserDn();
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Geniuses"),
|
||||
containsString("Users"),
|
||||
containsString("Domain Users")));
|
||||
}
|
||||
//Same user but login with sAMAccountName
|
||||
|
@ -151,6 +190,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
List<String> groups = ldap.groups();
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Geniuses"),
|
||||
containsString("Users"),
|
||||
containsString("Domain Users")));
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +198,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
@Test @SuppressWarnings("unchecked")
|
||||
public void testCustomUserFilter() {
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", false))
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", SearchScope.SUB_TREE, false))
|
||||
.put(ActiveDirectoryConnectionFactory.AD_USER_SEARCH_FILTER_SETTING, "(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))")
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
|
@ -169,7 +209,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
List<String> groups = ldap.groups();
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Geniuses"),
|
||||
containsString("Domain Users")));
|
||||
containsString("Domain Users"),
|
||||
containsString("Users")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,22 +219,34 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
public void testStandardLdapConnection(){
|
||||
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);
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
Settings settings = LdapTest.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, SearchScope.SUB_TREE);
|
||||
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings);
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
String user = "Bruce Banner";
|
||||
try (LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD))) {
|
||||
List<String> groups = ldap.getGroupsFromUserAttrs();
|
||||
List<String> groups2 = ldap.getGroupsFromSearch();
|
||||
List<String> groups = ldap.groups();
|
||||
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Avengers"),
|
||||
containsString("SHIELD"),
|
||||
containsString("Geniuses"),
|
||||
containsString("Philanthropists")));
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(groups2, containsInAnyOrder(
|
||||
@Test @SuppressWarnings("unchecked")
|
||||
public void testStandardLdapWithAttributeGroups(){
|
||||
String userTemplate = "CN={0},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
|
||||
Settings settings = LdapTest.buildLdapSettings(AD_LDAP_URL, userTemplate, false);
|
||||
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings);
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
String user = "Bruce Banner";
|
||||
try (LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD))) {
|
||||
List<String> groups = ldap.groups();
|
||||
|
||||
assertThat(groups, containsInAnyOrder(
|
||||
containsString("Avengers"),
|
||||
containsString("SHIELD"),
|
||||
containsString("Geniuses"),
|
||||
|
@ -203,7 +256,7 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
|
||||
@Test(expected = ActiveDirectoryException.class)
|
||||
public void testAdAuthWithHostnameVerification() {
|
||||
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN));
|
||||
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, true));
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(config);
|
||||
|
||||
String userName = "ironman";
|
||||
|
@ -216,7 +269,10 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
public void testStandardLdapHostnameVerification(){
|
||||
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);
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(LdapTest.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.put(LdapConnectionFactory.HOSTNAME_VERIFICATION_SETTING, true)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ad-test", settings);
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
|
@ -226,10 +282,6 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName) {
|
||||
return buildAdSettings(ldapUrl, adDomainName, true);
|
||||
}
|
||||
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName, boolean hostnameVerification) {
|
||||
return ImmutableSettings.builder()
|
||||
.put(ActiveDirectoryConnectionFactory.URLS_SETTING, ldapUrl)
|
||||
|
@ -238,15 +290,16 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
.build();
|
||||
}
|
||||
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName, String userSearchDN) {
|
||||
return buildAdSettings(ldapUrl, adDomainName, userSearchDN, true);
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName, SearchScope scope, String userSearchDN) {
|
||||
return buildAdSettings(ldapUrl, adDomainName, userSearchDN, scope, true);
|
||||
}
|
||||
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName, String userSearchDN, boolean hostnameVerification) {
|
||||
public static Settings buildAdSettings(String ldapUrl, String adDomainName, String userSearchDN, SearchScope scope, boolean hostnameVerification) {
|
||||
return ImmutableSettings.builder()
|
||||
.putArray(ActiveDirectoryConnectionFactory.URLS_SETTING, ldapUrl)
|
||||
.put(ActiveDirectoryConnectionFactory.AD_DOMAIN_NAME_SETTING, adDomainName)
|
||||
.put(ActiveDirectoryConnectionFactory.AD_USER_SEARCH_BASEDN_SETTING, userSearchDN)
|
||||
.put(ActiveDirectoryConnectionFactory.AD_USER_SEARCH_SCOPE_SETTING, scope)
|
||||
.put(ActiveDirectoryConnectionFactory.HOSTNAME_VERIFICATION_SETTING, hostnameVerification)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory;
|
||||
import org.elasticsearch.shield.authc.support.ldap.LdapTest;
|
||||
import org.elasticsearch.shield.authc.support.ldap.SearchScope;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -21,7 +22,7 @@ import java.util.List;
|
|||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class LdapConnectionTests extends LdapTest {
|
||||
public class LdapConnectionFactoryTests extends LdapTest {
|
||||
|
||||
public void testBindWithTimeout() throws Exception {
|
||||
int randomPort = randomIntBetween(49152, 65525); // ephemeral port
|
||||
|
@ -32,13 +33,13 @@ public class LdapConnectionTests extends LdapTest {
|
|||
serverSocket.setReuseAddress(true);
|
||||
serverSocket.bind(sa);
|
||||
|
||||
String[] ldapUrls = new String[] { "ldap://localhost:" + randomPort };
|
||||
String ldapUrl = "ldap://localhost:" + randomPort ;
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
String[] userTemplates = new String[] {
|
||||
"cn={0},ou=people,o=sevenSeas",
|
||||
};
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true))
|
||||
.put(buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.put(ConnectionFactory.TIMEOUT_TCP_CONNECTION_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("ldap_realm", settings);
|
||||
|
@ -60,14 +61,13 @@ public class LdapConnectionTests extends LdapTest {
|
|||
|
||||
@Test
|
||||
public void testBindWithTemplates() {
|
||||
String[] ldapUrls = new String[] { ldapUrl() };
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
String[] userTemplates = new String[] {
|
||||
"cn={0},ou=something,ou=obviously,ou=incorrect,o=sevenSeas",
|
||||
"wrongname={0},ou=people,o=sevenSeas",
|
||||
"cn={0},ou=people,o=sevenSeas", //this last one should work
|
||||
};
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true));
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplates, groupSearchBase, SearchScope.SUB_TREE));
|
||||
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
|
@ -77,22 +77,19 @@ public class LdapConnectionTests extends LdapTest {
|
|||
try (LdapConnection ldap = connectionFactory.open(user, userPass)) {
|
||||
String dn = ldap.authenticatedUserDn();
|
||||
assertThat(dn, containsString(user));
|
||||
//assertThat( attrs.get("uid"), arrayContaining("hhornblo"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = LdapException.class)
|
||||
public void testBindWithBogusTemplates() {
|
||||
String[] ldapUrl = new String[] { ldapUrl() };
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
boolean isSubTreeSearch = true;
|
||||
String[] userTemplates = new String[] {
|
||||
"cn={0},ou=something,ou=obviously,ou=incorrect,o=sevenSeas",
|
||||
"wrongname={0},ou=people,o=sevenSeas",
|
||||
"asdf={0},ou=people,o=sevenSeas", //none of these should work
|
||||
};
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, isSubTreeSearch));
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplates, groupSearchBase, SearchScope.SUB_TREE));
|
||||
|
||||
LdapConnectionFactory ldapFac = new LdapConnectionFactory(config);
|
||||
|
||||
|
@ -106,7 +103,7 @@ 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));
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.SUB_TREE));
|
||||
|
||||
LdapConnectionFactory ldapFac = new LdapConnectionFactory(config);
|
||||
|
||||
|
@ -114,8 +111,8 @@ public class LdapConnectionTests extends LdapTest {
|
|||
SecuredString userPass = SecuredStringTests.build("pass");
|
||||
|
||||
try (LdapConnection ldap = ldapFac.open(user, userPass)) {
|
||||
List<String> groups = ldap.getGroupsFromSearch();
|
||||
assertThat(groups, contains("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
List<String> groups = ldap.groups();
|
||||
assertThat(groups, containsInAnyOrder("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,35 +120,32 @@ 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";
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, false));
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.ONE_LEVEL));
|
||||
|
||||
LdapConnectionFactory ldapFac = new LdapConnectionFactory(config);
|
||||
|
||||
String user = "Horatio Hornblower";
|
||||
try (LdapConnection ldap = ldapFac.open(user, SecuredStringTests.build("pass"))) {
|
||||
List<String> groups = ldap.getGroupsFromSearch();
|
||||
assertThat(groups, contains("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
List<String> groups = ldap.groups();
|
||||
assertThat(groups, containsInAnyOrder("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAttributeLookup() {
|
||||
String groupSearchBase = "ou=crews,ou=groups,o=sevenSeas";
|
||||
public void testGroupLookup_Base() {
|
||||
String groupSearchBase = "cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas";
|
||||
String userTemplate = "cn={0},ou=people,o=sevenSeas";
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, false));
|
||||
RealmConfig config = new RealmConfig("ldap_realm", buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.BASE));
|
||||
|
||||
LdapConnectionFactory ldapFac = new LdapConnectionFactory(config);
|
||||
|
||||
|
||||
String user = "Horatio Hornblower";
|
||||
try (LdapConnection ldap = ldapFac.open(user, SecuredStringTests.build("pass"))) {
|
||||
assertThat(ldap.readUserAttribute("mail"), is("hhornblo@royalnavy.mod.uk"));
|
||||
assertThat(ldap.readUserAttribute("uid"), is("hhornblo"));
|
||||
try {
|
||||
ldap.readUserAttribute("nonexistentAttribute");
|
||||
fail("reading a non existent attribute should throw an LDAPException");
|
||||
} catch (LdapException e) {
|
||||
assertThat(e.getMessage(), containsString("No results"));
|
||||
}
|
||||
SecuredString userPass = SecuredStringTests.build("pass");
|
||||
|
||||
try (LdapConnection ldap = ldapFac.open(user, userPass)) {
|
||||
List<String> groups = ldap.groups();
|
||||
assertThat(groups.size(), is(1));
|
||||
assertThat(groups, containsInAnyOrder("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.shield.authc.support.SecuredString;
|
|||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.authc.support.ldap.LdapTest;
|
||||
import org.elasticsearch.shield.authc.support.ldap.SearchScope;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.After;
|
||||
|
@ -58,12 +59,10 @@ public class LdapRealmTest extends LdapTest {
|
|||
@Test
|
||||
public void testAuthenticate_SubTreeGroupSearch(){
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
boolean isSubTreeSearch = true;
|
||||
String userTemplate = VALID_USER_TEMPLATE;
|
||||
Settings settings = buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch);
|
||||
Settings settings = buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.SUB_TREE);
|
||||
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)));
|
||||
|
@ -74,11 +73,9 @@ public class LdapRealmTest extends LdapTest {
|
|||
@Test
|
||||
public void testAuthenticate_OneLevelGroupSearch(){
|
||||
String groupSearchBase = "ou=crews,ou=groups,o=sevenSeas";
|
||||
boolean isSubTreeSearch = false;
|
||||
String userTemplate = VALID_USER_TEMPLATE;
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch))
|
||||
.put(buildNonCachingSettings())
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.ONE_LEVEL))
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm", settings);
|
||||
|
||||
|
@ -93,19 +90,17 @@ public class LdapRealmTest extends LdapTest {
|
|||
@Test
|
||||
public void testAuthenticate_Caching(){
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
boolean isSubTreeSearch = true;
|
||||
String userTemplate = VALID_USER_TEMPLATE;
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch))
|
||||
.put(buildCachingSettings())
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm", settings);
|
||||
|
||||
LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config);
|
||||
ldapFactory = spy(ldapFactory);
|
||||
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)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
|
||||
//verify one and only one open -> caching is working
|
||||
verify(ldapFactory, times(1)).open(anyString(), any(SecuredString.class));
|
||||
|
@ -114,11 +109,9 @@ public class LdapRealmTest extends LdapTest {
|
|||
@Test
|
||||
public void testAuthenticate_Caching_Refresh(){
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
boolean isSubTreeSearch = true;
|
||||
String userTemplate = VALID_USER_TEMPLATE;
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch))
|
||||
.put(buildCachingSettings())
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm", settings);
|
||||
|
||||
|
@ -126,15 +119,15 @@ public class LdapRealmTest extends LdapTest {
|
|||
LdapGroupToRoleMapper roleMapper = buildGroupAsRoleMapper(resourceWatcherService);
|
||||
ldapFactory = spy(ldapFactory);
|
||||
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)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
|
||||
//verify one and only one open -> caching is working
|
||||
verify(ldapFactory, times(1)).open(anyString(), any(SecuredString.class));
|
||||
|
||||
roleMapper.notifyRefresh();
|
||||
|
||||
user = ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
|
||||
//we need to open again
|
||||
verify(ldapFactory, times(2)).open(anyString(), any(SecuredString.class));
|
||||
|
@ -143,23 +136,21 @@ public class LdapRealmTest extends LdapTest {
|
|||
@Test
|
||||
public void testAuthenticate_Noncaching(){
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
boolean isSubTreeSearch = true;
|
||||
String userTemplate = VALID_USER_TEMPLATE;
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, isSubTreeSearch))
|
||||
.put(buildNonCachingSettings())
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.put(LdapRealm.CACHE_TTL, -1)
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("test-ldap-realm", settings);
|
||||
|
||||
LdapConnectionFactory ldapFactory = new LdapConnectionFactory(config);
|
||||
ldapFactory = spy(ldapFactory);
|
||||
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)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
ldap.authenticate( new UsernamePasswordToken(VALID_USERNAME, SecuredStringTests.build(PASSWORD)));
|
||||
|
||||
//verify two and only two binds -> caching is disabled
|
||||
verify(ldapFactory, times(2)).open(anyString(), any(SecuredString.class));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -10,10 +10,7 @@ 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.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.authc.support.ldap.*;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.Network;
|
||||
|
@ -35,7 +32,7 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
|
||||
@Before
|
||||
public void initializeSslSocketFactory() throws Exception {
|
||||
Path keystore = Paths.get(LdapConnectionTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).toAbsolutePath();
|
||||
Path keystore = Paths.get(OpenLdapTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).toAbsolutePath();
|
||||
|
||||
/*
|
||||
* Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext.
|
||||
|
@ -60,7 +57,24 @@ 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";
|
||||
RealmConfig config = new RealmConfig("oldap-test", LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true, false));
|
||||
RealmConfig config = new RealmConfig("oldap-test", LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.ONE_LEVEL));
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" };
|
||||
for (String user : users) {
|
||||
LdapConnection ldap = connectionFactory.open(user, SecuredStringTests.build(PASSWORD));
|
||||
assertThat(ldap.groups(), hasItem(containsString("Avengers")));
|
||||
ldap.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupSearchScopeBase() {
|
||||
//base search on a groups means that the user can be in just one group
|
||||
|
||||
String groupSearchBase = "cn=Avengers,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
|
||||
String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
|
||||
RealmConfig config = new RealmConfig("oldap-test", LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.BASE));
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" };
|
||||
|
@ -76,9 +90,9 @@ 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";
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate,groupSearchBase, true, false))
|
||||
.put(LdapConnectionFactory.GROUP_SEARCH_FILTER_SETTING, "(&(objectclass=posixGroup)(memberUID={0}))")
|
||||
.put(LdapConnectionFactory.GROUP_SEARCH_USER_ATTRIBUTE_SETTING, "uid")
|
||||
.put(LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.ONE_LEVEL))
|
||||
.put("group_search.filter", "(&(objectclass=posixGroup)(memberUID={0}))")
|
||||
.put("group_search.user_attribute", "uid")
|
||||
.build();
|
||||
RealmConfig config = new RealmConfig("oldap-test", settings);
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
@ -93,7 +107,7 @@ 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";
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true))
|
||||
.put(LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.ONE_LEVEL))
|
||||
.put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false)
|
||||
.put(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
|
@ -113,7 +127,7 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
String groupSearchBase = "dc=elasticsearch,dc=com";
|
||||
String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true))
|
||||
.put(LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.SUB_TREE))
|
||||
.put(ConnectionFactory.HOSTNAME_VERIFICATION_SETTING, false)
|
||||
.put(ConnectionFactory.TIMEOUT_LDAP_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
|
@ -134,7 +148,12 @@ 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";
|
||||
RealmConfig config = new RealmConfig("oldap-test", LdapConnectionTests.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, true));
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(LdapTest.buildLdapSettings(OPEN_LDAP_URL, userTemplate, groupSearchBase, SearchScope.ONE_LEVEL))
|
||||
.put(LdapConnectionFactory.HOSTNAME_VERIFICATION_SETTING, true)
|
||||
.build();
|
||||
|
||||
RealmConfig config = new RealmConfig("oldap-test", settings);
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(config);
|
||||
|
||||
String user = "blackwidow";
|
||||
|
@ -142,4 +161,6 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
fail("OpenLDAP certificate does not contain the correct hostname/ip so hostname verification should fail on open");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,15 +11,15 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
|
|||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
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;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import static org.elasticsearch.shield.authc.ldap.LdapConnectionFactory.*;
|
||||
|
||||
@Ignore
|
||||
@ThreadLeakFilters(defaultFilters = true, filters = { LdapTest.ApachedsThreadLeakFilter.class })
|
||||
public abstract class LdapTest extends ElasticsearchTestCase {
|
||||
|
@ -42,36 +42,24 @@ public abstract class LdapTest extends ElasticsearchTestCase {
|
|||
return ldap.getUrl();
|
||||
}
|
||||
|
||||
public static Settings buildLdapSettings(String ldapUrl, String userTemplate, String groupSearchBase, boolean isSubTreeSearch) {
|
||||
return buildLdapSettings( new String[]{ldapUrl}, new String[]{userTemplate}, groupSearchBase, isSubTreeSearch );
|
||||
public static Settings buildLdapSettings(String ldapUrl, String userTemplate, String groupSearchBase, SearchScope scope) {
|
||||
return buildLdapSettings(ldapUrl, new String[] { userTemplate }, groupSearchBase, scope);
|
||||
}
|
||||
|
||||
public static Settings buildLdapSettings(String ldapUrl, String userTemplate, String groupSearchBase, boolean isSubTreeSearch, boolean hostnameVerification) {
|
||||
return buildLdapSettings( new String[]{ldapUrl}, new String[]{userTemplate}, groupSearchBase, isSubTreeSearch, hostnameVerification );
|
||||
}
|
||||
|
||||
public static Settings buildLdapSettings(String[] ldapUrl, String[] userTemplate, String groupSearchBase, boolean isSubTreeSearch) {
|
||||
return buildLdapSettings(ldapUrl, userTemplate, groupSearchBase, isSubTreeSearch, true);
|
||||
}
|
||||
|
||||
public static Settings buildLdapSettings(String[] ldapUrl, String[] userTemplate, String groupSearchBase, boolean isSubTreeSearch, boolean hostnameVerification) {
|
||||
public static Settings buildLdapSettings(String ldapUrl, String[] userTemplate, String groupSearchBase, SearchScope scope) {
|
||||
return ImmutableSettings.builder()
|
||||
.putArray(LdapConnectionFactory.URLS_SETTING, ldapUrl)
|
||||
.putArray(LdapConnectionFactory.USER_DN_TEMPLATES_SETTING, userTemplate)
|
||||
.put(LdapConnectionFactory.GROUP_SEARCH_BASEDN_SETTING, groupSearchBase)
|
||||
.put(LdapConnectionFactory.GROUP_SEARCH_SUBTREE_SETTING, isSubTreeSearch)
|
||||
.put(LdapConnectionFactory.HOSTNAME_VERIFICATION_SETTING, hostnameVerification).build();
|
||||
.putArray(URLS_SETTING, ldapUrl)
|
||||
.putArray(USER_DN_TEMPLATES_SETTING, userTemplate)
|
||||
.put("group_search.base_dn", groupSearchBase)
|
||||
.put("group_search.scope", scope)
|
||||
.put(HOSTNAME_VERIFICATION_SETTING, false).build();
|
||||
}
|
||||
|
||||
protected Settings buildNonCachingSettings() {
|
||||
public static Settings buildLdapSettings(String ldapUrl, String userTemplate, boolean hostnameVerification) {
|
||||
return ImmutableSettings.builder()
|
||||
.put(LdapRealm.CACHE_TTL, -1)
|
||||
.build();
|
||||
}
|
||||
|
||||
protected Settings buildCachingSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
.build();
|
||||
.putArray(URLS_SETTING, ldapUrl)
|
||||
.putArray(USER_DN_TEMPLATES_SETTING, userTemplate)
|
||||
.put(HOSTNAME_VERIFICATION_SETTING, hostnameVerification).build();
|
||||
}
|
||||
|
||||
protected LdapGroupToRoleMapper buildGroupAsRoleMapper(ResourceWatcherService resourceWatcherService) {
|
||||
|
|
Loading…
Reference in New Issue