cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From du...@apache.org
Subject git commit: updated refs/heads/master to b436a82
Date Thu, 31 Oct 2013 22:14:52 GMT
Updated Branches:
  refs/heads/master 856703cc1 -> b436a8239


added group and domain params to importLdapUsers api call

Signed-off-by: Ian Duffy <ian@ianduffy.ie>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b436a823
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b436a823
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b436a823

Branch: refs/heads/master
Commit: b436a82392111bd5052c6a1cfaa77174856d55f5
Parents: 856703c
Author: Rajani Karuturi <rajanikaruturi@gmail.com>
Authored: Thu Oct 31 18:44:01 2013 +0530
Committer: Ian Duffy <ian@ianduffy.ie>
Committed: Thu Oct 31 22:06:32 2013 +0000

----------------------------------------------------------------------
 .../api/command/LdapImportUsersCmd.java         |  52 ++++++--
 .../cloudstack/ldap/LdapConfiguration.java      |  10 ++
 .../org/apache/cloudstack/ldap/LdapManager.java |   2 +
 .../apache/cloudstack/ldap/LdapManagerImpl.java |  15 ++-
 .../apache/cloudstack/ldap/LdapUserManager.java |  65 +++++++++-
 .../ldap/LdapConfigurationSpec.groovy           |  33 +++++
 .../ldap/LdapCreateAccountCmdSpec.groovy        |   8 +-
 .../ldap/LdapImportUsersCmdSpec.groovy          | 124 ++++++++++++++++++-
 .../cloudstack/ldap/LdapManagerImplSpec.groovy  |  16 +++
 .../cloudstack/ldap/LdapUserManagerSpec.groovy  |  77 ++++++++++++
 server/src/com/cloud/configuration/Config.java  |   3 +
 setup/db/db/schema-421to430.sql                 |   5 +
 12 files changed, 392 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
index f872247..063db0e 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java
@@ -26,6 +26,7 @@ import org.apache.cloudstack.api.response.ListResponse;
 import org.apache.cloudstack.ldap.LdapManager;
 import org.apache.cloudstack.ldap.LdapUser;
 import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 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")
     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
     private LdapManager _ldapManager;
 
@@ -75,14 +85,15 @@ public class LdapImportUsersCmd extends BaseListCmd {
 	List<LdapUserResponse> ldapResponses = null;
 	final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
 	try {
-	    final List<LdapUser> users = _ldapManager.getUsers();
+	List<LdapUser> users;
+	if(StringUtils.isNotBlank(groupName)) {
+	    users = _ldapManager.getUsersInGroup(groupName);
+	} else {
+		users = _ldapManager.getUsers();
+	}
 	    for (LdapUser user : users) {
-		Domain domain = _domainService.getDomainByName(user.getDomain(), Domain.ROOT_DOMAIN);
-
-		if (domain == null) {
-		    domain = _domainService.createDomain(user.getDomain(), Domain.ROOT_DOMAIN, user.getDomain(),
UUID.randomUUID().toString());
-		}
-		_accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(),
user.getLastname(), user.getEmail(), timezone, user.getUsername(),
+	    Domain domain = getDomain(user);
+		    _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());
 	    }
 	    ldapResponses = createLdapUserResponse(users);
@@ -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)
{
 	final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>();
 	for (final LdapUser user : users) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
index a08dccb..7db55f7 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
@@ -143,6 +143,16 @@ public class LdapConfiguration {
 		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() {
 	return "cn";
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
index 683822d..2c99d08 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
@@ -47,6 +47,8 @@ public interface LdapManager extends PluggableService {
 
 	List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
 
+    List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException;
+
 	boolean isLdapEnabled();
 
 	Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
index 90a79b3..891d625 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
@@ -194,7 +194,20 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
 		}
 	}
 
-	@Override
+    @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
 	public boolean isLdapEnabled() {
 		return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0;
 	}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
index 47697c9..59a41de 100644
--- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
@@ -23,10 +23,7 @@ import java.util.List;
 import javax.inject.Inject;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
+import javax.naming.directory.*;
 
 public class LdapUserManager {
 
@@ -86,6 +83,28 @@ public class LdapUserManager {
 	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
{
 	final NamingEnumeration<SearchResult> result = searchUsers(username, context);
 	if (result.hasMoreElements()) {
@@ -114,6 +133,44 @@ public class LdapUserManager {
 	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 {
 	return searchUsers(null, context);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
index 66b4673..1017a0f 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
@@ -220,4 +220,37 @@ class LdapConfigurationSpec extends spock.lang.Specification {
 		then: "The response should be 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"]
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
index cc849de..b316a80 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapCreateAccountCmdSpec.groovy
@@ -52,7 +52,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
 	def "Test failed creation due to a null response from cloudstack account creater"() {
 		given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
 		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)
 		def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
 		ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
@@ -104,7 +104,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
 		AccountService accountService = Mock(AccountService)
 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
 		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"
 		result == true
    }
@@ -115,7 +115,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
 		AccountService accountService = Mock(AccountService)
 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
 		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"
 		thrown Exception
    }
@@ -137,7 +137,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
 		AccountService accountService = Mock(AccountService)
 		def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
 		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"
 		thrown Exception
    }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
index d04b094..0455640 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy
@@ -34,7 +34,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
 	given: "We have an LdapManager, DomainService and a LdapImportUsersCmd"
 	def ldapManager = Mock(LdapManager)
 	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"
 	String commandName = ldapImportUsersCmd.getCommandName()
 	then: "ldapuserresponse is returned"
@@ -42,7 +43,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
     }
 
     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 domainService = Mock(DomainService)
 	def accountService = Mock(AccountService)
@@ -68,4 +69,123 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
 	then: "a list of size 2 is returned"
 	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"
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
index 321e1af..42988e0 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
@@ -356,4 +356,20 @@ class LdapManagerImplSpec extends spock.lang.Specification {
 		then: "true is returned because a configuration was found"
 		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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
index 339923e..fa735d3 100644
--- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
@@ -21,8 +21,10 @@ import org.apache.cloudstack.ldap.LdapUserManager
 import spock.lang.Shared
 
 import javax.naming.NamingException
+import javax.naming.NamingEnumeration
 import javax.naming.directory.Attribute
 import javax.naming.directory.Attributes
+import javax.naming.directory.DirContext
 import javax.naming.directory.SearchControls
 import javax.naming.directory.SearchResult
 import javax.naming.ldap.LdapContext
@@ -47,6 +49,38 @@ class LdapUserManagerSpec extends spock.lang.Specification {
     @Shared
     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() {
 		Attributes attributes = createUserAttributes(username, email, firstname, lastname)
 		SearchResult searchResults = createSearchResult(attributes)
@@ -65,6 +99,7 @@ class LdapUserManagerSpec extends spock.lang.Specification {
 		search.getName() >> "cn=" + attributes.getAt("uid").get();
 
 		search.getAttributes() >> attributes
+	search.getNameInNamespace() >> principal
 
 		return search
     }
@@ -105,6 +140,9 @@ class LdapUserManagerSpec extends spock.lang.Specification {
         ldapConfiguration.getFirstnameAttribute() >> "givenname"
         ldapConfiguration.getLastnameAttribute() >> "sn"
         ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
+	ldapConfiguration.getCommonNameAttribute() >> "cn"
+	ldapConfiguration.getGroupObject() >> "groupOfUniqueNames"
+	ldapConfiguration.getGroupUniqueMemeberAttribute() >> "uniquemember"
 
         username = "rmurphy"
         email = "rmurphy@test.com"
@@ -203,4 +241,43 @@ class LdapUserManagerSpec extends spock.lang.Specification {
 		expect: "The result is not 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
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 3fdc343..e787576 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -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),
     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),
+    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
     VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10",
"Maximum vm snapshots for a vm", null),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b436a823/setup/db/db/schema-421to430.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql
index 0de9dfd..1e803dc 100644
--- a/setup/db/db/schema-421to430.sql
+++ b/setup/db/db/schema-421to430.sql
@@ -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`.`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';
+
+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);


Mime
View raw message