diff options
author | Olivier Lamy <olamy@apache.org> | 2013-11-08 01:22:14 +0000 |
---|---|---|
committer | Olivier Lamy <olamy@apache.org> | 2013-11-08 01:22:14 +0000 |
commit | 21834d0808bedc62cf72c387a3375f2bf238cd23 (patch) | |
tree | 3cf371c3e694dba3857031ec0e31583bd0e942af | |
parent | f67b16ab152116fce0e9edb2460d677fcc92bee3 (diff) | |
download | archiva-21834d0808bedc62cf72c387a3375f2bf238cd23.tar.gz archiva-21834d0808bedc62cf72c387a3375f2bf238cd23.zip |
[MRM-1791] ldap group mapping support for active directory
git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-core/trunk@1539894 13f79535-47bb-0310-9956-ffa450edef68
6 files changed, 272 insertions, 15 deletions
diff --git a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java index 76a561e33..10a615e88 100644 --- a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java +++ b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java @@ -20,11 +20,17 @@ package org.apache.archiva.redback.common.ldap.role; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; + import org.apache.archiva.redback.common.ldap.MappingException; import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; import org.apache.archiva.redback.common.ldap.connection.LdapException; +import org.apache.archiva.redback.common.ldap.user.LdapUser; import org.apache.archiva.redback.configuration.UserConfiguration; import org.apache.archiva.redback.configuration.UserConfigurationKeys; +import org.apache.archiva.redback.users.User; +import org.apache.archiva.redback.users.UserManager; +import org.apache.archiva.redback.users.UserManagerException; +import org.apache.archiva.redback.users.UserNotFoundException; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,6 +51,7 @@ import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -76,6 +83,10 @@ public class DefaultLdapRoleMapper @Named( value = "ldapRoleMapperConfiguration#default" ) private LdapRoleMapperConfiguration ldapRoleMapperConfiguration; + @Inject + @Named( value = "userManager#default" ) + private UserManager userManager; + //--------------------------- // fields //--------------------------- @@ -86,6 +97,8 @@ public class DefaultLdapRoleMapper private String baseDn; + private String ldapGroupMember = "uniquemember"; + private boolean useDefaultRoleName = false; /** @@ -112,6 +125,8 @@ public class DefaultLdapRoleMapper userConf.getBoolean( UserConfigurationKeys.LDAP_GROUPS_USE_ROLENAME, this.useDefaultRoleName ); this.userIdAttribute = userConf.getString( UserConfigurationKeys.LDAP_USER_ID_ATTRIBUTE, this.userIdAttribute ); + + this.ldapGroupMember = userConf.getString( UserConfigurationKeys.LDAP_GROUPS_MEMBER, this.ldapGroupMember ); } public List<String> getAllGroups( DirContext context ) @@ -283,7 +298,7 @@ public class DefaultLdapRoleMapper { SearchResult searchResult = namingEnumeration.next(); - Attribute uniqueMemberAttr = searchResult.getAttributes().get( "uniquemember" ); + Attribute uniqueMemberAttr = searchResult.getAttributes().get( getLdapGroupMember() ); if ( uniqueMemberAttr != null ) { @@ -335,11 +350,37 @@ public class DefaultLdapRoleMapper searchControls.setDerefLinkFlag( true ); searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE ); + String dn =null; + try + { + //try to look the user up + User user = userManager.findUser(username); + if (user instanceof LdapUser) + { + LdapUser ldapUser = (LdapUser)user; + Attribute dnAttribute = ldapUser.getOriginalAttributes().get("distinguishedName"); + if(dnAttribute!=null) + dn = (String)dnAttribute.get(); - String filter = - new StringBuilder().append( "(&" ).append( "(objectClass=" + getLdapGroupClass() + ")" ).append( - "(uniquemember=" ).append( this.userIdAttribute + "=" + username + "," + this.getBaseDn() ).append( - ")" ).append( ")" ).toString(); + } + } + catch (UserNotFoundException e) + { + log.warn("Failed to look up user "+username+". Computing distinguished name manually",e); + } + catch (UserManagerException e) + { + log.warn("Failed to look up user "+username+". Computing distinguished name manually",e); + } + if(dn==null) + { + //failed to look up the user directly + StringBuilder builder = new StringBuilder(); + builder.append(this.userIdAttribute).append("=").append(username).append(",").append(getBaseDn()); + dn = builder.toString(); + } + String filter = new StringBuilder().append( "(&" ).append( "(objectClass=" + getLdapGroupClass() + ")" ) + .append("(").append(getLdapGroupMember()).append("=").append(dn).append(")" ).append( ")" ).toString(); log.debug( "filter: {}", filter ); @@ -351,14 +392,17 @@ public class DefaultLdapRoleMapper List<String> allMembers = new ArrayList<String>(); - Attribute uniqueMemberAttr = searchResult.getAttributes().get( "uniquemember" ); + Attribute uniqueMemberAttr = searchResult.getAttributes().get(getLdapGroupMember() ); if ( uniqueMemberAttr != null ) { NamingEnumeration<String> allMembersEnum = (NamingEnumeration<String>) uniqueMemberAttr.getAll(); while ( allMembersEnum.hasMore() ) { + String userName = allMembersEnum.next(); + //the original dn + allMembers.add( userName ); // uid=blabla we only want bla bla userName = StringUtils.substringAfter( userName, "=" ); userName = StringUtils.substringBefore( userName, "," ); @@ -375,6 +419,13 @@ public class DefaultLdapRoleMapper userGroups.add( groupName ); } + else if ( allMembers.contains( dn ) ) + { + String groupName = searchResult.getName(); + // cn=blabla we only want bla bla + groupName = StringUtils.substringAfter( groupName, "=" ); + userGroups.add( groupName ); + } } @@ -488,8 +539,7 @@ public class DefaultLdapRoleMapper attributes.put( "cn", groupName ); // attribute mandatory when created a group so add admin as default member - // TODO make this default configurable - BasicAttribute basicAttribute = new BasicAttribute( "uniquemember" ); + BasicAttribute basicAttribute = new BasicAttribute( getLdapGroupMember() ); basicAttribute.add( this.userIdAttribute + "=admin," + getBaseDn() ); attributes.put( basicAttribute ); @@ -546,10 +596,10 @@ public class DefaultLdapRoleMapper while ( namingEnumeration.hasMore() ) { SearchResult searchResult = namingEnumeration.next(); - Attribute attribute = searchResult.getAttributes().get( "uniquemember" ); + Attribute attribute = searchResult.getAttributes().get( getLdapGroupMember()); if ( attribute == null ) { - BasicAttribute basicAttribute = new BasicAttribute( "uniquemember" ); + BasicAttribute basicAttribute = new BasicAttribute( getLdapGroupMember() ); basicAttribute.add( this.userIdAttribute + "=" + username + "," + getBaseDn() ); context.modifyAttributes( "cn=" + groupName + "," + getGroupsDn(), new ModificationItem[]{ new ModificationItem( DirContext.ADD_ATTRIBUTE, basicAttribute ) } ); @@ -617,10 +667,10 @@ public class DefaultLdapRoleMapper while ( namingEnumeration.hasMore() ) { SearchResult searchResult = namingEnumeration.next(); - Attribute attribute = searchResult.getAttributes().get( "uniquemember" ); + Attribute attribute = searchResult.getAttributes().get( getLdapGroupMember() ); if ( attribute != null ) { - BasicAttribute basicAttribute = new BasicAttribute( "uniquemember" ); + BasicAttribute basicAttribute = new BasicAttribute( getLdapGroupMember() ); basicAttribute.add( this.userIdAttribute + "=" + username + "," + getGroupsDn() ); context.modifyAttributes( "cn=" + groupName + "," + getGroupsDn(), new ModificationItem[]{ new ModificationItem( DirContext.REMOVE_ATTRIBUTE, basicAttribute ) } ); @@ -751,6 +801,16 @@ public class DefaultLdapRoleMapper this.baseDn = baseDn; } + public String getLdapGroupMember() + { + return ldapGroupMember; + } + + public void setLdapGroupMember(String ldapGroupMember) + { + this.ldapGroupMember = ldapGroupMember; + } + //------------------- // utils methods //------------------- diff --git a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/user/LdapUserMapper.java b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/user/LdapUserMapper.java index b615b0c37..1a94ae37a 100644 --- a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/user/LdapUserMapper.java +++ b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/user/LdapUserMapper.java @@ -64,6 +64,11 @@ public class LdapUserMapper /** * */ + String distinguishedNameAttribute = "distinguishedName"; + + /** + * + */ String userBaseDn; /** @@ -142,9 +147,19 @@ public class LdapUserMapper return passwordAttribute; } + public String getDistinguishedNameAttribute() + { + return distinguishedNameAttribute; + } + + public void setDistinguishedNameAttribute(String distinguishedNameAttribute) + { + this.distinguishedNameAttribute = distinguishedNameAttribute; + } + public String[] getUserAttributeNames() { - return new String[]{ emailAttribute, fullNameAttribute, passwordAttribute, userIdAttribute }; + return new String[]{ emailAttribute, fullNameAttribute, passwordAttribute, userIdAttribute, distinguishedNameAttribute }; } public int getMaxResultCount() @@ -303,7 +318,7 @@ public class LdapUserMapper public String[] getReturningAttributes() { return new String[]{ getUserIdAttribute(), getEmailAttribute(), getFullNameAttribute(), - getPasswordAttribute() }; + getPasswordAttribute(), getDistinguishedNameAttribute() }; } public UserConfiguration getUserConf() diff --git a/redback-common/redback-common-ldap/src/test/java/org/apache/archiva/redback/common/ldap/user/MockUserManager.java b/redback-common/redback-common-ldap/src/test/java/org/apache/archiva/redback/common/ldap/user/MockUserManager.java new file mode 100644 index 000000000..b2dd32e93 --- /dev/null +++ b/redback-common/redback-common-ldap/src/test/java/org/apache/archiva/redback/common/ldap/user/MockUserManager.java @@ -0,0 +1,178 @@ +package org.apache.archiva.redback.common.ldap.user; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.archiva.redback.users.User; +import org.apache.archiva.redback.users.UserManager; +import org.apache.archiva.redback.users.UserManagerException; +import org.apache.archiva.redback.users.UserManagerListener; +import org.apache.archiva.redback.users.UserNotFoundException; +import org.apache.archiva.redback.users.UserQuery; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author Olivier Lamy + */ +@Service( "userManager#mock" ) +public class MockUserManager + implements UserManager +{ + public boolean isReadOnly() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public String getId() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public void addUserManagerListener( UserManagerListener listener ) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void removeUserManagerListener( UserManagerListener listener ) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public User createUser( String username, String fullName, String emailAddress ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public User createGuestUser() + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public UserQuery createUserQuery() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> getUsers() + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> getUsers( boolean orderAscending ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public User addUser( User user ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public User updateUser( User user ) + throws UserNotFoundException, UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public User findUser( String username ) + throws UserNotFoundException, UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public User getGuestUser() + throws UserNotFoundException, UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> findUsersByUsernameKey( String usernameKey, boolean orderAscending ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> findUsersByFullNameKey( String fullNameKey, boolean orderAscending ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> findUsersByEmailKey( String emailKey, boolean orderAscending ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public List<User> findUsersByQuery( UserQuery query ) + throws UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean userExists( String principal ) + throws UserManagerException + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public void deleteUser( String username ) + throws UserNotFoundException, UserManagerException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void addUserUnchecked( User user ) + throws UserManagerException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void eraseDatabase() + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public User updateUser( User user, boolean passwordChangeRequired ) + throws UserNotFoundException, UserManagerException + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public void initialize() + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isFinalImplementation() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public String getDescriptionKey() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/redback-common/redback-common-ldap/src/test/resources/spring-context-role-mapper.xml b/redback-common/redback-common-ldap/src/test/resources/spring-context-role-mapper.xml index ad2dc1b9f..f8cba356a 100755 --- a/redback-common/redback-common-ldap/src/test/resources/spring-context-role-mapper.xml +++ b/redback-common/redback-common-ldap/src/test/resources/spring-context-role-mapper.xml @@ -29,6 +29,7 @@ <context:property-placeholder system-properties-mode="OVERRIDE"/> <alias name="userConfiguration#redback" alias="userConfiguration#default"/> + <alias name="userManager#mock" alias="userManager#default"/> <bean name="commons-configuration" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry" init-method="initialize"> diff --git a/redback-configuration/src/main/java/org/apache/archiva/redback/configuration/UserConfigurationKeys.java b/redback-configuration/src/main/java/org/apache/archiva/redback/configuration/UserConfigurationKeys.java index ade7bee3b..bd365923f 100644 --- a/redback-configuration/src/main/java/org/apache/archiva/redback/configuration/UserConfigurationKeys.java +++ b/redback-configuration/src/main/java/org/apache/archiva/redback/configuration/UserConfigurationKeys.java @@ -82,6 +82,8 @@ public interface UserConfigurationKeys String LDAP_GROUPS_BASEDN = "ldap.config.groups.base.dn"; + String LDAP_GROUPS_MEMBER = "ldap.config.groups.member"; + String LDAP_GROUPS_ROLE_START_KEY = "ldap.config.groups.role."; String LDAP_GROUPS_USE_ROLENAME = "ldap.config.groups.use.rolename"; diff --git a/redback-system/src/test/java/org/apache/archiva/redback/system/MockUserManager.java b/redback-system/src/test/java/org/apache/archiva/redback/system/MockUserManager.java index c51373dc8..b49dd5b0c 100644 --- a/redback-system/src/test/java/org/apache/archiva/redback/system/MockUserManager.java +++ b/redback-system/src/test/java/org/apache/archiva/redback/system/MockUserManager.java @@ -30,7 +30,8 @@ import java.util.List; /** * @author Olivier Lamy */ -public class MockUserManager implements UserManager +public class MockUserManager + implements UserManager { public boolean isReadOnly() { |