Search in sources :

Example 6 with LDAPDn

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

the class LDAPIdentityStore method populateAttributedType.

private LDAPObject populateAttributedType(SearchResult searchResult, LDAPQuery ldapQuery) {
    Set<String> readOnlyAttrNames = ldapQuery.getReturningReadOnlyLdapAttributes();
    Set<String> lowerCasedAttrNames = new TreeSet<>();
    for (String attrName : ldapQuery.getReturningLdapAttributes()) {
        lowerCasedAttrNames.add(attrName.toLowerCase());
    }
    try {
        String entryDN = searchResult.getNameInNamespace();
        Attributes attributes = searchResult.getAttributes();
        LDAPObject ldapObject = new LDAPObject();
        LDAPDn dn = LDAPDn.fromString(entryDN);
        ldapObject.setDn(dn);
        ldapObject.setRdnAttributeNames(dn.getFirstRdn().getAllKeys());
        NamingEnumeration<? extends Attribute> ldapAttributes = attributes.getAll();
        while (ldapAttributes.hasMore()) {
            Attribute ldapAttribute = ldapAttributes.next();
            try {
                ldapAttribute.get();
            } catch (NoSuchElementException nsee) {
                continue;
            }
            String ldapAttributeName = ldapAttribute.getID();
            // check for ranged attribute
            Matcher m = rangePattern.matcher(ldapAttributeName);
            if (m.matches()) {
                ldapAttributeName = m.group(1);
                // range=X-* means all the attributes returned
                if (!m.group(3).equals("*")) {
                    try {
                        int max = Integer.parseInt(m.group(3));
                        ldapObject.addRangedAttribute(ldapAttributeName, max);
                    } catch (NumberFormatException e) {
                        logger.warnf("Invalid ranged expresion for attribute: %s", m.group(0));
                    }
                }
            }
            if (ldapAttributeName.equalsIgnoreCase(getConfig().getUuidLDAPAttributeName())) {
                Object uuidValue = ldapAttribute.get();
                ldapObject.setUuid(this.operationManager.decodeEntryUUID(uuidValue));
            }
            // Note: UUID is normally not populated here. It's populated just in case that it's used for name of other attribute as well
            if (!ldapAttributeName.equalsIgnoreCase(getConfig().getUuidLDAPAttributeName()) || (lowerCasedAttrNames.contains(ldapAttributeName.toLowerCase()))) {
                Set<String> attrValues = new LinkedHashSet<>();
                NamingEnumeration<?> enumm = ldapAttribute.getAll();
                while (enumm.hasMoreElements()) {
                    Object val = enumm.next();
                    if (val instanceof byte[]) {
                        // byte[]
                        String attrVal = Base64.encodeBytes((byte[]) val);
                        attrValues.add(attrVal);
                    } else {
                        // String
                        String attrVal = val.toString().trim();
                        attrValues.add(attrVal);
                    }
                }
                if (ldapAttributeName.equalsIgnoreCase(LDAPConstants.OBJECT_CLASS)) {
                    ldapObject.setObjectClasses(attrValues);
                } else {
                    ldapObject.setAttribute(ldapAttributeName, attrValues);
                    // readOnlyAttrNames are lower-cased
                    if (readOnlyAttrNames.contains(ldapAttributeName.toLowerCase())) {
                        ldapObject.addReadOnlyAttributeName(ldapAttributeName);
                    }
                }
            }
        }
        if (logger.isTraceEnabled()) {
            logger.tracef("Found ldap object and populated with the attributes. LDAP Object: %s", ldapObject.toString());
        }
        return ldapObject;
    } catch (Exception e) {
        throw new ModelException("Could not populate attribute type " + searchResult.getNameInNamespace() + ".", e);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ModelException(org.keycloak.models.ModelException) BasicAttribute(javax.naming.directory.BasicAttribute) Attribute(javax.naming.directory.Attribute) Matcher(java.util.regex.Matcher) BasicAttributes(javax.naming.directory.BasicAttributes) Attributes(javax.naming.directory.Attributes) NamingException(javax.naming.NamingException) AuthenticationException(javax.naming.AuthenticationException) AttributeInUseException(javax.naming.directory.AttributeInUseException) NoSuchAttributeException(javax.naming.directory.NoSuchAttributeException) NoSuchElementException(java.util.NoSuchElementException) IOException(java.io.IOException) ModelException(org.keycloak.models.ModelException) SchemaViolationException(javax.naming.directory.SchemaViolationException) TreeSet(java.util.TreeSet) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn) NoSuchElementException(java.util.NoSuchElementException)

Example 7 with LDAPDn

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

the class LDAPIdentityStore method checkRename.

protected void checkRename(LDAPObject ldapObject) {
    LDAPDn.RDN firstRdn = ldapObject.getDn().getFirstRdn();
    String oldDn = ldapObject.getDn().toString();
    // Detect which keys will need to be updated in RDN, which are new keys to be added, and which are to be removed
    List<String> toUpdateKeys = firstRdn.getAllKeys();
    toUpdateKeys.retainAll(ldapObject.getRdnAttributeNames());
    List<String> toRemoveKeys = firstRdn.getAllKeys();
    toRemoveKeys.removeAll(ldapObject.getRdnAttributeNames());
    List<String> toAddKeys = new ArrayList<>(ldapObject.getRdnAttributeNames());
    toAddKeys.removeAll(firstRdn.getAllKeys());
    // Go through all the keys in the oldRDN and doublecheck if they are changed or not
    boolean changed = false;
    for (String attrKey : toUpdateKeys) {
        if (ldapObject.getReadOnlyAttributeNames().contains(attrKey.toLowerCase())) {
            continue;
        }
        String rdnAttrVal = ldapObject.getAttributeAsString(attrKey);
        // Could be the case when RDN attribute of the target object is not included in Keycloak mappers
        if (rdnAttrVal == null) {
            continue;
        }
        String oldRdnAttrVal = firstRdn.getAttrValue(attrKey);
        if (!oldRdnAttrVal.equalsIgnoreCase(rdnAttrVal)) {
            changed = true;
            firstRdn.setAttrValue(attrKey, rdnAttrVal);
        }
    }
    // Add new keys
    for (String attrKey : toAddKeys) {
        String rdnAttrVal = ldapObject.getAttributeAsString(attrKey);
        // Could be the case when RDN attribute of the target object is not included in Keycloak mappers
        if (rdnAttrVal == null) {
            continue;
        }
        changed = true;
        firstRdn.setAttrValue(attrKey, rdnAttrVal);
    }
    // Remove old keys
    for (String attrKey : toRemoveKeys) {
        changed |= firstRdn.removeAttrValue(attrKey);
    }
    if (changed) {
        LDAPDn newLdapDn = ldapObject.getDn().getParentDn();
        newLdapDn.addFirst(firstRdn);
        String newDn = newLdapDn.toString();
        logger.debugf("Renaming LDAP Object. Old DN: [%s], New DN: [%s]", oldDn, newDn);
        // In case, that there is conflict (For example already existing "CN=John Anthony"), the different DN is returned
        newDn = this.operationManager.renameEntry(oldDn, newDn, true);
        ldapObject.setDn(LDAPDn.fromString(newDn));
    }
}
Also used : ArrayList(java.util.ArrayList) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn)

Example 8 with LDAPDn

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

the class LDAPOperationManager method findNextDNForFallback.

private String findNextDNForFallback(String newDn, int counter) {
    LDAPDn dn = LDAPDn.fromString(newDn);
    LDAPDn.RDN firstRdn = dn.getFirstRdn();
    String rdnAttrName = firstRdn.getAllKeys().get(0);
    String rdnAttrVal = firstRdn.getAttrValue(rdnAttrName);
    LDAPDn parentDn = dn.getParentDn();
    parentDn.addFirst(rdnAttrName, rdnAttrVal + counter);
    return parentDn.toString();
}
Also used : LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn)

Example 9 with LDAPDn

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

the class LDAPTestUtils method addLdapOU.

public static LDAPObject addLdapOU(LDAPStorageProvider ldapProvider, String name) {
    LDAPObject ldapObject = new LDAPObject();
    ldapObject.setRdnAttributeName("ou");
    ldapObject.setObjectClasses(Collections.singletonList("organizationalUnit"));
    ldapObject.setSingleAttribute("ou", name);
    LDAPDn dn = LDAPDn.fromString(ldapProvider.getLdapIdentityStore().getConfig().getUsersDn());
    dn.addFirst("ou", name);
    ldapObject.setDn(dn);
    ldapProvider.getLdapIdentityStore().add(ldapObject);
    return ldapObject;
}
Also used : LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn)

Example 10 with LDAPDn

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

the class LDAPGroupMapperTest method test04_groupReferencingNonExistentMember.

// KEYCLOAK-2682
@Test
public void test04_groupReferencingNonExistentMember() {
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "groupsMapper");
        LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, GroupMapperConfig.MODE, LDAPGroupMapperMode.LDAP_ONLY.toString());
        appRealm.updateComponent(mapperModel);
        // Ignoring this test on ActiveDirectory as it's not allowed to have LDAP group referencing nonexistent member. KEYCLOAK-2682 was related to OpenLDAP TODO: Better solution than programmatic...
        LDAPConfig config = ctx.getLdapProvider().getLdapIdentityStore().getConfig();
        if (config.isActiveDirectory()) {
            return;
        }
        String descriptionAttrName = getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
        // 1 - Add some group to LDAP for testing
        LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
        GroupLDAPStorageMapper groupMapper = LDAPTestUtils.getGroupMapper(mapperModel, ldapProvider, appRealm);
        LDAPObject group2 = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "group2", descriptionAttrName, "group2 - description");
        // 2 - Add one existing user rob to LDAP group
        LDAPObject jamesLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "jameskeycloak");
        LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, "not-used", group2, jamesLdap);
        // 3 - Add non-existing user to LDAP group
        LDAPDn nonExistentDn = LDAPDn.fromString(ldapProvider.getLdapIdentityStore().getConfig().getUsersDn());
        nonExistentDn.addFirst(jamesLdap.getRdnAttributeNames().get(0), "nonexistent");
        LDAPObject nonExistentLdapUser = new LDAPObject();
        nonExistentLdapUser.setDn(nonExistentDn);
        LDAPUtils.addMember(ldapProvider, MembershipType.DN, LDAPConstants.MEMBER, "not-used", group2, nonExistentLdapUser);
        // 4 - Check group members. Just existing user rob should be present
        groupMapper.syncDataFromFederationProviderToKeycloak(appRealm);
        GroupModel kcGroup2 = KeycloakModelUtils.findGroupByPath(appRealm, "/group2");
        List<UserModel> groupUsers = session.users().getGroupMembersStream(appRealm, kcGroup2, 0, 5).collect(Collectors.toList());
        Assert.assertEquals(1, groupUsers.size());
        UserModel rob = groupUsers.get(0);
        Assert.assertEquals("jameskeycloak", rob.getUsername());
    });
}
Also used : RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) LDAPConfig(org.keycloak.storage.ldap.LDAPConfig) ComponentModel(org.keycloak.component.ComponentModel) LDAPStorageProvider(org.keycloak.storage.ldap.LDAPStorageProvider) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) GroupModel(org.keycloak.models.GroupModel) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn) GroupLDAPStorageMapper(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper) Test(org.junit.Test)

Aggregations

LDAPDn (org.keycloak.storage.ldap.idm.model.LDAPDn)10 LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)6 HashSet (java.util.HashSet)2 GroupModel (org.keycloak.models.GroupModel)2 ModelException (org.keycloak.models.ModelException)2 UserModel (org.keycloak.models.UserModel)2 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 NoSuchElementException (java.util.NoSuchElementException)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1 Matcher (java.util.regex.Matcher)1 Stream (java.util.stream.Stream)1 AuthenticationException (javax.naming.AuthenticationException)1 NamingException (javax.naming.NamingException)1 Attribute (javax.naming.directory.Attribute)1 AttributeInUseException (javax.naming.directory.AttributeInUseException)1