keycloak-aplcache
Changes
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java 39(+28 -11)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java 2(+1 -1)
Details
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 a5ad49e..00108bc 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
@@ -288,29 +288,46 @@ 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);
- List<GroupModel> groups = realm.getGroups();
- for (GroupModel group : groups) {
- if (group.getName().equals(groupName)) {
- return group;
+ 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)) {
+ return group;
+ }
}
- }
- return null;
+ 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 (!syncFromLDAPPerformedInThisTransaction) {
- syncDataFromFederationProviderToKeycloak();
- kcGroup = findKcGroupByLDAPGroup(ldapGroup);
+
+ 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
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
index 135c4f3..3ee6b70 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
@@ -556,7 +556,7 @@ public class FederationProvidersIntegrationTest {
keycloakRule.stopSession(session, true);
}
-
+
// Assert changed user available in Keycloak
session = keycloakRule.startSession();
try {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapper2WaySyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapper2WaySyncTest.java
index 45ad9e7..493996a 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapper2WaySyncTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapper2WaySyncTest.java
@@ -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);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperSyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperSyncTest.java
index d218f26..9308e04 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperSyncTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/LDAPGroupMapperSyncTest.java
@@ -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);
+ }
+ }
+
}