From 060e17bc91913bb7dce859ecbe3932518901f25c Mon Sep 17 00:00:00 2001 From: c-a-m Date: Thu, 11 Dec 2014 14:19:57 -0700 Subject: [PATCH] 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@3e6ed97d52fe47eedafcd7a016da3be13939373d --- .../ActiveDirectoryConnectionFactory.java | 2 + .../authc/ldap/LdapConnectionFactory.java | 5 ++- .../authc/support/ldap/ConnectionFactory.java | 6 +++ .../support/ldap/LdapSslSocketFactory.java | 5 +++ .../authc/ldap/LdapConnectionTests.java | 43 +++++++++++++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) 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 3fb1b2b6931..73482e01538 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 @@ -53,6 +53,8 @@ public class ActiveDirectoryConnectionFactory extends ConnectionFactory { ImmutableMap.Builder builder = ImmutableMap.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("java.naming.ldap.attributes.binary", "tokenGroups") .put(Context.REFERRAL, "follow"); 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 12487f76e22..98f7ff4d4f9 100644 --- a/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java +++ b/src/main/java/org/elasticsearch/shield/authc/ldap/LdapConnectionFactory.java @@ -41,7 +41,8 @@ public class LdapConnectionFactory extends ConnectionFactory { protected final boolean groupSubTreeSearch; protected final boolean findGroupsByAttribute; - @Inject + + @Inject() public LdapConnectionFactory(Settings settings) { super(settings); userDnTemplates = settings.getAsArray(USER_DN_TEMPLATES_SETTING); @@ -56,6 +57,8 @@ public class LdapConnectionFactory extends ConnectionFactory { ImmutableMap.Builder builder = ImmutableMap.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(Context.REFERRAL, "follow"); LdapSslSocketFactory.configureJndiSSL(ldapUrls, builder); 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 b811eac7ae1..f13d053a8db 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,6 +8,7 @@ package org.elasticsearch.shield.authc.support.ldap; 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.authc.support.SecuredString; /** @@ -25,6 +26,11 @@ import org.elasticsearch.shield.authc.support.SecuredString; 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 TimeValue TIMEOUT_DEFAULT = TimeValue.timeValueSeconds(5); protected final ESLogger logger = Loggers.getLogger(getClass()); private final Settings settings; 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 4f51c64afaf..bd10f6d015a 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 @@ -85,6 +85,11 @@ public class LdapSslSocketFactory extends SocketFactory { //The following methods are all wrappers around the instance of socketFactory + @Override + public Socket createSocket() throws IOException { + return socketFactory.createSocket(); + } + @Override public Socket createSocket(String host, int port) throws IOException { return socketFactory.createSocket(host, port); 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 70ba827f6be..3b05ce6b5e4 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/LdapConnectionTests.java @@ -5,8 +5,11 @@ */ 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.SecuredStringTests; +import org.elasticsearch.shield.authc.support.ldap.ConnectionFactory; import org.elasticsearch.shield.authc.support.ldap.LdapTest; import org.junit.Test; @@ -17,6 +20,26 @@ import static org.hamcrest.Matchers.containsString; 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 public void testBindWithTemplates() { String[] ldapUrls = new String[] { ldapUrl() }; @@ -39,6 +62,7 @@ public class LdapConnectionTests extends LdapTest { } } + @Test(expected = LdapException.class) public void testBindWithBogusTemplates() { 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")); } } + + @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 groups = ldap.getGroupsFromSearch(ldap.authenticatedUserDn()); + } + } }