Ensure LDAPStorageMapper.getGroupMembers is taking the fetch strategy in consideration when retrieving the members

- fixes issue when MEMBER-OF strategy is selected but ignored when listing members

Closes #33477

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
(cherry picked from commit b2e8942dd1)
This commit is contained in:
Stefan Guilhen
2025-01-30 10:35:17 -03:00
committed by Pedro Igor
parent f76b7e80a7
commit 845f8489c5
4 changed files with 36 additions and 4 deletions

View File

@@ -19,6 +19,8 @@ package org.keycloak.storage.ldap.mappers.membership;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.ldap.LDAPConfig;
import org.keycloak.storage.ldap.LDAPUtils;
import org.keycloak.storage.ldap.idm.model.LDAPDn;
@@ -26,10 +28,12 @@ import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.Condition;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.utils.StreamsUtil;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -42,6 +46,8 @@ public interface UserRolesRetrieveStrategy {
List<LDAPObject> getLDAPRoleMappings(CommonLDAPGroupMapper roleOrGroupMapper, LDAPObject ldapUser, LDAPConfig ldapConfig);
List<UserModel> getLDAPRoleMembers(RealmModel realm, CommonLDAPGroupMapper roleOrGroupMapper, LDAPObject ldapRoleOrGroup, int firstResult, int maxResults);
void beforeUserLDAPQuery(CommonLDAPGroupMapper roleOrGroupMapper, LDAPQuery query);
@@ -67,6 +73,12 @@ public interface UserRolesRetrieveStrategy {
}
}
@Override
public List<UserModel> getLDAPRoleMembers(RealmModel realm, CommonLDAPGroupMapper roleOrGroupMapper, LDAPObject ldapRoleOrGroup, int firstResult, int maxResults) {
MembershipType membershipType = roleOrGroupMapper.getConfig().getMembershipTypeLdapAttribute();
return membershipType.getGroupMembers(realm, roleOrGroupMapper, ldapRoleOrGroup, firstResult, maxResults);
}
@Override
public void beforeUserLDAPQuery(CommonLDAPGroupMapper roleOrGroupMapper, LDAPQuery query) {
}
@@ -113,6 +125,15 @@ public interface UserRolesRetrieveStrategy {
return roles;
}
@Override
public List<UserModel> getLDAPRoleMembers(RealmModel realm, CommonLDAPGroupMapper roleOrGroupMapper, LDAPObject ldapRoleOrGroup, int firstResult, int maxResults) {
String memberOfLdapAttrName = roleOrGroupMapper.getConfig().getMemberOfLdapAttribute();
String roleOrGroupDn = ldapRoleOrGroup.getDn().toString();
return StreamsUtil.paginatedStream(
roleOrGroupMapper.getLdapProvider().searchForUserByUserAttributeStream(realm, memberOfLdapAttrName, roleOrGroupDn), firstResult, maxResults)
.toList();
}
@Override
public void beforeUserLDAPQuery(CommonLDAPGroupMapper roleOrGroupMapper, LDAPQuery query) {
String memberOfLdapAttrName = roleOrGroupMapper.getConfig().getMemberOfLdapAttribute();

View File

@@ -580,8 +580,9 @@ public class GroupLDAPStorageMapper extends AbstractLDAPStorageMapper implements
return Collections.emptyList();
}
MembershipType membershipType = config.getMembershipTypeLdapAttribute();
return membershipType.getGroupMembers(realm, this, ldapGroup, firstResult, maxResults);
String strategyKey = config.getUserGroupsRetrieveStrategy();
UserRolesRetrieveStrategy strategy = factory.getUserGroupsRetrieveStrategy(strategyKey);
return strategy.getLDAPRoleMembers(realm, this, ldapGroup, firstResult, maxResults);
}
public void addGroupMappingInLDAP(RealmModel realm, GroupModel kcGroup, LDAPObject ldapUser) {

View File

@@ -500,7 +500,8 @@ public class RoleLDAPStorageMapper extends AbstractLDAPStorageMapper implements
return Collections.emptyList();
}
MembershipType membershipType = config.getMembershipTypeLdapAttribute();
return membershipType.getGroupMembers(realm, this, ldapGroup, firstResult, maxResults);
String strategyKey = config.getUserRolesRetrieveStrategy();
UserRolesRetrieveStrategy strategy = factory.getUserRolesRetrieveStrategy(strategyKey);
return strategy.getLDAPRoleMembers(realm, this, ldapGroup, firstResult, maxResults);
}
}

View File

@@ -17,6 +17,7 @@
package org.keycloak.testsuite.federation.ldap;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
@@ -52,6 +53,9 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.keycloak.testsuite.util.LDAPTestUtils.getGroupDescriptionLDAPAttrName;
/**
@@ -582,6 +586,11 @@ public class LDAPGroupMapperTest extends AbstractLDAPTest {
Assert.assertFalse(carlosGroups.contains(group12));
Assert.assertEquals(1, carlosGroups.size());
// check the user is listed as the sole member of group1
List<UserModel> group1Members = session.users().getGroupMembersStream(appRealm, group1, 0, 10).toList();
assertThat(group1Members, hasSize(1));
assertThat(group1Members.get(0).getUsername(), equalTo("carloskeycloak"));
});
// Revert mappers