Search in sources :

Example 36 with GroupModel

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

the class UserModelTest method testAddDirtyRemoveFederationUsersInTheSameGroupConcurrent.

@Test
@RequireProvider(UserStorageProvider.class)
public void testAddDirtyRemoveFederationUsersInTheSameGroupConcurrent() {
    final ConcurrentSkipListSet<String> userIds = new ConcurrentSkipListSet<>();
    String groupId = groupIds.get(0);
    registerUserFederationWithRealm();
    // Create users and let them join first group
    IntStream.range(0, 100).parallel().forEach(index -> inComittedTransaction(index, (session, i) -> {
        final RealmModel realm = session.realms().getRealm(realmId);
        final UserModel user = session.users().addUser(realm, "user-" + i);
        user.joinGroup(session.groups().getGroupById(realm, groupId));
        log.infof("Created user with id: %s", user.getId());
        userIds.add(user.getId());
        return null;
    }));
    // Remove users _from the federation_, simulates eg. user being removed from LDAP without Keycloak knowing
    withRealm(realmId, (session, realm) -> {
        UserStorageProvider instance = getUserFederationInstance(session, realm);
        log.debugf("Removing selected users from backend");
        IntStream.range(FIRST_DELETED_USER_INDEX, LAST_DELETED_USER_INDEX).forEach(j -> {
            final UserModel user = session.users().getUserByUsername(realm, "user-" + j);
            ((UserRegistrationProvider) instance).removeUser(realm, user);
        });
        return null;
    });
    IntStream.range(0, 7).parallel().forEach(index -> withRealm(realmId, (session, realm) -> {
        final GroupModel group = session.groups().getGroupById(realm, groupId);
        assertThat(session.users().getGroupMembersStream(realm, group).count(), is(100L - DELETED_USER_COUNT));
        return null;
    }));
    inComittedTransaction(session -> {
        // the cache manually.
        if (session.userCache() != null) {
            session.userCache().clear();
        }
        return null;
    });
    // Now delete the users, and count those that were not found to be deleted. This should be equal to the number
    // of users removed directly in the user federation.
    // Some of the transactions may fail due to conflicts as there are many parallel request, so repeat until all users are removed
    AtomicInteger notFoundUsers = new AtomicInteger();
    Set<String> remainingUserIds = new HashSet<>();
    do {
        userIds.stream().parallel().forEach(index -> inComittedTransaction(index, (session, userId) -> {
            final RealmModel realm = session.realms().getRealm(realmId);
            final UserModel user = session.users().getUserById(realm, userId);
            if (user != null) {
                log.debugf("Deleting user: %s", userId);
                session.users().removeUser(realm, user);
            } else {
                log.debugf("Failed deleting user: %s", userId);
                notFoundUsers.incrementAndGet();
            }
            return null;
        }, null, (session, userId) -> {
            log.debugf("Could not delete user %s", userId);
            remainingUserIds.add(userId);
        }));
        userIds.clear();
        userIds.addAll(remainingUserIds);
        remainingUserIds.clear();
    } while (!userIds.isEmpty());
    assertThat(notFoundUsers.get(), is(DELETED_USER_COUNT));
    withRealm(realmId, (session, realm) -> {
        final GroupModel group = session.groups().getGroupById(realm, groupId);
        assertThat(session.users().getGroupMembersStream(realm, group).collect(Collectors.toList()), Matchers.empty());
        return null;
    });
}
Also used : IntStream(java.util.stream.IntStream) Assume.assumeThat(org.junit.Assume.assumeThat) Constants(org.keycloak.models.Constants) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) UserModel(org.keycloak.models.UserModel) UserRegistrationProvider(org.keycloak.storage.user.UserRegistrationProvider) RealmProvider(org.keycloak.models.RealmProvider) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ComponentModel(org.keycloak.component.ComponentModel) Matchers.hasSize(org.hamcrest.Matchers.hasSize) GroupModel(org.keycloak.models.GroupModel) UserStorageProviderModel(org.keycloak.storage.UserStorageProviderModel) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) UserStorageProviderFactory(org.keycloak.storage.UserStorageProviderFactory) RealmModel(org.keycloak.models.RealmModel) UserStorageProvider(org.keycloak.storage.UserStorageProvider) KeycloakSession(org.keycloak.models.KeycloakSession) Set(java.util.Set) Matchers(org.hamcrest.Matchers) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Collectors(java.util.stream.Collectors) UserProvider(org.keycloak.models.UserProvider) List(java.util.List) Matchers.hasItem(org.hamcrest.Matchers.hasItem) Assert.assertNull(org.junit.Assert.assertNull) ConcurrentSkipListSet(java.util.concurrent.ConcurrentSkipListSet) Assert.assertFalse(org.junit.Assert.assertFalse) Matchers.is(org.hamcrest.Matchers.is) RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) UserStorageProvider(org.keycloak.storage.UserStorageProvider) ConcurrentSkipListSet(java.util.concurrent.ConcurrentSkipListSet) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) GroupModel(org.keycloak.models.GroupModel) UserRegistrationProvider(org.keycloak.storage.user.UserRegistrationProvider) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 37 with GroupModel

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

