Skip to content

Commit

Permalink
tests: in-memory ldap server runs on a random port
Browse files Browse the repository at this point in the history
- This will allow tests to run in parallel without having LDAP servers
  competing for the same port.
  • Loading branch information
Kehrlann committed Dec 18, 2024
1 parent 0b51f76 commit e69e4dc
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class LdapLoginIT {

@BeforeClass
public static void startLocalLdap() {
server = InMemoryLdapServer.startLdap(33389);
server = InMemoryLdapServer.startLdap();
}

@AfterClass
Expand Down Expand Up @@ -107,7 +107,7 @@ public void cleanup() {
@Test
public void ldapLogin_with_StartTLS() throws Exception {
Long beforeTest = System.currentTimeMillis();
performLdapLogin("testzone2", server.getLdapBaseUrl(), "marissa4", "ldap4");
performLdapLogin("testzone2", server.getUrl(), "marissa4", "ldap4");
Long afterTest = System.currentTimeMillis();
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to?"));
ScimUser user = IntegrationTestUtils.getUserByZone(zoneAdminToken, baseUrl, "testzone2", "marissa4");
Expand All @@ -117,7 +117,7 @@ public void ldapLogin_with_StartTLS() throws Exception {

@Test
public void ldap_login_using_utf8_characters() throws Exception {
performLdapLogin("testzone2", server.getLdapBaseUrl(), "\u7433\u8D3A", "koala");
performLdapLogin("testzone2", server.getUrl(), "\u7433\u8D3A", "koala");
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to?"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ MockMvc getMockMvc() {

protected abstract void stopLdapServer();

protected abstract String getLdapOrLdapSBaseUrl();
protected abstract String getLdapUrl();

// Called by child classes. Allows this abstract parent class to act like a parameterized test.
AbstractLdapMockMvcTest(String ldapProfile, String ldapGroup, String tlsConfig) {
Expand All @@ -190,11 +190,13 @@ void setUp(@Autowired WebApplicationContext webApplicationContext,
zone = MockMvcUtils.createZoneForInvites(getMockMvc(), getWebApplicationContext(), userId, REDIRECT_URI, IdentityZoneHolder.getCurrentZoneId());

try {
ensureLdapServerIsRunning();

LdapIdentityProviderDefinition definition = new LdapIdentityProviderDefinition();
definition.setLdapProfileFile("ldap/" + ldapProfile);
definition.setLdapGroupFile("ldap/" + ldapGroup);
definition.setMaxGroupSearchDepth(10);
definition.setBaseUrl(getLdapOrLdapSBaseUrl());
definition.setBaseUrl(getLdapUrl());
definition.setBindUserDn("cn=admin,ou=Users,dc=test,dc=com");
definition.setBindPassword("adminsecret");
definition.setSkipSSLVerification(false);
Expand All @@ -210,8 +212,6 @@ void setUp(@Autowired WebApplicationContext webApplicationContext,
listener = (ApplicationListener<AbstractUaaEvent>) mock(ApplicationListener.class);
configurableApplicationContext.addApplicationListener(listener);

ensureLdapServerIsRunning();

testLogger = new InterceptingLogger();
originalAuditServiceLogger = loggingAuditService.getLogger();
loggingAuditService.setLogger(testLogger);
Expand Down Expand Up @@ -806,19 +806,14 @@ void passcodeGrantIdTokenContainsExternalGroupsAsRolesClaim() throws Exception {
@Test
void testTwoLdapServers() throws Exception {
// Setup second ldap server
int port = 33000 + getRandomPortOffset();
int sslPort = 34000 + getRandomPortOffset();

InMemoryLdapServer secondLdapServer;

String ldapBaseUrl;
if (getLdapOrLdapSBaseUrl().contains("ldap://")) {
ldapBaseUrl = getLdapOrLdapSBaseUrl() + " ldap://localhost:" + port;
secondLdapServer = InMemoryLdapServer.startLdap(port);
if (getLdapUrl().contains("ldap://")) {
secondLdapServer = InMemoryLdapServer.startLdap();
} else {
ldapBaseUrl = getLdapOrLdapSBaseUrl() + " ldaps://localhost:" + sslPort;
secondLdapServer = InMemoryLdapServer.startLdapWithTls(port, sslPort, KEYSTORE);
secondLdapServer = InMemoryLdapServer.startLdapWithTls(KEYSTORE);
}
ldapBaseUrl = getLdapUrl() + " " + secondLdapServer.getUrl();

provider.getConfig().setBaseUrl(ldapBaseUrl);
updateLdapProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@
@DefaultTestContext
@ExtendWith(InMemoryLdapServer.LdapTrustStoreExtension.class)
class LdapCertificateMockMvcTests {
private static final int LDAP_VALID_LDAP_PORT = 33390;
private static final int LDAP_EXPIRED_LDAP_PORT = LDAP_VALID_LDAP_PORT + 1;
private static final int LDAP_VALID_LDAPS_PORT = 33637;
private static final int LDAP_EXPIRED_LDAPS_PORT = LDAP_VALID_LDAPS_PORT + 1;

private static File ldapRootDirectoryExpired;
private static File ldapRootDirectoryValid;
private static InMemoryLdapServer validLdapCertServer;
Expand All @@ -58,8 +53,8 @@ static void startLdapsServers() {
ldapRootDirectoryValid = new File(System.getProperty("java.io.tmpdir"), generator.generate());
ldapRootDirectoryExpired = new File(System.getProperty("java.io.tmpdir"), generator.generate());

validLdapCertServer = InMemoryLdapServer.startLdapWithTls(LDAP_VALID_LDAP_PORT, LDAP_VALID_LDAPS_PORT, validKeystore);
expiredLdapCertServer = InMemoryLdapServer.startLdapWithTls(LDAP_EXPIRED_LDAP_PORT, LDAP_EXPIRED_LDAPS_PORT, expiredKeystore);
validLdapCertServer = InMemoryLdapServer.startLdapWithTls(validKeystore);
expiredLdapCertServer = InMemoryLdapServer.startLdapWithTls(expiredKeystore);
}

@AfterAll
Expand All @@ -81,7 +76,7 @@ void setUp(@Autowired WebApplicationContext webApplicationContext, @Autowired Mo
null, IdentityZoneHolder.getCurrentZoneId());

LdapIdentityProviderDefinition definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
validLdapCertServer.getLdapSBaseUrl(),
validLdapCertServer.getUrl(),
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
Expand All @@ -103,7 +98,7 @@ void setUp(@Autowired WebApplicationContext webApplicationContext, @Autowired Mo
mockMvc,
webApplicationContext,
null, IdentityZoneHolder.getCurrentZoneId());
definition.setBaseUrl(expiredLdapCertServer.getLdapSBaseUrl());
definition.setBaseUrl(expiredLdapCertServer.getUrl());
MockMvcUtils.createIdentityProvider(mockMvc, trustedButExpiredCertZone, OriginKeys.LDAP, definition);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cloudfoundry.identity.uaa.mock.ldap;

import org.assertj.core.api.Assertions;
import org.cloudfoundry.identity.uaa.DefaultTestContext;
import org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils;
import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
Expand All @@ -9,9 +10,15 @@
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;

import java.io.File;

import static org.cloudfoundry.identity.uaa.constants.OriginKeys.LDAP;
import static org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition.LDAP_TLS_NONE;
import static org.hamcrest.Matchers.containsString;
Expand Down Expand Up @@ -39,7 +46,6 @@ class LdapMockMvcTests {

class LdapSimpleBindTest extends AbstractLdapMockMvcTest {
private static InMemoryLdapServer ldapContainer;
private static final int ldapPort = 44389;

LdapSimpleBindTest() {
super(
Expand All @@ -51,7 +57,7 @@ class LdapSimpleBindTest extends AbstractLdapMockMvcTest {

@BeforeAll
static void beforeAll() {
ldapContainer = InMemoryLdapServer.startLdap(ldapPort);
ldapContainer = InMemoryLdapServer.startLdap();
}

@AfterAll
Expand All @@ -62,7 +68,7 @@ static void afterAll() {
@Override
protected void ensureLdapServerIsRunning() {
if (!ldapContainer.isRunning()) {
ldapContainer = InMemoryLdapServer.startLdap(ldapPort);
ldapContainer = InMemoryLdapServer.startLdap();
}
}

Expand All @@ -74,15 +80,13 @@ protected void stopLdapServer() {
}

@Override
protected String getLdapOrLdapSBaseUrl() {
return "ldap://localhost:" + ldapPort;
protected String getLdapUrl() {
return ldapContainer.getUrl();
}
}

class LdapSearchAndCompareTest extends AbstractLdapMockMvcTest {
private static InMemoryLdapServer ldapContainer;
private static final int ldapPort = 44390;
private static final int ldapSPort = 44337;

LdapSearchAndCompareTest() {
super(
Expand All @@ -94,7 +98,7 @@ class LdapSearchAndCompareTest extends AbstractLdapMockMvcTest {

@BeforeAll
static void beforeAll() {
ldapContainer = InMemoryLdapServer.startLdapWithTls(ldapPort, ldapSPort, KEYSTORE);
ldapContainer = InMemoryLdapServer.startLdapWithTls(KEYSTORE);
}

@AfterAll
Expand All @@ -105,7 +109,7 @@ static void afterAll() {
@Override
protected void ensureLdapServerIsRunning() {
if (!ldapContainer.isRunning()) {
ldapContainer = InMemoryLdapServer.startLdapWithTls(ldapPort, ldapSPort, KEYSTORE);
ldapContainer = InMemoryLdapServer.startLdapWithTls(KEYSTORE);
}
}

Expand All @@ -117,15 +121,13 @@ protected void stopLdapServer() {
}

@Override
protected String getLdapOrLdapSBaseUrl() {
return "ldaps://localhost:" + ldapSPort;
protected String getLdapUrl() {
return ldapContainer.getUrl();
}
}

class LdapSearchAndBindTest extends AbstractLdapMockMvcTest {
private static InMemoryLdapServer ldapContainer;
private static final int ldapPort = 44391;
private static final int ldapSPort = 44338;

LdapSearchAndBindTest() {
super(
Expand All @@ -137,7 +139,7 @@ class LdapSearchAndBindTest extends AbstractLdapMockMvcTest {

@BeforeAll
static void beforeAll() {
ldapContainer = InMemoryLdapServer.startLdapWithTls(ldapPort, ldapSPort, KEYSTORE);
ldapContainer = InMemoryLdapServer.startLdapWithTls(KEYSTORE);
}

@AfterAll
Expand All @@ -148,7 +150,7 @@ static void afterAll() {
@Override
protected void ensureLdapServerIsRunning() {
if (!ldapContainer.isRunning()) {
ldapContainer = InMemoryLdapServer.startLdapWithTls(ldapPort, ldapSPort, KEYSTORE);
ldapContainer = InMemoryLdapServer.startLdapWithTls(KEYSTORE);
}
}

Expand All @@ -160,8 +162,8 @@ protected void stopLdapServer() {
}

@Override
protected String getLdapOrLdapSBaseUrl() {
return "ldap://localhost:" + ldapPort;
protected String getLdapUrl() {
return ldapContainer.getUrl();
}

@Nested
Expand All @@ -183,7 +185,7 @@ void setUp() throws Exception {
String zoneAdminToken = MockMvcUtils.getZoneAdminToken(getMockMvc(), adminAccessToken, zone.getId());

definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
getLdapOrLdapSBaseUrl(),
getLdapUrl(),
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
Expand Down Expand Up @@ -289,36 +291,19 @@ void invalidSearchBase() throws Exception {
*/
@Test
void unableToConnectToLdapWithInvalidSsl() {
int port = 37000 + getRandomPortOffset();
int sslPort = 38000 + getRandomPortOffset();

try (InMemoryLdapServer inMemoryLdapServer = InMemoryLdapServer.startLdapWithTls(port, sslPort, null)) {
definition.setBaseUrl(inMemoryLdapServer.getLdapSBaseUrl());
File expiredKeystore = new File(getClass().getClassLoader().getResource("certs/expired-self-signed-ldap-cert.jks").getFile());
try (InMemoryLdapServer inMemoryLdapServer = InMemoryLdapServer.startLdapWithTls(expiredKeystore)) {
definition.setBaseUrl(inMemoryLdapServer.getUrl());
definition.setSkipSSLVerification(false);

getMockMvc().perform(
baseRequest.content(JsonUtils.writeValueAsString(request)))
baseRequest.content(JsonUtils.writeValueAsString(request)))
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(content().string(containsString("Caused by:")));
} catch (Exception ignored) {

Assertions.fail("should not be able to connect to LDAP server");
}
}

/**
* TODO: We're not sure what this test is trying to do
* Is the UAA SSL configuration invalid?
* Is the LDAP server configuration invalid?
*/
@Test
void ableToConnectToLdapWithInvalidSsl_WithSkipValidation() throws Exception {
definition.setBaseUrl("ldaps://localhost:" + ldapSPort);

getMockMvc().perform(
baseRequest.content(JsonUtils.writeValueAsString(request)))
.andExpect(status().isOk())
.andExpect(content().string("\"ok\""));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@
@DefaultTestContext
@ExtendWith(InMemoryLdapServer.LdapTrustStoreExtension.class)
class LdapSkipCertificateMockMvcTests {
private static final int LDAP_VALID_LDAP_PORT = 33390;
private static final int LDAP_EXPIRED_LDAP_PORT = LDAP_VALID_LDAP_PORT + 1;
private static final int LDAP_VALID_LDAPS_PORT = 33637;
private static final int LDAP_EXPIRED_LDAPS_PORT = LDAP_VALID_LDAPS_PORT + 1;

private static File ldapRootDirectoryExpired;
private static InMemoryLdapServer expiredLdapCertServer;
private MockMvcUtils.IdentityZoneCreationResult trustedCertZone;
Expand All @@ -53,8 +48,7 @@ static void startLdapsServers() {
File expiredKeystore = new File(classLoader.getResource("certs/expired-self-signed-ldap-cert.jks").getFile());
RandomValueStringGenerator generator = new RandomValueStringGenerator();
ldapRootDirectoryExpired = new File(System.getProperty("java.io.tmpdir"), generator.generate());

expiredLdapCertServer = InMemoryLdapServer.startLdapWithTls(LDAP_EXPIRED_LDAP_PORT, LDAP_EXPIRED_LDAPS_PORT, expiredKeystore);
expiredLdapCertServer = InMemoryLdapServer.startLdapWithTls(expiredKeystore);
}

@AfterAll
Expand All @@ -74,7 +68,7 @@ void setUp(@Autowired WebApplicationContext webApplicationContext, @Autowired Mo
null, IdentityZoneHolder.getCurrentZoneId());

LdapIdentityProviderDefinition definition = LdapIdentityProviderDefinition.searchAndBindMapGroupToScopes(
expiredLdapCertServer.getLdapSBaseUrl(),
expiredLdapCertServer.getUrl(),
"cn=admin,ou=Users,dc=test,dc=com",
"adminsecret",
"dc=test,dc=com",
Expand All @@ -97,7 +91,7 @@ void setUp(@Autowired WebApplicationContext webApplicationContext, @Autowired Mo
mockMvc,
webApplicationContext,
null, IdentityZoneHolder.getCurrentZoneId());
definition.setBaseUrl(expiredLdapCertServer.getLdapSBaseUrl());
definition.setBaseUrl(expiredLdapCertServer.getUrl());
MockMvcUtils.createIdentityProvider(mockMvc, trustedButExpiredCertZone, OriginKeys.LDAP, definition);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ class IdentityProviderEndpointDocs extends EndpointDocs {
private static final SnippetUtils.ConstrainableField VERSION = (SnippetUtils.ConstrainableField) fieldWithPath("version").type(NUMBER).description(VERSION_DESC);
private static final Snippet commonRequestParams = requestParameters(parameterWithName("rawConfig").optional("false").type(BOOLEAN).description("<small><mark>UAA 3.4.0</mark></small> Flag indicating whether the response should use raw, unescaped JSON for the `config` field of the IDP, rather than the default behavior of encoding the JSON as a string."));

private static final int LDAP_PORT = 23389;

private String adminToken;
private IdentityProviderProvisioning identityProviderProvisioning;

Expand Down Expand Up @@ -241,7 +239,7 @@ static void afterClass() throws Exception {

@BeforeAll
static void startLdapContainer() {
ldapContainer = InMemoryLdapServer.startLdap(LDAP_PORT);
ldapContainer = InMemoryLdapServer.startLdap();
}

private final FieldDescriptor ldapType = fieldWithPath("type").required().description("`ldap`");
Expand Down Expand Up @@ -792,7 +790,7 @@ void create_Simple_Bind_LDAPIdentityProvider() throws Exception {
LdapIdentityProviderDefinition providerDefinition = new LdapIdentityProviderDefinition();
providerDefinition.setLdapProfileFile("ldap/ldap-simple-bind.xml");
providerDefinition.setLdapGroupFile("ldap/ldap-groups-null.xml");
providerDefinition.setBaseUrl(ldapContainer.getLdapBaseUrl());
providerDefinition.setBaseUrl(ldapContainer.getUrl());
providerDefinition.setUserDNPattern("cn={0},ou=Users,dc=test,dc=com");
providerDefinition.setUserDNPatternDelimiter(";");
providerDefinition.setMailAttributeName("mail");
Expand All @@ -812,7 +810,7 @@ void create_SearchAndBind_Groups_Map_ToScopes_LDAPIdentityProvider() throws Exce
LdapIdentityProviderDefinition providerDefinition = new LdapIdentityProviderDefinition();
providerDefinition.setLdapProfileFile("ldap/ldap-search-and-bind.xml");
providerDefinition.setLdapGroupFile("ldap/ldap-groups-map-to-scopes.xml");
providerDefinition.setBaseUrl(ldapContainer.getLdapBaseUrl());
providerDefinition.setBaseUrl(ldapContainer.getUrl());
providerDefinition.setBindUserDn("cn=admin,ou=Users,dc=test,dc=com");
providerDefinition.setBindPassword("adminsecret");
providerDefinition.setUserSearchBase("dc=test,dc=com");
Expand Down Expand Up @@ -841,7 +839,7 @@ void create_SearchAndCompare_Groups_As_Scopes_LDAPIdentityProvider() throws Exce
LdapIdentityProviderDefinition providerDefinition = new LdapIdentityProviderDefinition();
providerDefinition.setLdapProfileFile("ldap/ldap-search-and-compare.xml");
providerDefinition.setLdapGroupFile("ldap/ldap-groups-as-scopes.xml");
providerDefinition.setBaseUrl(ldapContainer.getLdapBaseUrl());
providerDefinition.setBaseUrl(ldapContainer.getUrl());
providerDefinition.setBindUserDn("cn=admin,ou=Users,dc=test,dc=com");
providerDefinition.setBindPassword("adminsecret");
providerDefinition.setUserSearchBase("dc=test,dc=com");
Expand Down
Loading

0 comments on commit e69e4dc

Please sign in to comment.