Search in sources :

Example 6 with GroupModel

use of org.keycloak.models.GroupModel in project keycloak by keycloak.

the class LDAPGroupMapper2WaySyncTest method test02_syncWithGroupInheritance.

@Test
public void test02_syncWithGroupInheritance() throws Exception {
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel realm = ctx.getRealm();
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(realm, ctx.getLdapModel(), "groupsMapper");
        LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
        // Update group mapper to skip preserve inheritance and check it will pass now
        LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.PRESERVE_GROUP_INHERITANCE, "true");
        LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.DROP_NON_EXISTING_GROUPS_DURING_SYNC, "false");
        realm.updateComponent(mapperModel);
        // Sync from Keycloak into LDAP
        SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromKeycloakToFederationProvider(realm);
        LDAPTestAsserts.assertSyncEquals(syncResult, 4, 0, 0, 0);
    });
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel realm = ctx.getRealm();
        // Delete all KC groups now
        removeAllModelGroups(realm);
        Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group1"));
        Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group11"));
        Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, "/group2"));
    });
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel realm = ctx.getRealm();
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(realm, ctx.getLdapModel(), "groupsMapper");
        LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
        String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
        // Sync from LDAP back into Keycloak
        SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
        LDAPTestAsserts.assertSyncEquals(syncResult, 4, 0, 0, 0);
        // Assert groups are imported to keycloak. All are at top level
        GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, "/group1");
        GroupModel kcGroup11 = KeycloakModelUtils.findGroupByPath(realm, "/group1/group11");
        GroupModel kcGroup12 = KeycloakModelUtils.findGroupByPath(realm, "/group1/group12");
        GroupModel kcGroup2 = KeycloakModelUtils.findGroupByPath(realm, "/group2");
        Assert.assertEquals(2, kcGroup1.getSubGroupsStream().count());
        Assert.assertEquals("group1 - description1", kcGroup1.getFirstAttribute(descriptionAttrName));
        Assert.assertNull(kcGroup11.getFirstAttribute(descriptionAttrName));
        Assert.assertEquals("group12 - description12", kcGroup12.getFirstAttribute(descriptionAttrName));
        Assert.assertNull(kcGroup2.getFirstAttribute(descriptionAttrName));
        // test drop non-existing works
        testDropNonExisting(session, ctx, mapperModel);
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) ComponentModel(org.keycloak.component.ComponentModel) LDAPStorageProvider(org.keycloak.storage.ldap.LDAPStorageProvider) GroupModel(org.keycloak.models.GroupModel) GroupLDAPStorageMapperFactory(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) Test(org.junit.Test)

Example 7 with GroupModel

use of org.keycloak.models.GroupModel in project keycloak by keycloak.

the class LDAPGroupMapperSyncWithGroupsPathTest method test01_syncWithGroupInheritance.

@Test
public void test01_syncWithGroupInheritance() {
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel realm = ctx.getRealm();
        String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(realm, ctx.getLdapModel(), "groupsMapper");
        LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
        GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, realm);
        // KEYCLOAK-11415 - This test requires the group mapper to be configured with preserve group inheritance
        // set to 'true' (the default setting). If preservation of group inheritance isn't configured, some of
        // the previous test(s) failed to cleanup properly. Check the requirement as part of running the test
        Assert.assertEquals(mapperModel.getConfig().getFirst("preserve.group.inheritance"), "true");
        // Sync groups with inheritance
        SynchronizationResult syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
        LDAPTestAsserts.assertSyncEquals(syncResult, 3, 0, 0, 0);
        // Assert groups are imported to keycloak including their inheritance from LDAP
        GroupModel kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1");
        Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group11"));
        Assert.assertNull(KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group12"));
        GroupModel kcGroup11 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group11");
        GroupModel kcGroup12 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group12");
        Assert.assertEquals(2, kcGroup1.getSubGroupsStream().count());
        Assert.assertEquals("group1 - description", kcGroup1.getFirstAttribute(descriptionAttrName));
        Assert.assertNull(kcGroup11.getFirstAttribute(descriptionAttrName));
        Assert.assertEquals("group12 - description", kcGroup12.getFirstAttribute(descriptionAttrName));
        // Update description attributes in LDAP
        LDAPObject group1 = groupMapper.loadLDAPGroupByName("group1");
        group1.setSingleAttribute(descriptionAttrName, "group1 - changed description");
        ldapProvider.getLdapIdentityStore().update(group1);
        LDAPObject group12 = groupMapper.loadLDAPGroupByName("group12");
        group12.setAttribute(descriptionAttrName, null);
        ldapProvider.getLdapIdentityStore().update(group12);
        // Sync and assert groups updated
        syncResult = new GroupLDAPStorageMapperFactory().create(session, mapperModel).syncDataFromFederationProviderToKeycloak(realm);
        LDAPTestAsserts.assertSyncEquals(syncResult, 0, 3, 0, 0);
        // Assert attributes changed in keycloak
        kcGroup1 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1");
        kcGroup12 = KeycloakModelUtils.findGroupByPath(realm, LDAP_GROUPS_PATH + "/group1/group12");
        Assert.assertEquals("group1 - changed description", kcGroup1.getFirstAttribute(descriptionAttrName));
        Assert.assertNull(kcGroup12.getFirstAttribute(descriptionAttrName));
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) ComponentModel(org.keycloak.component.ComponentModel) LDAPStorageProvider(org.keycloak.storage.ldap.LDAPStorageProvider) GroupModel(org.keycloak.models.GroupModel) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) GroupLDAPStorageMapperFactory(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) GroupLDAPStorageMapper(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper) Test(org.junit.Test)

