You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ap...@apache.org on 2013/07/25 14:28:37 UTC

[4/4] git commit: updated refs/heads/ldapplugin to eaa4143

Merge LDAPPlugin

Signed-off-by: Abhinandan Prateek <ap...@apache.org>


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

Branch: refs/heads/ldapplugin
Commit: eaa41433715ba1a1137ad9f346ea8569e31e4560
Parents: 1f64354
Author: Ian Duffy <ia...@ianduffy.ie>
Authored: Thu Jul 25 10:24:13 2013 +0100
Committer: Abhinandan Prateek <ap...@apache.org>
Committed: Thu Jul 25 17:54:52 2013 +0530

----------------------------------------------------------------------
 .../configuration/ConfigurationService.java     |   8 -
 .../org/apache/cloudstack/api/ApiConstants.java |  11 -
 .../cloudstack/api/ResponseGenerator.java       |   3 -
 .../api/command/admin/ldap/LDAPConfigCmd.java   | 206 ------------
 .../api/command/admin/ldap/LDAPRemoveCmd.java   |  71 -----
 .../api/response/LDAPConfigResponse.java        | 105 ------
 .../api/response/LDAPRemoveResponse.java        |  26 --
 client/tomcatconf/applicationContext.xml.in     |   7 +-
 client/tomcatconf/commands.properties.in        |  18 +-
 client/tomcatconf/componentContext.xml.in       |   4 +-
 client/tomcatconf/nonossComponentContext.xml.in |   4 +-
 .../tomcatconf/simulatorComponentContext.xml.in |   4 +-
 .../ratelimit/ApiRateLimitServiceImpl.java      |   1 -
 plugins/user-authenticators/ldap/pom.xml        | 119 +++++--
 .../server/auth/LDAPUserAuthenticator.java      | 173 ----------
 .../api/command/LdapAddConfigurationCmd.java    |  80 +++++
 .../api/command/LdapCreateAccount.java          | 141 ++++++++
 .../api/command/LdapDeleteConfigurationCmd.java |  76 +++++
 .../api/command/LdapListAllUsersCmd.java        |  88 +++++
 .../api/command/LdapListConfigurationCmd.java   | 106 ++++++
 .../api/command/LdapUserSearchCmd.java          |  96 ++++++
 .../api/response/LdapConfigurationResponse.java |  63 ++++
 .../api/response/LdapUserResponse.java          |  98 ++++++
 .../cloudstack/ldap/LdapAuthenticator.java      |  73 +++++
 .../cloudstack/ldap/LdapConfiguration.java      | 116 +++++++
 .../cloudstack/ldap/LdapConfigurationVO.java    |  66 ++++
 .../cloudstack/ldap/LdapContextFactory.java     | 103 ++++++
 .../org/apache/cloudstack/ldap/LdapManager.java |  50 +++
 .../apache/cloudstack/ldap/LdapManagerImpl.java | 205 ++++++++++++
 .../org/apache/cloudstack/ldap/LdapUser.java    |  75 +++++
 .../apache/cloudstack/ldap/LdapUserManager.java |  98 ++++++
 .../org/apache/cloudstack/ldap/LdapUtils.java   |  61 ++++
 .../ldap/NoLdapUserMatchingQueryException.java  |  32 ++
 .../ldap/NoSuchLdapUserException.java           |  31 ++
 .../ldap/dao/LdapConfigurationDao.java          |  30 ++
 .../ldap/dao/LdapConfigurationDaoImpl.java      |  66 ++++
 .../ldap/BasicNamingEnumerationImpl.groovy      |  56 ++++
 .../ldap/LdapAddConfigurationCmdSpec.groovy     |  89 ++++++
 .../ldap/LdapAuthenticatorSpec.groovy           |  90 ++++++
 .../ldap/LdapConfigurationDaoImplSpec.groovy    |  29 ++
 .../ldap/LdapConfigurationResponseSpec.groovy   |  49 +++
 .../ldap/LdapConfigurationSpec.groovy           | 181 +++++++++++
 .../cloudstack/ldap/LdapConfigurationVO.groovy  |  36 +++
 .../ldap/LdapContextFactorySpec.groovy          | 134 ++++++++
 .../ldap/LdapDeleteConfigurationCmdSpec.groovy  |  68 ++++
 .../ldap/LdapListAllUsersCmdSpec.groovy         |  72 +++++
 .../ldap/LdapListConfigurationCmdSpec.groovy    | 100 ++++++
 .../cloudstack/ldap/LdapManagerImplSpec.groovy  | 319 +++++++++++++++++++
 .../ldap/LdapSearchUserCmdSpec.groovy           |  72 +++++
 .../cloudstack/ldap/LdapUserManagerSpec.groovy  | 207 ++++++++++++
 .../cloudstack/ldap/LdapUserResponseSpec.groovy |  67 ++++
 .../apache/cloudstack/ldap/LdapUserSpec.groovy  |  79 +++++
 .../apache/cloudstack/ldap/LdapUtilsSpec.groovy |  68 ++++
 .../NoLdapUserMatchingQueryExceptionSpec.groovy |  30 ++
 .../ldap/NoSuchLdapUserExceptionSpec.groovy     |  30 ++
 .../ldap/test/resources/cloudstack.org.ldif     |  19 ++
 server/src/com/cloud/api/ApiResponseHelper.java |  15 -
 server/src/com/cloud/configuration/Config.java  |  12 +-
 .../configuration/ConfigurationManagerImpl.java | 172 ----------
 .../com/cloud/server/ManagementServerImpl.java  |   4 -
 .../cloud/vpc/MockConfigurationManagerImpl.java |  31 --
 setup/db/db/schema-410to420.sql                 |  33 +-
 test/integration/component/test_ldap.py         | 287 ++++++-----------
 tools/apidoc/gen_toc.py                         |   2 +-
 ui/css/cloudstack3.css                          |  84 ++++-
 ui/index.jsp                                    |  61 +++-
 ui/scripts/accounts.js                          |  13 +-
 ui/scripts/accountsWizard.js                    | 158 +++++++++
 ui/scripts/globalSettings.js                    | 143 +--------
 ui/scripts/ui-custom/accountsWizard.js          | 116 +++++++
 70 files changed, 4230 insertions(+), 1210 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/com/cloud/configuration/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java
