ldap: Adds configuration for timeouts

This adds configuration for ldap connection timeouts and ldap operation timeouts.  Both default to 5 seconds.

Fixes https://github.com/elasticsearch/elasticsearch-shield/issues/461

Original commit: elastic/x-pack-elasticsearch@3e6ed97d52
This commit is contained in:
c-a-m 2014-12-11 14:19:57 -07:00
parent a710deb505
commit 060e17bc91
5 changed files with 60 additions and 1 deletions

View File

@ -53,6 +53,8 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory {
ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder() ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder()
.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory") .put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
.put(Context.PROVIDER_URL, Strings.arrayToCommaDelimitedString(ldapUrls)) .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("java.naming.ldap.attributes.binary", "tokenGroups") .put("java.naming.ldap.attributes.binary", "tokenGroups")
.put(Context.REFERRAL, "follow"); .put(Context.REFERRAL, "follow");

View File

@ -41,7 +41,8 @@ public class LdapConnectionFactory extends ConnectionFactory {
protected final boolean groupSubTreeSearch; protected final boolean groupSubTreeSearch;
protected final boolean findGroupsByAttribute; protected final boolean findGroupsByAttribute;
@Inject
@Inject()
public LdapConnectionFactory(Settings settings) { public LdapConnectionFactory(Settings settings) {
super(settings); super(settings);
userDnTemplates = settings.getAsArray(USER_DN_TEMPLATES_SETTING); userDnTemplates = settings.getAsArray(USER_DN_TEMPLATES_SETTING);
@ -56,6 +57,8 @@ public class LdapConnectionFactory extends ConnectionFactory {
ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder() ImmutableMap.Builder<String, Serializable> builder = ImmutableMap.<String, Serializable>builder()
.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory") .put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory")
.put(Context.PROVIDER_URL, Strings.arrayToCommaDelimitedString(ldapUrls)) .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(Context.REFERRAL, "follow"); .put(Context.REFERRAL, "follow");
LdapSslSocketFactory.configureJndiSSL(ldapUrls, builder); LdapSslSocketFactory.configureJndiSSL(ldapUrls, builder);

View File

@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.support.ldap;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredString;
/** /**
@ -25,6 +26,11 @@ import org.elasticsearch.shield.authc.support.SecuredString;
public abstract class ConnectionFactory { public abstract class ConnectionFactory {
public static final String URLS_SETTING = "url"; 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 TimeValue TIMEOUT_DEFAULT = TimeValue.timeValueSeconds(5);
protected final ESLogger logger = Loggers.getLogger(getClass()); protected final ESLogger logger = Loggers.getLogger(getClass());
private final Settings settings; private final Settings settings;

View File

@ -85,6 +85,11 @@ public class LdapSslSocketFactory extends SocketFactory {
//The following methods are all wrappers around the instance of socketFactory //The following methods are all wrappers around the instance of socketFactory
@Override
public Socket createSocket() throws IOException {
return socketFactory.createSocket();
}
@Override @Override
public Socket createSocket(String host, int port) throws IOException { public Socket createSocket(String host, int port) throws IOException {
return socketFactory.createSocket(host, port); return socketFactory.createSocket(host, port);

View File

@ -5,8 +5,11 @@
*/ */
package org.elasticsearch.shield.authc.ldap; package org.elasticsearch.shield.authc.ldap;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.authc.support.SecuredStringTests; 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.LdapTest;
import org.junit.Test; import org.junit.Test;
@ -17,6 +20,26 @@ import static org.hamcrest.Matchers.containsString;
public class LdapConnectionTests extends LdapTest { 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() {
String[] ldapUrls = new String[] { "ldap://example.com:1111" };
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(ConnectionFactory.TIMEOUT_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)) {
}
}
@Test @Test
public void testBindWithTemplates() { public void testBindWithTemplates() {
String[] ldapUrls = new String[] { ldapUrl() }; String[] ldapUrls = new String[] { ldapUrl() };
@ -39,6 +62,7 @@ public class LdapConnectionTests extends LdapTest {
} }
} }
@Test(expected = LdapException.class) @Test(expected = LdapException.class)
public void testBindWithBogusTemplates() { public void testBindWithBogusTemplates() {
String[] ldapUrl = new String[] { ldapUrl() }; String[] ldapUrl = new String[] { ldapUrl() };
@ -88,4 +112,23 @@ public class LdapConnectionTests extends LdapTest {
assertThat(groups, contains("cn=HMS Lydia,ou=crews,ou=groups,o=sevenSeas")); 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());
}
}
} }