Example 8 with GroupModel

use of org.keycloak.models.GroupModel in project keycloak by keycloak.

the class LDAPGroupMapperSyncWithGroupsPathTest method afterImportTestRealm.

@Override
protected void afterImportTestRealm() {
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
        // Create groups path
        GroupModel parentGroup = appRealm.createGroup("Applications");
        appRealm.createGroup("App1", parentGroup);
        // Add group mapper
        LDAPTestUtils.addOrUpdateGroupMapper(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.LDAP_ONLY, descriptionAttrName, GroupMapperConfig.LDAP_GROUPS_PATH, LDAP_GROUPS_PATH);
        // Remove all LDAP groups
        LDAPTestUtils.removeAllLDAPGroups(session, appRealm, ctx.getLdapModel(), "groupsMapper");
        // Add some groups for testing
        LDAPObject group1 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group1", descriptionAttrName, "group1 - description");
        LDAPObject group11 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group11");
        LDAPObject group12 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group12", descriptionAttrName, "group12 - description");
        LDAPUtils.addMember(ctx.getLdapProvider(), MembershipType.DN, LDAPConstants.MEMBER, "not-used", group1, group11);
        LDAPUtils.addMember(ctx.getLdapProvider(), MembershipType.DN, LDAPConstants.MEMBER, "not-used", group1, group12);
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) GroupModel(org.keycloak.models.GroupModel) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject)

Example 9 with GroupModel

use of org.keycloak.models.GroupModel in project keycloak by keycloak.

the class GroupLDAPStorageMapper method syncFlatGroupStructure.

private void syncFlatGroupStructure(RealmModel realm, SynchronizationResult syncResult, Map<String, LDAPObject> ldapGroupsMap) {
    Set<String> visitedGroupIds = new HashSet<>();
    // Just add flat structure of groups with all groups at groups path
    LDAPConfig ldapConfig = ldapProvider.getLdapIdentityStore().getConfig();
    final int groupsPerTransaction = ldapConfig.getBatchSizeForSync();
    Set<Map.Entry<String, LDAPObject>> entries = ldapGroupsMap.entrySet();
    for (Iterator<Map.Entry<String, LDAPObject>> it = entries.iterator(); it.hasNext(); ) {
        KeycloakModelUtils.runJobInTransaction(ldapProvider.getSession().getKeycloakSessionFactory(), session -> {
            // KEYCLOAK-8253 The retrieval of the current realm to operate at, was intentionally left
            // outside the following for loop! This prevents the scenario, when LDAP group sync time
            // initially improves, but during the time (after ~20K groups are synced) degrades again
            // due to the realm cache being bloated with huge amount of (temporary) realm entities
            RealmModel currentRealm = session.realms().getRealm(realm.getId());
            // List of group path groups known to the whole transaction
            Map<String, GroupModel> transactionGroupPathGroups = getKcSubGroups(currentRealm, null).collect(Collectors.toMap(GroupModel::getName, Function.identity()));
            for (int i = 0; i < groupsPerTransaction && it.hasNext(); i++) {
                Map.Entry<String, LDAPObject> groupEntry = it.next();
                String groupName = groupEntry.getKey();
                GroupModel kcExistingGroup = transactionGroupPathGroups.get(groupName);
                if (kcExistingGroup != null) {
                    syncExistingGroup(kcExistingGroup, groupEntry, syncResult, visitedGroupIds, groupName);
                } else {
                    syncNonExistingGroup(realm, groupEntry, syncResult, visitedGroupIds, groupName);
                }
            }
        });
    }
    // Possibly remove keycloak groups, which don't exist in LDAP
    if (config.isDropNonExistingGroupsDuringSync()) {
        dropNonExistingKcGroups(realm, syncResult, visitedGroupIds);
    }
}
Also used : GroupModel(org.keycloak.models.GroupModel) RealmModel(org.keycloak.models.RealmModel) LDAPConfig(org.keycloak.storage.ldap.LDAPConfig) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 10 with GroupModel

use of org.keycloak.models.GroupModel in project keycloak by keycloak.

the class GroupLDAPStorageMapper method processKeycloakGroupMembershipsSyncToLDAP.

// Update memberships of group in LDAP based on subgroups from KC. Do it recursively
private void processKeycloakGroupMembershipsSyncToLDAP(GroupModel kcGroup, Map<String, LDAPObject> ldapGroupsMap) {
    LDAPObject ldapGroup = ldapGroupsMap.get(kcGroup.getName());
    Set<LDAPDn> toRemoveSubgroupsDNs = getLDAPSubgroups(ldapGroup);
    // Not applicable for groups, but needs to be here
    String membershipUserLdapAttrName = getMembershipUserLdapAttribute();
    // Add LDAP subgroups, which are KC subgroups
    Set<GroupModel> kcSubgroups = kcGroup.getSubGroupsStream().collect(Collectors.toSet());
    for (GroupModel kcSubgroup : kcSubgroups) {
        LDAPObject ldapSubgroup = ldapGroupsMap.get(kcSubgroup.getName());
        if (!toRemoveSubgroupsDNs.remove(ldapSubgroup.getDn())) {
            // if the group is not in the ldap group => add it
            LDAPUtils.addMember(ldapProvider, MembershipType.DN, config.getMembershipLdapAttribute(), membershipUserLdapAttrName, ldapGroup, ldapSubgroup);
        }
    }
    // Remove LDAP subgroups, which are not members in KC anymore
    for (LDAPDn toRemoveDN : toRemoveSubgroupsDNs) {
        LDAPObject fakeGroup = new LDAPObject();
        fakeGroup.setDn(toRemoveDN);
        LDAPUtils.deleteMember(ldapProvider, MembershipType.DN, config.getMembershipLdapAttribute(), membershipUserLdapAttrName, ldapGroup, fakeGroup);
    }
    for (GroupModel kcSubgroup : kcSubgroups) {
        processKeycloakGroupMembershipsSyncToLDAP(kcSubgroup, ldapGroupsMap);
    }
}
Also used : LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) GroupModel(org.keycloak.models.GroupModel) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn)

Aggregations

GroupModel (org.keycloak.models.GroupModel)72 RealmModel (org.keycloak.models.RealmModel)40 Test (org.junit.Test)26 ComponentModel (org.keycloak.component.ComponentModel)23 UserModel (org.keycloak.models.UserModel)20 LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)18 LDAPStorageProvider (org.keycloak.storage.ldap.LDAPStorageProvider)13 GroupLDAPStorageMapper (org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper)12 RoleModel (org.keycloak.models.RoleModel)10 ClientModel (org.keycloak.models.ClientModel)9 GroupLDAPStorageMapperFactory (org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory)9 HashMap (java.util.HashMap)8 List (java.util.List)8 NotFoundException (javax.ws.rs.NotFoundException)7 SynchronizationResult (org.keycloak.storage.user.SynchronizationResult)7 HashSet (java.util.HashSet)6 Map (java.util.Map)6 Collectors (java.util.stream.Collectors)6 Path (javax.ws.rs.Path)6 Policy (org.keycloak.authorization.model.Policy)6