Fix test LDAP connection with multiple ldap connection urls

Previously, the given connection string was check with URI.create(..) which
failed when multiple space separated LDAP URLs were given.

Closes #31267

Signed-off-by: Thomas Darimont <thomas.darimont@googlemail.com>
This commit is contained in:
Thomas Darimont 2024-07-16 08:57:50 +02:00 committed by GitHub
parent 887db25f00
commit 2140e573f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 2 deletions

View file

@ -27,6 +27,7 @@ import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel; import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants; import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ModelValidationException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.ComponentRepresentation; import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.TestLdapConnectionRepresentation; import org.keycloak.representations.idm.TestLdapConnectionRepresentation;
@ -73,7 +74,7 @@ public class LDAPServerCapabilitiesManager {
ComponentModel component = realm.getComponent(config.getComponentId()); ComponentModel component = realm.getComponent(config.getComponentId());
if (component != null) { if (component != null) {
LDAPConfig ldapConfig = new LDAPConfig(component.getConfig()); LDAPConfig ldapConfig = new LDAPConfig(component.getConfig());
if (Objects.equals(URI.create(config.getConnectionUrl()), URI.create(ldapConfig.getConnectionUrl())) if (checkLdapConnectionUrl(config, ldapConfig)
&& config.getBindDn() != null && config.getBindDn().equalsIgnoreCase(ldapConfig.getBindDN())) { && config.getBindDn() != null && config.getBindDn().equalsIgnoreCase(ldapConfig.getBindDN())) {
bindCredential = ldapConfig.getBindCredential(); bindCredential = ldapConfig.getBindCredential();
} }
@ -94,6 +95,28 @@ public class LDAPServerCapabilitiesManager {
return new LDAPConfig(configMap); return new LDAPConfig(configMap);
} }
/**
* Ensure provided connection URI matches parsed LDAP connection URI.
*
* See: https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html
* @param config
* @param ldapConfig
* @return
*/
private static boolean checkLdapConnectionUrl(TestLdapConnectionRepresentation config, LDAPConfig ldapConfig) {
// There could be multiple connection URIs separated via spaces.
String[] configConnectionUrls = config.getConnectionUrl().trim().split(" ");
String[] ldapConfigConnectionUrls = ldapConfig.getConnectionUrl().trim().split(" ");
if (configConnectionUrls.length != ldapConfigConnectionUrls.length) {
return false;
}
boolean urlsMatch = true;
for (int i = 0; i < configConnectionUrls.length && urlsMatch; i++) {
urlsMatch = Objects.equals(URI.create(configConnectionUrls[i]), URI.create(ldapConfigConnectionUrls[i]));
}
return urlsMatch;
}
public static Set<LDAPCapabilityRepresentation> queryServerCapabilities(TestLdapConnectionRepresentation config, KeycloakSession session, public static Set<LDAPCapabilityRepresentation> queryServerCapabilities(TestLdapConnectionRepresentation config, KeycloakSession session,
RealmModel realm) { RealmModel realm) {

View file

@ -131,6 +131,7 @@ public class UserFederationLdapConnectionTest extends AbstractAdminTest {
@Test @Test
public void testLdapConnectionMoreServers() { public void testLdapConnectionMoreServers() {
// Both servers work // Both servers work
Response response = realm.testLDAPConnection(new TestLdapConnectionRepresentation(LDAPServerCapabilitiesManager.TEST_AUTHENTICATION, "ldap://localhost:10389 ldaps://localhost:10636", "uid=admin,ou=system", "secret", "true", null)); Response response = realm.testLDAPConnection(new TestLdapConnectionRepresentation(LDAPServerCapabilitiesManager.TEST_AUTHENTICATION, "ldap://localhost:10389 ldaps://localhost:10636", "uid=admin,ou=system", "secret", "true", null));
assertStatus(response, 204); assertStatus(response, 204);
@ -155,11 +156,23 @@ public class UserFederationLdapConnectionTest extends AbstractAdminTest {
response = realm.testLDAPConnection(new TestLdapConnectionRepresentation(LDAPServerCapabilitiesManager.TEST_AUTHENTICATION, "ldap://localhostt:10389 ldaps://localhostt:10636", "uid=admin,ou=system", "secret", "true", null)); response = realm.testLDAPConnection(new TestLdapConnectionRepresentation(LDAPServerCapabilitiesManager.TEST_AUTHENTICATION, "ldap://localhostt:10389 ldaps://localhostt:10636", "uid=admin,ou=system", "secret", "true", null));
assertStatus(response, 400); assertStatus(response, 400);
// create LDAP component model using ldap
Map<String, String> cfg = ldapRule.getConfig();
cfg.put(LDAPConstants.CONNECTION_URL, "ldap://invalid:10389 ldap://localhost:10389");
cfg.put(LDAPConstants.CONNECTION_TIMEOUT, "1000");
String ldapModelId = testingClient.testing().ldap(REALM_NAME).createLDAPProvider(cfg, false);
// Only 2nd server works with stored LDAP federation provider
response = realm.testLDAPConnection(new TestLdapConnectionRepresentation(LDAPServerCapabilitiesManager.TEST_AUTHENTICATION,
cfg.get(LDAPConstants.CONNECTION_URL), cfg.get(LDAPConstants.BIND_DN), ComponentRepresentation.SECRET_VALUE,
cfg.get(LDAPConstants.USE_TRUSTSTORE_SPI), cfg.get(LDAPConstants.CONNECTION_TIMEOUT),cfg.get(LDAPConstants.START_TLS),
cfg.get(LDAPConstants.AUTH_TYPE), ldapModelId));
assertStatus(response, 204);
} }
@Test @Test
public void testLdapConnectionComponentAlreadyCreated() { public void testLdapConnectionComponentAlreadyCreated() {
// create ldap componnet model using ldaps // create ldap component model using ldaps
Map<String, String> cfg = ldapRule.getConfig(); Map<String, String> cfg = ldapRule.getConfig();
cfg.put(LDAPConstants.CONNECTION_URL, "ldaps://localhost:10636"); cfg.put(LDAPConstants.CONNECTION_URL, "ldaps://localhost:10636");
cfg.put(LDAPConstants.START_TLS, "false"); cfg.put(LDAPConstants.START_TLS, "false");