the class GroupPolicyProviderFactory method onExport.

@Override
public void onExport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
    Map<String, String> config = new HashMap<>();
    GroupPolicyRepresentation groupPolicy = toRepresentation(policy, authorization);
    Set<GroupPolicyRepresentation.GroupDefinition> groups = groupPolicy.getGroups();
    for (GroupPolicyRepresentation.GroupDefinition definition : groups) {
        GroupModel group = authorization.getRealm().getGroupById(definition.getId());
        definition.setId(null);
        definition.setPath(ModelToRepresentation.buildGroupPath(group));
    }
    try {
        String groupsClaim = groupPolicy.getGroupsClaim();
        if (groupsClaim != null) {
            config.put("groupsClaim", groupsClaim);
        }
        config.put("groups", JsonSerialization.writeValueAsString(groups));
    } catch (IOException cause) {
        throw new RuntimeException("Failed to export group policy [" + policy.getName() + "]", cause);
    }
    representation.setConfig(config);
}
Also used : HashMap(java.util.HashMap) GroupModel(org.keycloak.models.GroupModel) IOException(java.io.IOException) GroupPolicyRepresentation(org.keycloak.representations.idm.authorization.GroupPolicyRepresentation)

Example 38 with GroupModel

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

the class GroupPolicyProviderFactory method updatePolicy.

private void updatePolicy(Policy policy, String groupsClaim, Set<GroupPolicyRepresentation.GroupDefinition> groups, AuthorizationProvider authorization) {
    if (groups == null || groups.isEmpty()) {
        throw new RuntimeException("You must provide at least one group");
    }
    Map<String, String> config = new HashMap<>(policy.getConfig());
    if (groupsClaim != null) {
        config.put("groupsClaim", groupsClaim);
    }
    List<GroupModel> topLevelGroups = authorization.getRealm().getTopLevelGroupsStream().collect(Collectors.toList());
    for (GroupPolicyRepresentation.GroupDefinition definition : groups) {
        GroupModel group = null;
        if (definition.getId() != null) {
            group = authorization.getRealm().getGroupById(definition.getId());
        }
        String path = definition.getPath();
        if (group == null && path != null) {
            String canonicalPath = path.startsWith("/") ? path.substring(1, path.length()) : path;
            if (canonicalPath != null) {
                String[] parts = canonicalPath.split("/");
                GroupModel parent = null;
                for (String part : parts) {
                    if (parent == null) {
                        parent = topLevelGroups.stream().filter(groupModel -> groupModel.getName().equals(part)).findFirst().orElseThrow(() -> new RuntimeException("Top level group with name [" + part + "] not found"));
                    } else {
                        group = parent.getSubGroupsStream().filter(groupModel -> groupModel.getName().equals(part)).findFirst().orElseThrow(() -> new RuntimeException("Group with name [" + part + "] not found"));
                        parent = group;
                    }
                }
                if (parts.length == 1) {
                    group = parent;
                }
            }
        }
        if (group == null) {
            throw new RuntimeException("Group with id [" + definition.getId() + "] not found");
        }
        definition.setId(group.getId());
        definition.setPath(null);
    }
    try {
        config.put("groups", JsonSerialization.writeValueAsString(groups));
    } catch (IOException cause) {
        throw new RuntimeException("Failed to serialize groups", cause);
    }
    policy.setConfig(config);
}
Also used : Arrays(java.util.Arrays) PolicyProviderFactory(org.keycloak.authorization.policy.provider.PolicyProviderFactory) GroupPolicyRepresentation(org.keycloak.representations.idm.authorization.GroupPolicyRepresentation) Set(java.util.Set) KeycloakSession(org.keycloak.models.KeycloakSession) IOException(java.io.IOException) HashMap(java.util.HashMap) Config(org.keycloak.Config) Collectors(java.util.stream.Collectors) PolicyRepresentation(org.keycloak.representations.idm.authorization.PolicyRepresentation) HashSet(java.util.HashSet) JsonSerialization(org.keycloak.util.JsonSerialization) Policy(org.keycloak.authorization.model.Policy) List(java.util.List) ModelToRepresentation(org.keycloak.models.utils.ModelToRepresentation) Map(java.util.Map) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) GroupModel(org.keycloak.models.GroupModel) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) PolicyProvider(org.keycloak.authorization.policy.provider.PolicyProvider) HashMap(java.util.HashMap) GroupModel(org.keycloak.models.GroupModel) IOException(java.io.IOException) GroupPolicyRepresentation(org.keycloak.representations.idm.authorization.GroupPolicyRepresentation)

Example 39 with GroupModel

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

the class GroupPolicyProvider method evaluate.

@Override
public void evaluate(Evaluation evaluation) {
    AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
    GroupPolicyRepresentation policy = representationFunction.apply(evaluation.getPolicy(), authorizationProvider);
    RealmModel realm = authorizationProvider.getRealm();
    Attributes.Entry groupsClaim = evaluation.getContext().getIdentity().getAttributes().getValue(policy.getGroupsClaim());
    if (groupsClaim == null || groupsClaim.isEmpty()) {
        List<String> userGroups = evaluation.getRealm().getUserGroups(evaluation.getContext().getIdentity().getId());
        groupsClaim = new Entry(policy.getGroupsClaim(), userGroups);
    }
    for (GroupPolicyRepresentation.GroupDefinition definition : policy.getGroups()) {
        GroupModel allowedGroup = realm.getGroupById(definition.getId());
        for (int i = 0; i < groupsClaim.size(); i++) {
            String group = groupsClaim.asString(i);
            if (group.indexOf('/') != -1) {
                String allowedGroupPath = buildGroupPath(allowedGroup);
                if (group.equals(allowedGroupPath) || (definition.isExtendChildren() && group.startsWith(allowedGroupPath))) {
                    evaluation.grant();
                    return;
                }
            }
            // in case the group from the claim does not represent a path, we just check an exact name match
            if (group.equals(allowedGroup.getName())) {
                evaluation.grant();
                return;
            }
        }
    }
}
Also used : RealmModel(org.keycloak.models.RealmModel) Entry(org.keycloak.authorization.attribute.Attributes.Entry) Entry(org.keycloak.authorization.attribute.Attributes.Entry) AuthorizationProvider(org.keycloak.authorization.AuthorizationProvider) Attributes(org.keycloak.authorization.attribute.Attributes) GroupModel(org.keycloak.models.GroupModel) GroupPolicyRepresentation(org.keycloak.representations.idm.authorization.GroupPolicyRepresentation)

Example 40 with GroupModel

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

the class GroupLDAPStorageMapper method onImportUserFromLDAP.

@Override
public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, RealmModel realm, boolean isCreate) {
    LDAPGroupMapperMode mode = config.getMode();
    // For now, import LDAP group mappings just during create
    if (mode == LDAPGroupMapperMode.IMPORT && isCreate) {
        List<LDAPObject> ldapGroups = getLDAPGroupMappings(ldapUser);
        // Import role mappings from LDAP into Keycloak DB
        for (LDAPObject ldapGroup : ldapGroups) {
            GroupModel kcGroup = findKcGroupOrSyncFromLDAP(realm, ldapGroup, user);
            if (kcGroup != null) {
                logger.debugf("User '%s' joins group '%s' during import from LDAP", user.getUsername(), kcGroup.getName());
                user.joinGroup(kcGroup);
            }
        }
    }
}
Also used : LDAPGroupMapperMode(org.keycloak.storage.ldap.mappers.membership.LDAPGroupMapperMode) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) GroupModel(org.keycloak.models.GroupModel)

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