index 381fcad..cc6e47f 100644
--- a/api/src/com/cloud/configuration/ConfigurationService.java
+++ b/api/src/com/cloud/configuration/ConfigurationService.java
@@ -26,8 +26,6 @@ import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.exception.ResourceAllocationException;
 import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
-import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd;
-import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd;
 import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
 import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
 import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
@@ -272,12 +270,6 @@ public interface ConfigurationService {
 
     DiskOffering getDiskOffering(long diskOfferingId);
 
-    boolean updateLDAP(LDAPConfigCmd cmd) throws NamingException;
-
-	boolean removeLDAP(LDAPRemoveCmd cmd);
-
-    LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd);
-
     /**
      * @param offering
      * @return

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 121403f..4fbbf52 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -525,15 +525,4 @@ public class ApiConstants {
     public enum VMDetails {
         all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp;
     }
-
-    public enum LDAPParams {
-        hostname, port, usessl, queryfilter, searchbase, dn, passwd, truststore, truststorepass;
-
-        @Override
-        public String toString() {
-            return "ldap." + name();
-        }
-    }
-
-
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/ResponseGenerator.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index d8d07cb..372fc9d 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -129,7 +129,6 @@ import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
 import org.apache.cloudstack.api.response.IsolationMethodResponse;
 import org.apache.cloudstack.api.response.LBHealthCheckResponse;
 import org.apache.cloudstack.api.response.LBStickinessResponse;
-import org.apache.cloudstack.api.response.LDAPConfigResponse;
 import org.apache.cloudstack.api.response.LoadBalancerResponse;
 import org.apache.cloudstack.api.response.NetworkACLItemResponse;
 import org.apache.cloudstack.api.response.NetworkACLResponse;
@@ -363,8 +362,6 @@ public interface ResponseGenerator {
 
     VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result);
 
-    LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String baseSearch, String dn);
-
     StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result);
 
     RegionResponse createRegionResponse(Region region);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java
deleted file mode 100644
index 6f8b7b1..0000000
--- a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java
+++ /dev/null
@@ -1,206 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.api.command.admin.ldap;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.NamingException;
-
-import org.apache.cloudstack.api.APICommand;
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.Parameter;
-import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.response.LDAPConfigResponse;
-import org.apache.cloudstack.api.response.ListResponse;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.log4j.Logger;
-
-import com.cloud.exception.ConcurrentOperationException;
-import com.cloud.exception.InsufficientCapacityException;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.user.Account;
-
-@APICommand(name = "ldapConfig", description="Configure the LDAP context for this site.", responseObject=LDAPConfigResponse.class, since="3.0.0")
-public class LDAPConfigCmd extends BaseCmd  {
-    public static final Logger s_logger = Logger.getLogger(LDAPConfigCmd.class.getName());
-
-    private static final String s_name = "ldapconfigresponse";
-
-    /////////////////////////////////////////////////////
-    //////////////// API parameters /////////////////////
-    /////////////////////////////////////////////////////
-    @Parameter(name=ApiConstants.LIST_ALL, type=CommandType.BOOLEAN,  description="If true return current LDAP configuration")
-    private Boolean listAll;
-    
-    @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING,  description="Hostname or ip address of the ldap server eg: my.ldap.com")
-    private String hostname;
-
-    @Parameter(name=ApiConstants.PORT, type=CommandType.INTEGER, description="Specify the LDAP port if required, default is 389.")
-    private Integer port=0;
-
-    @Parameter(name=ApiConstants.USE_SSL, type=CommandType.BOOLEAN, description="Check Use SSL if the external LDAP server is configured for LDAP over SSL.")
-    private Boolean useSSL;
-
-    @Parameter(name=ApiConstants.SEARCH_BASE, type=CommandType.STRING,  description="The search base defines the starting point for the search in the directory tree Example:  dc=cloud,dc=com.")
-    private String searchBase;
-
-    @Parameter(name=ApiConstants.QUERY_FILTER, type=CommandType.STRING,  description="You specify a query filter here, which narrows down the users, who can be part of this domain.")
-    private String queryFilter;
-
-    @Parameter(name=ApiConstants.BIND_DN, type=CommandType.STRING, description="Specify the distinguished name of a user with the search permission on the directory.")
-    private String bindDN;
-
-    @Parameter(name=ApiConstants.BIND_PASSWORD, type=CommandType.STRING, description="Enter the password.")
-    private String bindPassword;
-
-    @Parameter(name=ApiConstants.TRUST_STORE, type=CommandType.STRING, description="Enter the path to trust certificates store.")
-    private String trustStore;
-
-    @Parameter(name=ApiConstants.TRUST_STORE_PASSWORD, type=CommandType.STRING, description="Enter the password for trust store.")
-    private String trustStorePassword;
-
-    /////////////////////////////////////////////////////
-    /////////////////// Accessors ///////////////////////
-    /////////////////////////////////////////////////////
-
-    public Boolean getListAll() {
-    	return listAll == null ? Boolean.FALSE : listAll;
-    }
-    
-    public String getBindPassword() {
-        return bindPassword;
-    }
-
-    public String getBindDN() {
-        return bindDN;
-    }
-
-    public void setBindDN(String bdn) {
-        this.bindDN=bdn;
-    }
-
-    public String getQueryFilter() {
-        return queryFilter;
-    }
-
-    public void setQueryFilter(String queryFilter) {
-        this.queryFilter=StringEscapeUtils.unescapeHtml(queryFilter);
-    }
-    public String getSearchBase() {
-        return searchBase;
-    }
-
-    public void setSearchBase(String searchBase) {
-        this.searchBase=searchBase;
-    }
-
-    public Boolean getUseSSL() {
-        return useSSL == null ? Boolean.FALSE : useSSL;
-    }
-
-    public void setUseSSL(Boolean useSSL) {
-        this.useSSL=useSSL;
-    }
-
-    public String getHostname() {
-        return hostname;
-    }
-
-    public void setHostname(String hostname) {
-        this.hostname=hostname;
-    }
-
-    public Integer getPort() {
-        return port <= 0 ? 389 : port;
-    }
-
-    public void setPort(Integer port) {
-        this.port=port;
-    }
-
-    public String getTrustStore() {
-        return trustStore;
-    }
-
-    public void setTrustStore(String trustStore) {
-        this.trustStore=trustStore;
-    }
-
-    public String getTrustStorePassword() {
-        return trustStorePassword;
-    }
-
-
-    /////////////////////////////////////////////////////
-    /////////////// API Implementation///////////////////
-    /////////////////////////////////////////////////////
-
-
-    @Override
-    public void execute() throws ResourceUnavailableException,
-            InsufficientCapacityException, ServerApiException,
-            ConcurrentOperationException, ResourceAllocationException {
-          try {
-              if (getListAll()){
-                  // return the existing conf
-                  LDAPConfigCmd cmd = _configService.listLDAPConfig(this);
-                  ListResponse<LDAPConfigResponse> response = new ListResponse<LDAPConfigResponse>();
-                  List<LDAPConfigResponse> responses = new ArrayList<LDAPConfigResponse>();
-
-                  if(!cmd.getHostname().equals("")) {
-                  	responses.add(_responseGenerator.createLDAPConfigResponse(cmd.getHostname(), cmd.getPort(), cmd.getUseSSL(), cmd.getQueryFilter(), cmd.getSearchBase(), cmd.getBindDN()));
-                  }
-                  
-                  response.setResponses(responses);
-                  response.setResponseName(getCommandName());
-                  this.setResponseObject(response);
-              }
-              else if (getHostname()==null || getSearchBase() == null || getQueryFilter() == null) {
-                  throw new InvalidParameterValueException("You need to provide hostname, searchbase and queryfilter to configure your LDAP server");
-              }
-              else {
-                  boolean result = _configService.updateLDAP(this);
-                  if (result){
-                      LDAPConfigResponse lr = _responseGenerator.createLDAPConfigResponse(getHostname(), getPort(), getUseSSL(), getQueryFilter(), getSearchBase(), getBindDN());
-                      lr.setResponseName(getCommandName());
-                      this.setResponseObject(lr);
-                  }
-              }
-          }
-          catch (NamingException ne){
-              ne.printStackTrace();
-          }
-
-    }
-
-    @Override
-    public String getCommandName() {
-        return s_name;
-    }
-
-    @Override
-    public long getEntityOwnerId() {
-        return Account.ACCOUNT_ID_SYSTEM;
-    }
-
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPRemoveCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPRemoveCmd.java b/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPRemoveCmd.java
deleted file mode 100644
index 5159fba..0000000
--- a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPRemoveCmd.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.api.command.admin.ldap;
-
-
-import org.apache.cloudstack.api.APICommand;
-import org.apache.cloudstack.api.BaseCmd;
-import org.apache.cloudstack.api.response.LDAPConfigResponse;
-import org.apache.cloudstack.api.response.LDAPRemoveResponse;
-import org.apache.log4j.Logger;
-
-import com.cloud.user.Account;
-
-@APICommand(name = "ldapRemove", description="Remove the LDAP context for this site.", responseObject=LDAPConfigResponse.class, since="3.0.1")
-public class LDAPRemoveCmd extends BaseCmd  {
-    public static final Logger s_logger = Logger.getLogger(LDAPRemoveCmd.class.getName());
-
-    private static final String s_name = "ldapremoveresponse";
-
-    /////////////////////////////////////////////////////
-    //////////////// API parameters /////////////////////
-    /////////////////////////////////////////////////////
-
-
-    /////////////////////////////////////////////////////
-    /////////////////// Accessors ///////////////////////
-    /////////////////////////////////////////////////////
-
-
-    /////////////////////////////////////////////////////
-    /////////////// API Implementation///////////////////
-    /////////////////////////////////////////////////////
-
-
-    @Override
-    public void execute(){
-          boolean result = _configService.removeLDAP(this);
-          if (result){
-              LDAPRemoveResponse lr = new LDAPRemoveResponse();
-              lr.setObjectName("ldapremove");
-              lr.setResponseName(getCommandName());
-              this.setResponseObject(lr);
-          }
-    }
-
-    @Override
-    public String getCommandName() {
-        return s_name;
-    }
-
-    @Override
-    public long getEntityOwnerId() {
-        return Account.ACCOUNT_ID_SYSTEM;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java b/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java
deleted file mode 100644
index bbeec63..0000000
--- a/api/src/org/apache/cloudstack/api/response/LDAPConfigResponse.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.api.response;
-
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
-
-import com.cloud.serializer.Param;
-import com.google.gson.annotations.SerializedName;
-
-public class LDAPConfigResponse  extends BaseResponse {
-
-    @SerializedName(ApiConstants.HOST_NAME) @Param(description="Hostname or ip address of the ldap server eg: my.ldap.com")
-    private String hostname;
-
-    @SerializedName(ApiConstants.PORT) @Param(description="Specify the LDAP port if required, default is 389")
-    private String port;
-
-    @SerializedName(ApiConstants.USE_SSL) @Param(description="Check Use SSL if the external LDAP server is configured for LDAP over SSL")
-    private String useSSL;
-
-    @SerializedName(ApiConstants.SEARCH_BASE) @Param(description="The search base defines the starting point for the search in the directory tree Example:  dc=cloud,dc=com")
-    private String searchBase;
-
-    @SerializedName(ApiConstants.QUERY_FILTER) @Param(description="You specify a query filter here, which narrows down the users, who can be part of this domain")
-    private String queryFilter;
-
-    @SerializedName(ApiConstants.BIND_DN) @Param(description="Specify the distinguished name of a user with the search permission on the directory")
-    private String bindDN;
-
-    @SerializedName(ApiConstants.BIND_PASSWORD) @Param(description="DN password")
-    private String bindPassword;
-
-    public String getHostname() {
-        return hostname;
-    }
-
-    public void setHostname(String hostname) {
-        this.hostname = hostname;
-    }
-
-    public String getPort() {
-        return port;
-    }
-
-    public void setPort(String port) {
-        this.port = port;
-    }
-
-    public String getUseSSL() {
-        return useSSL;
-    }
-
-    public void setUseSSL(String useSSL) {
-        this.useSSL = useSSL;
-    }
-
-    public String getSearchBase() {
-        return searchBase;
-    }
-
-    public void setSearchBase(String searchBase) {
-        this.searchBase = searchBase;
-    }
-
-    public String getQueryFilter() {
-        return queryFilter;
-    }
-
-    public void setQueryFilter(String queryFilter) {
-        this.queryFilter = queryFilter;
-    }
-
-    public String getBindDN() {
-        return bindDN;
-    }
-
-    public void setBindDN(String bindDN) {
-        this.bindDN = bindDN;
-    }
-
-    public String getBindPassword() {
-        return bindPassword;
-    }
-
-    public void setBindPassword(String bindPassword) {
-        this.bindPassword = bindPassword;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/api/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java b/api/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java
deleted file mode 100644
index 0feec5b..0000000
--- a/api/src/org/apache/cloudstack/api/response/LDAPRemoveResponse.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.api.response;
-
-import org.apache.cloudstack.api.BaseResponse;
-
-public class LDAPRemoveResponse extends BaseResponse {
-
-    public LDAPRemoveResponse(){
-        super();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/client/tomcatconf/applicationContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 343a8a1..f29d72f 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -391,7 +391,7 @@
   <bean id="MD5UserAuthenticator" class="com.cloud.server.auth.MD5UserAuthenticator">
     <property name="name" value="MD5"/>
   </bean>
-  <bean id="LDAPUserAuthenticator" class="com.cloud.server.auth.LDAPUserAuthenticator">
+  <bean id="LdapAuthenticator" class="org.apache.cloudstack.ldap.LdapAuthenticator">
     <property name="name" value="LDAP"/>
   </bean>
   <bean id="SHA256SaltedUserAuthenticator" class="com.cloud.server.auth.SHA256SaltedUserAuthenticator">
@@ -400,6 +400,11 @@
   <bean id="PlainTextUserAuthenticator" class="com.cloud.server.auth.PlainTextUserAuthenticator">
     <property name="name" value="PLAINTEXT"/>
   </bean>
+  <bean id="LdapManager" class="org.apache.cloudstack.ldap.LdapManagerImpl" />
+  <bean id="LdapUserManager" class="org.apache.cloudstack.ldap.LdapUserManager" />
+  <bean id="LdapContextFactory" class="org.apache.cloudstack.ldap.LdapContextFactory" />
+  <bean id="LdapConfigurationDao" class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
+  <bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
 
   <!--
       Network Elements

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index d8d176f..b275017 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-# 
+#
 #   http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -210,8 +210,6 @@ scaleSystemVm=1
 #### configuration commands
 updateConfiguration=1
 listConfigurations=1
-ldapConfig=1
-ldapRemove=1
 listCapabilities=15
 listDeploymentPlanners=1
 cleanVMReservations=1
@@ -381,12 +379,12 @@ listProjectInvitations=15
 updateProjectInvitation=15
 deleteProjectInvitation=15
 
-#### 
+####
 createFirewallRule=15
 deleteFirewallRule=15
 listFirewallRules=15
 
-#### 
+####
 createEgressFirewallRule=15
 deleteEgressFirewallRule=15
 listEgressFirewallRules=15
@@ -666,3 +664,11 @@ listDedicatedZones=1
 listDedicatedPods=1
 listDedicatedClusters=1
 listDedicatedHosts=1
+
+### LDAP
+searchLdap=3
+listLdapConfigurations=3
+addLdapConfiguration=3
+deleteLdapConfiguration=3
+listAllLdapUsers=3
+ldapCreateAccount=3

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/client/tomcatconf/componentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in
index 1fbec61..39eab5e 100644
--- a/client/tomcatconf/componentContext.xml.in
+++ b/client/tomcatconf/componentContext.xml.in
@@ -127,7 +127,7 @@
       <list>
           <ref bean="SHA256SaltedUserAuthenticator"/>
           <ref bean="MD5UserAuthenticator"/>
-          <ref bean="LDAPUserAuthenticator"/>
+          <ref bean="LdapAuthenticator"/>
           <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>
@@ -137,7 +137,7 @@
       <list>
           <ref bean="SHA256SaltedUserAuthenticator"/>
           <ref bean="MD5UserAuthenticator"/>
-          <ref bean="LDAPUserAuthenticator"/>
+          <ref bean="LdapAuthenticator"/>
           <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/client/tomcatconf/nonossComponentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in
index 6fd51ef..c8a71eb 100644
--- a/client/tomcatconf/nonossComponentContext.xml.in
+++ b/client/tomcatconf/nonossComponentContext.xml.in
@@ -224,7 +224,7 @@
       <list>
           <ref bean="SHA256SaltedUserAuthenticator"/>
           <ref bean="MD5UserAuthenticator"/>
-          <ref bean="LDAPUserAuthenticator"/>
+          <ref bean="LdapAuthenticator"/>
           <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>
@@ -234,7 +234,7 @@
       <list>
           <ref bean="SHA256SaltedUserAuthenticator"/>
           <ref bean="MD5UserAuthenticator"/>
-          <ref bean="LDAPUserAuthenticator"/>
+          <ref bean="LdapAuthenticator"/>
           <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/client/tomcatconf/simulatorComponentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in
index 7225e84..099bdb6 100644
--- a/client/tomcatconf/simulatorComponentContext.xml.in
+++ b/client/tomcatconf/simulatorComponentContext.xml.in
@@ -73,7 +73,7 @@
       <list>
         <ref bean="SHA256SaltedUserAuthenticator"/>
         <ref bean="MD5UserAuthenticator"/>
-        <ref bean="LDAPUserAuthenticator"/>
+        <ref bean="LdapAuthenticator"/>
         <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>
@@ -83,7 +83,7 @@
       <list>
         <ref bean="SHA256SaltedUserAuthenticator"/>
         <ref bean="MD5UserAuthenticator"/>
-        <ref bean="LDAPUserAuthenticator"/>
+        <ref bean="LdapAuthenticator"/>
         <ref bean="PlainTextUserAuthenticator"/>
       </list>
     </property>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java
----------------------------------------------------------------------
diff --git a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java
index 7d1b43a..5566511 100644
--- a/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java
+++ b/plugins/api/rate-limit/src/org/apache/cloudstack/ratelimit/ApiRateLimitServiceImpl.java
@@ -29,7 +29,6 @@ import net.sf.ehcache.CacheManager;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.acl.APIChecker;
-import org.apache.cloudstack.api.ApiConstants.LDAPParams;
 import org.apache.cloudstack.api.command.admin.ratelimit.ResetApiLimitCmd;
 import org.apache.cloudstack.api.command.user.ratelimit.GetApiLimitCmd;
 import org.apache.cloudstack.api.response.ApiLimitResponse;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml
index 5c45f11..a00d189 100644
--- a/plugins/user-authenticators/ldap/pom.xml
+++ b/plugins/user-authenticators/ldap/pom.xml
@@ -1,22 +1,14 @@
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements. See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership. The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License. You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied. See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+  license agreements. See the NOTICE file distributed with this work for additional
+  information regarding copyright ownership. The ASF licenses this file to you under
+  the Apache License, Version 2.0 (the "License"); you may not use this file except
+  in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+  Unless required by applicable law or agreed to in writing, software distributed under
+  the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+  OF ANY KIND, either express or implied. See the License for the specific language
+  governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <artifactId>cloud-plugin-user-authenticator-ldap</artifactId>
   <name>Apache CloudStack Plugin - User Authenticator LDAP</name>
@@ -26,4 +18,93 @@
     <version>4.2.0-SNAPSHOT</version>
     <relativePath>../../pom.xml</relativePath>
   </parent>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.gmaven</groupId>
+        <artifactId>gmaven-plugin</artifactId>
+        <version>1.3</version>
+        <configuration>
+          <providerSelection>1.7</providerSelection>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>compile</goal>
+              <goal>testCompile</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <fileset>
+                  <directory>test/groovy</directory>
+                  <includes>
+                    <include>**/*.groovy</include>
+                  </includes>
+                </fileset>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+        <dependencies>
+          <dependency>
+            <groupId>org.codehaus.gmaven.runtime</groupId>
+            <artifactId>gmaven-runtime-1.7</artifactId>
+            <version>1.3</version>
+            <exclusions>
+              <exclusion>
+                <groupId>org.codehaus.groovy</groupId>
+                <artifactId>groovy-all</artifactId>
+              </exclusion>
+            </exclusions>
+          </dependency>
+          <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+            <version>2.0.5</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>**/*Spec*</include>
+          </includes>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>com.btmatthews.maven.plugins</groupId>
+        <artifactId>ldap-maven-plugin</artifactId>
+        <version>1.1.0</version>
+        <configuration>
+          <monitorPort>11389</monitorPort>
+            <monitorKey>ldap</monitorKey>
+            <daemon>false</daemon>
+            <rootDn>dc=cloudstack,dc=org</rootDn>
+            <ldapPort>10389</ldapPort>
+            <ldifFile>test/resources/cloudstack.org.ldif</ldifFile>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
+
+  <dependencies>
+    <!-- Mandatory dependencies for using Spock -->
+    <dependency>
+      <groupId>org.spockframework</groupId>
+      <artifactId>spock-core</artifactId>
+      <version>0.7-groovy-2.0</version>
+    </dependency>
+
+    <!-- Optional dependencies for using Spock -->
+    <dependency> <!-- enables mocking of classes (in addition to interfaces) -->
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <version>2.2</version>
+    </dependency>
+  </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java b/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java
deleted file mode 100644
index d928a5b..0000000
--- a/plugins/user-authenticators/ldap/src/com/cloud/server/auth/LDAPUserAuthenticator.java
+++ /dev/null
@@ -1,173 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one or more
-// contributor license agreements.  See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership.
-// The ASF licenses this file to You under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with
-// the License.  You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-package com.cloud.server.auth;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Hashtable;
-import java.util.Map;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-
-import org.apache.cloudstack.api.ApiConstants.LDAPParams;
-import org.apache.log4j.Logger;
-import org.bouncycastle.util.encoders.Base64;
-
-import com.cloud.configuration.dao.ConfigurationDao;
-import com.cloud.user.UserAccount;
-import com.cloud.user.dao.UserAccountDao;
-import com.cloud.utils.exception.CloudRuntimeException;
-
-@Local(value={UserAuthenticator.class})
-public class LDAPUserAuthenticator extends DefaultUserAuthenticator {
-    public static final Logger s_logger = Logger.getLogger(LDAPUserAuthenticator.class);
-
-    @Inject private ConfigurationDao _configDao;
-    @Inject private UserAccountDao _userAccountDao;
-
-    @Override
-    public boolean authenticate(String username, String password, Long domainId, Map<String, Object[]> requestParameters ) {
-        if (s_logger.isDebugEnabled()) {
-            s_logger.debug("Retrieving user: " + username);
-        }
-        UserAccount user = _userAccountDao.getUserAccount(username, domainId);
-        if (user == null) {
-            s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
-            return false;
-        }
-
-        String url = _configDao.getValue(LDAPParams.hostname.toString());
-        if (url==null){
-            s_logger.debug("LDAP authenticator is not configured.");
-            return false;
-        }
-        String port = _configDao.getValue(LDAPParams.port.toString());
-        String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString());
-        String searchBase = _configDao.getValue(LDAPParams.searchbase.toString());
-        Boolean useSSL = Boolean.valueOf(_configDao.getValue(LDAPParams.usessl.toString()));
-        String bindDN = _configDao.getValue(LDAPParams.dn.toString());
-        String bindPasswd = _configDao.getValue(LDAPParams.passwd.toString());
-        String trustStore = _configDao.getValue(LDAPParams.truststore.toString());
-        String trustStorePassword = _configDao.getValue(LDAPParams.truststorepass.toString());
-
-        try {
-            // get all params
-            Hashtable<String, String> env = new Hashtable<String, String>(11);
-            env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
-            String protocol = "ldap://" ;
-            if (useSSL){
-                env.put(Context.SECURITY_PROTOCOL, "ssl");
-                protocol="ldaps://" ;
-                System.setProperty("javax.net.ssl.trustStore", trustStore);
-                System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
-            }
-            env.put(Context.PROVIDER_URL, protocol + url  + ":" + port);
-
-            if (bindDN != null && bindPasswd != null){
-                env.put(Context.SECURITY_PRINCIPAL, bindDN);
-                env.put(Context.SECURITY_CREDENTIALS, bindPasswd);
-            }
-            else {
-                // Use anonymous authentication
-                env.put(Context.SECURITY_AUTHENTICATION, "none");
-            }
-            // Create the initial context
-            DirContext ctx = new InitialDirContext(env);
-            // use this context to search
-
-            // substitute the queryFilter with this user info
-            queryFilter = queryFilter.replaceAll("\\%u", username);
-            queryFilter = queryFilter.replaceAll("\\%n", user.getFirstname() + " " + user.getLastname());
-            queryFilter = queryFilter.replaceAll("\\%e", user.getEmail());
-
-
-            SearchControls sc = new SearchControls();
-            String[] searchFilter = { "dn" };
-            sc.setReturningAttributes(new String[0]); //return no attributes
-            sc.setReturningAttributes(searchFilter);
-            sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
-            sc.setCountLimit(1);
-
-            // Search for objects with those matching attributes
-            NamingEnumeration<SearchResult> answer = ctx.search(searchBase, queryFilter,  sc);
-            SearchResult sr = answer.next();
-            String cn = sr.getName();
-            answer.close();
-            ctx.close();
-
-            s_logger.info("DN from LDAP =" + cn);
-
-            // check the password
-            env = new Hashtable<String, String>(11);
-            env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
-            protocol = "ldap://" ;
-            if (useSSL){
-                env.put(Context.SECURITY_PROTOCOL, "ssl");
-                protocol="ldaps://" ;
-            }
-            env.put(Context.PROVIDER_URL, protocol + url  + ":" + port);
-            env.put(Context.SECURITY_PRINCIPAL, cn + "," + searchBase);
-            env.put(Context.SECURITY_CREDENTIALS, password);
-            // Create the initial context
-            ctx = new InitialDirContext(env);
-            ctx.close();
-
-        } catch (NamingException ne) {
-            s_logger.warn("Authentication Failed ! " + ne.getMessage() + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : ""));
-            return false;
-        }
-        catch (Exception e){
-            e.printStackTrace();
-            s_logger.warn("Unknown error encountered " + e.getMessage());
-            return false;
-        }
-
-        // authenticate
-        return true;
-    }
-
-    @Override
-    public boolean configure(String name, Map<String, Object> params)
-            throws ConfigurationException {
-        if (name == null) {
-            name = "LDAP";
-        }
-	super.configure(name, params);
-        return true;
-    }
-
-    @Override
-    public String encode(String password) {
-        // Password is not used, so set to a random string
-        try {
-            SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
-            byte bytes[] = new byte[20];
-            randomGen.nextBytes(bytes);
-            return Base64.encode(bytes).toString();
-        } catch (NoSuchAlgorithmException e) {
-            throw new CloudRuntimeException("Failed to generate random password",e);
-        }	
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
new file mode 100644
index 0000000..b8e08e5
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
@@ -0,0 +1,80 @@
+package org.apache.cloudstack.api.command;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.LdapConfigurationResponse;
+import org.apache.cloudstack.ldap.LdapManager;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+
+@APICommand(name = "addLdapConfiguration", description = "Add a new Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
+public class LdapAddConfigurationCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(LdapAddConfigurationCmd.class.getName());
+    private static final String s_name = "ldapconfigurationresponse";
+
+    @Inject
+    private LdapManager _ldapManager;
+
+    @Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
+    private String hostname;
+
+    @Parameter(name = "port", type = CommandType.INTEGER, required = true, description = "Port")
+    private int port;
+
+    public LdapAddConfigurationCmd() {
+        super();
+    }
+
+    public LdapAddConfigurationCmd(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    @Override
+    public void execute() throws ServerApiException {
+        try {
+            final LdapConfigurationResponse response = _ldapManager.addConfiguration(hostname, port);
+            response.setObjectName("LdapAddConfiguration");
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } catch (final InvalidParameterValueException e) {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.toString());
+        }
+
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    public String getHostname() {
+        return hostname;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setHostname(final String hostname) {
+        this.hostname = hostname;
+    }
+
+    public void setPort(final int port) {
+        this.port = port;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccount.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccount.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccount.java
new file mode 100644
index 0000000..01aebce
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccount.java
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.naming.NamingException;
+
+import org.apache.log4j.Logger;
+import org.bouncycastle.util.encoders.Base64;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.ldap.LdapManager;
+import org.apache.cloudstack.ldap.LdapUser;
+
+import com.cloud.user.Account;
+import com.cloud.user.UserAccount;
+
+@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0")
+public class LdapCreateAccount extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(LdapCreateAccount.class.getName());
+    private static final String s_name = "createaccountresponse";
+
+    @Inject
+    private LdapManager _ldapManager;
+
+    @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.")
+    private String accountName;
+
+    @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account.  Specify 0 for user, 1 for root admin, and 2 for domain admin")
+    private Short accountType;
+
+    @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class,
+            description = "Creates the user under the specified domain.")
+    private Long domainId;
+
+    @Parameter(name = ApiConstants.TIMEZONE, type = CommandType.STRING, description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
+    private String timeZone;
+
+    @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Unique username.")
+    private String userName;
+
+    @Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "Network domain for the account's networks")
+    private String networkDomain;
+
+    @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.ACCOUNT_ID, type = CommandType.STRING, description = "Account UUID, required for adding account from external provisioning system")
+    private String accountUUID;
+
+    @Parameter(name = ApiConstants.USER_ID, type = CommandType.STRING, description = "User UUID, required for adding account from external provisioning system")
+    private String userUUID;
+
+    public LdapCreateAccount() {
+        super();
+    }
+
+    public LdapCreateAccount(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    @Override
+    public void execute() throws ServerApiException {
+        CallContext.current().setEventDetails("Account Name: " + accountName + ", Domain Id:" + domainId);
+        try {
+            LdapUser user = _ldapManager.getUser(userName);
+            validateUser(user);
+            UserAccount userAccount = _accountService.createUserAccount(userName, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timeZone,
+                    accountName, accountType, domainId, networkDomain, details, accountUUID, userUUID);
+            if (userAccount != null) {
+                AccountResponse response = _responseGenerator.createUserAccountResponse(userAccount);
+                response.setResponseName(getCommandName());
+                setResponseObject(response);
+            } else {
+                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a user account");
+            }
+        } catch (NamingException e) {
+            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, "No LDAP user exists with the username of " + userName);
+        }
+    }
+
+    private String generatePassword() throws ServerApiException {
+        try {
+            SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
+            byte bytes[] = new byte[20];
+            randomGen.nextBytes(bytes);
+            return Base64.encode(bytes).toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate random password");
+        }
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    private void validateUser(LdapUser user) throws ServerApiException {
+        if (user.getEmail() == null) {
+            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no email address set within LDAP");
+        }
+        if (user.getFirstname() == null) {
+            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no firstname set within LDAP");
+        }
+        if (user.getLastname() == null) {
+            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no lastname set within LDAP");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
new file mode 100644
index 0000000..b45bce5
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.LdapConfigurationResponse;
+import org.apache.cloudstack.ldap.LdapManager;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteLdapConfiguration", description = "Remove an Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
+public class LdapDeleteConfigurationCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(LdapDeleteConfigurationCmd.class.getName());
+    private static final String s_name = "ldapconfigurationresponse";
+
+    @Inject
+    private LdapManager _ldapManager;
+
+    @Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
+    private String hostname;
+
+    public LdapDeleteConfigurationCmd() {
+        super();
+    }
+
+    public LdapDeleteConfigurationCmd(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    @Override
+    public void execute() throws ServerApiException {
+        try {
+            final LdapConfigurationResponse response = _ldapManager.deleteConfiguration(hostname);
+            response.setObjectName("LdapDeleteConfiguration");
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } catch (final InvalidParameterValueException e) {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.toString());
+        }
+
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListAllUsersCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListAllUsersCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListAllUsersCmd.java
new file mode 100644
index 0000000..98c9fcf
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListAllUsersCmd.java
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.LdapUserResponse;
+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 com.cloud.user.Account;
+
+@APICommand(name = "listAllLdapUsers", responseObject = LdapUserResponse.class, description = "Lists all LDAP Users", since = "4.2.0")
+public class LdapListAllUsersCmd extends BaseListCmd {
+
+    public static final Logger s_logger = Logger.getLogger(LdapListAllUsersCmd.class.getName());
+    private static final String s_name = "ldapuserresponse";
+    @Inject
+    private LdapManager _ldapManager;
+
+    public LdapListAllUsersCmd() {
+        super();
+    }
+
+    public LdapListAllUsersCmd(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) {
+        final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>();
+        for (final LdapUser user : users) {
+            final LdapUserResponse ldapResponse = _ldapManager.createLdapUserResponse(user);
+            ldapResponse.setObjectName("LdapUser");
+            ldapResponses.add(ldapResponse);
+        }
+        return ldapResponses;
+    }
+
+    @Override
+    public void execute() throws ServerApiException {
+        try {
+            final List<LdapUser> users = _ldapManager.getUsers();
+            final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
+            final List<LdapUserResponse> ldapResponses = createLdapUserResponse(users);
+            response.setResponses(ldapResponses);
+            response.setResponseName(getCommandName());
+            setResponseObject(response);
+        } catch (final NoLdapUserMatchingQueryException ex) {
+            throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
+        }
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
new file mode 100644
index 0000000..fc9bd35
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
@@ -0,0 +1,106 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.LdapConfigurationResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.ldap.LdapConfigurationVO;
+import org.apache.cloudstack.ldap.LdapManager;
+
+import com.cloud.user.Account;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listLdapConfigurations", responseObject = LdapConfigurationResponse.class, description = "Lists all LDAP configurations", since = "4.2.0")
+public class LdapListConfigurationCmd extends BaseListCmd {
+    public static final Logger s_logger = Logger.getLogger(LdapListConfigurationCmd.class.getName());
+
+    private static final String s_name = "ldapconfigurationresponse";
+
+    @Inject
+    private LdapManager _ldapManager;
+
+    @Parameter(name = "hostname", type = CommandType.STRING, required = false, description = "Hostname")
+    private String hostname;
+
+    @Parameter(name = "port", type = CommandType.INTEGER, required = false, description = "Port")
+    private int port;
+
+    public LdapListConfigurationCmd() {
+        super();
+    }
+
+    public LdapListConfigurationCmd(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    private List<LdapConfigurationResponse> createLdapConfigurationResponses(List<? extends LdapConfigurationVO> configurations) {
+        final List<LdapConfigurationResponse> responses = new ArrayList<LdapConfigurationResponse>();
+        for (final LdapConfigurationVO resource : configurations) {
+            final LdapConfigurationResponse configurationResponse = _ldapManager.createLdapConfigurationResponse(resource);
+            configurationResponse.setObjectName("LdapConfiguration");
+            responses.add(configurationResponse);
+        }
+        return responses;
+    }
+
+    @Override
+    public void execute() {
+        final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(this);
+        final List<LdapConfigurationResponse> responses = createLdapConfigurationResponses(result.first());
+        final ListResponse<LdapConfigurationResponse> response = new ListResponse<LdapConfigurationResponse>();
+        response.setResponses(responses, result.second());
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+
+    public String getHostname() {
+        return hostname;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setHostname(final String hostname) {
+        this.hostname = hostname;
+    }
+
+    public void setPort(final int port) {
+        this.port = port;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapUserSearchCmd.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapUserSearchCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapUserSearchCmd.java
new file mode 100644
index 0000000..314581b
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapUserSearchCmd.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.LdapUserResponse;
+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 com.cloud.user.Account;
+
+@APICommand(name = "searchLdap", responseObject = LdapUserResponse.class, description = "Searches LDAP based on the username attribute", since = "4.2.0")
+public class LdapUserSearchCmd extends BaseListCmd {
+
+    public static final Logger s_logger = Logger.getLogger(LdapUserSearchCmd.class.getName());
+    private static final String s_name = "ldapuserresponse";
+    @Inject
+    private LdapManager _ldapManager;
+
+    @Parameter(name = "query", type = CommandType.STRING, entityType = LdapUserResponse.class, required = true, description = "query to search using")
+    private String query;
+
+    public LdapUserSearchCmd() {
+        super();
+    }
+
+    public LdapUserSearchCmd(final LdapManager ldapManager) {
+        super();
+        _ldapManager = ldapManager;
+    }
+
+    private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) {
+        final List<LdapUserResponse> ldapUserResponses = new ArrayList<LdapUserResponse>();
+        if (users != null) {
+            for (final LdapUser user : users) {
+                final LdapUserResponse ldapUserResponse = _ldapManager.createLdapUserResponse(user);
+                ldapUserResponse.setObjectName("LdapUser");
+                ldapUserResponses.add(ldapUserResponse);
+            }
+        }
+        return ldapUserResponses;
+    }
+
+    @Override
+    public void execute() {
+        final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
+        List<LdapUser> users = null;
+
+        try {
+            users = _ldapManager.searchUsers(query);
+        } catch (final NoLdapUserMatchingQueryException e) {
+            s_logger.debug(e.getMessage());
+        }
+
+        final List<LdapUserResponse> ldapUserResponses = createLdapUserResponse(users);
+
+        response.setResponses(ldapUserResponses);
+        response.setResponseName(getCommandName());
+        setResponseObject(response);
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
new file mode 100644
index 0000000..a4e4782
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class LdapConfigurationResponse extends BaseResponse {
+    @SerializedName("hostname")
+    @Param(description = "hostname")
+    private String hostname;
+
+    @SerializedName("port")
+    @Param(description = "port")
+    private int port;
+
+    public LdapConfigurationResponse() {
+        super();
+    }
+
+    public LdapConfigurationResponse(final String hostname) {
+        super();
+        this.hostname = hostname;
+    }
+
+    public LdapConfigurationResponse(final String hostname, final int port) {
+        this.hostname = hostname;
+        this.port = port;
+    }
+
+    public String getHostname() {
+        return hostname;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setHostname(final String hostname) {
+        this.hostname = hostname;
+    }
+
+    public void setPort(final int port) {
+        this.port = port;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapUserResponse.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapUserResponse.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapUserResponse.java
new file mode 100644
index 0000000..eb1c14c
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapUserResponse.java
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class LdapUserResponse extends BaseResponse {
+    @SerializedName("email")
+    @Param(description = "The user's email")
+    private String email;
+
+    @SerializedName("principal")
+    @Param(description = "The user's principle")
+    private String principal;
+
+    @SerializedName("firstname")
+    @Param(description = "The user's firstname")
+    private String firstname;
+
+    @SerializedName("lastname")
+    @Param(description = "The user's lastname")
+    private String lastname;
+
+    @SerializedName("username")
+    @Param(description = "The user's username")
+    private String username;
+
+    public LdapUserResponse() {
+        super();
+    }
+
+    public LdapUserResponse(final String username, final String email, final String firstname, final String lastname, final String principal) {
+        super();
+        this.username = username;
+        this.email = email;
+        this.firstname = firstname;
+        this.lastname = lastname;
+        this.principal = principal;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public String getFirstname() {
+        return firstname;
+    }
+
+    public String getLastname() {
+        return lastname;
+    }
+
+    public String getPrincipal() {
+        return principal;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setEmail(final String email) {
+        this.email = email;
+    }
+
+    public void setFirstname(final String firstname) {
+        this.firstname = firstname;
+    }
+
+    public void setLastname(final String lastname) {
+        this.lastname = lastname;
+    }
+
+    public void setPrincipal(final String principal) {
+        this.principal = principal;
+    }
+
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
new file mode 100644
index 0000000..54b6a8b
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.ldap;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
+
+import com.cloud.server.auth.DefaultUserAuthenticator;
+import com.cloud.user.UserAccount;
+import com.cloud.user.dao.UserAccountDao;
+
+public class LdapAuthenticator extends DefaultUserAuthenticator {
+    private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
+
+    @Inject
+    private LdapManager _ldapManager;
+    @Inject
+    private UserAccountDao _userAccountDao;
+
+    public LdapAuthenticator() {
+        super();
+    }
+
+    public LdapAuthenticator(final LdapManager ldapManager, final UserAccountDao userAccountDao) {
+        super();
+        _ldapManager = ldapManager;
+        _userAccountDao = userAccountDao;
+    }
+
+    @Override
+    public boolean authenticate(final String username, final String password, final Long domainId, final Map<String, Object[]> requestParameters) {
+
+        final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
+
+        if (user == null) {
+            s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
+            return false;
+        } else if (isLdapConfigurationPresent()) {
+            return _ldapManager.canAuthenticate(username, password);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String encode(final String password) {
+        return password;
+    }
+
+    private boolean isLdapConfigurationPresent() {
+        return _ldapManager.listConfigurations(new LdapListConfigurationCmd(_ldapManager)).second() > 0;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eaa41433/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
new file mode 100644
index 0000000..d0ae4d2
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
@@ -0,0 +1,116 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.ldap;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.naming.directory.SearchControls;
+
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
+
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.utils.Pair;
+
+public class LdapConfiguration {
+    private final static String factory = "com.sun.jndi.ldap.LdapCtxFactory";
+
+    private final static int scope = SearchControls.SUBTREE_SCOPE;
+
+    @Inject
+    private ConfigurationDao _configDao;
+
+    @Inject
+    private LdapManager _ldapManager;
+
+    public LdapConfiguration() {
+    }
+
+    public LdapConfiguration(final ConfigurationDao configDao, final LdapManager ldapManager) {
+        _configDao = configDao;
+        _ldapManager = ldapManager;
+    }
+
+    public String getAuthentication() {
+        if ((getBindPrincipal() == null) && (getBindPassword() == null)) {
+            return "none";
+        } else {
+            return "simple";
+        }
+    }
+
+    public String getBaseDn() {
+        return _configDao.getValue("ldap.basedn");
+    }
+
+    public String getBindPassword() {
+        return _configDao.getValue("ldap.bind.password");
+    }
+
+    public String getBindPrincipal() {
+        return _configDao.getValue("ldap.bind.principal");
+    }
+
+    public String getEmailAttribute() {
+        final String emailAttribute = _configDao.getValue("ldap.email.attribute");
+        return emailAttribute == null ? "mail" : emailAttribute;
+    }
+
+    public String getFactory() {
+        return factory;
+    }
+
+    public String getFirstnameAttribute() {
+        final String firstnameAttribute = _configDao.getValue("ldap.firstname.attribute");
+        return firstnameAttribute == null ? "givenname" : firstnameAttribute;
+    }
+
+    public String getLastnameAttribute() {
+        final String lastnameAttribute = _configDao.getValue("ldap.lastname.attribute");
+        return lastnameAttribute == null ? "sn" : lastnameAttribute;
+    }
+
+    public String getProviderUrl() {
+        final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(new LdapListConfigurationCmd(_ldapManager));
+        final StringBuilder providerUrls = new StringBuilder();
+        String delim = "";
+        for (final LdapConfigurationVO resource : result.first()) {
+            final String providerUrl = "ldap://" + resource.getHostname() + ":" + resource.getPort();
+            providerUrls.append(delim).append(providerUrl);
+            delim = " ";
+        }
+        return providerUrls.toString();
+    }
+
+    public String[] getReturnAttributes() {
+        return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute()};
+    }
+
+    public int getScope() {
+        return scope;
+    }
+
+    public String getUsernameAttribute() {
+        final String usernameAttribute = _configDao.getValue("ldap.username.attribute");
+        return usernameAttribute == null ? "uid" : usernameAttribute;
+    }
+
+    public String getUserObject() {
+        final String userObject = _configDao.getValue("ldap.user.object");
+        return userObject == null ? "inetOrgPerson" : userObject;
+    }
+}
\ No newline at end of file