test: ldap timeout test failing on windows
This extends the connect timeout on windows to give it enought time to complete. It moves the ldap read timeout test to openldap and active directory. We now have three timeouts configurable. The timeout tests on active directory only work for TCP connect, and TCP read, but not LDAP Search. Original commit: elastic/x-pack-elasticsearch@ff97396f60
This commit is contained in:
parent
38a0ec9c3e
commit
661b755639
|
@ -24,13 +24,15 @@ 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) {
|
||||
ActiveDirectoryConnection(DirContext ctx, String boundName, String groupSearchDN, int timeoutMilliseconds) {
|
||||
super(ctx, boundName);
|
||||
this.groupSearchDN = groupSearchDN;
|
||||
this.timeoutMilliseconds = timeoutMilliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,6 +61,7 @@ public class ActiveDirectoryConnection extends AbstractLdapConnection {
|
|||
//Specify the search scope
|
||||
groupsSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
groupsSearchCtls.setReturningAttributes(Strings.EMPTY_ARRAY); //we only need the entry DN
|
||||
groupsSearchCtls.setTimeLimit(timeoutMilliseconds);
|
||||
|
||||
ImmutableList.Builder<String> groups = ImmutableList.builder();
|
||||
try {
|
||||
|
|
|
@ -38,6 +38,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory {
|
|||
private final ImmutableMap<String, Serializable> sharedLdapEnv;
|
||||
private final String userSearchDN;
|
||||
private final String domainName;
|
||||
private final int timeoutMilliseconds;
|
||||
|
||||
@Inject
|
||||
public ActiveDirectoryConnectionFactory(Settings settings) {
|
||||
|
@ -47,14 +48,14 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory {
|
|||
throw new ShieldSettingsException("Missing [" + AD_DOMAIN_NAME_SETTING + "] setting for active directory");
|
||||
}
|
||||
userSearchDN = settings.get(AD_USER_SEARCH_BASEDN_SETTING, buildDnFromDomain(domainName));
|
||||
|
||||
timeoutMilliseconds = (int) settings.getAsTime(TIMEOUT_LDAP_SETTING, TIMEOUT_DEFAULT).millis();
|
||||
String[] ldapUrls = settings.getAsArray(URLS_SETTING, new String[] { "ldaps://" + domainName + ":636" });
|
||||
|
||||
ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder()
|
||||
.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
|
||||
.put(Context.PROVIDER_URL, Strings.arrayToCommaDelimitedString(ldapUrls))
|
||||
.put(JNDI_LDAP_CONNECT_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_CONNECTION_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_READ_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_CONNECTION_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_CONNECT_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_TCP_CONNECTION_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_READ_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_TCP_READ_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put("java.naming.ldap.attributes.binary", "tokenGroups")
|
||||
.put(Context.REFERRAL, "follow");
|
||||
|
||||
|
@ -82,7 +83,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory {
|
|||
SearchControls searchCtls = new SearchControls();
|
||||
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
searchCtls.setReturningAttributes(Strings.EMPTY_ARRAY);
|
||||
|
||||
searchCtls.setTimeLimit(timeoutMilliseconds);
|
||||
String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))";
|
||||
NamingEnumeration<SearchResult> results = ctx.search(userSearchDN, searchFilter, new Object[] { userPrincipal }, searchCtls);
|
||||
|
||||
|
@ -91,7 +92,7 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory {
|
|||
String name = entry.getNameInNamespace();
|
||||
|
||||
if (!results.hasMore()) {
|
||||
return new ActiveDirectoryConnection(ctx, name, userSearchDN);
|
||||
return new ActiveDirectoryConnection(ctx, name, userSearchDN, timeoutMilliseconds);
|
||||
}
|
||||
throw new ActiveDirectoryException("Search for user [" + userName + "] by principle name yielded multiple results");
|
||||
}
|
||||
|
|
|
@ -34,16 +34,18 @@ public class LdapConnection extends AbstractLdapConnection {
|
|||
private final String groupSearchDN;
|
||||
private final boolean isGroupSubTreeSearch;
|
||||
private final boolean isFindGroupsByAttribute;
|
||||
protected final String groupAttribute = "memberOf";
|
||||
private final String groupAttribute = "memberOf";
|
||||
private final int timeoutMilliseconds;
|
||||
|
||||
/**
|
||||
* This object is intended to be constructed by the LdapConnectionFactory
|
||||
*/
|
||||
LdapConnection(DirContext ctx, String boundName, boolean isFindGroupsByAttribute, boolean isGroupSubTreeSearch, String groupSearchDN) {
|
||||
LdapConnection(DirContext ctx, String boundName, boolean isFindGroupsByAttribute, boolean isGroupSubTreeSearch, String groupSearchDN, int timeoutMilliseconds) {
|
||||
super(ctx, boundName);
|
||||
this.isGroupSubTreeSearch = isGroupSubTreeSearch;
|
||||
this.groupSearchDN = groupSearchDN;
|
||||
this.isFindGroupsByAttribute = isFindGroupsByAttribute;
|
||||
this.timeoutMilliseconds = timeoutMilliseconds;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,6 +74,7 @@ public class LdapConnection extends AbstractLdapConnection {
|
|||
SearchControls search = new SearchControls();
|
||||
search.setReturningAttributes(Strings.EMPTY_ARRAY);
|
||||
search.setSearchScope(this.isGroupSubTreeSearch ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
|
||||
search.setTimeLimit(timeoutMilliseconds);
|
||||
|
||||
//This could be made could be made configurable but it should cover all cases
|
||||
String filter = "(&" +
|
||||
|
|
|
@ -40,7 +40,7 @@ public class LdapConnectionFactory extends ConnectionFactory {
|
|||
protected final String groupSearchDN;
|
||||
protected final boolean groupSubTreeSearch;
|
||||
protected final boolean findGroupsByAttribute;
|
||||
|
||||
private final int timeoutMilliseconds;
|
||||
|
||||
@Inject()
|
||||
public LdapConnectionFactory(Settings settings) {
|
||||
|
@ -54,11 +54,13 @@ public class LdapConnectionFactory extends ConnectionFactory {
|
|||
throw new ShieldSettingsException("Missing required ldap setting [" + URLS_SETTING + "]");
|
||||
}
|
||||
|
||||
timeoutMilliseconds = (int) settings.getAsTime(TIMEOUT_LDAP_SETTING, TIMEOUT_DEFAULT).millis();
|
||||
|
||||
ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder()
|
||||
.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
|
||||
.put(Context.PROVIDER_URL, Strings.arrayToCommaDelimitedString(ldapUrls))
|
||||
.put(JNDI_LDAP_READ_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_READ_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_CONNECT_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_CONNECTION_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_READ_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_TCP_READ_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(JNDI_LDAP_CONNECT_TIMEOUT, Long.toString(settings.getAsTime(TIMEOUT_TCP_CONNECTION_SETTING, TIMEOUT_DEFAULT).millis()))
|
||||
.put(Context.REFERRAL, "follow");
|
||||
|
||||
LdapSslSocketFactory.configureJndiSSL(ldapUrls, builder);
|
||||
|
@ -90,7 +92,7 @@ public class LdapConnectionFactory extends ConnectionFactory {
|
|||
DirContext ctx = new InitialDirContext(ldapEnv);
|
||||
|
||||
//return the first good connection
|
||||
return new LdapConnection(ctx, dn, findGroupsByAttribute, groupSubTreeSearch, groupSearchDN);
|
||||
return new LdapConnection(ctx, dn, findGroupsByAttribute, groupSubTreeSearch, groupSearchDN, timeoutMilliseconds);
|
||||
|
||||
} catch (NamingException e) {
|
||||
logger.warn("Failed ldap authentication with user template [{}], dn [{}]", e, template, dn);
|
||||
|
|
|
@ -28,8 +28,9 @@ 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";
|
||||
public static final String JNDI_LDAP_CONNECT_TIMEOUT = "com.sun.jndi.ldap.connect.timeout";
|
||||
public static final String TIMEOUT_CONNECTION_SETTING = "connect_timeout";
|
||||
public static final String TIMEOUT_READ_SETTING = "read_timeout";
|
||||
public static final String TIMEOUT_TCP_CONNECTION_SETTING = "timeout.tcp_connect";
|
||||
public static final String TIMEOUT_TCP_READ_SETTING = "timeout.tcp_read";
|
||||
public static final String TIMEOUT_LDAP_SETTING = "timeout.ldap_search";
|
||||
public static final TimeValue TIMEOUT_DEFAULT = TimeValue.timeValueSeconds(5);
|
||||
|
||||
protected final ESLogger logger = Loggers.getLogger(getClass());
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.shield.authc.ldap.LdapConnectionFactory;
|
|||
import org.elasticsearch.shield.authc.ldap.LdapConnectionTests;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.ldap.AbstractLdapConnection;
|
||||
import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory;
|
||||
import org.elasticsearch.shield.authc.support.ldap.LdapSslSocketFactory;
|
||||
import org.elasticsearch.shield.authc.support.ldap.LdapTest;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
|
@ -70,6 +71,22 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTcpReadTimeout() {
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN))
|
||||
.put(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms")
|
||||
.build();
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(settings);
|
||||
|
||||
try (AbstractLdapConnection ldap = connectionFactory.open("ironman", SecuredStringTests.build(PASSWORD))) {
|
||||
List<String> groups = ldap.groups();
|
||||
fail("The TCP connection should timeout before getting groups back");
|
||||
} catch (ActiveDirectoryException e) {
|
||||
assertThat(e.getCause().getMessage(), containsString("LDAP response read timed out"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdAuth_avengers() {
|
||||
ActiveDirectoryConnectionFactory connectionFactory = new ActiveDirectoryConnectionFactory(
|
||||
|
|
|
@ -20,12 +20,10 @@ import java.net.Socket;
|
|||
import java.net.SocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class LdapConnectionTests extends LdapTest {
|
||||
|
||||
@Test(expected = LdapException.class, timeout = 2000) //if the LDAP timeout doesn't occur within 2 seconds, fail
|
||||
public void testBindWithTimeout() throws Exception {
|
||||
int randomPort = randomIntBetween(49152, 65525); // ephemeral port
|
||||
|
||||
|
@ -42,14 +40,20 @@ public class LdapConnectionTests extends LdapTest {
|
|||
};
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrls, userTemplates, groupSearchBase, true))
|
||||
.put(ConnectionFactory.TIMEOUT_CONNECTION_SETTING, "1ms") //1 millisecond
|
||||
.put(ConnectionFactory.TIMEOUT_TCP_CONNECTION_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings);
|
||||
String user = "Horatio Hornblower";
|
||||
SecuredString userPass = SecuredStringTests.build("pass");
|
||||
|
||||
try (LdapConnection ldap = connectionFactory.open(user, userPass)) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try (LdapConnection connection = connectionFactory.open(user, userPass)) {
|
||||
fail("expected connection timeout error here");
|
||||
} catch (Throwable t) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
assertThat(time, lessThan(1000l));
|
||||
assertThat(t, instanceOf(LdapException.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,23 +130,4 @@ public class LdapConnectionTests extends LdapTest {
|
|||
assertThat(groups, contains("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = LdapException.class, timeout = 2000) //if the LDAP timeout doesn't occur in 2 seconds, fail
|
||||
public void testGroupLookupWithTimeout() {
|
||||
String groupSearchBase = "o=sevenSeas";
|
||||
String userTemplate = "cn={0},ou=people,o=sevenSeas";
|
||||
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put(buildLdapSettings(ldapUrl(), userTemplate, groupSearchBase, true))
|
||||
.put(ConnectionFactory.TIMEOUT_READ_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
|
||||
LdapConnectionFactory ldapFac = new LdapConnectionFactory(settings);
|
||||
String user = "Horatio Hornblower";
|
||||
SecuredString userPass = SecuredStringTests.build("pass");
|
||||
|
||||
try (LdapConnection ldap = ldapFac.open(user, userPass)) {
|
||||
List<String> groups = ldap.getGroupsFromSearch(ldap.authenticatedUserDn());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
package org.elasticsearch.shield.authc.ldap;
|
||||
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory;
|
||||
import org.elasticsearch.shield.authc.support.ldap.LdapSslSocketFactory;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
|
@ -42,7 +44,7 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test_standardLdapConnection_uid() {
|
||||
public void testConnect() {
|
||||
//openldap does not use cn as naming attributes by default
|
||||
|
||||
String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com";
|
||||
|
@ -58,4 +60,41 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTcpTimeout() {
|
||||
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(ConnectionFactory.TIMEOUT_TCP_READ_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings);
|
||||
|
||||
try (LdapConnection ldap = connectionFactory.open("thor", SecuredStringTests.build(PASSWORD))){
|
||||
ldap.groups();
|
||||
fail("The TCP connection should timeout before getting groups back");
|
||||
} catch (LdapException e) {
|
||||
assertThat(e.getCause().getMessage(), containsString("LDAP response read timed out"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLdapTimeout() {
|
||||
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(ConnectionFactory.TIMEOUT_LDAP_SETTING, "1ms") //1 millisecond
|
||||
.build();
|
||||
|
||||
LdapConnectionFactory connectionFactory = new LdapConnectionFactory(settings);
|
||||
|
||||
try (LdapConnection ldap = connectionFactory.open("thor", SecuredStringTests.build(PASSWORD))){
|
||||
ldap.groups();
|
||||
fail("The server should timeout the group request");
|
||||
} catch (LdapException e) {
|
||||
assertThat(e.getCause().getMessage(), containsString("error code 32")); //openldap response for timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue