mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	added group and domain params to importLdapUsers api call
Signed-off-by: Ian Duffy <ian@ianduffy.ie>
This commit is contained in:
		
							parent
							
								
									856703cc1c
								
							
						
					
					
						commit
						b436a82392
					
				| @ -26,6 +26,7 @@ import org.apache.cloudstack.api.response.ListResponse; | |||||||
| import org.apache.cloudstack.ldap.LdapManager; | import org.apache.cloudstack.ldap.LdapManager; | ||||||
| import org.apache.cloudstack.ldap.LdapUser; | import org.apache.cloudstack.ldap.LdapUser; | ||||||
| import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException; | import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException; | ||||||
|  | import org.apache.commons.lang.StringUtils; | ||||||
| import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | ||||||
| import org.bouncycastle.util.encoders.Base64; | import org.bouncycastle.util.encoders.Base64; | ||||||
| 
 | 
 | ||||||
| @ -55,6 +56,15 @@ public class LdapImportUsersCmd extends BaseListCmd { | |||||||
|     @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters") |     @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters") | ||||||
|     private Map<String, String> details; |     private Map<String, String> details; | ||||||
| 
 | 
 | ||||||
|  |     @Parameter(name = ApiConstants.DOMAIN, type = CommandType.STRING, | ||||||
|  | 	       description = "Specifies the domain to which the ldap users are to be imported. If no domain is specified, a domain will created using group parameter. If the " + | ||||||
|  | 		   "group is also not specified, a domain name based on the OU information will be created. If no OU hierarchy exists, will be defaulted to ROOT domain") | ||||||
|  |     private String domainName; | ||||||
|  | 
 | ||||||
|  |     @Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, | ||||||
|  | 	       description = "Specifies the group name from which the ldap users are to be imported. If no group is specified, all the users will be imported.") | ||||||
|  |     private String groupName; | ||||||
|  | 
 | ||||||
|     @Inject |     @Inject | ||||||
|     private LdapManager _ldapManager; |     private LdapManager _ldapManager; | ||||||
| 
 | 
 | ||||||
| @ -75,13 +85,14 @@ public class LdapImportUsersCmd extends BaseListCmd { | |||||||
| 	List<LdapUserResponse> ldapResponses = null; | 	List<LdapUserResponse> ldapResponses = null; | ||||||
| 	final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>(); | 	final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>(); | ||||||
| 	try { | 	try { | ||||||
| 	    final List<LdapUser> users = _ldapManager.getUsers(); | 	List<LdapUser> users; | ||||||
| 	    for (LdapUser user : users) { | 	if(StringUtils.isNotBlank(groupName)) { | ||||||
| 		Domain domain = _domainService.getDomainByName(user.getDomain(), Domain.ROOT_DOMAIN); | 	    users = _ldapManager.getUsersInGroup(groupName); | ||||||
| 
 | 	} else { | ||||||
| 		if (domain == null) { | 		users = _ldapManager.getUsers(); | ||||||
| 		    domain = _domainService.createDomain(user.getDomain(), Domain.ROOT_DOMAIN, user.getDomain(), UUID.randomUUID().toString()); |  | ||||||
| 	} | 	} | ||||||
|  | 	    for (LdapUser user : users) { | ||||||
|  | 	    Domain domain = getDomain(user); | ||||||
| 		    _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, user.getUsername(), | 		    _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, user.getUsername(), | ||||||
| 						  accountType, domain.getId(), domain.getNetworkDomain(), details, UUID.randomUUID().toString(), UUID.randomUUID().toString()); | 						  accountType, domain.getId(), domain.getNetworkDomain(), details, UUID.randomUUID().toString(), UUID.randomUUID().toString()); | ||||||
| 	    } | 	    } | ||||||
| @ -95,6 +106,33 @@ public class LdapImportUsersCmd extends BaseListCmd { | |||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private Domain getDomain(LdapUser user) { | ||||||
|  | 	String csDomainName = null; | ||||||
|  | 	if (StringUtils.isNotBlank(domainName)) { | ||||||
|  | 	    csDomainName = domainName; | ||||||
|  | 	} else { | ||||||
|  | 	    if (StringUtils.isNotBlank(groupName)) { | ||||||
|  | 		csDomainName = groupName; | ||||||
|  | 	    } else if (StringUtils.isNotBlank(user.getDomain())) { | ||||||
|  | 		csDomainName = user.getDomain(); | ||||||
|  | 	    } | ||||||
|  | 	    //removing all the special characters and trimming it length 190 to make the domain valid. | ||||||
|  | 	    csDomainName = StringUtils.substring(csDomainName.replaceAll("\\W",""),0,190); | ||||||
|  | 	} | ||||||
|  | 	Domain domain; | ||||||
|  | 	if (StringUtils.isNotBlank(csDomainName)) { | ||||||
|  | 	    domain = _domainService.getDomainByName(csDomainName, Domain.ROOT_DOMAIN); | ||||||
|  | 
 | ||||||
|  | 	    if (domain == null) { | ||||||
|  | 		domain = _domainService.createDomain(csDomainName, Domain.ROOT_DOMAIN, csDomainName, UUID.randomUUID().toString()); | ||||||
|  | 	    } | ||||||
|  | 	} else { | ||||||
|  | 	    domain = _domainService.getDomain(Domain.ROOT_DOMAIN); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return domain; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) { |     private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) { | ||||||
| 	final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>(); | 	final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>(); | ||||||
| 	for (final LdapUser user : users) { | 	for (final LdapUser user : users) { | ||||||
|  | |||||||
| @ -143,6 +143,16 @@ public class LdapConfiguration { | |||||||
| 		return userObject == null ? "inetOrgPerson" : userObject; | 		return userObject == null ? "inetOrgPerson" : userObject; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |     public String getGroupObject() { | ||||||
|  | 	final String groupObject = _configDao.getValue("ldap.group.object"); | ||||||
|  | 	return groupObject == null ? "groupOfUniqueNames" : groupObject; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getGroupUniqueMemeberAttribute() { | ||||||
|  | 	final String uniqueMemberAttribute = _configDao.getValue("ldap.group.user.uniquemember"); | ||||||
|  | 	return uniqueMemberAttribute == null ? "uniquemember" : uniqueMemberAttribute; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public String getCommonNameAttribute() { |     public String getCommonNameAttribute() { | ||||||
| 	return "cn"; | 	return "cn"; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -47,6 +47,8 @@ public interface LdapManager extends PluggableService { | |||||||
| 
 | 
 | ||||||
| 	List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException; | 	List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException; | ||||||
| 
 | 
 | ||||||
|  |     List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException; | ||||||
|  | 
 | ||||||
| 	boolean isLdapEnabled(); | 	boolean isLdapEnabled(); | ||||||
| 
 | 
 | ||||||
| 	Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations( | 	Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations( | ||||||
|  | |||||||
| @ -194,6 +194,19 @@ public class LdapManagerImpl implements LdapManager, LdapValidator { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException { | ||||||
|  | 	DirContext context = null; | ||||||
|  | 	try { | ||||||
|  | 	    context = _ldapContextFactory.createBindContext(); | ||||||
|  | 	    return _ldapUserManager.getUsersInGroup(groupName, context); | ||||||
|  | 	} catch (final NamingException e) { | ||||||
|  | 	    throw new NoLdapUserMatchingQueryException("groupName=" + groupName); | ||||||
|  | 	} finally { | ||||||
|  | 	    closeContext(context); | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
| 	public boolean isLdapEnabled() { | 	public boolean isLdapEnabled() { | ||||||
| 		return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0; | 		return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0; | ||||||
|  | |||||||
| @ -23,10 +23,7 @@ import java.util.List; | |||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import javax.naming.NamingEnumeration; | import javax.naming.NamingEnumeration; | ||||||
| import javax.naming.NamingException; | import javax.naming.NamingException; | ||||||
| import javax.naming.directory.Attributes; | import javax.naming.directory.*; | ||||||
| import javax.naming.directory.DirContext; |  | ||||||
| import javax.naming.directory.SearchControls; |  | ||||||
| import javax.naming.directory.SearchResult; |  | ||||||
| 
 | 
 | ||||||
| public class LdapUserManager { | public class LdapUserManager { | ||||||
| 
 | 
 | ||||||
| @ -86,6 +83,28 @@ public class LdapUserManager { | |||||||
| 	return result.toString(); | 	return result.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private String generateGroupSearchFilter(final String groupName) { | ||||||
|  | 	final StringBuilder groupObjectFilter = new StringBuilder(); | ||||||
|  | 	groupObjectFilter.append("(objectClass="); | ||||||
|  | 	groupObjectFilter.append(_ldapConfiguration.getGroupObject()); | ||||||
|  | 	groupObjectFilter.append(")"); | ||||||
|  | 
 | ||||||
|  | 	final StringBuilder groupNameFilter = new StringBuilder(); | ||||||
|  | 	groupNameFilter.append("("); | ||||||
|  | 	groupNameFilter.append(_ldapConfiguration.getCommonNameAttribute()); | ||||||
|  | 	groupNameFilter.append("="); | ||||||
|  | 	groupNameFilter.append((groupName == null ? "*" : groupName)); | ||||||
|  | 	groupNameFilter.append(")"); | ||||||
|  | 
 | ||||||
|  | 	final StringBuilder result = new StringBuilder(); | ||||||
|  | 	result.append("(&"); | ||||||
|  | 	result.append(groupObjectFilter); | ||||||
|  | 	result.append(groupNameFilter); | ||||||
|  | 	result.append(")"); | ||||||
|  | 
 | ||||||
|  | 	return result.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public LdapUser getUser(final String username, final DirContext context) throws NamingException { |     public LdapUser getUser(final String username, final DirContext context) throws NamingException { | ||||||
| 	final NamingEnumeration<SearchResult> result = searchUsers(username, context); | 	final NamingEnumeration<SearchResult> result = searchUsers(username, context); | ||||||
| 	if (result.hasMoreElements()) { | 	if (result.hasMoreElements()) { | ||||||
| @ -114,6 +133,44 @@ public class LdapUserManager { | |||||||
| 	return users; | 	return users; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public List<LdapUser> getUsersInGroup(String groupName, DirContext context) throws NamingException { | ||||||
|  | 	String attributeName = _ldapConfiguration.getGroupUniqueMemeberAttribute(); | ||||||
|  | 	final SearchControls controls = new SearchControls(); | ||||||
|  | 	controls.setSearchScope(_ldapConfiguration.getScope()); | ||||||
|  | 	controls.setReturningAttributes(new String[]{attributeName}); | ||||||
|  | 
 | ||||||
|  | 	NamingEnumeration<SearchResult> result = context.search(_ldapConfiguration.getBaseDn(), generateGroupSearchFilter(groupName), controls); | ||||||
|  | 
 | ||||||
|  | 	final List<LdapUser> users = new ArrayList<LdapUser>(); | ||||||
|  | 	//Expecting only one result which has all the users | ||||||
|  | 	if (result.hasMoreElements()) { | ||||||
|  | 	    Attribute attribute = result.nextElement().getAttributes().get(attributeName); | ||||||
|  | 	    NamingEnumeration<?> values = attribute.getAll(); | ||||||
|  | 
 | ||||||
|  | 	    while (values.hasMoreElements()) { | ||||||
|  | 		String userdn = String.valueOf(values.nextElement()); | ||||||
|  | 		users.add(getUserForDn(userdn,context)); | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Collections.sort(users); | ||||||
|  | 
 | ||||||
|  | 	return users; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private LdapUser getUserForDn(String userdn, DirContext context) throws NamingException { | ||||||
|  | 	final SearchControls controls = new SearchControls(); | ||||||
|  | 	controls.setSearchScope(_ldapConfiguration.getScope()); | ||||||
|  | 	controls.setReturningAttributes(_ldapConfiguration.getReturnAttributes()); | ||||||
|  | 
 | ||||||
|  | 	NamingEnumeration<SearchResult> result = context.search(userdn, "(objectClass="+_ldapConfiguration.getUserObject()+")", controls); | ||||||
|  | 	if (result.hasMoreElements()) { | ||||||
|  | 	    return createUser(result.nextElement()); | ||||||
|  | 	} else { | ||||||
|  | 	    throw new NamingException("No user found for dn " + userdn); | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public NamingEnumeration<SearchResult> searchUsers(final DirContext context) throws NamingException { |     public NamingEnumeration<SearchResult> searchUsers(final DirContext context) throws NamingException { | ||||||
| 	return searchUsers(null, context); | 	return searchUsers(null, context); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -220,4 +220,37 @@ class LdapConfigurationSpec extends spock.lang.Specification { | |||||||
| 		then: "The response should be true" | 		then: "The response should be true" | ||||||
| 		result == true | 		result == true | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  |     def "Test getgroupobject"() { | ||||||
|  | 	given: "We have configdao for ldap group object" | ||||||
|  | 	def configDao = Mock(ConfigurationDao) | ||||||
|  | 	configDao.getValue("ldap.group.object") >> groupObject | ||||||
|  | 
 | ||||||
|  | 	def ldapManger = Mock(LdapManager) | ||||||
|  | 	LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManger) | ||||||
|  | 	def expectedResult = groupObject == null ? "groupOfUniqueNames" : groupObject | ||||||
|  | 
 | ||||||
|  | 	def result = ldapConfiguration.getGroupObject() | ||||||
|  | 	expect: | ||||||
|  | 	result == expectedResult | ||||||
|  | 	where: | ||||||
|  | 	groupObject << [null, "", "groupOfUniqueNames"] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "Test getGroupUniqueMemeberAttribute"() { | ||||||
|  | 	given: "We have configdao for ldap group object" | ||||||
|  | 	def configDao = Mock(ConfigurationDao) | ||||||
|  | 	configDao.getValue("ldap.group.user.uniquemember") >> groupObject | ||||||
|  | 
 | ||||||
|  | 	def ldapManger = Mock(LdapManager) | ||||||
|  | 	LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManger) | ||||||
|  | 	def expectedResult = groupObject == null ? "uniquemember" : groupObject | ||||||
|  | 
 | ||||||
|  | 	def result = ldapConfiguration.getGroupUniqueMemeberAttribute() | ||||||
|  | 	expect: | ||||||
|  | 	result == expectedResult | ||||||
|  | 	where: | ||||||
|  | 	groupObject << [null, "", "uniquemember"] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,7 +52,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification { | |||||||
| 	def "Test failed creation due to a null response from cloudstack account creater"() { | 	def "Test failed creation due to a null response from cloudstack account creater"() { | ||||||
| 		given: "We have an LdapManager, AccountService and LdapCreateAccountCmd" | 		given: "We have an LdapManager, AccountService and LdapCreateAccountCmd" | ||||||
| 		LdapManager ldapManager = Mock(LdapManager) | 		LdapManager ldapManager = Mock(LdapManager) | ||||||
| 		ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org") | 		ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
| 		AccountService accountService = Mock(AccountService) | 		AccountService accountService = Mock(AccountService) | ||||||
| 		def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService]) | 		def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService]) | ||||||
| 		ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext) | 		ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext) | ||||||
| @ -104,7 +104,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification { | |||||||
| 		AccountService accountService = Mock(AccountService) | 		AccountService accountService = Mock(AccountService) | ||||||
| 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService); | 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService); | ||||||
| 		when: "a user with an username, email, firstname and lastname is validated" | 		when: "a user with an username, email, firstname and lastname is validated" | ||||||
| 		def result = ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname","lastname","principal")) | 		def result = ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname","lastname","principal","domain")) | ||||||
| 		then: "the result is true" | 		then: "the result is true" | ||||||
| 		result == true | 		result == true | ||||||
|    } |    } | ||||||
| @ -115,7 +115,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification { | |||||||
| 		AccountService accountService = Mock(AccountService) | 		AccountService accountService = Mock(AccountService) | ||||||
| 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService) | 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService) | ||||||
| 		when: "A user with no email address attempts to validate" | 		when: "A user with no email address attempts to validate" | ||||||
| 		ldapCreateAccountCmd.validateUser(new LdapUser("username",null,"firstname","lastname","principal")) | 		ldapCreateAccountCmd.validateUser(new LdapUser("username",null,"firstname","lastname","principal","domain")) | ||||||
| 		then: "An exception is thrown" | 		then: "An exception is thrown" | ||||||
| 		thrown Exception | 		thrown Exception | ||||||
|    } |    } | ||||||
| @ -137,7 +137,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification { | |||||||
| 		AccountService accountService = Mock(AccountService) | 		AccountService accountService = Mock(AccountService) | ||||||
| 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService) | 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService) | ||||||
| 		when: "A user with no lastname attempts to validate" | 		when: "A user with no lastname attempts to validate" | ||||||
| 		ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname",null,"principal")) | 		ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname",null,"principal","domain")) | ||||||
| 		then: "An exception is thown" | 		then: "An exception is thown" | ||||||
| 		thrown Exception | 		thrown Exception | ||||||
|    } |    } | ||||||
|  | |||||||
| @ -34,7 +34,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification { | |||||||
| 	given: "We have an LdapManager, DomainService and a LdapImportUsersCmd" | 	given: "We have an LdapManager, DomainService and a LdapImportUsersCmd" | ||||||
| 	def ldapManager = Mock(LdapManager) | 	def ldapManager = Mock(LdapManager) | ||||||
| 	def domainService = Mock(DomainService) | 	def domainService = Mock(DomainService) | ||||||
| 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService) |     def accountService = Mock(AccountService) | ||||||
|  | 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) | ||||||
| 	when: "Get command name is called" | 	when: "Get command name is called" | ||||||
| 	String commandName = ldapImportUsersCmd.getCommandName() | 	String commandName = ldapImportUsersCmd.getCommandName() | ||||||
| 	then: "ldapuserresponse is returned" | 	then: "ldapuserresponse is returned" | ||||||
| @ -42,7 +43,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     def "Test successful response from execute"() { |     def "Test successful response from execute"() { | ||||||
| 	given: "We have an LdapManager, DomainService, one user and a LdapImportUsersCmd" | 	given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" | ||||||
| 	def ldapManager = Mock(LdapManager) | 	def ldapManager = Mock(LdapManager) | ||||||
| 	def domainService = Mock(DomainService) | 	def domainService = Mock(DomainService) | ||||||
| 	def accountService = Mock(AccountService) | 	def accountService = Mock(AccountService) | ||||||
| @ -68,4 +69,123 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification { | |||||||
| 	then: "a list of size 2 is returned" | 	then: "a list of size 2 is returned" | ||||||
| 	ldapImportUsersCmd.responseObject.getResponses().size() == 2 | 	ldapImportUsersCmd.responseObject.getResponses().size() == 2 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     def "Test successful response from execute with group specified"() { | ||||||
|  | 	given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" | ||||||
|  | 	def ldapManager = Mock(LdapManager) | ||||||
|  | 	def domainService = Mock(DomainService) | ||||||
|  | 	def accountService = Mock(AccountService) | ||||||
|  | 
 | ||||||
|  | 	List<LdapUser> users = new ArrayList() | ||||||
|  | 	users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	ldapManager.getUsersInGroup("TestGroup") >> users | ||||||
|  | 	LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	ldapManager.createLdapUserResponse(_) >>>[response1, response2] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	Domain domain = new DomainVO("TestGroup", 1L, 1L, "TestGroup", UUID.randomUUID().toString()) | ||||||
|  | 	domainService.getDomainByName("TestGroup", 1L) >>> [null, domain] | ||||||
|  | 	1 * domainService.createDomain("TestGroup", 1L, "TestGroup", _) >> domain | ||||||
|  | 
 | ||||||
|  | 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) | ||||||
|  | 	ldapImportUsersCmd.accountType = 2; | ||||||
|  | 	ldapImportUsersCmd.groupName = "TestGroup"; | ||||||
|  | 
 | ||||||
|  | 	when: "LdapListUsersCmd is executed" | ||||||
|  | 	ldapImportUsersCmd.execute() | ||||||
|  | 	then: "a list of size 2 is returned" | ||||||
|  | 	ldapImportUsersCmd.responseObject.getResponses().size() == 2 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "Test successful response from execute with group and domain specified"() { | ||||||
|  | 	given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" | ||||||
|  | 	def ldapManager = Mock(LdapManager) | ||||||
|  | 	def domainService = Mock(DomainService) | ||||||
|  | 	def accountService = Mock(AccountService) | ||||||
|  | 
 | ||||||
|  | 	List<LdapUser> users = new ArrayList() | ||||||
|  | 	users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	ldapManager.getUsersInGroup("TestGroup") >> users | ||||||
|  | 	LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	ldapManager.createLdapUserResponse(_) >>>[response1, response2] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	Domain domain = new DomainVO("TestDomain", 1L, 1L, "TestDomain", UUID.randomUUID().toString()) | ||||||
|  | 	domainService.getDomainByName("TestDomain", 1L) >>> [null, domain] | ||||||
|  | 	1 * domainService.createDomain("TestDomain", 1L, "TestDomain", _) >> domain | ||||||
|  | 
 | ||||||
|  | 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) | ||||||
|  | 	ldapImportUsersCmd.accountType = 2; | ||||||
|  | 	ldapImportUsersCmd.groupName = "TestGroup"; | ||||||
|  | 	ldapImportUsersCmd.domainName = "TestDomain"; | ||||||
|  | 
 | ||||||
|  | 	when: "LdapListUsersCmd is executed" | ||||||
|  | 	ldapImportUsersCmd.execute() | ||||||
|  | 	then: "a list of size 2 is returned" | ||||||
|  | 	ldapImportUsersCmd.responseObject.getResponses().size() == 2 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "Test successful response from execute with domain specified"() { | ||||||
|  | 	given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" | ||||||
|  | 	def ldapManager = Mock(LdapManager) | ||||||
|  | 	def domainService = Mock(DomainService) | ||||||
|  | 	def accountService = Mock(AccountService) | ||||||
|  | 
 | ||||||
|  | 	List<LdapUser> users = new ArrayList() | ||||||
|  | 	users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	ldapManager.getUsers() >> users | ||||||
|  | 	LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	ldapManager.createLdapUserResponse(_) >>>[response1, response2] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	Domain domain = new DomainVO("TestDomain", 1L, 1L, "TestDomain", UUID.randomUUID().toString()) | ||||||
|  | 	domainService.getDomainByName("TestDomain", 1L) >>> [null, domain] | ||||||
|  | 	1 * domainService.createDomain("TestDomain", 1L, "TestDomain", _) >> domain | ||||||
|  | 
 | ||||||
|  | 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) | ||||||
|  | 	ldapImportUsersCmd.accountType = 2; | ||||||
|  | 	ldapImportUsersCmd.domainName = "TestDomain"; | ||||||
|  | 
 | ||||||
|  | 	when: "LdapListUsersCmd is executed" | ||||||
|  | 	ldapImportUsersCmd.execute() | ||||||
|  | 	then: "a list of size 2 is returned" | ||||||
|  | 	ldapImportUsersCmd.responseObject.getResponses().size() == 2 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "Test getDomain with no domain or group name specified specified"() { | ||||||
|  | 	given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd" | ||||||
|  | 	def ldapManager = Mock(LdapManager) | ||||||
|  | 	def domainService = Mock(DomainService) | ||||||
|  | 	def accountService = Mock(AccountService) | ||||||
|  | 	def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) | ||||||
|  | 	ldapImportUsersCmd.domainName = varDomainName | ||||||
|  | 	ldapImportUsersCmd.groupName = varGroupName | ||||||
|  | 
 | ||||||
|  | 	def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering") | ||||||
|  | 	def ldapUser2 = new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering"); | ||||||
|  | 
 | ||||||
|  | 	Domain domain = new DomainVO(expectedDomainName, 1L, 1L, expectedDomainName, UUID.randomUUID().toString()) | ||||||
|  | 	2 * domainService.getDomainByName(expectedDomainName, 1L) >>> [null, domain] | ||||||
|  | 	1 * domainService.createDomain(expectedDomainName, 1L, expectedDomainName, _) >> domain | ||||||
|  | 
 | ||||||
|  | 	def result1 = ldapImportUsersCmd.getDomain(ldapUser1) | ||||||
|  | 	def result2 = ldapImportUsersCmd.getDomain(ldapUser2) | ||||||
|  | 	expect: "engineering domain is returned" | ||||||
|  | 	result1 == domain | ||||||
|  | 	result2 == domain | ||||||
|  | 	where: "The domain and group are set to the following values" | ||||||
|  | 	varDomainName | varGroupName | expectedDomainName | ||||||
|  | 	null | null | "engineering" | ||||||
|  | 	"TestDomain" | null | "TestDomain" | ||||||
|  | 	"TestDomain" | "TestGroup" | "TestDomain" | ||||||
|  | 	null | "TestGroup" | "TestGroup" | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -356,4 +356,20 @@ class LdapManagerImplSpec extends spock.lang.Specification { | |||||||
| 		then: "true is returned because a configuration was found" | 		then: "true is returned because a configuration was found" | ||||||
| 		result == true; | 		result == true; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  |     def "Test success getUsersInGroup"() { | ||||||
|  | 	given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager" | ||||||
|  | 	def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl) | ||||||
|  | 	def ldapContextFactory = Mock(LdapContextFactory) | ||||||
|  | 	def ldapUserManager = Mock(LdapUserManager) | ||||||
|  | 	ldapContextFactory.createBindContext() >> null | ||||||
|  | 	List<LdapUser> users = new ArrayList<>(); | ||||||
|  | 	users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering")) | ||||||
|  | 	ldapUserManager.getUsersInGroup("engineering", _) >> users; | ||||||
|  | 	def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager) | ||||||
|  | 	when: "We search for a group of users" | ||||||
|  | 	def result = ldapManager.getUsersInGroup("engineering") | ||||||
|  | 	then: "A list greater of size one is returned" | ||||||
|  | 	result.size() == 1; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -21,8 +21,10 @@ import org.apache.cloudstack.ldap.LdapUserManager | |||||||
| import spock.lang.Shared | import spock.lang.Shared | ||||||
| 
 | 
 | ||||||
| import javax.naming.NamingException | import javax.naming.NamingException | ||||||
|  | import javax.naming.NamingEnumeration | ||||||
| import javax.naming.directory.Attribute | import javax.naming.directory.Attribute | ||||||
| import javax.naming.directory.Attributes | import javax.naming.directory.Attributes | ||||||
|  | import javax.naming.directory.DirContext | ||||||
| import javax.naming.directory.SearchControls | import javax.naming.directory.SearchControls | ||||||
| import javax.naming.directory.SearchResult | import javax.naming.directory.SearchResult | ||||||
| import javax.naming.ldap.LdapContext | import javax.naming.ldap.LdapContext | ||||||
| @ -47,6 +49,38 @@ class LdapUserManagerSpec extends spock.lang.Specification { | |||||||
|     @Shared |     @Shared | ||||||
|     private def principal |     private def principal | ||||||
| 
 | 
 | ||||||
|  |     private def createGroupSearchContext() { | ||||||
|  | 
 | ||||||
|  | 	def umSearchResult = Mock(SearchResult) | ||||||
|  | 	umSearchResult.getName() >> principal; | ||||||
|  | 	umSearchResult.getAttributes() >> principal | ||||||
|  | 
 | ||||||
|  | 	def uniqueMembers = new BasicNamingEnumerationImpl() | ||||||
|  | 	uniqueMembers.add(umSearchResult); | ||||||
|  | 	def attributes = Mock(Attributes) | ||||||
|  | 	def uniqueMemberAttribute = Mock(Attribute) | ||||||
|  | 	uniqueMemberAttribute.getId() >> "uniquemember" | ||||||
|  | 	uniqueMemberAttribute.getAll() >> uniqueMembers | ||||||
|  | 	attributes.get("uniquemember") >> uniqueMemberAttribute | ||||||
|  | 
 | ||||||
|  | 	def groupSearchResult = Mock(SearchResult) | ||||||
|  | 	groupSearchResult.getName() >> principal; | ||||||
|  | 	groupSearchResult.getAttributes() >> attributes | ||||||
|  | 
 | ||||||
|  | 	def searchGroupResults = new BasicNamingEnumerationImpl() | ||||||
|  | 	searchGroupResults.add(groupSearchResult); | ||||||
|  | 
 | ||||||
|  | 	attributes = createUserAttributes(username, email, firstname, lastname) | ||||||
|  | 	SearchResult userSearchResult = createSearchResult(attributes) | ||||||
|  | 	def searchUsersResults = new BasicNamingEnumerationImpl() | ||||||
|  | 	searchUsersResults.add(userSearchResult); | ||||||
|  | 
 | ||||||
|  | 	def context = Mock(LdapContext) | ||||||
|  | 	context.search(_, _, _) >>> [searchGroupResults, searchUsersResults]; | ||||||
|  | 
 | ||||||
|  | 	return context | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private def createContext() { |     private def createContext() { | ||||||
| 		Attributes attributes = createUserAttributes(username, email, firstname, lastname) | 		Attributes attributes = createUserAttributes(username, email, firstname, lastname) | ||||||
| 		SearchResult searchResults = createSearchResult(attributes) | 		SearchResult searchResults = createSearchResult(attributes) | ||||||
| @ -65,6 +99,7 @@ class LdapUserManagerSpec extends spock.lang.Specification { | |||||||
| 		search.getName() >> "cn=" + attributes.getAt("uid").get(); | 		search.getName() >> "cn=" + attributes.getAt("uid").get(); | ||||||
| 
 | 
 | ||||||
| 		search.getAttributes() >> attributes | 		search.getAttributes() >> attributes | ||||||
|  | 	search.getNameInNamespace() >> principal | ||||||
| 
 | 
 | ||||||
| 		return search | 		return search | ||||||
|     } |     } | ||||||
| @ -105,6 +140,9 @@ class LdapUserManagerSpec extends spock.lang.Specification { | |||||||
|         ldapConfiguration.getFirstnameAttribute() >> "givenname" |         ldapConfiguration.getFirstnameAttribute() >> "givenname" | ||||||
|         ldapConfiguration.getLastnameAttribute() >> "sn" |         ldapConfiguration.getLastnameAttribute() >> "sn" | ||||||
|         ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org" |         ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org" | ||||||
|  | 	ldapConfiguration.getCommonNameAttribute() >> "cn" | ||||||
|  | 	ldapConfiguration.getGroupObject() >> "groupOfUniqueNames" | ||||||
|  | 	ldapConfiguration.getGroupUniqueMemeberAttribute() >> "uniquemember" | ||||||
| 
 | 
 | ||||||
|         username = "rmurphy" |         username = "rmurphy" | ||||||
|         email = "rmurphy@test.com" |         email = "rmurphy@test.com" | ||||||
| @ -203,4 +241,43 @@ class LdapUserManagerSpec extends spock.lang.Specification { | |||||||
| 		expect: "The result is not null" | 		expect: "The result is not null" | ||||||
| 		result != null | 		result != null | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     def "test successful generateGroupSearchFilter"() { | ||||||
|  | 	given: "ldap user manager and ldap config" | ||||||
|  | 	def ldapUserManager = new LdapUserManager(ldapConfiguration) | ||||||
|  | 	def groupName = varGroupName == null ? "*" : varGroupName | ||||||
|  | 	def expectedResult = "(&(objectClass=groupOfUniqueNames)(cn="+groupName+"))"; | ||||||
|  | 
 | ||||||
|  | 	def result = ldapUserManager.generateGroupSearchFilter(varGroupName) | ||||||
|  | 	expect: | ||||||
|  | 	result == expectedResult | ||||||
|  | 	where: "The group name passed is set to " | ||||||
|  | 	varGroupName << ["", null, "Murphy"] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "test successful getUsersInGroup"(){ | ||||||
|  | 	given: "ldap user manager and ldap config" | ||||||
|  | 	def ldapUserManager = new LdapUserManager(ldapConfiguration) | ||||||
|  | 
 | ||||||
|  | 	when: "A request for users is made" | ||||||
|  | 	def result = ldapUserManager.getUsersInGroup("engineering", createGroupSearchContext()) | ||||||
|  | 	then: "one user is returned" | ||||||
|  | 	result.size() == 1 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     def "test successful getUserForDn"(){ | ||||||
|  | 	given: "ldap user manager and ldap config" | ||||||
|  | 	def ldapUserManager = new LdapUserManager(ldapConfiguration) | ||||||
|  | 
 | ||||||
|  | 	when: "A request for users is made" | ||||||
|  | 	def result = ldapUserManager.getUserForDn("cn=Ryan Murphy,ou=engineering,dc=cloudstack,dc=org",createContext()) | ||||||
|  | 	then: "A list of users is returned" | ||||||
|  | 	result != 1 | ||||||
|  | 	result.username == username | ||||||
|  | 	result.email == email | ||||||
|  | 	result.firstname == firstname | ||||||
|  | 	result.lastname == lastname | ||||||
|  | 	result.principal == principal | ||||||
|  | 
 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -394,6 +394,9 @@ public enum Config { | |||||||
|     LdapSearchGroupPrinciple("Advanced", ManagementServer.class, String.class, "ldap.search.group.principle", null, "Sets the principle of the group that users must be a member of", null), |     LdapSearchGroupPrinciple("Advanced", ManagementServer.class, String.class, "ldap.search.group.principle", null, "Sets the principle of the group that users must be a member of", null), | ||||||
|     LdapTrustStore("Advanced", ManagementServer.class, String.class, "ldap.truststore", null, "Sets the path to the truststore to use for SSL", null), |     LdapTrustStore("Advanced", ManagementServer.class, String.class, "ldap.truststore", null, "Sets the path to the truststore to use for SSL", null), | ||||||
|     LdapTrustStorePassword("Advanced", ManagementServer.class, String.class, "ldap.truststore.password", null, "Sets the password for the truststore", null), |     LdapTrustStorePassword("Advanced", ManagementServer.class, String.class, "ldap.truststore.password", null, "Sets the password for the truststore", null), | ||||||
|  |     LdapGroupObject("Advanced", ManagementServer.class, String.class, "ldap.group.object", "groupOfUniqueNames", "Sets the object type of groups within LDAP", null), | ||||||
|  |     LdapGroupUniqueMemberAttribute("Advanced", ManagementServer.class, String.class, "ldap.group.user.uniquemember", "uniquemember", | ||||||
|  | 				   "Sets the attribute for uniquemembers within a group", null), | ||||||
| 
 | 
 | ||||||
| 	// VMSnapshots | 	// VMSnapshots | ||||||
|     VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), |     VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), | ||||||
|  | |||||||
| @ -483,3 +483,8 @@ ALTER TABLE `cloud`.`nic_details` CHANGE `display_detail` `display` tinyint(1) N | |||||||
| ALTER TABLE `cloud`.`user_vm_details` CHANGE `display_detail` `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ALTER TABLE `cloud`.`user_vm_details` CHANGE `display_detail` `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ||||||
| ALTER TABLE `cloud`.`service_offering_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ALTER TABLE `cloud`.`service_offering_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ||||||
| ALTER TABLE `cloud`.`storage_pool_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ALTER TABLE `cloud`.`storage_pool_details` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'True if the detail can be displayed to the end user'; | ||||||
|  | 
 | ||||||
|  | INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.group.object', 'groupOfUniqueNames', | ||||||
|  | 'Sets the object type of groups within LDAP','groupOfUniqueNames',NULL,NULL,0); | ||||||
|  | INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.group.user.uniquemember', 'uniquemember', | ||||||
|  | 'Sets the attribute for uniquemembers within a group','uniquemember',NULL,NULL,0); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user