You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by se...@apache.org on 2013/07/11 16:04:34 UTC

[2/3] Add LDAP Plugin Implementation

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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
new file mode 100644
index 0000000..77dd33e
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManagerImpl.java
@@ -0,0 +1,185 @@
+package org.apache.cloudstack.ldap;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.api.command.LdapAddConfigurationCmd;
+import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd;
+import org.apache.cloudstack.api.command.LdapListAllUsersCmd;
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
+import org.apache.cloudstack.api.command.LdapUserSearchCmd;
+import org.apache.cloudstack.api.response.LdapConfigurationResponse;
+import org.apache.cloudstack.api.response.LdapUserResponse;
+import org.apache.cloudstack.ldap.dao.LdapConfigurationDao;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.Pair;
+
+@Component
+@Local(value = LdapManager.class)
+public class LdapManagerImpl implements LdapManager {
+    private static final Logger s_logger = Logger.getLogger(LdapManagerImpl.class.getName());
+
+    @Inject
+    private LdapConfigurationDao _ldapConfigurationDao;
+
+    @Inject
+    private LdapContextFactory _ldapContextFactory;
+
+    @Inject
+    private LdapUserManager _ldapUserManager;
+
+    public LdapManagerImpl() {
+        super();
+    }
+
+    public LdapManagerImpl(final LdapConfigurationDao ldapConfigurationDao, final LdapContextFactory ldapContextFactory, final LdapUserManager ldapUserManager) {
+        super();
+        _ldapConfigurationDao = ldapConfigurationDao;
+        _ldapContextFactory = ldapContextFactory;
+        _ldapUserManager = ldapUserManager;
+    }
+
+    @Override
+    public LdapConfigurationResponse addConfiguration(final String hostname, final int port) throws InvalidParameterValueException {
+        LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname);
+        if (configuration == null) {
+            try {
+                final String providerUrl = "ldap://" + hostname + ":" + port;
+                _ldapContextFactory.createBindContext(providerUrl);
+                configuration = new LdapConfigurationVO(hostname, port);
+                _ldapConfigurationDao.persist(configuration);
+                s_logger.info("Added new ldap server with hostname: " + hostname);
+                return new LdapConfigurationResponse(hostname, port);
+            } catch (final NamingException e) {
+                throw new InvalidParameterValueException("Unable to bind to the given LDAP server");
+            }
+        } else {
+            throw new InvalidParameterValueException("Duplicate configuration");
+        }
+    }
+
+    @Override
+    public boolean canAuthenticate(final String username, final String password) {
+        final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
+        try {
+            final LdapUser user = getUser(escapedUsername);
+            final String principal = user.getPrincipal();
+            final LdapContext context = _ldapContextFactory.createUserContext(principal, password);
+            closeContext(context);
+            return true;
+        } catch (final NamingException e) {
+            s_logger.info("Failed to authenticate user: " + username + ". incorrent password.");
+            return false;
+        }
+    }
+
+    private void closeContext(final LdapContext context) {
+        try {
+            if (context != null) {
+                context.close();
+            }
+        } catch (final NamingException e) {
+            s_logger.warn(e.getMessage());
+        }
+    }
+
+    @Override
+    public LdapConfigurationResponse createLdapConfigurationResponse(final LdapConfigurationVO configuration) {
+        final LdapConfigurationResponse response = new LdapConfigurationResponse();
+        response.setHostname(configuration.getHostname());
+        response.setPort(configuration.getPort());
+        return response;
+    }
+
+    @Override
+    public LdapUserResponse createLdapUserResponse(final LdapUser user) {
+        final LdapUserResponse response = new LdapUserResponse();
+        response.setUsername(user.getUsername());
+        response.setRealname(user.getRealname());
+        response.setEmail(user.getEmail());
+        response.setPrincipal(user.getPrincipal());
+        return response;
+    }
+
+    @Override
+    public LdapConfigurationResponse deleteConfiguration(final String hostname) throws InvalidParameterValueException {
+        final LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname);
+        if (configuration == null) {
+            throw new InvalidParameterValueException("Cannot find configuration with hostname " + hostname);
+        } else {
+            _ldapConfigurationDao.remove(configuration.getId());
+            s_logger.info("Removed ldap server with hostname: " + hostname);
+            return new LdapConfigurationResponse(configuration.getHostname(), configuration.getPort());
+        }
+    }
+
+    @Override
+    public List<Class<?>> getCommands() {
+        final List<Class<?>> cmdList = new ArrayList<Class<?>>();
+        cmdList.add(LdapUserSearchCmd.class);
+        cmdList.add(LdapListAllUsersCmd.class);
+        cmdList.add(LdapAddConfigurationCmd.class);
+        cmdList.add(LdapDeleteConfigurationCmd.class);
+        cmdList.add(LdapListConfigurationCmd.class);
+        return cmdList;
+    }
+
+    public LdapUser getUser(final String username) throws NamingException {
+        LdapContext context = null;
+        try {
+            context = _ldapContextFactory.createBindContext();
+
+            final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
+            return _ldapUserManager.getUser(escapedUsername, context);
+
+        } catch (final NamingException e) {
+            throw e;
+        } finally {
+            closeContext(context);
+        }
+    }
+
+    @Override
+    public List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException {
+        LdapContext context = null;
+        try {
+            context = _ldapContextFactory.createBindContext();
+            return _ldapUserManager.getUsers(context);
+        } catch (final NamingException e) {
+            throw new NoLdapUserMatchingQueryException("*");
+        } finally {
+            closeContext(context);
+        }
+    }
+
+    @Override
+    public Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(final LdapListConfigurationCmd cmd) {
+        final String hostname = cmd.getHostname();
+        final int port = cmd.getPort();
+        final Pair<List<LdapConfigurationVO>, Integer> result = _ldapConfigurationDao.searchConfigurations(hostname, port);
+        return new Pair<List<? extends LdapConfigurationVO>, Integer>(result.first(), result.second());
+    }
+
+    @Override
+    public List<LdapUser> searchUsers(final String username) throws NoLdapUserMatchingQueryException {
+        LdapContext context = null;
+        try {
+            context = _ldapContextFactory.createBindContext();
+            final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
+            return _ldapUserManager.getUsers("*" + escapedUsername + "*", context);
+        } catch (final NamingException e) {
+            throw new NoLdapUserMatchingQueryException(username);
+        } finally {
+            closeContext(context);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
new file mode 100644
index 0000000..046447f
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUser.java
@@ -0,0 +1,53 @@
+package org.apache.cloudstack.ldap;
+
+public class LdapUser implements Comparable<LdapUser> {
+    private final String email;
+    private final String principal;
+    private final String realname;
+    private final String username;
+
+    public LdapUser(final String username, final String email, final String realname, final String principal) {
+        this.username = username;
+        this.email = email;
+        this.realname = realname;
+        this.principal = principal;
+    }
+
+    @Override
+    public int compareTo(final LdapUser other) {
+        return getUsername().compareTo(other.getUsername());
+    }
+
+    @Override
+    public boolean equals(final Object other) {
+        if (this == other) {
+            return true;
+        }
+        if (other instanceof LdapUser) {
+            final LdapUser otherLdapUser = (LdapUser)other;
+            return getUsername().equals(otherLdapUser.getUsername());
+        }
+        return false;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public String getPrincipal() {
+        return principal;
+    }
+
+    public String getRealname() {
+        return realname;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    @Override
+    public int hashCode() {
+        return getUsername().hashCode();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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
new file mode 100644
index 0000000..e53a320
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUserManager.java
@@ -0,0 +1,81 @@
+package org.apache.cloudstack.ldap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+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.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapContext;
+
+public class LdapUserManager {
+
+    @Inject
+    private LdapConfiguration _ldapConfiguration;
+
+    public LdapUserManager() {
+    }
+
+    public LdapUserManager(final LdapConfiguration ldapConfiguration) {
+        _ldapConfiguration = ldapConfiguration;
+    }
+
+    private LdapUser createUser(final SearchResult result) throws NamingException {
+        final Attributes attributes = result.getAttributes();
+
+        final String username = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getUsernameAttribute());
+        final String email = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getEmailAttribute());
+        final String realname = LdapUtils.getAttributeValue(attributes, _ldapConfiguration.getRealnameAttribute());
+        final String principal = result.getName() + "," + _ldapConfiguration.getBaseDn();
+
+        return new LdapUser(username, email, realname, principal);
+    }
+
+    public LdapUser getUser(final String username, final LdapContext context) throws NamingException {
+        final NamingEnumeration<SearchResult> result = searchUsers(username, context);
+        if (result.hasMoreElements()) {
+            return createUser(result.nextElement());
+        } else {
+            throw new NamingException("No user found for username " + username);
+        }
+    }
+
+    public List<LdapUser> getUsers(final LdapContext context) throws NamingException {
+        return getUsers(null, context);
+    }
+
+    public List<LdapUser> getUsers(final String username, final LdapContext context) throws NamingException {
+        final NamingEnumeration<SearchResult> results = searchUsers(username, context);
+
+        final List<LdapUser> users = new ArrayList<LdapUser>();
+
+        while (results.hasMoreElements()) {
+            final SearchResult result = results.nextElement();
+            users.add(createUser(result));
+        }
+
+        Collections.sort(users);
+
+        return users;
+    }
+
+    public NamingEnumeration<SearchResult> searchUsers(final LdapContext context) throws NamingException {
+        return searchUsers(null, context);
+    }
+
+    public NamingEnumeration<SearchResult> searchUsers(final String username, final LdapContext context) throws NamingException {
+        final SearchControls controls = new SearchControls();
+
+        controls.setSearchScope(_ldapConfiguration.getScope());
+        controls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
+
+        final String filter = "(&(objectClass=" + _ldapConfiguration.getUserObject() + ")" + "("
+                + _ldapConfiguration.getUsernameAttribute() + "=" + (username == null ? "*" : username) + "))";
+
+        return context.search(_ldapConfiguration.getBaseDn(), filter, controls);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
new file mode 100644
index 0000000..d7c4831
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapUtils.java
@@ -0,0 +1,46 @@
+package org.apache.cloudstack.ldap;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+public final class LdapUtils {
+
+    public static String escapeLDAPSearchFilter(final String filter) {
+        final StringBuilder sb = new StringBuilder();
+        for (char character : filter.toCharArray()) {
+            switch (character) {
+            case '\\':
+                sb.append("\\5c");
+                break;
+            case '*':
+                sb.append("\\2a");
+                break;
+            case '(':
+                sb.append("\\28");
+                break;
+            case ')':
+                sb.append("\\29");
+                break;
+            case '\u0000':
+                sb.append("\\00");
+                break;
+            default:
+                sb.append(character);
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String getAttributeValue(final Attributes attributes, final String attributeName) throws NamingException {
+        final Attribute attribute = attributes.get(attributeName);
+        if (attribute != null) {
+            final Object value = attribute.get();
+            return String.valueOf(value);
+        }
+        return null;
+    }
+
+    private LdapUtils() {
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryException.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryException.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryException.java
new file mode 100644
index 0000000..3194653
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryException.java
@@ -0,0 +1,16 @@
+package org.apache.cloudstack.ldap;
+
+public class NoLdapUserMatchingQueryException extends Exception {
+    private static final long serialVersionUID = 7124360347208388174L;
+
+    private final String query;
+
+    public NoLdapUserMatchingQueryException(final String query) {
+        super("No users matching: " + query);
+        this.query = query;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoSuchLdapUserException.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoSuchLdapUserException.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoSuchLdapUserException.java
new file mode 100644
index 0000000..c089664
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/NoSuchLdapUserException.java
@@ -0,0 +1,15 @@
+package org.apache.cloudstack.ldap;
+
+public class NoSuchLdapUserException extends Exception {
+    private static final long serialVersionUID = 6782938919658010900L;
+    private final String username;
+
+    public NoSuchLdapUserException(final String username) {
+        super("No such user: " + username);
+        this.username = username;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
new file mode 100644
index 0000000..14f9947
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDao.java
@@ -0,0 +1,14 @@
+package org.apache.cloudstack.ldap.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.ldap.LdapConfigurationVO;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.GenericDao;
+
+public interface LdapConfigurationDao extends GenericDao<LdapConfigurationVO, Long> {
+    LdapConfigurationVO findByHostname(String hostname);
+
+    Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(String hostname, int port);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
new file mode 100644
index 0000000..eaeae99
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/dao/LdapConfigurationDaoImpl.java
@@ -0,0 +1,50 @@
+package org.apache.cloudstack.ldap.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.ldap.LdapConfigurationVO;
+
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+@Component
+@Local(value = {LdapConfigurationDao.class})
+public class LdapConfigurationDaoImpl extends GenericDaoBase<LdapConfigurationVO, Long> implements LdapConfigurationDao {
+    private final SearchBuilder<LdapConfigurationVO> hostnameSearch;
+    private final SearchBuilder<LdapConfigurationVO> listAllConfigurationsSearch;
+
+    public LdapConfigurationDaoImpl() {
+        super();
+        hostnameSearch = createSearchBuilder();
+        hostnameSearch.and("hostname", hostnameSearch.entity().getHostname(), SearchCriteria.Op.EQ);
+        hostnameSearch.done();
+
+        listAllConfigurationsSearch = createSearchBuilder();
+        listAllConfigurationsSearch.and("hostname", listAllConfigurationsSearch.entity().getHostname(), Op.EQ);
+        listAllConfigurationsSearch.and("port", listAllConfigurationsSearch.entity().getPort(), Op.EQ);
+        listAllConfigurationsSearch.done();
+    }
+
+    @Override
+    public LdapConfigurationVO findByHostname(final String hostname) {
+        final SearchCriteria<LdapConfigurationVO> sc = hostnameSearch.create();
+        sc.setParameters("hostname", hostname);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(final String hostname, final int port) {
+        final SearchCriteria<LdapConfigurationVO> sc = listAllConfigurationsSearch.create();
+        if (hostname != null) {
+            sc.setParameters("hostname", hostname);
+        }
+        return searchAndCount(sc, null);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/BasicNamingEnumerationImpl.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/BasicNamingEnumerationImpl.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/BasicNamingEnumerationImpl.groovy
new file mode 100644
index 0000000..6dd81b8
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/BasicNamingEnumerationImpl.groovy
@@ -0,0 +1,40 @@
+package groovy.org.apache.cloudstack.ldap
+
+import javax.naming.NamingEnumeration
+import javax.naming.NamingException
+import javax.naming.directory.SearchResult
+
+class BasicNamingEnumerationImpl implements NamingEnumeration {
+
+    private LinkedList<String> items = new LinkedList<SearchResult>();
+
+    @Override
+    public boolean hasMoreElements() {
+        return items.size != 0;
+    }
+
+    @Override
+    public Object nextElement() {
+        SearchResult result = items.getFirst();
+        items.removeFirst();
+        return result;
+    }
+
+    @Override
+    public void close() throws NamingException {
+    }
+
+    @Override
+    public boolean hasMore() throws NamingException {
+        return hasMoreElements();
+    }
+
+    @Override
+    public Object next() throws NamingException {
+        return nextElement();
+    }
+
+    public void add(SearchResult item) {
+        items.add(item)
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAddConfigurationCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAddConfigurationCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAddConfigurationCmdSpec.groovy
new file mode 100644
index 0000000..225d660
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAddConfigurationCmdSpec.groovy
@@ -0,0 +1,73 @@
+package groovy.org.apache.cloudstack.ldap
+
+import com.cloud.exception.InvalidParameterValueException
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.api.command.LdapAddConfigurationCmd
+import org.apache.cloudstack.api.response.LdapConfigurationResponse
+import org.apache.cloudstack.ldap.LdapManager
+
+class LdapAddConfigurationCmdSpec extends spock.lang.Specification {
+
+    def "Test successful response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.addConfiguration(_, _) >> new LdapConfigurationResponse("localhost", 389)
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        ldapAddConfigurationCmd.execute()
+        then:
+        ldapAddConfigurationCmd.responseObject.hostname == "localhost"
+        ldapAddConfigurationCmd.responseObject.port == 389
+    }
+
+    def "Test failed response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.addConfiguration(_, _) >> { throw new InvalidParameterValueException() }
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        ldapAddConfigurationCmd.execute()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test successful setting of hostname"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        ldapAddConfigurationCmd.setHostname("localhost")
+        then:
+        ldapAddConfigurationCmd.getHostname() == "localhost"
+    }
+
+    def "Test successful setting of port"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        ldapAddConfigurationCmd.setPort(389)
+        then:
+        ldapAddConfigurationCmd.getPort() == 389
+    }
+
+    def "Test getEntityOwnerId is 0"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        long ownerId = ldapAddConfigurationCmd.getEntityOwnerId()
+        then:
+        ownerId == 0
+    }
+
+    def "Test successful return of getCommandName"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
+        when:
+        String commandName = ldapAddConfigurationCmd.getCommandName()
+        then:
+        commandName == "ldapconfigurationresponse"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
new file mode 100644
index 0000000..912df30
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapAuthenticatorSpec.groovy
@@ -0,0 +1,74 @@
+package groovy.org.apache.cloudstack.ldap
+
+import com.cloud.user.UserAccountVO
+import com.cloud.user.dao.UserAccountDao
+import com.cloud.utils.Pair
+import org.apache.cloudstack.ldap.LdapAuthenticator
+import org.apache.cloudstack.ldap.LdapConfigurationVO
+import org.apache.cloudstack.ldap.LdapManager
+
+class LdapAuthenticatorSpec extends spock.lang.Specification {
+
+    def "Test a failed authentication due to user not being found within cloudstack"() {
+        given:
+        LdapManager ldapManager = Mock(LdapManager)
+        UserAccountDao userAccountDao = Mock(UserAccountDao)
+        userAccountDao.getUserAccount(_, _) >> null
+        def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
+        when:
+        def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
+        then:
+        result == false
+    }
+
+    def "Test failed authentication due to ldap not being configured"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
+        ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> ldapConfigurations
+
+        UserAccountDao userAccountDao = Mock(UserAccountDao)
+        userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
+
+        def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
+        when:
+        def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
+        then:
+        result == false
+    }
+
+    def "Test failed authentication due to ldap bind being unsuccessful"() {
+        given:
+
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
+        Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
+        ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> ldapConfigurations
+        ldapManager.canAuthenticate(_, _) >> false
+
+        UserAccountDao userAccountDao = Mock(UserAccountDao)
+        userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
+        def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
+
+        when:
+        def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
+
+        then:
+        result == false
+    }
+
+    def "Test that encode doesn't change the input"() {
+        given:
+        LdapManager ldapManager = Mock(LdapManager)
+        UserAccountDao userAccountDao = Mock(UserAccountDao)
+        def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
+        when:
+        def result = ldapAuthenticator.encode("password")
+        then:
+        result == "password"
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
new file mode 100644
index 0000000..2ceae5d
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationDaoImplSpec.groovy
@@ -0,0 +1,13 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl
+
+class LdapConfigurationDaoImplSpec extends spock.lang.Specification {
+    def "Test setting up of a LdapConfigurationDao"() {
+        given:
+        def ldapConfigurationDaoImpl = new LdapConfigurationDaoImpl();
+        expect:
+        ldapConfigurationDaoImpl.hostnameSearch != null;
+        ldapConfigurationDaoImpl.listAllConfigurationsSearch != null
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationResponseSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationResponseSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationResponseSpec.groovy
new file mode 100644
index 0000000..899267a
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationResponseSpec.groovy
@@ -0,0 +1,33 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.api.response.LdapConfigurationResponse
+
+class LdapConfigurationResponseSpec extends spock.lang.Specification {
+    def "Testing succcessful setting of LdapConfigurationResponse hostname"() {
+        given:
+        LdapConfigurationResponse response = new LdapConfigurationResponse();
+        when:
+        response.setHostname("localhost");
+        then:
+        response.getHostname() == "localhost";
+    }
+
+    def "Testing successful setting of LdapConfigurationResponse port"() {
+        given:
+        LdapConfigurationResponse response = new LdapConfigurationResponse()
+        when:
+        response.setPort(389)
+        then:
+        response.getPort() == 389
+    }
+
+    def "Testing successful setting of LdapConfigurationResponse hostname and port via constructor"() {
+        given:
+        LdapConfigurationResponse response
+        when:
+        response = new LdapConfigurationResponse("localhost", 389)
+        then:
+        response.getHostname() == "localhost"
+        response.getPort() == 389
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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
new file mode 100644
index 0000000..c0208a8
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationSpec.groovy
@@ -0,0 +1,167 @@
+package groovy.org.apache.cloudstack.ldap
+
+import com.cloud.configuration.dao.ConfigurationDao
+import com.cloud.utils.Pair
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.ldap.LdapConfiguration
+import org.apache.cloudstack.ldap.LdapConfigurationVO
+import org.apache.cloudstack.ldap.LdapManager
+
+import javax.naming.directory.SearchControls
+
+class LdapConfigurationSpec extends spock.lang.Specification {
+    def "Test that providerUrl successfully returns a URL when a configuration is available"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
+        Pair<List<LdapConfigurationVO>, Integer> result = new Pair<List<LdapConfigurationVO>, Integer>();
+        result.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> result
+
+        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+
+        when:
+        String providerUrl = ldapConfiguration.getProviderUrl()
+
+        then:
+        providerUrl == "ldap://localhost:389"
+    }
+
+    def "Test that exception is thrown when no configuration is found"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        Pair<List<LdapConfigurationVO>, Integer> result = new Pair<List<LdapConfigurationVO>, Integer>();
+        result.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> result
+        LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        ldapConfiguration.getProviderUrl()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test that getAuthentication returns simple"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        configDao.getValue("ldap.bind.password") >> "password"
+        configDao.getValue("ldap.bind.principal") >> "cn=rmurphy,dc=cloudstack,dc=org"
+        when:
+        String authentication = ldapConfiguration.getAuthentication()
+        then:
+        authentication == "simple"
+    }
+
+    def "Test that getAuthentication returns none"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String authentication = ldapConfiguration.getAuthentication()
+        then:
+        authentication == "none"
+    }
+
+    def "Test that getEmailAttribute returns mail"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.email.attribute") >> "mail"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String emailAttribute = ldapConfiguration.getEmailAttribute()
+        then:
+        emailAttribute == "mail"
+    }
+
+    def "Test that getUsernameAttribute returns uid"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.username.attribute") >> "uid"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String usernameAttribute = ldapConfiguration.getUsernameAttribute()
+        then:
+        usernameAttribute == "uid"
+    }
+
+    def "Test that getRealnameAttribute returns cn"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.realname.attribute") >> "cn"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String realname = ldapConfiguration.getRealnameAttribute()
+        then:
+        realname == "cn"
+    }
+
+    def "Test that getUserObject returns inetOrgPerson"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.user.object") >> "inetOrgPerson"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String realname = ldapConfiguration.getUserObject()
+        then:
+        realname == "inetOrgPerson"
+    }
+
+    def "Test that getReturnAttributes returns the correct data"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.realname.attribute") >> "cn"
+        configDao.getValue("ldap.username.attribute") >> "uid"
+        configDao.getValue("ldap.email.attribute") >> "mail"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String[] returnAttributes = ldapConfiguration.getReturnAttributes()
+        then:
+        returnAttributes == ["uid", "mail", "cn"]
+    }
+
+    def "Test that getScope returns SearchControls.SUBTREE_SCOPE"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        int scope = ldapConfiguration.getScope()
+        then:
+        scope == SearchControls.SUBTREE_SCOPE;
+    }
+
+    def "Test that getBaseDn returns dc=cloudstack,dc=org"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        configDao.getValue("ldap.basedn") >> "dc=cloudstack,dc=org"
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String baseDn = ldapConfiguration.getBaseDn();
+        then:
+        baseDn == "dc=cloudstack,dc=org"
+    }
+
+    def "Test that getFactory returns com.sun.jndi.ldap.LdapCtxFactory"() {
+        given:
+        def configDao = Mock(ConfigurationDao)
+        def ldapManager = Mock(LdapManager)
+        def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
+        when:
+        String factory = ldapConfiguration.getFactory();
+        then:
+        factory == "com.sun.jndi.ldap.LdapCtxFactory"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationVO.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationVO.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationVO.groovy
new file mode 100644
index 0000000..dabf805
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapConfigurationVO.groovy
@@ -0,0 +1,36 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.LdapConfigurationVO
+
+
+class LdapConfigurationVOSpec extends spock.lang.Specification {
+    def "Testing that the hostname is correctly set with the LDAP configuration VO"() {
+        given: "You have created a LDAP configuration VO with a hostname set"
+        def configuration = new LdapConfigurationVO()
+        configuration.setHostname(hostname)
+        expect: "The hostname is equal to the given data source"
+        configuration.getHostname() == hostname
+        where: "The hostname is set to "
+        hostname << ["", null, "localhost"]
+    }
+
+    def "Testing that the port is correctly set within the LDAP configuration VO"() {
+        given: "You have created a LDAP configuration VO with a port set"
+        def configuration = new LdapConfigurationVO()
+        configuration.setPort(port)
+        expect: "The port is equal to the given data source"
+        configuration.getPort() == port
+        where: "The port is set to "
+        port << [0, 1000, -1000, -0]
+    }
+
+    def "Testing that the ID is correctly set within the LDAP configuration VO"() {
+        given: "You have created an LDAP Configuration VO"
+        def configuration = new LdapConfigurationVO("localhost", 389);
+        configuration.setId(id);
+        expect: "The id is equal to the given data source"
+        configuration.getId() == id;
+        where: "The id is set to "
+        id << [0, 1000, -1000, -0]
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
new file mode 100644
index 0000000..1f97012
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapContextFactorySpec.groovy
@@ -0,0 +1,117 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.LdapConfiguration
+import org.apache.cloudstack.ldap.LdapContextFactory
+import spock.lang.Shared
+
+import javax.naming.NamingException
+import javax.naming.directory.SearchControls
+import javax.naming.ldap.LdapContext
+
+class LdapContextFactorySpec extends spock.lang.Specification {
+    @Shared
+    private def ldapConfiguration
+
+    @Shared
+    private def username
+
+    @Shared
+    private def principal
+
+    @Shared
+    private def password
+
+    def setupSpec() {
+        ldapConfiguration = Mock(LdapConfiguration)
+
+        ldapConfiguration.getFactory() >> "com.sun.jndi.ldap.LdapCtxFactory"
+        ldapConfiguration.getProviderUrl() >> "ldap://localhost:389"
+        ldapConfiguration.getAuthentication() >> "none"
+        ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
+        ldapConfiguration.getReturnAttributes() >> ["uid", "mail", "cn"]
+        ldapConfiguration.getUsernameAttribute() >> "uid"
+        ldapConfiguration.getEmailAttribute() >> "mail"
+        ldapConfiguration.getRealnameAttribute() >> "cn"
+        ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
+
+        username = "rmurphy"
+        principal = "cn=" + username + "," + ldapConfiguration.getBaseDn()
+        password = "password"
+    }
+
+    def "Test successfully creating a system environment with anon bind"() {
+        given:
+        def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
+
+        when:
+        def result = ldapContextFactory.getEnvironment(principal, password, null, false)
+
+        then:
+        result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
+        result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
+        result['java.naming.security.principal'] == principal
+        result['java.naming.security.authentication'] == "simple"
+        result['java.naming.security.credentials'] == password
+    }
+
+    def "Test successfully creating a environment with username and password"() {
+        given:
+        def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
+
+        when:
+        def result = ldapContextFactory.getEnvironment(null, null, null, true)
+
+        then:
+        result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
+        result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
+        result['java.naming.security.principal'] == null
+        result['java.naming.security.authentication'] == ldapConfiguration.getAuthentication()
+        result['java.naming.security.credentials'] == null
+    }
+
+    def "Test successfully binding as a user"() {
+        given:
+        def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
+        when:
+        ldapContextFactory.createUserContext(principal, password)
+        then:
+        thrown NamingException
+    }
+
+    def "Test successully binding as system"() {
+        given:
+        def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
+        when:
+        ldapContextFactory.createBindContext()
+        then:
+        thrown NamingException
+    }
+
+    def "Test succcessfully creating a initial context"() {
+        given:
+        def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
+        when:
+        ldapContextFactory.createInitialDirContext(null, null, true)
+        then:
+        thrown NamingException
+    }
+
+    def "Test successful failed connection"() {
+        given:
+        def ldapContextFactory = Spy(LdapContextFactory, constructorArgs: [ldapConfiguration])
+        when:
+        ldapContextFactory.testConnection(ldapConfiguration.getProviderUrl())
+        then:
+        thrown NamingException
+    }
+
+    def "Test successful connection"() {
+        given:
+        def ldapContextFactory = Spy(LdapContextFactory, constructorArgs: [ldapConfiguration])
+        ldapContextFactory.createBindContext(_) >> Mock(LdapContext)
+        when:
+        ldapContextFactory.testConnection(ldapConfiguration.getProviderUrl())
+        then:
+        notThrown NamingException
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
new file mode 100644
index 0000000..31a2047
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapDeleteConfigurationCmdSpec.groovy
@@ -0,0 +1,62 @@
+package groovy.org.apache.cloudstack.ldap
+
+import com.cloud.exception.InvalidParameterValueException
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd
+import org.apache.cloudstack.api.response.LdapConfigurationResponse
+import org.apache.cloudstack.ldap.LdapManager
+
+class LdapDeleteConfigurationCmdSpec extends spock.lang.Specification {
+
+    def "Test successful response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.deleteConfiguration(_) >> new LdapConfigurationResponse("localhost")
+        def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
+        when:
+        ldapDeleteConfigurationCmd.execute()
+        then:
+        ldapDeleteConfigurationCmd.responseObject.hostname == "localhost"
+    }
+
+    def "Test failed response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.deleteConfiguration(_) >> { throw new InvalidParameterValueException() }
+        def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
+        when:
+        ldapDeleteConfigurationCmd.execute()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test successful setting of hostname"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
+        when:
+        ldapDeleteConfigurationCmd.setHostname("localhost")
+        then:
+        ldapDeleteConfigurationCmd.getHostname() == "localhost"
+    }
+
+    def "Test getEntityOwnerId is 0"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
+        when:
+        long ownerId = ldapDeleteConfigurationCmd.getEntityOwnerId()
+        then:
+        ownerId == 0
+    }
+
+    def "Test successful return of getCommandName"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
+        when:
+        String commandName = ldapDeleteConfigurationCmd.getCommandName()
+        then:
+        commandName == "ldapconfigurationresponse"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListAllUsersCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListAllUsersCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListAllUsersCmdSpec.groovy
new file mode 100644
index 0000000..ee0808e
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListAllUsersCmdSpec.groovy
@@ -0,0 +1,56 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.api.command.LdapListAllUsersCmd
+import org.apache.cloudstack.api.response.LdapUserResponse
+import org.apache.cloudstack.ldap.LdapManager
+import org.apache.cloudstack.ldap.LdapUser
+import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
+
+class LdapListAllUsersCmdSpec extends spock.lang.Specification {
+    def "Test successful response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        List<LdapUser> users = new ArrayList()
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
+        ldapManager.getUsers() >> users
+        LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
+        ldapManager.createLdapUserResponse(_) >> response
+        def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
+        when:
+        ldapListAllUsersCmd.execute()
+        then:
+        ldapListAllUsersCmd.responseObject.getResponses().size() != 0
+    }
+
+    def "Test successful empty response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.getUsers() >> {throw new NoLdapUserMatchingQueryException()}
+        def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
+        when:
+        ldapListAllUsersCmd.execute()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test getEntityOwnerId is 0"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
+        when:
+        long ownerId = ldapListAllUsersCmd.getEntityOwnerId()
+        then:
+        ownerId == 0
+    }
+
+    def "Test successful return of getCommandName"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
+        when:
+        String commandName = ldapListAllUsersCmd.getCommandName()
+        then:
+        commandName == "ldapuserresponse"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListConfigurationCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListConfigurationCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListConfigurationCmdSpec.groovy
new file mode 100644
index 0000000..c3ca237
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapListConfigurationCmdSpec.groovy
@@ -0,0 +1,85 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd
+import org.apache.cloudstack.api.response.LdapConfigurationResponse
+import org.apache.cloudstack.ldap.LdapConfigurationVO
+import org.apache.cloudstack.ldap.LdapManager
+
+import com.cloud.utils.Pair
+
+class LdapListConfigurationCmdSpec extends spock.lang.Specification {
+
+    def "Test successful response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
+        Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
+        ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> ldapConfigurations
+        ldapManager.createLdapConfigurationResponse(_) >> new LdapConfigurationResponse("localhost", 389)
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        ldapListConfigurationCmd.execute()
+        then:
+        ldapListConfigurationCmd.getResponseObject().getResponses().size() != 0
+    }
+
+    def "Test failed response from execute"() {
+        given:
+
+        def ldapManager = Mock(LdapManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
+        ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapManager.listConfigurations(_) >> ldapConfigurations
+
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        ldapListConfigurationCmd.execute()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test successful setting of hostname"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        ldapListConfigurationCmd.setHostname("localhost")
+        then:
+        ldapListConfigurationCmd.getHostname() == "localhost"
+    }
+
+    def "Test successful setting of Port"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        ldapListConfigurationCmd.setPort(389)
+        then:
+        ldapListConfigurationCmd.getPort() == 389
+    }
+
+    def "Test getEntityOwnerId is 0"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        long ownerId = ldapListConfigurationCmd.getEntityOwnerId()
+        then:
+        ownerId == 0
+    }
+
+    def "Test successful return of getCommandName"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
+        when:
+        String commandName = ldapListConfigurationCmd.getCommandName()
+        then:
+        commandName == "ldapconfigurationresponse"
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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
new file mode 100644
index 0000000..689c52b
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapManagerImplSpec.groovy
@@ -0,0 +1,301 @@
+package groovy.org.apache.cloudstack.ldap
+
+import javax.naming.NamingException
+import javax.naming.ldap.InitialLdapContext
+
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd
+import org.apache.cloudstack.ldap.*
+import org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl
+
+import com.cloud.exception.InvalidParameterValueException
+import com.cloud.utils.Pair
+
+class LdapManagerImplSpec extends spock.lang.Specification {
+    def "Test that addConfiguration fails when a duplicate configuration exists"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapConfigurationDao.findByHostname(_) >> new LdapConfigurationVO("localhost", 389)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.addConfiguration("localhost", 389)
+        then:
+        thrown InvalidParameterValueException
+    }
+
+    def "Test that addConfiguration fails when a binding fails"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext(_) >> { throw new NamingException() }
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.addConfiguration("localhost", 389)
+        then:
+        thrown InvalidParameterValueException
+    }
+
+    def "Test successfully addConfiguration"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext(_) >> null
+        ldapConfigurationDao.persist(_) >> null
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.addConfiguration("localhost", 389)
+        then:
+        result.hostname == "localhost"
+        result.port == 389
+    }
+
+    def "Test successful failed result from deleteConfiguration due to configuration not existing"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapConfigurationDao.findByHostname(_) >> null
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.deleteConfiguration("localhost")
+        then:
+        thrown InvalidParameterValueException
+    }
+
+    def "Test successful result from deleteConfiguration"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapConfigurationDao.findByHostname(_) >> {
+            def configuration = new LdapConfigurationVO("localhost", 389)
+            configuration.setId(0);
+            return configuration;
+        }
+        ldapConfigurationDao.remove(_) >> null
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.deleteConfiguration("localhost")
+        then:
+        result.hostname == "localhost"
+        result.port == 389
+    }
+
+    def "Test successful failed result from canAuthenticate due to user not found"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
+        ldapManager.getUser(_) >> { throw new NamingException() }
+        when:
+        def result = ldapManager.canAuthenticate("rmurphy", "password")
+        then:
+        result == false
+    }
+
+    def "Test successful failed result from canAuthenticate due to bad password"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        ldapContextFactory.createUserContext(_, _) >> { throw new NamingException() }
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
+        ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org") }
+        when:
+        def result = ldapManager.canAuthenticate("rmurphy", "password")
+        then:
+        result == false
+    }
+
+    def "Test successful result from canAuthenticate"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        ldapContextFactory.createUserContext(_, _) >> null
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
+        ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org") }
+        when:
+        def result = ldapManager.canAuthenticate("rmurphy", "password")
+        then:
+        result == true
+    }
+
+    def "Test successful closing of context"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def context = Mock(InitialLdapContext)
+        ldapManager.closeContext(context)
+        then:
+        context.defaultInitCtx == null
+    }
+
+    def "Test successful failing to close of context"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def context = Mock(InitialLdapContext)
+        context.close() >> { throw new NamingException() }
+        ldapManager.closeContext(context)
+        then:
+        context.defaultInitCtx == null
+    }
+
+    def "Test LdapConfigurationResponse generation"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.createLdapConfigurationResponse(new LdapConfigurationVO("localhost", 389))
+        then:
+        result.hostname == "localhost"
+        result.port == 389
+    }
+
+    def "Test LdapUserResponse generation"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
+        then:
+        result.username == "rmurphy"
+        result.email == "rmurphy@test.com"
+        result.realname == "Ryan Murphy"
+        result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
+    }
+
+    def "Test that getCommands isn't empty"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.getCommands()
+        then:
+        result.size() > 0
+    }
+
+    def "Test failing of getUser due to bind issue"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext() >> { throw new NamingException() }
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.getUser("rmurphy")
+        then:
+        thrown NamingException
+    }
+
+    def "Test success of getUser"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext() >> null
+        ldapUserManager.getUser(_, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.getUser("rmurphy")
+        then:
+        result.username == "rmurphy"
+        result.email == "rmurphy@test.com"
+        result.realname == "Ryan Murphy"
+        result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
+    }
+
+    def "Test failing of getUsers due to bind issue"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext() >> { throw new NamingException() }
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.getUsers()
+        then:
+        thrown NoLdapUserMatchingQueryException
+    }
+
+    def "Test success getUsers"() {
+        given:
+        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"))
+        ldapUserManager.getUsers(_) >> users;
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.getUsers()
+        then:
+        result.size() > 0;
+    }
+
+    def "Testing of listConfigurations"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
+        ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
+        Pair<List<LdapConfigurationVO>, Integer> configurations = new Pair<List<LdapConfigurationVO>, Integer>();
+        configurations.set(ldapConfigurationList, ldapConfigurationList.size())
+        ldapConfigurationDao.searchConfigurations(_, _) >> configurations
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.listConfigurations(new LdapListConfigurationCmd())
+        then:
+        result.second() > 0
+    }
+
+    def "Test failing of searchUsers due to a failure to bind"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext() >> { throw new NamingException() }
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        ldapManager.searchUsers("rmurphy")
+        then:
+        thrown NoLdapUserMatchingQueryException
+    }
+
+    def "Test successful result from searchUsers"() {
+        given:
+        def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
+        def ldapContextFactory = Mock(LdapContextFactory)
+        def ldapUserManager = Mock(LdapUserManager)
+        ldapContextFactory.createBindContext() >> null;
+
+        List<LdapUser> users = new ArrayList<LdapUser>();
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
+        ldapUserManager.getUsers(_, _) >> users;
+
+        def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
+        when:
+        def result = ldapManager.searchUsers("rmurphy");
+        then:
+        result.size() > 0;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
new file mode 100644
index 0000000..64f55c3
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapSearchUserCmdSpec.groovy
@@ -0,0 +1,66 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.api.ServerApiException
+import org.apache.cloudstack.api.command.LdapUserSearchCmd
+import org.apache.cloudstack.api.response.LdapUserResponse
+import org.apache.cloudstack.ldap.LdapManager
+import org.apache.cloudstack.ldap.LdapUser
+import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
+
+class LdapSearchUserCmdSpec extends spock.lang.Specification {
+    def "Test successful response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        List<LdapUser> users = new ArrayList()
+        users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
+        ldapManager.searchUsers(_) >> users
+        LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
+        ldapManager.createLdapUserResponse(_) >> response
+        def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
+        when:
+        ldapUserSearchCmd.execute()
+        then:
+        ldapUserSearchCmd.responseObject.getResponses().size() != 0
+    }
+
+    def "Test successful empty response from execute"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        ldapManager.searchUsers(_) >> {throw new NoLdapUserMatchingQueryException()}
+        def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
+        when:
+        ldapUserSearchCmd.execute()
+        then:
+        thrown ServerApiException
+    }
+
+    def "Test getEntityOwnerId is 0"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
+        when:
+        long ownerId = ldapUserSearchCmd.getEntityOwnerId()
+        then:
+        ownerId == 0
+    }
+
+    def "Test successful setting of ldapUserSearchCmd Query"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
+        when:
+        ldapUserSearchCmd.setQuery("")
+        then:
+        ldapUserSearchCmd.getQuery() == ""
+    }
+
+    def "Test successful return of getCommandName"() {
+        given:
+        def ldapManager = Mock(LdapManager)
+        def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
+        when:
+        String commandName = ldapUserSearchCmd.getCommandName()
+        then:
+        commandName == "ldapuserresponse"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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
new file mode 100644
index 0000000..1ee7d6f
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserManagerSpec.groovy
@@ -0,0 +1,179 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.LdapConfiguration
+import org.apache.cloudstack.ldap.LdapUserManager
+import spock.lang.Shared
+
+import javax.naming.NamingException
+import javax.naming.directory.Attribute
+import javax.naming.directory.Attributes
+import javax.naming.directory.SearchControls
+import javax.naming.directory.SearchResult
+import javax.naming.ldap.LdapContext
+
+class LdapUserManagerSpec extends spock.lang.Specification {
+
+    @Shared
+    private def ldapConfiguration
+
+    @Shared
+    private def username
+
+    @Shared
+    private def email
+
+    @Shared
+    private def realname
+
+    @Shared
+    private def principal
+
+    def setupSpec() {
+        ldapConfiguration = Mock(LdapConfiguration)
+
+        ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
+        ldapConfiguration.getReturnAttributes() >> ["uid", "mail", "cn"]
+        ldapConfiguration.getUsernameAttribute() >> "uid"
+        ldapConfiguration.getEmailAttribute() >> "mail"
+        ldapConfiguration.getRealnameAttribute() >> "cn"
+        ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
+
+        username = "rmurphy"
+        email = "rmurphy@test.com"
+        realname = "Ryan Murphy"
+        principal = "cn=" + username + "," + ldapConfiguration.getBaseDn()
+    }
+
+    def "Test that a newly created Ldap User Manager is not null"() {
+        given: "You have created a new Ldap user manager object"
+        def result = new LdapUserManager();
+        expect: "The result is not null"
+        result != null
+    }
+
+    def "Test successfully creating an Ldap User from Search result"() {
+        given:
+        def attributes = createUserAttributes(username, email, realname)
+        def search = createSearchResult(attributes)
+        def userManager = new LdapUserManager(ldapConfiguration)
+        def result = userManager.createUser(search)
+
+        expect:
+
+        result.username == username
+        result.email == email
+        result.realname == realname
+        result.principal == principal
+    }
+
+    def "Test successfully returning an Ldap user from a get user request"() {
+        given:
+
+        def userManager = new LdapUserManager(ldapConfiguration)
+
+        when:
+        def result = userManager.getUser(username, createContext())
+
+        then:
+        result.username == username
+        result.email == email
+        result.realname == realname
+        result.principal == principal
+    }
+
+    def "Test successfully returning a list from get users"() {
+        given:
+
+        def userManager = new LdapUserManager(ldapConfiguration)
+
+        when:
+        def result = userManager.getUsers(username, createContext())
+
+        then:
+        result.size() == 1
+    }
+
+    def "Test successfully returning a list from get users when no username is given"() {
+        given:
+
+        def userManager = new LdapUserManager(ldapConfiguration)
+
+        when:
+        def result = userManager.getUsers(createContext())
+
+        then:
+        result.size() == 1
+    }
+
+    def "Test successfully throwing an exception when no users are found with getUser"() {
+        given:
+
+        def searchUsersResults = new BasicNamingEnumerationImpl()
+
+        def context = Mock(LdapContext)
+        context.search(_, _, _) >> searchUsersResults;
+
+        def userManager = new LdapUserManager(ldapConfiguration)
+
+        when:
+        def result = userManager.getUser(username, context)
+
+        then:
+        thrown NamingException
+    }
+
+    def "Test successfully returning a NamingEnumeration from searchUsers"() {
+        given:
+        def userManager = new LdapUserManager(ldapConfiguration)
+
+        when:
+        def result = userManager.searchUsers(createContext())
+
+        then:
+        result.next().getName() + "," + ldapConfiguration.getBaseDn() == principal
+    }
+
+    private def createContext() {
+
+        Attributes attributes = createUserAttributes(username, email, realname)
+        SearchResult searchResults = createSearchResult(attributes)
+        def searchUsersResults = new BasicNamingEnumerationImpl()
+        searchUsersResults.add(searchResults);
+
+        def context = Mock(LdapContext)
+        context.search(_, _, _) >> searchUsersResults;
+
+        return context
+    }
+
+    private SearchResult createSearchResult(attributes) {
+        def search = Mock(SearchResult)
+
+        search.getName() >> "cn=" + attributes.getAt("uid").get();
+
+        search.getAttributes() >> attributes
+
+        return search
+    }
+
+    private Attributes createUserAttributes(String username, String email, String realname) {
+        def attributes = Mock(Attributes)
+
+        def nameAttribute = Mock(Attribute)
+        nameAttribute.getId() >> "uid"
+        nameAttribute.get() >> username
+        attributes.get("uid") >> nameAttribute
+
+        def mailAttribute = Mock(Attribute)
+        mailAttribute.getId() >> "mail"
+        mailAttribute.get() >> email
+        attributes.get("mail") >> mailAttribute
+
+        def cnAttribute = Mock(Attribute)
+        cnAttribute.getId() >> "cn"
+        cnAttribute.get() >> realname
+        attributes.get("cn") >> cnAttribute
+
+        return attributes
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserResponseSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserResponseSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserResponseSpec.groovy
new file mode 100644
index 0000000..f96f33d
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserResponseSpec.groovy
@@ -0,0 +1,42 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.api.response.LdapUserResponse
+
+
+class LdapUserResponseSpec extends spock.lang.Specification {
+    def "Testing succcessful setting of LdapUserResponse email"() {
+        given:
+        LdapUserResponse response = new LdapUserResponse();
+        when:
+        response.setEmail("rmurphy@test.com");
+        then:
+        response.getEmail() == "rmurphy@test.com";
+    }
+
+    def "Testing successful setting of LdapUserResponse principal"() {
+        given:
+        LdapUserResponse response = new LdapUserResponse()
+        when:
+        response.setPrincipal("dc=cloudstack,dc=org")
+        then:
+        response.getPrincipal() == "dc=cloudstack,dc=org"
+    }
+
+    def "Testing successful setting of LdapUserResponse username"() {
+        given:
+        LdapUserResponse response = new LdapUserResponse()
+        when:
+        response.setUsername("rmurphy")
+        then:
+        response.getUsername() == "rmurphy"
+    }
+
+    def "Testing successful setting of LdapUserResponse realname"() {
+        given:
+        LdapUserResponse response = new LdapUserResponse()
+        when:
+        response.setRealname("Ryan Murphy")
+        then:
+        response.getRealname() == "Ryan Murphy"
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
new file mode 100644
index 0000000..1293a0e
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUserSpec.groovy
@@ -0,0 +1,54 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.LdapUser
+
+class LdapUserSpec extends spock.lang.Specification {
+
+    def "Testing that the username is correctly set with the ldap object"() {
+        given: "You have created a LDAP user object with a username"
+        def user = new LdapUser(username, "", "", "")
+        expect: "The username is equal to the given data source"
+        user.getUsername() == username
+        where: "The username is set to "
+        username << ["", null, "rmurphy"]
+    }
+
+    def "Testing the email is correctly set with the ldap object"() {
+        given: "You have created a LDAP user object with a realname"
+        def user = new LdapUser("", email, "", "")
+        expect: "The email is equal to the given data source"
+        user.getEmail() == email
+        where: "The email is set to "
+        email << ["", null, "test@test.com"]
+    }
+
+    def "Testing the realname is correctly set with the ldap object"() {
+        given: "You have created a LDAP user object with a realname"
+        def user = new LdapUser("", "", realname, "")
+        expect: "The realname is equal to the given data source"
+        user.getRealname() == realname
+        where: "The realname is set to "
+        realname << ["", null, "Ryan Murphy"]
+    }
+
+    def "Testing the principal is correctly set with the ldap object"() {
+        given: "You have created a LDAP user object with a principal"
+        def user = new LdapUser("", "", "", principal)
+        expect: "The principal is equal to the given data source"
+        user.getPrincipal() == principal
+        where: "The username is set to "
+        principal << ["", null, "cn=rmurphy,dc=cloudstack,dc=org"]
+    }
+
+    def "Testing that LdapUser successfully gives the correct result for a compare to"() {
+        given: "You have created two LDAP user objects"
+        def userA = new LdapUser(usernameA, "", "", "")
+        def userB = new LdapUser(usernameB, "", "", "")
+        expect: "That when compared the result is less than or equal to 0"
+        userA.compareTo(userB) <= 0
+        where: "The following values are used"
+        usernameA | usernameB
+        "A"       | "B"
+        "A"       | "A"
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUtilsSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUtilsSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUtilsSpec.groovy
new file mode 100644
index 0000000..3133493
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapUtilsSpec.groovy
@@ -0,0 +1,52 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.LdapUtils
+
+import javax.naming.directory.Attribute
+import javax.naming.directory.Attributes
+
+class LdapUtilsSpec extends spock.lang.Specification {
+    def "Testing that a Ldap Search Filter is correctly escaped"() {
+        given: "You have some input from a user"
+
+        expect: "That the input is escaped"
+        LdapUtils.escapeLDAPSearchFilter(input) == result
+
+        where: "The following inputs are given "
+        input                                       | result
+        "Hi This is a test #çà"                     | "Hi This is a test #çà"
+        "Hi (This) = is * a \\ test # ç à ô \u0000" | "Hi \\28This\\29 = is \\2a a \\5c test # ç à ô \\00"
+    }
+
+    def "Testing than an attribute is successfully returned"() {
+        given: "You have an attributes object with some attribute"
+        def attributes = Mock(Attributes)
+        def attribute = Mock(Attribute)
+        attribute.getId() >> name
+        attribute.get() >> value
+        attributes.get(name) >> attribute
+
+        when: "You get the attribute"
+        String foundValue = LdapUtils.getAttributeValue(attributes, name)
+
+        then: "Its value equals uid"
+        foundValue == value
+
+        where:
+        name    | value
+        "uid"   | "rmurphy"
+        "email" | "rmurphy@test.com"
+    }
+
+    def "Testing than an attribute is not successfully returned"() {
+        given: "You have an attributes object with some attribute"
+        def attributes = Mock(Attributes)
+        attributes.get("uid") >> null
+
+        when: "You get the attribute"
+        String foundValue = LdapUtils.getAttributeValue(attributes, "uid")
+
+        then: "Its value equals uid"
+        foundValue == null
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryExceptionSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryExceptionSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryExceptionSpec.groovy
new file mode 100644
index 0000000..e2b78dd
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoLdapUserMatchingQueryExceptionSpec.groovy
@@ -0,0 +1,14 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
+
+class NoLdapUserMatchingQueryExceptionSpec extends spock.lang.Specification {
+    def "Test that the query is correctly set within the No LDAP user matching query exception object"() {
+        given: "You have created an No LDAP user matching query exception object with a query set"
+        def exception = new NoLdapUserMatchingQueryException(query)
+        expect: "The username is equal to the given data source"
+        exception.getQuery() == query
+        where: "The username is set to "
+        query << ["", null, "murp*"]
+    }
+}
\ No newline at end of file