KEYCLOAK-2655 Support of lazy sync LDAP groups, which user is member of
This commit is contained in:
parent
85ccd64e01
commit
1142ed5583
4 changed files with 81 additions and 12 deletions
|
@ -288,11 +288,13 @@ public class GroupLDAPFederationMapper extends AbstractLDAPFederationMapper impl
|
|||
}
|
||||
}
|
||||
|
||||
// Override if better effectivity or different algorithm is needed
|
||||
|
||||
protected GroupModel findKcGroupByLDAPGroup(LDAPObject ldapGroup) {
|
||||
String groupNameAttr = config.getGroupNameLdapAttribute();
|
||||
String groupName = ldapGroup.getAttributeAsString(groupNameAttr);
|
||||
|
||||
if (config.isPreserveGroupsInheritance()) {
|
||||
// Override if better effectivity or different algorithm is needed
|
||||
List<GroupModel> groups = realm.getGroups();
|
||||
for (GroupModel group : groups) {
|
||||
if (group.getName().equals(groupName)) {
|
||||
|
@ -301,17 +303,32 @@ public class GroupLDAPFederationMapper extends AbstractLDAPFederationMapper impl
|
|||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
// Without preserved inheritance, it's always top-level group
|
||||
return KeycloakModelUtils.findGroupByPath(realm, "/" + groupName);
|
||||
}
|
||||
}
|
||||
|
||||
protected GroupModel findKcGroupOrSyncFromLDAP(LDAPObject ldapGroup, UserModel user) {
|
||||
GroupModel kcGroup = findKcGroupByLDAPGroup(ldapGroup);
|
||||
|
||||
if (kcGroup == null) {
|
||||
// Sync groups from LDAP
|
||||
|
||||
if (config.isPreserveGroupsInheritance()) {
|
||||
|
||||
// Better to sync all groups from LDAP with preserved inheritance
|
||||
if (!syncFromLDAPPerformedInThisTransaction) {
|
||||
syncDataFromFederationProviderToKeycloak();
|
||||
kcGroup = findKcGroupByLDAPGroup(ldapGroup);
|
||||
}
|
||||
} else {
|
||||
String groupNameAttr = config.getGroupNameLdapAttribute();
|
||||
String groupName = ldapGroup.getAttributeAsString(groupNameAttr);
|
||||
|
||||
kcGroup = realm.createGroup(groupName);
|
||||
updateAttributesOfKCGroup(kcGroup, ldapGroup);
|
||||
realm.moveGroup(kcGroup, null);
|
||||
}
|
||||
|
||||
// Could theoretically happen on some LDAP servers if 'memberof' style is used and 'memberof' attribute of user references non-existing group
|
||||
if (kcGroup == null) {
|
||||
|
|
|
@ -61,6 +61,7 @@ public class LDAPGroupMapper2WaySyncTest {
|
|||
Map<String,String> ldapConfig = ldapRule.getConfig();
|
||||
ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "true");
|
||||
ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.WRITABLE.toString());
|
||||
ldapConfig.put(LDAPConstants.BATCH_SIZE_FOR_SYNC, "4"); // Issues with pagination on ApacheDS
|
||||
|
||||
ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap", -1, -1, 0);
|
||||
LDAPFederationProvider ldapFedProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.federation.ldap.base;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -46,6 +47,7 @@ import org.keycloak.models.UserFederationMapperModel;
|
|||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
import org.keycloak.models.UserFederationSyncResult;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.federation.ldap.FederationTestUtils;
|
||||
|
@ -258,4 +260,53 @@ public class LDAPGroupMapperSyncTest {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void test04_syncNoPreserveGroupInheritanceWithLazySync() throws Exception {
|
||||
KeycloakSession session = keycloakRule.startSession();
|
||||
try {
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserFederationMapperModel mapperModel = realm.getUserFederationMapperByName(ldapModel.getId(), "groupsMapper");
|
||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel);
|
||||
GroupLDAPFederationMapper groupMapper = FederationTestUtils.getGroupMapper(mapperModel, ldapProvider, realm);
|
||||
|
||||
// Update group mapper to skip preserve inheritance
|
||||
FederationTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "false");
|
||||
realm.updateUserFederationMapper(mapperModel);
|
||||
|
||||
// Add user to LDAP and put him as member of group11
|
||||
FederationTestUtils.removeAllLDAPUsers(ldapProvider, realm);
|
||||
LDAPObject johnLdap = FederationTestUtils.addLDAPUser(ldapProvider, realm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||
FederationTestUtils.updateLDAPPassword(ldapProvider, johnLdap, "Password1");
|
||||
groupMapper.addGroupMappingInLDAP("group11", johnLdap);
|
||||
|
||||
// Assert groups not yet imported to Keycloak DB
|
||||
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group1"));
|
||||
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group11"));
|
||||
Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group12"));
|
||||
|
||||
// Load user from LDAP to Keycloak DB
|
||||
UserModel john = session.users().getUserByUsername("johnkeycloak", realm);
|
||||
Set<GroupModel> johnGroups = john.getGroups();
|
||||
|
||||
// Assert just those groups, which john was memberOf exists because they were lazily created
|
||||
GroupModel group1 = KeycloakModelUtils.findGroupByPath(realm, "/group1");
|
||||
GroupModel group11 = KeycloakModelUtils.findGroupByPath(realm, "/group11");
|
||||
GroupModel group12 = KeycloakModelUtils.findGroupByPath(realm, "/group12");
|
||||
Assert.assertNull(group1);
|
||||
Assert.assertNotNull(group11);
|
||||
Assert.assertNull(group12);
|
||||
|
||||
Assert.assertEquals(1, johnGroups.size());
|
||||
Assert.assertTrue(johnGroups.contains(group11));
|
||||
|
||||
// Delete group mapping
|
||||
john.leaveGroup(group11);
|
||||
|
||||
} finally {
|
||||
keycloakRule.stopSession(session, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue