Search in sources :

Example 21 with LDAPObject

use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.

the class UserAttributeLDAPStorageMapper method proxy.

@Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
    final String userModelAttrName = getUserModelAttribute();
    final String ldapAttrName = getLdapAttributeName();
    boolean isAlwaysReadValueFromLDAP = parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP);
    final boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
    final boolean isBinaryAttribute = parseBooleanParameter(mapperModel, IS_BINARY_ATTRIBUTE);
    // For writable mode, we want to propagate writing of attribute to LDAP as well
    if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
        delegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {

            @Override
            public void setSingleAttribute(String name, String value) {
                if (UserModel.USERNAME.equals(name)) {
                    setUsername(value);
                } else if (UserModel.EMAIL.equals(name)) {
                    setEmail(value);
                } else if (setLDAPAttribute(name, value)) {
                    super.setSingleAttribute(name, value);
                }
            }

            @Override
            public void setAttribute(String name, List<String> values) {
                if (UserModel.USERNAME.equals(name)) {
                    setUsername((values != null && values.size() > 0) ? values.get(0) : null);
                } else if (UserModel.EMAIL.equals(name)) {
                    setEmail((values != null && values.size() > 0) ? values.get(0) : null);
                } else if (setLDAPAttribute(name, values)) {
                    super.setAttribute(name, values);
                }
            }

            @Override
            public void removeAttribute(String name) {
                if (!UserModel.USERNAME.equals(name)) {
                    // do not remove username
                    if (setLDAPAttribute(name, null)) {
                        super.removeAttribute(name);
                    }
                }
            }

            @Override
            public void setUsername(String username) {
                String lowercaseUsername = KeycloakModelUtils.toLowerCaseSafe(username);
                checkDuplicateUsername(userModelAttrName, lowercaseUsername, realm, ldapProvider.getSession(), this);
                setLDAPAttribute(UserModel.USERNAME, lowercaseUsername);
                super.setUsername(lowercaseUsername);
            }

            @Override
            public void setEmail(String email) {
                String lowercaseEmail = KeycloakModelUtils.toLowerCaseSafe(email);
                checkDuplicateEmail(userModelAttrName, email, realm, ldapProvider.getSession(), this);
                setLDAPAttribute(UserModel.EMAIL, email);
                super.setEmail(lowercaseEmail);
            }

            @Override
            public void setEnabled(boolean enabled) {
                setLDAPAttribute(UserModel.ENABLED, Boolean.toString(enabled));
                super.setEnabled(enabled);
            }

            @Override
            public void setLastName(String lastName) {
                setLDAPAttribute(UserModel.LAST_NAME, lastName);
                super.setLastName(lastName);
            }

            @Override
            public void setFirstName(String firstName) {
                setLDAPAttribute(UserModel.FIRST_NAME, firstName);
                super.setFirstName(firstName);
            }

            @Override
            public void setEmailVerified(boolean verified) {
                setLDAPAttribute(UserModel.EMAIL_VERIFIED, Boolean.toString(verified));
                super.setEmailVerified(verified);
            }

            protected boolean setLDAPAttribute(String modelAttrName, Object value) {
                if (modelAttrName.equalsIgnoreCase(userModelAttrName)) {
                    if (UserAttributeLDAPStorageMapper.logger.isTraceEnabled()) {
                        UserAttributeLDAPStorageMapper.logger.tracef("Pushing user attribute to LDAP. username: %s, Model attribute name: %s, LDAP attribute name: %s, Attribute value: %s", getUsername(), modelAttrName, ldapAttrName, value);
                    }
                    markUpdatedAttributeInTransaction(modelAttrName);
                    if (value == null) {
                        if (isMandatoryInLdap) {
                            ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
                        } else {
                            ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<String>());
                        }
                    } else if (value instanceof String) {
                        ldapUser.setSingleAttribute(ldapAttrName, (String) value);
                    } else {
                        List<String> asList = (List<String>) value;
                        if (asList.isEmpty() && isMandatoryInLdap) {
                            ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
                        } else {
                            ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<>(asList));
                        }
                    }
                    if (isBinaryAttribute) {
                        UserAttributeLDAPStorageMapper.logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute.", userModelAttrName, getUsername());
                        return false;
                    } else {
                        return true;
                    }
                }
                return true;
            }
        };
    } else if (isBinaryAttribute) {
        delegate = new UserModelDelegate(delegate) {

            @Override
            public void setSingleAttribute(String name, String value) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.setSingleAttribute(name, value);
                }
            }

            @Override
            public void setAttribute(String name, List<String> values) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.setAttribute(name, values);
                }
            }

            @Override
            public void removeAttribute(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    logSkipDBWrite();
                } else {
                    super.removeAttribute(name);
                }
            }

            private void logSkipDBWrite() {
                logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute", userModelAttrName, getUsername());
            }
        };
    }
    // We prefer to read attribute value from LDAP instead of from local Keycloak DB
    if (isAlwaysReadValueFromLDAP) {
        delegate = new UserModelDelegate(delegate) {

            @Override
            public String getFirstAttribute(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getFirstAttribute(name);
                }
            }

            @Override
            public Stream<String> getAttributeStream(String name) {
                if (name.equalsIgnoreCase(userModelAttrName)) {
                    Collection<String> ldapAttrValue = ldapUser.getAttributeAsSet(ldapAttrName);
                    if (ldapAttrValue == null) {
                        return Stream.empty();
                    } else {
                        return ldapAttrValue.stream();
                    }
                } else {
                    return super.getAttributeStream(name);
                }
            }

            @Override
            public Map<String, List<String>> getAttributes() {
                Map<String, List<String>> attrs = new HashMap<>(super.getAttributes());
                // Ignore UserModel properties
                if (userModelProperties.get(userModelAttrName.toLowerCase()) != null) {
                    return attrs;
                }
                Set<String> allLdapAttrValues = ldapUser.getAttributeAsSet(ldapAttrName);
                if (allLdapAttrValues != null) {
                    attrs.put(userModelAttrName, new ArrayList<>(allLdapAttrValues));
                }
                return attrs;
            }

            @Override
            public String getEmail() {
                if (UserModel.EMAIL.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getEmail();
                }
            }

            @Override
            public boolean isEnabled() {
                if (UserModel.ENABLED.equalsIgnoreCase(userModelAttrName)) {
                    return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
                } else {
                    return super.isEnabled();
                }
            }

            @Override
            public boolean isEmailVerified() {
                if (UserModel.EMAIL_VERIFIED.equalsIgnoreCase(userModelAttrName)) {
                    return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
                } else {
                    return super.isEmailVerified();
                }
            }

            @Override
            public String getLastName() {
                if (UserModel.LAST_NAME.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getLastName();
                }
            }

            @Override
            public String getFirstName() {
                if (UserModel.FIRST_NAME.equalsIgnoreCase(userModelAttrName)) {
                    return ldapUser.getAttributeAsString(ldapAttrName);
                } else {
                    return super.getFirstName();
                }
            }
        };
    }
    return delegate;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) UserModelDelegate(org.keycloak.models.utils.UserModelDelegate) Collection(java.util.Collection) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) ArrayList(java.util.ArrayList) List(java.util.List) Stream(java.util.stream.Stream) HashMap(java.util.HashMap) Map(java.util.Map)

Example 22 with LDAPObject

use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.

the class LDAPSamlIdPInitiatedVaryingLetterCaseTest method afterImportTestRealm.

@Override
protected void afterImportTestRealm() {
    getTestingClient().server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        // Delete all LDAP users
        LDAPTestUtils.removeAllLDAPUsers(ctx.getLdapProvider(), appRealm);
        // Add some new LDAP users for testing
        LDAPObject user = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), appRealm, USER_NAME_LDAP, USER_FIRST_NAME, USER_LAST_NAME, USER_EMAIL, USER_STREET, USER_POSTAL_CODE);
        LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), user, USER_PASSWORD);
    });
    ComponentRepresentation ldap = testRealm().components().query(null, "org.keycloak.storage.UserStorageProvider").get(0);
    ComponentRepresentation ldapMapper = new ComponentRepresentation();
    ldapMapper.setName("uid-to-user-attr-mapper");
    ldapMapper.setProviderId(UserAttributeLDAPStorageMapperFactory.PROVIDER_ID);
    ldapMapper.setProviderType("org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
    ldapMapper.setParentId(ldap.getId());
    MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
    config.add(UserAttributeLDAPStorageMapper.USER_MODEL_ATTRIBUTE, "ldapUid");
    config.add(UserAttributeLDAPStorageMapper.LDAP_ATTRIBUTE, "uid");
    config.add(UserAttributeLDAPStorageMapper.READ_ONLY, "true");
    config.add(UserAttributeLDAPStorageMapper.IS_MANDATORY_IN_LDAP, "true");
    ldapMapper.setConfig(config);
    testRealm().components().add(ldapMapper);
}
Also used : RealmModel(org.keycloak.models.RealmModel) ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) MultivaluedHashMap(org.keycloak.common.util.MultivaluedHashMap) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) Matchers.containsString(org.hamcrest.Matchers.containsString)

Example 23 with LDAPObject

use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.

the class LDAPRoleMappingsTest method test03_importRoleMappings.

@Test
public void test03_importRoleMappings() {
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        LDAPTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.IMPORT);
        // Add some role mappings directly in LDAP
        ComponentModel roleMapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
        LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
        RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(roleMapperModel, ldapProvider, appRealm);
        LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak");
        roleMapper.addRoleMappingInLDAP("realmRole1", robLdap);
        roleMapper.addRoleMappingInLDAP("realmRole2", robLdap);
        // Get user and check that he has requested roles from LDAP
        UserModel rob = session.users().getUserByUsername(appRealm, "robkeycloak");
        RoleModel realmRole1 = appRealm.getRole("realmRole1");
        RoleModel realmRole2 = appRealm.getRole("realmRole2");
        RoleModel realmRole3 = appRealm.getRole("realmRole3");
        if (realmRole3 == null) {
            realmRole3 = appRealm.addRole("realmRole3");
        }
        Set<RoleModel> robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
        Assert.assertTrue(robRoles.contains(realmRole1));
        Assert.assertTrue(robRoles.contains(realmRole2));
        Assert.assertFalse(robRoles.contains(realmRole3));
        // Add some role mappings in model and check that user has it
        rob.grantRole(realmRole3);
        robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
        Assert.assertTrue(robRoles.contains(realmRole3));
        // Delete some role mappings in LDAP and check that it doesn't have any effect and user still has role
        deleteRoleMappingsInLDAP(roleMapper, robLdap, "realmRole1");
        deleteRoleMappingsInLDAP(roleMapper, robLdap, "realmRole2");
        robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
        Assert.assertTrue(robRoles.contains(realmRole1));
        Assert.assertTrue(robRoles.contains(realmRole2));
        // Delete role mappings through model and verifies that user doesn't have them anymore
        rob.deleteRoleMapping(realmRole1);
        rob.deleteRoleMapping(realmRole2);
        rob.deleteRoleMapping(realmRole3);
        robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
        Assert.assertFalse(robRoles.contains(realmRole1));
        Assert.assertFalse(robRoles.contains(realmRole2));
        Assert.assertFalse(robRoles.contains(realmRole3));
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) ComponentModel(org.keycloak.component.ComponentModel) LDAPStorageProvider(org.keycloak.storage.ldap.LDAPStorageProvider) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) RoleModel(org.keycloak.models.RoleModel) RoleLDAPStorageMapper(org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapper) Test(org.junit.Test)

Example 24 with LDAPObject

use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.

the class LDAPRoleMappingsTest method test05_getRolesFromUserMemberOfStrategyTest.

// KEYCLOAK-5848
// Test GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE with custom 'Member-Of LDAP Attribute'. As a workaround, we are testing this with custom attribute "street"
// just because it's available on all the LDAP servers
@Test
public void test05_getRolesFromUserMemberOfStrategyTest() throws Exception {
    ComponentRepresentation realmRoleMapper = findMapperRepByName("realmRolesMapper");
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        // Create street attribute mapper
        LDAPTestUtils.addUserAttributeMapper(appRealm, ctx.getLdapModel(), "streetMapper", "street", LDAPConstants.STREET);
        // Find DN of "group1"
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
        RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(mapperModel, ctx.getLdapProvider(), appRealm);
        LDAPObject ldapRole = roleMapper.loadLDAPRoleByName("realmRole1");
        String ldapRoleDN = ldapRole.getDn().toString();
        // Create new user in LDAP. Add him some "street" referencing existing LDAP Group
        LDAPObject carlos = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), appRealm, "carloskeycloak", "Carlos", "Doel", "carlos.doel@email.org", ldapRoleDN, "1234");
        LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), carlos, "Password1");
        // Update group mapper
        LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, RoleMapperConfig.USER_ROLES_RETRIEVE_STRATEGY, RoleMapperConfig.GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE, RoleMapperConfig.MEMBEROF_LDAP_ATTRIBUTE, LDAPConstants.STREET);
        appRealm.updateComponent(mapperModel);
    });
    ComponentRepresentation streetMapper = findMapperRepByName("streetMapper");
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        // Get user in Keycloak. Ensure that he is member of requested group
        UserModel carlos = session.users().getUserByUsername(appRealm, "carloskeycloak");
        Set<RoleModel> carlosRoles = carlos.getRealmRoleMappingsStream().collect(Collectors.toSet());
        RoleModel realmRole1 = appRealm.getRole("realmRole1");
        RoleModel realmRole2 = appRealm.getRole("realmRole2");
        Assert.assertTrue(carlosRoles.contains(realmRole1));
        Assert.assertFalse(carlosRoles.contains(realmRole2));
    });
    // Revert mappers
    testRealm().components().component(streetMapper.getId()).remove();
    testRealm().components().component(realmRoleMapper.getId()).remove();
    realmRoleMapper.setId(null);
    testRealm().components().add(realmRoleMapper);
}
Also used : ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) ComponentModel(org.keycloak.component.ComponentModel) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) RoleModel(org.keycloak.models.RoleModel) RoleLDAPStorageMapper(org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapper) Test(org.junit.Test)

Example 25 with LDAPObject

use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.

the class LDAPRoleMappingsTest method deleteRoleMappingsInLDAP.

private static void deleteRoleMappingsInLDAP(RoleLDAPStorageMapper roleMapper, LDAPObject ldapUser, String roleName) {
    LDAPObject ldapRole1 = roleMapper.loadLDAPRoleByName(roleName);
    roleMapper.deleteRoleMappingInLDAP(ldapUser, ldapRole1);
}
Also used : LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject)

Aggregations

LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)105 RealmModel (org.keycloak.models.RealmModel)61 Test (org.junit.Test)38 LDAPStorageProvider (org.keycloak.storage.ldap.LDAPStorageProvider)37 ComponentModel (org.keycloak.component.ComponentModel)35 UserModel (org.keycloak.models.UserModel)28 GroupModel (org.keycloak.models.GroupModel)18 SynchronizationResult (org.keycloak.storage.user.SynchronizationResult)16 GroupLDAPStorageMapper (org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper)14 ModelException (org.keycloak.models.ModelException)11 LDAPDn (org.keycloak.storage.ldap.idm.model.LDAPDn)10 LDAPQuery (org.keycloak.storage.ldap.idm.query.internal.LDAPQuery)10 HashMap (java.util.HashMap)9 AbstractAuthTest (org.keycloak.testsuite.AbstractAuthTest)8 HashSet (java.util.HashSet)7 List (java.util.List)7 CachedUserModel (org.keycloak.models.cache.CachedUserModel)7 LDAPConfig (org.keycloak.storage.ldap.LDAPConfig)7 LDAPStorageMapper (org.keycloak.storage.ldap.mappers.LDAPStorageMapper)7 Map (java.util.Map)6