Skip to content

Commit ed20d7c

Browse files
authored
Add await busy loop for SimpleKdcLdapServer initialization (elastic#39221)
There have been intermittent failures where either LDAP server could not be started or KDC server could not be started causing failures during test runs. `KdcNetwork` class from Apache kerby project does not set reuse address to `true` on the socket so if the port that we found to be free is in `TIME_WAIT` state it may fail to bind. As this is an internal class for kerby, I could not find a way to extend. This commit adds a retry loop for initialization. It will keep trying in an await busy loop and fail after 10 seconds if not initialized. Closes elastic#35982
1 parent c897140 commit ed20d7c

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

x-pack/qa/evil-tests/src/test/java/org/elasticsearch/xpack/security/authc/kerberos/SimpleKdcLdapServer.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,43 @@ public Boolean run() throws Exception {
9090
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
9191
@Override
9292
public Void run() throws Exception {
93-
init();
93+
if (ESTestCase.awaitBusy(() -> init()) == false) {
94+
throw new IllegalStateException("could not initialize SimpleKdcLdapServer");
95+
}
9496
return null;
9597
}
9698
});
9799
logger.info("SimpleKdcLdapServer started.");
98100
}
99101

100102
@SuppressForbidden(reason = "Uses Apache Kdc which requires usage of java.io.File in order to create a SimpleKdcServer")
101-
private void init() throws Exception {
102-
// start ldap server
103-
createLdapServiceAndStart();
104-
// create ldap backend conf
105-
createLdapBackendConf();
106-
// Kdc Server
107-
simpleKdc = new SimpleKdcServer(this.workDir.toFile(), new KrbConfig());
108-
prepareKdcServerAndStart();
103+
private boolean init() {
104+
boolean initialized = false;
105+
try {
106+
// start ldap server
107+
createLdapServiceAndStart();
108+
// create ldap backend conf
109+
createLdapBackendConf();
110+
// Kdc Server
111+
simpleKdc = new SimpleKdcServer(this.workDir.toFile(), new KrbConfig());
112+
prepareKdcServerAndStart();
113+
initialized = true;
114+
} catch (Exception e) {
115+
if (simpleKdc != null) {
116+
try {
117+
simpleKdc.stop();
118+
} catch (KrbException krbException) {
119+
logger.debug("error occurred while cleaning up after init failure for SimpleKdcLdapServer");
120+
}
121+
}
122+
if (ldapServer != null) {
123+
ldapServer.shutDown(true);
124+
}
125+
ldapPort = 0;
126+
kdcPort = 0;
127+
initialized = false;
128+
}
129+
return initialized;
109130
}
110131

111132
private void createLdapServiceAndStart() throws Exception {
@@ -229,12 +250,14 @@ private static int getServerPort(String transport) {
229250
if (transport != null && transport.trim().equalsIgnoreCase("TCP")) {
230251
try (ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 1,
231252
InetAddress.getByName("127.0.0.1"))) {
253+
serverSocket.setReuseAddress(true);
232254
return serverSocket.getLocalPort();
233255
} catch (Exception ex) {
234256
throw new RuntimeException("Failed to get a TCP server socket point");
235257
}
236258
} else if (transport != null && transport.trim().equalsIgnoreCase("UDP")) {
237259
try (DatagramSocket socket = new DatagramSocket(0, InetAddress.getByName("127.0.0.1"))) {
260+
socket.setReuseAddress(true);
238261
return socket.getLocalPort();
239262
} catch (Exception ex) {
240263
throw new RuntimeException("Failed to get a UDP server socket point");

0 commit comments

Comments
 (0)