Skip to content

Commit

Permalink
Fix failures in SessionFactoryLoadBalancingTests (elastic#39154)
Browse files Browse the repository at this point in the history
This change aims to fix failures in the session factory load balancing
tests that mock failure scenarios. For these tests, we randomly shut
down ldap servers and bind a client socket to the port they were
listening on. Unfortunately, we would occasionally encounter failures
in these tests where a socket was already in use and/or the port
we expected to connect to was wrong and in fact was to one of the ldap
instances that should have been shut down.

The failures are caused by the behavior of certain operating systems
when it comes to binding ports and wildcard addresses. It is possible
for a separate application to be bound to a wildcard address and still
allow our code to bind to that port on a specific address. So when we
close the server socket and open the client socket, we are still able
to establish a connection since the other application is already
listening on that port on a wildcard address. Another variant is that
the os will allow a wildcard bind of a server socket when there is
already an application listening on that port for a specific address.

In order to do our best to prevent failures in these scenarios, this
change does the following:

1. Binds a client socket to all addresses in an awaitBusy
2. Adds assumption that we could bind all valid addresses
3. In the case that we still establish a connection to an address that
   we should not be able to, try to bind and expect a failure of not
   being connected

Closes elastic#32190
  • Loading branch information
jaymode authored and weizijun committed Feb 22, 2019
1 parent 13177f8 commit 3acfae0
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPURL;
import com.unboundid.ldap.sdk.SimpleBindRequest;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
Expand All @@ -29,6 +30,7 @@
import org.junit.After;
import org.junit.Before;

import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
Expand Down Expand Up @@ -73,7 +75,12 @@ public void shutdown() throws InterruptedException {
public void testBindWithReadTimeout() throws Exception {
InMemoryDirectoryServer ldapServer = randomFrom(ldapServers);
String protocol = randomFrom("ldap", "ldaps");
String ldapUrl = new LDAPURL(protocol, "localhost", ldapServer.getListenPort(protocol), null, null, null, null).toString();
InetAddress listenAddress = ldapServer.getListenAddress(protocol);
if (listenAddress == null) {
listenAddress = InetAddress.getLoopbackAddress();
}
String ldapUrl = new LDAPURL(protocol, NetworkAddress.format(listenAddress), ldapServer.getListenPort(protocol),
null, null, null, null).toString();
String groupSearchBase = "o=sevenSeas";
String userTemplates = "cn={0},ou=people,o=sevenSeas";

Expand Down Expand Up @@ -233,7 +240,12 @@ public void testGroupLookupBase() throws Exception {
*/
public void testSslTrustIsReloaded() throws Exception {
InMemoryDirectoryServer ldapServer = randomFrom(ldapServers);
String ldapUrl = new LDAPURL("ldaps", "localhost", ldapServer.getListenPort("ldaps"), null, null, null, null).toString();
InetAddress listenAddress = ldapServer.getListenAddress("ldaps");
if (listenAddress == null) {
listenAddress = InetAddress.getLoopbackAddress();
}
String ldapUrl = new LDAPURL("ldaps", NetworkAddress.format(listenAddress), ldapServer.getListenPort("ldaps"),
null, null, null, null).toString();
String groupSearchBase = "o=sevenSeas";
String userTemplates = "cn={0},ou=people,o=sevenSeas";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.ldap.LdapSessionFactorySettings;
import org.elasticsearch.xpack.core.security.authc.ldap.SearchGroupsResolverSettings;
Expand All @@ -46,6 +48,7 @@
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import java.net.InetAddress;
import java.security.AccessController;
import java.security.KeyStore;
import java.security.PrivilegedAction;
Expand Down Expand Up @@ -76,7 +79,7 @@ public void startLdap() throws Exception {
for (int i = 0; i < numberOfLdapServers; i++) {
InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("o=sevenSeas");
List<InMemoryListenerConfig> listeners = new ArrayList<>(2);
listeners.add(InMemoryListenerConfig.createLDAPConfig("ldap"));
listeners.add(InMemoryListenerConfig.createLDAPConfig("ldap", null, 0, null));
if (openLdapsPort()) {
final char[] ldapPassword = "ldap-password".toCharArray();
final KeyStore ks = CertParsingUtils.getKeyStoreFromPEM(
Expand All @@ -85,7 +88,7 @@ public void startLdap() throws Exception {
ldapPassword
);
X509ExtendedKeyManager keyManager = CertParsingUtils.keyManager(ks, ldapPassword, KeyManagerFactory.getDefaultAlgorithm());
final SSLContext context = SSLContext.getInstance("TLSv1.2");
final SSLContext context = SSLContext.getInstance(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS.get(0));
context.init(new KeyManager[] { keyManager }, null, null);
SSLServerSocketFactory serverSocketFactory = context.getServerSocketFactory();
SSLSocketFactory clientSocketFactory = context.getSocketFactory();
Expand All @@ -111,7 +114,7 @@ protected boolean openLdapsPort() {
}

@After
public void stopLdap() throws Exception {
public void stopLdap() {
for (int i = 0; i < numberOfLdapServers; i++) {
ldapServers[i].shutDown(true);
}
Expand All @@ -120,7 +123,11 @@ public void stopLdap() throws Exception {
protected String[] ldapUrls() throws LDAPException {
List<String> urls = new ArrayList<>(numberOfLdapServers);
for (int i = 0; i < numberOfLdapServers; i++) {
LDAPURL url = new LDAPURL("ldap", "localhost", ldapServers[i].getListenPort(), null, null, null, null);
InetAddress listenAddress = ldapServers[i].getListenAddress();
if (listenAddress == null) {
listenAddress = InetAddress.getLoopbackAddress();
}
LDAPURL url = new LDAPURL("ldap", NetworkAddress.format(listenAddress), ldapServers[i].getListenPort(), null, null, null, null);
urls.add(url.toString());
}
return urls.toArray(Strings.EMPTY_ARRAY);
Expand Down
Loading

0 comments on commit 3acfae0

Please sign in to comment.