From d65c17ebc7642b63fe9bde7ad0a5e3f09ab5c2a5 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Fri, 12 Sep 2025 11:41:59 -0300 Subject: [PATCH] Do not fail when querying user federation providers and log messages to indicate the problem Closes #42276 Signed-off-by: Pedro Igor --- .../storage/ldap/LDAPStorageProvider.java | 33 +++++++++++++++---- .../keycloak/storage/UserStorageManager.java | 14 +++++--- .../org/keycloak/models/ModelException.java | 21 ++++++++++++ 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java index 19273ba37e2..bd66f8fc06a 100755 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java @@ -35,6 +35,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.naming.AuthenticationException; +import javax.naming.CommunicationException; +import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.directory.SearchControls; @@ -1123,19 +1125,36 @@ public class LDAPStorageProvider implements UserStorageProvider, return Stream.iterate(ldapQuery, query -> { //the very 1st page - Pagination context might not yet be present - if (query.getPaginationContext() == null) try { - query.initPagination(); - //returning true for first iteration as the LDAP was not queried yet - return true; - } catch (NamingException e) { - throw new ModelException("Querying of LDAP failed " + query, e); + if (query.getPaginationContext() == null) { + try { + query.initPagination(); + //returning true for first iteration as the LDAP was not queried yet + return true; + } catch (NameNotFoundException | CommunicationException e) { + logger.errorf(e, "Failed to init LDAP query pagination %s", query); + return false; + } catch (NamingException e) { + throw new ModelException("Querying of LDAP failed " + query, e); + } } return query.getPaginationContext().hasNextPage(); }, query -> query ).flatMap(query -> { query.setLimit(limit); - List ldapObjects = query.getResultList(); + List ldapObjects; + + try { + ldapObjects = query.getResultList(); + } catch (ModelException mde) { + if (mde.isCausedBy(NameNotFoundException.class, CommunicationException.class)) { + logger.errorf(mde, "Failed to query LDAP %s", query); + return Stream.empty(); + } else { + throw mde; + } + } + if (ldapObjects.isEmpty()) { return Stream.empty(); } diff --git a/model/storage-private/src/main/java/org/keycloak/storage/UserStorageManager.java b/model/storage-private/src/main/java/org/keycloak/storage/UserStorageManager.java index e276ff5ba8e..820bb4c052f 100755 --- a/model/storage-private/src/main/java/org/keycloak/storage/UserStorageManager.java +++ b/model/storage-private/src/main/java/org/keycloak/storage/UserStorageManager.java @@ -163,13 +163,19 @@ public class UserStorageManager extends AbstractStorageManagerStian Thorgersen */ @@ -47,4 +49,23 @@ public class ModelException extends RuntimeException { public void setParameters(Object[] parameters) { this.parameters = parameters; } + + @SafeVarargs + public final boolean isCausedBy(Class... type) { + int limit = 3; + List> types = List.of(type); + Throwable cause = getCause(); + + while (cause != null) { + if (limit-- == 0) { + break; + } + if (types.contains(cause.getClass())) { + return true; + } + cause = cause.getCause(); + } + + return false; + } }