diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java index b075d19029..e406c11d3f 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java @@ -19,6 +19,7 @@ package org.keycloak.federation.ldap; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -229,6 +230,45 @@ public class LDAPUtils { } + /** + * Load all LDAP objects corresponding to given query. We will load them paginated, so we allow to bypass the limitation of 1000 + * maximum loaded objects in single query in MSAD + * + * @param ldapQuery + * @param ldapProvider + * @return + */ + public static List loadAllLDAPObjects(LDAPQuery ldapQuery, LDAPFederationProvider ldapProvider) { + LDAPConfig ldapConfig = ldapProvider.getLdapIdentityStore().getConfig(); + boolean pagination = ldapConfig.isPagination(); + if (pagination) { + // For now reuse globally configured batch size in LDAP provider page + int pageSize = ldapConfig.getBatchSizeForSync(); + + List result = new LinkedList<>(); + boolean nextPage = true; + + while (nextPage) { + ldapQuery.setLimit(pageSize); + final List currentPageGroups = ldapQuery.getResultList(); + result.addAll(currentPageGroups); + nextPage = ldapQuery.getPaginationContext() != null; + } + + return result; + } else { + // LDAP pagination not available. Do everything in single transaction + return ldapQuery.getResultList(); + } + } + + + /** + * Validate configured customFilter matches the requested format + * + * @param customFilter + * @throws FederationConfigValidationException + */ public static void validateCustomLdapFilter(String customFilter) throws FederationConfigValidationException { if (customFilter != null) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java index 00108bc6be..cd220b292a 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java @@ -343,28 +343,7 @@ public class GroupLDAPFederationMapper extends AbstractLDAPFederationMapper impl // Send LDAP query to retrieve all groups protected List getAllLDAPGroups() { LDAPQuery ldapGroupQuery = createGroupQuery(); - - LDAPConfig ldapConfig = ldapProvider.getLdapIdentityStore().getConfig(); - boolean pagination = ldapConfig.isPagination(); - if (pagination) { - // For now reuse globally configured batch size in LDAP provider page - int pageSize = ldapConfig.getBatchSizeForSync(); - - List result = new LinkedList<>(); - boolean nextPage = true; - - while (nextPage) { - ldapGroupQuery.setLimit(pageSize); - final List currentPageGroups = ldapGroupQuery.getResultList(); - result.addAll(currentPageGroups); - nextPage = ldapGroupQuery.getPaginationContext() != null; - } - - return result; - } else { - // LDAP pagination not available. Do everything in single transaction - return ldapGroupQuery.getResultList(); - } + return LDAPUtils.loadAllLDAPObjects(ldapGroupQuery, ldapProvider); } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java index fb6056b743..169875d0a6 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java @@ -88,9 +88,9 @@ public class GroupLDAPFederationMapperFactory extends AbstractLDAPFederationMapp for (MembershipType membershipType : MembershipType.values()) { membershipTypes.add(membershipType.toString()); } - ProviderConfigProperty membershipType = createConfigProperty(RoleMapperConfig.MEMBERSHIP_ATTRIBUTE_TYPE, "Membership Attribute Type", - "DN means that LDAP role has it's members declared in form of their full DN. For example 'member: uid=john,ou=users,dc=example,dc=com' . " + - "UID means that LDAP role has it's members declared in form of pure user uids. For example 'memberUid: john' .", + ProviderConfigProperty membershipType = createConfigProperty(GroupMapperConfig.MEMBERSHIP_ATTRIBUTE_TYPE, "Membership Attribute Type", + "DN means that LDAP group has it's members declared in form of their full DN. For example 'member: uid=john,ou=users,dc=example,dc=com' . " + + "UID means that LDAP group has it's members declared in form of pure user uids. For example 'memberUid: john' .", ProviderConfigProperty.LIST_TYPE, membershipTypes); configProperties.add(membershipType); @@ -165,6 +165,7 @@ public class GroupLDAPFederationMapperFactory extends AbstractLDAPFederationMapp defaultValues.put(GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "true"); defaultValues.put(GroupMapperConfig.MEMBERSHIP_LDAP_ATTRIBUTE, LDAPConstants.MEMBER); + defaultValues.put(GroupMapperConfig.MEMBERSHIP_ATTRIBUTE_TYPE, MembershipType.DN.toString()); String mode = config.getEditMode() == UserFederationProvider.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString(); defaultValues.put(GroupMapperConfig.MODE, mode); diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java index cbafcc4cee..9dbeec95cc 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java @@ -122,9 +122,9 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper imple logger.debugf("Syncing roles from LDAP into Keycloak DB. Mapper is [%s], LDAP provider is [%s]", mapperModel.getName(), ldapProvider.getModel().getDisplayName()); - // Send LDAP query - LDAPQuery ldapQuery = createRoleQuery(); - List ldapRoles = ldapQuery.getResultList(); + // Send LDAP query to load all roles + LDAPQuery ldapRoleQuery = createRoleQuery(); + List ldapRoles = LDAPUtils.loadAllLDAPObjects(ldapRoleQuery, ldapProvider); RoleContainerModel roleContainer = getTargetRoleContainer(); String rolesRdnAttr = config.getRoleNameLdapAttribute();