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:33 UTC
[1/3] Add LDAP Plugin Implementation
Updated Branches:
refs/heads/ldapplugin 92884d1aa -> a90affe4b
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoSuchLdapUserExceptionSpec.groovy
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoSuchLdapUserExceptionSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoSuchLdapUserExceptionSpec.groovy
new file mode 100644
index 0000000..ece8d4b
--- /dev/null
+++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/NoSuchLdapUserExceptionSpec.groovy
@@ -0,0 +1,14 @@
+package groovy.org.apache.cloudstack.ldap
+
+import org.apache.cloudstack.ldap.NoSuchLdapUserException;
+
+class NoSuchLdapUserExceptionSpec extends spock.lang.Specification {
+ def "Test that the username is correctly set within the No such LDAP user exception object"() {
+ given: "You have created an No such LDAP user exception object with the username set"
+ def exception = new NoSuchLdapUserException(username)
+ expect: "The username is equal to the given data source"
+ exception.getUsername() == username
+ where: "The username is set to "
+ username << ["", null, "rmurphy"]
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 090d9c2..e667c69 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -78,7 +78,6 @@ import org.apache.cloudstack.api.response.LBHealthCheckPolicyResponse;
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
import org.apache.cloudstack.api.response.LBStickinessPolicyResponse;
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;
@@ -2807,20 +2806,6 @@ public class ApiResponseHelper implements ResponseGenerator {
}
@Override
- public LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String searchBase,
- String bindDN) {
- LDAPConfigResponse lr = new LDAPConfigResponse();
- lr.setHostname(hostname);
- lr.setPort(port.toString());
- lr.setUseSSL(useSSL.toString());
- lr.setQueryFilter(queryFilter);
- lr.setBindDN(bindDN);
- lr.setSearchBase(searchBase);
- lr.setObjectName("ldapconfig");
- return lr;
- }
-
- @Override
public StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result) {
StorageNetworkIpRangeResponse response = new StorageNetworkIpRangeResponse();
response.setUuid(result.getUuid());
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index d3ed718..d47a2a5 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation (ASF) under one
+//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
@@ -422,6 +422,15 @@ public enum Config {
// object store
S3EnableRRS("Advanced", ManagementServer.class, Boolean.class, "s3.rrs.enabled", "false", "enable s3 reduced redundancy storage", null),
+ // Ldap
+ LdapBasedn("Advanced", ManagementServer.class, String.class, "ldap.basedn", null, "Sets the basedn for LDAP", null),
+ LdapBindPassword("Advanced", ManagementServer.class, String.class, "ldap.bind.password", null, "Sets the bind password for LDAP", null),
+ LdapBindPrincipal("Advanced", ManagementServer.class, String.class, "ldap.bind.principal", null, "Sets the bind principal for LDAP", null),
+ LdapEmailAttribute("Advanced", ManagementServer.class, String.class, "ldap.email.attribute", "mail", "Sets the email attribute used within LDAP", null),
+ LdapRealnameAttribute("Advanced", ManagementServer.class, String.class, "ldap.realname.attribute", "cn", "Sets the realname attribute used within LDAP", null),
+ LdapUsernameAttribute("Advanced", ManagementServer.class, String.class, "ldap.username.attribute", "uid", "Sets the username attribute used within LDAP", null),
+ LdapUserObject("Advanced", ManagementServer.class, String.class, "ldap.user.object", "inetOrgPerson", "Sets the object type of users within LDAP", null),
+
// VMSnapshots
VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null),
VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null),
@@ -434,7 +443,7 @@ public enum Config {
InternalLbVmServiceOfferingId("Advanced", ManagementServer.class, String.class, "internallbvm.service.offering", null, "Uuid of the service offering used by internal lb vm; if NULL - default system internal lb offering will be used", null),
ExecuteInSequence("Advanced", ManagementServer.class, Boolean.class, "execute.in.sequence.hypervisor.commands", "false", "If set to true, StartCommand, StopCommand, CopyVolumeCommand, CreateCommand will be synchronized on the agent side." +
" If set to false, these commands become asynchronous. Default value is false.", null),
- ExecuteInSequenceNetworkElementCommands("Advanced", NetworkManager.class, Boolean.class, "execute.in.sequence.network.element.commands", "false", "If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side." +
+ ExecuteInSequenceNetworkElementCommands("Advanced", NetworkManager.class, Boolean.class, "execute.in.sequence.network.element.commands", "false", "If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side." +
" If set to false, these commands become asynchronous. Default value is false.", null);
private final String _category;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 8d8b126..8d73102 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -40,10 +40,7 @@ import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.apache.cloudstack.acl.SecurityChecker;
-import org.apache.cloudstack.api.ApiConstants.LDAPParams;
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;
@@ -1551,175 +1548,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override
@DB
- public boolean removeLDAP(LDAPRemoveCmd cmd) {
- _configDao.expunge(LDAPParams.hostname.toString());
- _configDao.expunge(LDAPParams.port.toString());
- _configDao.expunge(LDAPParams.queryfilter.toString());
- _configDao.expunge(LDAPParams.searchbase.toString());
- _configDao.expunge(LDAPParams.usessl.toString());
- _configDao.expunge(LDAPParams.dn.toString());
- _configDao.expunge(LDAPParams.passwd.toString());
- _configDao.expunge(LDAPParams.truststore.toString());
- _configDao.expunge(LDAPParams.truststorepass.toString());
- return true;
- }
-
- @Override
- @DB
- public LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd) {
- String hostname = _configDao.getValue(LDAPParams.hostname.toString());
- cmd.setHostname(hostname == null ? "" : hostname);
- String port = _configDao.getValue(LDAPParams.port.toString());
- cmd.setPort(port == null ? 0 : Integer.valueOf(port));
- String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString());
- cmd.setQueryFilter(queryFilter == null ? "" : queryFilter);
- String searchBase = _configDao.getValue(LDAPParams.searchbase.toString());
- cmd.setSearchBase(searchBase == null ? "" : searchBase);
- String useSSL = _configDao.getValue(LDAPParams.usessl.toString());
- cmd.setUseSSL(useSSL == null ? Boolean.FALSE : Boolean.valueOf(useSSL));
- String binddn = _configDao.getValue(LDAPParams.dn.toString());
- cmd.setBindDN(binddn == null ? "" : binddn);
- String truststore = _configDao.getValue(LDAPParams.truststore.toString());
- cmd.setTrustStore(truststore == null ? "" : truststore);
- return cmd;
- }
-
- @Override
- @DB
- public boolean updateLDAP(LDAPConfigCmd cmd) {
- try {
- // set the ldap details in the zone details table with a zone id of
- // -12
- String hostname = cmd.getHostname();
- Integer port = cmd.getPort();
- String queryFilter = cmd.getQueryFilter();
- String searchBase = cmd.getSearchBase();
- Boolean useSSL = cmd.getUseSSL();
- String bindDN = cmd.getBindDN();
- String bindPasswd = cmd.getBindPassword();
- String trustStore = cmd.getTrustStore();
- String trustStorePassword = cmd.getTrustStorePassword();
-
- if (bindDN != null && bindPasswd == null) {
- throw new InvalidParameterValueException(
- "If you specify a bind name then you need to provide bind password too.");
- }
-
- // check query filter if it contains valid substitution
- if (!queryFilter.contains("%u") && !queryFilter.contains("%n") && !queryFilter.contains("%e")) {
- throw new InvalidParameterValueException(
- "QueryFilter should contain at least one of the substitutions: %u, %n or %e: " + queryFilter);
- }
-
- // check if the info is correct
- 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://";
- if (trustStore == null || trustStorePassword == null) {
- throw new InvalidParameterValueException(
- "If you plan to use SSL then you need to configure the trust store.");
- }
- System.setProperty("javax.net.ssl.trustStore", trustStore);
- System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
- }
- env.put(Context.PROVIDER_URL, protocol + hostname + ":" + port);
- if (bindDN != null && bindPasswd != null) {
- env.put(Context.SECURITY_AUTHENTICATION, "simple");
- env.put(Context.SECURITY_PRINCIPAL, bindDN);
- env.put(Context.SECURITY_CREDENTIALS, bindPasswd);
- }
- // Create the initial context
- DirContext ctx = new InitialDirContext(env);
- ctx.close();
-
- // store the result in DB Configuration
- ConfigurationVO cvo = _configDao.findByName(LDAPParams.hostname.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.hostname.toString(),
- null, "Hostname or ip address of the ldap server eg: my.ldap.com");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(hostname));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.port.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.port.toString(), null,
- "Specify the LDAP port if required, default is 389");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(port.toString()));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.queryfilter.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.queryfilter.toString(),
- null,
- "You specify a query filter here, which narrows down the users, who can be part of this domain");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(queryFilter));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.searchbase.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.searchbase.toString(),
- null,
- "The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com.");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(searchBase));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.usessl.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.usessl.toString(), null,
- "Check Use SSL if the external LDAP server is configured for LDAP over SSL.");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(useSSL.toString()));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.dn.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.dn.toString(), null,
- "Specify the distinguished name of a user with the search permission on the directory");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(bindDN));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.passwd.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.passwd.toString(), null,
- "Enter the password");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(bindPasswd));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.truststore.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server", LDAPParams.truststore.toString(),
- null, "Enter the path to trusted keystore");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(trustStore));
- _configDao.persist(cvo);
-
- cvo = _configDao.findByName(LDAPParams.truststorepass.toString());
- if (cvo == null) {
- cvo = new ConfigurationVO("Hidden", "DEFAULT", "management-server",
- LDAPParams.truststorepass.toString(), null, "Enter the password for trusted keystore");
- }
- cvo.setValue(DBEncryptionUtil.encrypt(trustStorePassword));
- _configDao.persist(cvo);
-
- s_logger.debug("The ldap server is configured: " + hostname);
- } catch (NamingException ne) {
- throw new InvalidParameterValueException("Naming Exception, check you ldap data ! " + ne.getMessage()
- + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : ""));
- }
- return true;
- }
-
- @Override
- @DB
@ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "editing zone", async = false)
public DataCenter editZone(UpdateZoneCmd cmd) {
// Parameter validation as from execute() method in V1
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index da9d6a2..e5e28f9 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -88,8 +88,6 @@ import org.apache.cloudstack.api.command.admin.internallb.ListInternalLBVMsCmd;
import org.apache.cloudstack.api.command.admin.internallb.ListInternalLoadBalancerElementsCmd;
import org.apache.cloudstack.api.command.admin.internallb.StartInternalLBVMCmd;
import org.apache.cloudstack.api.command.admin.internallb.StopInternalLBVMCmd;
-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.AddNetworkDeviceCmd;
import org.apache.cloudstack.api.command.admin.network.AddNetworkServiceProviderCmd;
import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
@@ -2465,8 +2463,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(ReconnectHostCmd.class);
cmdList.add(UpdateHostCmd.class);
cmdList.add(UpdateHostPasswordCmd.class);
- cmdList.add(LDAPConfigCmd.class);
- cmdList.add(LDAPRemoveCmd.class);
cmdList.add(AddNetworkDeviceCmd.class);
cmdList.add(AddNetworkServiceProviderCmd.class);
cmdList.add(CreateNetworkOfferingCmd.class);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
index 7a61978..fe146b0 100755
--- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
@@ -26,8 +26,6 @@ import javax.naming.ConfigurationException;
import javax.naming.NamingException;
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;
@@ -87,8 +85,6 @@ import com.cloud.user.Account;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.VirtualMachine.Type;
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;
@@ -384,33 +380,6 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
}
/* (non-Javadoc)
- * @see com.cloud.configuration.ConfigurationService#updateLDAP(org.apache.cloudstack.api.commands.LDAPConfigCmd)
- */
- @Override
- public boolean updateLDAP(LDAPConfigCmd cmd) throws NamingException {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see com.cloud.configuration.ConfigurationService#removeLDAP(org.apache.cloudstack.api.commands.LDAPRemoveCmd)
- */
- @Override
- public boolean removeLDAP(LDAPRemoveCmd cmd) {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see com.cloud.configuration.ConfigurationService#listLDAPConfig(org.apache.cloudstack.api.commands.LDAPConfigCmd)
- */
- @Override
- public LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
* @see com.cloud.configuration.ConfigurationService#isOfferingForVpc(com.cloud.offering.NetworkOffering)
*/
@Override
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index 5edf733..039afd5 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -2238,3 +2238,18 @@ CREATE VIEW `cloud`.`project_view` AS
and resource_tags.resource_type = 'Project'
left join
`cloud`.`project_account` pacct ON projects.id = pacct.project_id;
+
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.bind.principal', NULL, 'Specifies the bind principal to use for bind to LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.bind.password', NULL, 'Specifies the password to use for binding to LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.username.attribute', 'uid', 'Sets the username attribute used within LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.email.attribute', 'mail', 'Sets the email attribute used within LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.realname.attribute', 'cn', 'Sets the realname attribute used within LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.user.object', 'inetOrgPerson', 'Sets the object type of users within LDAP');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.basedn', NULL, 'Sets the basedn for LDAP');
+
+CREATE TABLE `cloud`.`ldap_configuration` (
+ `id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
+ `hostname` varchar(255) NOT NULL COMMENT 'the hostname of the ldap server',
+ `port` int(10) COMMENT 'port that the ldap server is listening on',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/tools/apidoc/gen_toc.py
----------------------------------------------------------------------
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index 33a7e75..f582340 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -118,7 +118,7 @@ known_categories = {
'TrafficType': 'Usage',
'Product': 'Product',
'LB': 'Load Balancer',
- 'ldap': 'LDAP',
+ 'Ldap': 'LDAP',
'Swift': 'Swift',
'S3' : 'S3',
'SecondaryStorage': 'Host',
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/ui/scripts/globalSettings.js
----------------------------------------------------------------------
diff --git a/ui/scripts/globalSettings.js b/ui/scripts/globalSettings.js
index 1ae73b7..ac63015 100644
--- a/ui/scripts/globalSettings.js
+++ b/ui/scripts/globalSettings.js
@@ -14,343 +14,316 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-
-(function(cloudStack) {
- cloudStack.sections['global-settings'] = {
- title: 'label.menu.global.settings',
- id: 'global-settings',
- sectionSelect: {
- label: 'label.select-view'
- },
- sections: {
- globalSettings: {
- type: 'select',
+(function (cloudStack) {
+ cloudStack.sections['global-settings'] = {
title: 'label.menu.global.settings',
- listView: {
- label: 'label.menu.global.settings',
- actions: {
- edit: {
- label: 'label.change.value',
- action: function(args) {
- var data = {
- name: args.data.jsonObj.name,
- value: args.data.value
- };
- $.ajax({
- url: createURL('updateConfiguration'),
- data: data,
- success: function(json) {
- var item = json.updateconfigurationresponse.configuration;
- if(item.category == "Usage")
- cloudStack.dialog.notice({ message: _l('message.restart.mgmt.usage.server') });
- else
- cloudStack.dialog.notice({ message: _l('message.restart.mgmt.server') });
- args.response.success({data: item});
- },
- error: function(json) {
- args.response.error(parseXMLHttpResponse(json));
- }
- });
- }
- }
- },
- fields: {
- name: { label: 'label.name', id: true },
- description: { label: 'label.description' },
- value: { label: 'label.value', editable: true, truncate: true }
- },
- dataProvider: function(args) {
- var data = {
- page: args.page,
- pagesize: pageSize
- };
-
- if (args.filterBy.search.value) {
- data.name = args.filterBy.search.value;
- }
-
- $.ajax({
- url: createURL('listConfigurations'),
- data: data,
- dataType: "json",
- async: true,
- success: function(json) {
- var items = json.listconfigurationsresponse.configuration;
- args.response.success({ data: items });
- }
- });
- }
- }
- },
-
- ldapConfiguration:{
- type:'select',
- title:'LDAP Configuration',
- listView:{
- id:'ldap',
- label:'LDAP Configuration',
- fields:{
- hostname: {label: 'Hostname'},
- queryfilter: {label: 'Query Filter'},
- searchbase: {label: 'Search Base'},
- port: {label: 'LDAP Port'},
- ssl: {
- label: 'SSL'
-
- }
-
- },
- dataProvider:function(args){
- var data = {};
- listViewDataProvider(args, data);
- $.ajax({
- url: createURL('ldapConfig&listall=true'), //Need a list LDAP configuration API call which needs to be implemented
- data: data,
- success: function(json) {
- var items = json.ldapconfigresponse.ldapconfig;
- args.response.success({data:items});
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- },
-
- detailView: {
- name: 'label.details',
- actions: {
-
- // Remove LDAP
- remove: {
- label: 'Remove LDAP',
- messages: {
- notification: function(args) {
- return 'LDAP Configuration Deleted';
- },
- confirm: function() {
- return 'Are you sure you want to delete the LDAP configuration?';
- }
- },
- action: function(args) {
-
- $.ajax({
- url:createURL("ldapRemove"),
- success:function(json){
-
- args.response.success();
-
- }
-
- });
- $(window).trigger('cloudStack.fullRefresh');
-
- }
- }
- },
-
- tabs:{
-
- details: {
- title: 'LDAP Configuration Details',
- fields: [
- {
- hostname: { label: 'Hostname' },
- description: { label: 'label.description' },
- ssl : { label: 'SSL'}
- }
- ],
- dataProvider: function(args) {
- $.ajax({
- url: createURL("ldapConfig&listAll=true" ),
- dataType: "json",
- async: true,
- success: function(json) {
- var item = json.ldapconfigresponse.ldapconfig;
- args.response.success({data: item});
- }
- });
- }
-
- }
-
- }
- },
-
- actions: {
- add:{
-
- label: 'Configure LDAP',
-
- messages: {
- confirm: function(args) {
- return 'Do you really want to configure LDAP ? ';
- },
- notification: function(args) {
- return 'LDAP configured';
+ id: 'global-settings',
+ sectionSelect: {
+ label: 'label.select-view'
+ },
+ sections: {
+ globalSettings: {
+ type: 'select',
+ title: 'label.menu.global.settings',
+ listView: {
+ label: 'label.menu.global.settings',
+ actions: {
+ edit: {
+ label: 'label.change.value',
+ action: function (args) {
+ var data = {
+ name: args.data.jsonObj.name,
+ value: args.data.value
+ };
+ $.ajax({
+ url: createURL('updateConfiguration'),
+ data: data,
+ success: function (json) {
+ var item = json.updateconfigurationresponse.configuration;
+ if (item.category == "Usage")
+ cloudStack.dialog.notice({
+ message: _l('message.restart.mgmt.usage.server')
+ });
+ else
+ cloudStack.dialog.notice({
+ message: _l('message.restart.mgmt.server')
+ });
+ args.response.success({
+ data: item
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ }
+ }
+ },
+ fields: {
+ name: {
+ label: 'label.name',
+ id: true
+ },
+ description: {
+ label: 'label.description'
+ },
+ value: {
+ label: 'label.value',
+ editable: true,
+ truncate: true
+ }
+ },
+ dataProvider: function (args) {
+ var data = {
+ page: args.page,
+ pagesize: pageSize
+ };
+ if (args.filterBy.search.value) {
+ data.name = args.filterBy.search.value;
+ }
+ $.ajax({
+ url: createURL('listConfigurations'),
+ data: data,
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var items = json.listconfigurationsresponse.configuration;
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ }
}
- },
-
- createForm: {
-
- title: 'Configure LDAP',
- fields:{
- name:{label: 'Bind DN' , validation: {required:true} },
- password: {label: 'Bind Password', validation: {required: true },isPassword:true },
- hostname: {label:'Hostname' , validation:{required:true}},
- queryfilter: {label:'Query Filter' , validation: {required:true} , docID:'helpLdapQueryFilter'},
- searchbase: {label:'SearchBase',validation:{required:true}},
- ssl: {
- label:'SSL' ,
- isBoolean:true,
- isChecked:false
-
+ },
+ ldapConfiguration: {
+ type: 'select',
+ title: 'LDAP Configuration',
+ listView: {
+ id: 'ldap',
+ label: 'LDAP Configuration',
+ fields: {
+ hostname: {
+ label: 'Hostname'
+ },
+ port: {
+ label: 'LDAP Port'
+ },
+ },
+ dataProvider: function (args) {
+ var data = {};
+ listViewDataProvider(args, data);
+ $.ajax({
+ url: createURL('listLdapConfigurations'),
+ data: data,
+ success: function (json) {
+ var items = json.ldapconfigurationresponse.LdapConfiguration;
+ args.response.success({
+ data: items
+ });
},
- port: { label: 'Port' , defaultValue: '389' },
- truststore:{ label:'Trust Store' , isHidden:true , dependsOn:'ssl',validation:{required:true} },
- truststorepassword:{ label:'Trust Store Password' ,isHidden:true , dependsOn:'ssl', validation:{required:true}}
-
- }
-
-
- },
-
-
- action:function(args) {
- var array = [];
- array.push("&binddn=" + todb(args.data.name));
- array.push("&bindpass=" + todb(args.data.password));
- array.push("&hostname=" + todb(args.data.hostname));
- array.push("&searchbase=" +todb(args.data.searchbase));
- array.push("&queryfilter=" +todb(args.data.queryfilter));
- array.push("&port=" +todb(args.data.port));
-
- if(args.$form.find('.form-item[rel=ssl]').find('input[type=checkbox]').is(':Checked')== true) {
-
- array.push("&ssl=true");
- if(args.data.truststore != "")
- array.push("&truststore=" +todb(args.data.truststore));
-
- if(args.data.truststorepassword !="")
- array.push("&truststorepass=" +todb(args.data.truststorepassword));
-
+ error: function (data) {
+ args.response.error(parseXMLHttpResponse(data));
+ }
+ });
+ },
+ detailView: {
+ name: 'label.details',
+ actions: {
+ remove: {
+ label: 'Remove LDAP',
+ messages: {
+ notification: function (args) {
+ return 'LDAP Configuration Deleted';
+ },
+ confirm: function () {
+ return 'Are you sure you want to delete the LDAP configuration?';
+ }
+ },
+ action: function (args) {
+ $.ajax({
+ url: createURL("deleteLdapConfiguration&hostname=" + args.context.ldapConfiguration[0].hostname),
+ success: function (json) {
+ args.response.success();
+ }
+ });
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ }
+ },
+ tabs: {
+ details: {
+ title: 'LDAP Configuration Details',
+ fields: [{
+ hostname: {
+ label: 'Hostname'
+ },
+ port: {
+ label: 'Port'
+ }
+ }],
+ dataProvider: function (args) {
+ var items = [];
+ console.log(args);
+ $.ajax({
+ url: createURL("listLdapConfigurations&hostname=" + args.context.ldapConfiguration[0].hostname),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var item = json.ldapconfigurationresponse.LdapConfiguration;
+ args.response.success({
+ data: item[0]
+ });
+ }
+ });
+ }
+ }
}
-
- else
- array.push("&ssl=false");
-
- $.ajax({
- url: createURL("ldapConfig" + array.join("")),
- dataType: "json",
- async: true,
- success: function(json) {
- var items = json.ldapconfigresponse.ldapconfig;
- args.response.success({
- data: items
- });
-
- },
-
- error:function(json){
- args.response.error(parseXMLHttpResponse(json));
-
- }
-
-
- });
-
-
- }
- }
-
- }
-
-
-
- }
-
-
-
- },
- hypervisorCapabilities: {
- type: 'select',
- title: 'label.hypervisor.capabilities',
- listView: {
- id: 'hypervisorCapabilities',
- label: 'label.hypervisor.capabilities',
- fields: {
- hypervisor: { label: 'label.hypervisor' },
- hypervisorversion: { label: 'label.hypervisor.version' },
- maxguestslimit: { label: 'label.max.guest.limit' }
- },
- dataProvider: function(args) {
- var data = {};
- listViewDataProvider(args, data);
-
- $.ajax({
- url: createURL('listHypervisorCapabilities'),
- data: data,
- success: function(json) {
- var items = json.listhypervisorcapabilitiesresponse.hypervisorCapabilities;
- args.response.success({data:items});
- },
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
- }
- });
- },
-
- detailView: {
- name: 'label.details',
- actions: {
- edit: {
- label: 'label.edit',
- action: function(args) {
- var data = {
- id: args.context.hypervisorCapabilities[0].id,
- maxguestslimit: args.data.maxguestslimit
- };
-
- $.ajax({
- url: createURL('updateHypervisorCapabilities'),
- data: data,
- success: function(json) {
- var item = json.updatehypervisorcapabilitiesresponse['null'];
- args.response.success({data: item});
},
- error: function(data) {
- args.response.error(parseXMLHttpResponse(data));
+ actions: {
+ add: {
+ label: 'Configure LDAP',
+ messages: {
+ confirm: function (args) {
+ return 'Do you really want to configure LDAP ? ';
+ },
+ notification: function (args) {
+ console.log(args);
+ return 'Successfully added a new LDAP server';
+ }
+ },
+ createForm: {
+ title: 'Configure LDAP',
+ fields: {
+ hostname: {
+ label: 'Hostname',
+ validation: {
+ required: true
+ }
+ },
+ port: {
+ label: 'Port',
+ validation: {
+ required: true
+ }
+ }
+ }
+ },
+ action: function (args) {
+ var array = [];
+ array.push("&hostname=" + todb(args.data.hostname));
+ array.push("&port=" + todb(args.data.port));;
+ $.ajax({
+ url: createURL("addLdapConfiguration" + array.join("")),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var items = json.ldapconfigurationresponse.LdapAddConfiguration;
+ args.response.success({
+ data: items
+ });
+ },
+ error: function (json) {
+ args.response.error(parseXMLHttpResponse(json));
+ }
+ });
+ }
+ }
}
- });
}
- }
},
+ hypervisorCapabilities: {
+ type: 'select',
+ title: 'label.hypervisor.capabilities',
+ listView: {
+ id: 'hypervisorCapabilities',
+ label: 'label.hypervisor.capabilities',
+ fields: {
+ hypervisor: {
+ label: 'label.hypervisor'
+ },
+ hypervisorversion: {
+ label: 'label.hypervisor.version'
+ },
+ maxguestslimit: {
+ label: 'label.max.guest.limit'
+ }
+ },
+ dataProvider: function (args) {
+ var data = {};
+ listViewDataProvider(args, data);
+
+ $.ajax({
+ url: createURL('listHypervisorCapabilities'),
+ data: data,
+ success: function (json) {
+ var items = json.listhypervisorcapabilitiesresponse.hypervisorCapabilities;
+ args.response.success({
+ data: items
+ });
+ },
+ error: function (data) {
+ args.response.error(parseXMLHttpResponse(data));
+ }
+ });
+ },
- tabs: {
- details: {
- title: 'label.details',
- fields: [
- {
- id: { label: 'label.id' },
- hypervisor: { label: 'label.hypervisor' },
- hypervisorversion: { label: 'label.hypervisor.version' },
- maxguestslimit: {
- label: 'label.max.guest.limit',
- isEditable: true
- }
- }
- ],
- dataProvider: function(args) {
- args.response.success(
- {
- data:args.context.hypervisorCapabilities[0]
+ detailView: {
+ name: 'label.details',
+ actions: {
+ edit: {
+ label: 'label.edit',
+ action: function (args) {
+ var data = {
+ id: args.context.hypervisorCapabilities[0].id,
+ maxguestslimit: args.data.maxguestslimit
+ };
+
+ $.ajax({
+ url: createURL('updateHypervisorCapabilities'),
+ data: data,
+ success: function (json) {
+ var item = json.updatehypervisorcapabilitiesresponse['null'];
+ args.response.success({
+ data: item
+ });
+ },
+ error: function (data) {
+ args.response.error(parseXMLHttpResponse(data));
+ }
+ });
+ }
+ }
+ },
+
+ tabs: {
+ details: {
+ title: 'label.details',
+ fields: [{
+ id: {
+ label: 'label.id'
+ },
+ hypervisor: {
+ label: 'label.hypervisor'
+ },
+ hypervisorversion: {
+ label: 'label.hypervisor.version'
+ },
+ maxguestslimit: {
+ label: 'label.max.guest.limit',
+ isEditable: true
+ }
+ }],
+ dataProvider: function (args) {
+ args.response.success({
+ data: args.context.hypervisorCapabilities[0]
+ });
+ }
+ }
+ }
}
- );
}
- }
}
- }
}
- }
- }
- };
+ };
})(cloudStack);
[2/3] Add LDAP Plugin Implementation
Posted by se...@apache.org.
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
[3/3] git commit: updated refs/heads/ldapplugin to a90affe
Posted by se...@apache.org.
Add LDAP Plugin Implementation
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a90affe4
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a90affe4
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a90affe4
Branch: refs/heads/ldapplugin
Commit: a90affe4b34e9c2307b72f2ba6767cb93a617085
Parents: 92884d1
Author: Ian Duffy <ia...@ianduffy.ie>
Authored: Thu Jul 11 14:29:10 2013 +0100
Committer: Sebastien Goasguen <ru...@gmail.com>
Committed: Thu Jul 11 10:04:16 2013 -0400
----------------------------------------------------------------------
.../configuration/ConfigurationService.java | 8 -
.../org/apache/cloudstack/api/ApiConstants.java | 11 -
.../cloudstack/api/ResponseGenerator.java | 3 -
.../api/command/admin/ldap/LDAPConfigCmd.java | 205 ------
.../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 | 9 +-
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 | 149 ++++-
.../server/auth/LDAPUserAuthenticator.java | 173 -----
.../api/command/LdapAddConfigurationCmd.java | 84 +++
.../api/command/LdapDeleteConfigurationCmd.java | 74 +++
.../api/command/LdapListAllUsersCmd.java | 73 +++
.../api/command/LdapListConfigurationCmd.java | 96 +++
.../api/command/LdapUserSearchCmd.java | 86 +++
.../api/response/LdapConfigurationResponse.java | 46 ++
.../api/response/LdapUserResponse.java | 68 ++
.../cloudstack/ldap/LdapAuthenticator.java | 53 ++
.../cloudstack/ldap/LdapConfiguration.java | 102 +++
.../cloudstack/ldap/LdapConfigurationVO.java | 58 ++
.../cloudstack/ldap/LdapContextFactory.java | 89 +++
.../org/apache/cloudstack/ldap/LdapManager.java | 30 +
.../apache/cloudstack/ldap/LdapManagerImpl.java | 185 ++++++
.../org/apache/cloudstack/ldap/LdapUser.java | 53 ++
.../apache/cloudstack/ldap/LdapUserManager.java | 81 +++
.../org/apache/cloudstack/ldap/LdapUtils.java | 46 ++
.../ldap/NoLdapUserMatchingQueryException.java | 16 +
.../ldap/NoSuchLdapUserException.java | 15 +
.../ldap/dao/LdapConfigurationDao.java | 14 +
.../ldap/dao/LdapConfigurationDaoImpl.java | 50 ++
.../ldap/BasicNamingEnumerationImpl.groovy | 40 ++
.../ldap/LdapAddConfigurationCmdSpec.groovy | 73 +++
.../ldap/LdapAuthenticatorSpec.groovy | 74 +++
.../ldap/LdapConfigurationDaoImplSpec.groovy | 13 +
.../ldap/LdapConfigurationResponseSpec.groovy | 33 +
.../ldap/LdapConfigurationSpec.groovy | 167 +++++
.../cloudstack/ldap/LdapConfigurationVO.groovy | 36 ++
.../ldap/LdapContextFactorySpec.groovy | 117 ++++
.../ldap/LdapDeleteConfigurationCmdSpec.groovy | 62 ++
.../ldap/LdapListAllUsersCmdSpec.groovy | 56 ++
.../ldap/LdapListConfigurationCmdSpec.groovy | 85 +++
.../cloudstack/ldap/LdapManagerImplSpec.groovy | 301 +++++++++
.../ldap/LdapSearchUserCmdSpec.groovy | 66 ++
.../cloudstack/ldap/LdapUserManagerSpec.groovy | 179 ++++++
.../cloudstack/ldap/LdapUserResponseSpec.groovy | 42 ++
.../apache/cloudstack/ldap/LdapUserSpec.groovy | 54 ++
.../apache/cloudstack/ldap/LdapUtilsSpec.groovy | 52 ++
.../NoLdapUserMatchingQueryExceptionSpec.groovy | 14 +
.../ldap/NoSuchLdapUserExceptionSpec.groovy | 14 +
server/src/com/cloud/api/ApiResponseHelper.java | 15 -
server/src/com/cloud/configuration/Config.java | 13 +-
.../configuration/ConfigurationManagerImpl.java | 172 -----
.../com/cloud/server/ManagementServerImpl.java | 4 -
.../cloud/vpc/MockConfigurationManagerImpl.java | 31 -
setup/db/db/schema-410to420.sql | 15 +
tools/apidoc/gen_toc.py | 2 +-
ui/scripts/globalSettings.js | 625 +++++++++----------
62 files changed, 3265 insertions(+), 1189 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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/a90affe4/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 e2857b8..93fbff3 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -527,15 +527,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/a90affe4/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/a90affe4/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 38f58ec..0000000
--- a/api/src/org/apache/cloudstack/api/command/admin/ldap/LDAPConfigCmd.java
+++ /dev/null
@@ -1,205 +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.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=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/a90affe4/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/a90affe4/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/a90affe4/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/a90affe4/client/tomcatconf/applicationContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 610fdfd..4b6bd34 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -393,7 +393,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">
@@ -402,6 +402,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/a90affe4/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index f4b41a7..dce938f 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -210,8 +210,6 @@ scaleSystemVm=1
#### configuration commands
updateConfiguration=1
listConfigurations=1
-ldapConfig=1
-ldapRemove=1
listCapabilities=15
listDeploymentPlanners=1
@@ -668,3 +666,10 @@ listDedicatedZones=1
listDedicatedPods=1
listDedicatedClusters=1
listDedicatedHosts=1
+
+### LDAP
+searchLdap=1
+listLdapConfigurations=1
+addLdapConfiguration=1
+deleteLdapConfiguration=1
+listAllLdapUsers=1
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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/a90affe4/client/tomcatconf/nonossComponentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in
index ffa6281..8371e37 100644
--- a/client/tomcatconf/nonossComponentContext.xml.in
+++ b/client/tomcatconf/nonossComponentContext.xml.in
@@ -223,7 +223,7 @@
<list>
<ref bean="SHA256SaltedUserAuthenticator"/>
<ref bean="MD5UserAuthenticator"/>
- <ref bean="LDAPUserAuthenticator"/>
+ <ref bean="LdapAuthenticator"/>
<ref bean="PlainTextUserAuthenticator"/>
</list>
</property>
@@ -233,7 +233,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/a90affe4/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/a90affe4/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/a90affe4/plugins/user-authenticators/ldap/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/pom.xml b/plugins/user-authenticators/ldap/pom.xml
index 5c45f11..8ea67fe 100644
--- a/plugins/user-authenticators/ldap/pom.xml
+++ b/plugins/user-authenticators/ldap/pom.xml
@@ -1,29 +1,126 @@
-<!--
- 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
+<!-- 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>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.2.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
- http://www.apache.org/licenses/LICENSE-2.0
+ <build>
+ <plugins>
+ <!-- Mandatory plugins for using Spock -->
+ <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>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.codehaus.gmaven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <versionRange>[1.3,)</versionRange>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
- 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>
- <parent>
- <groupId>org.apache.cloudstack</groupId>
- <artifactId>cloudstack-plugins</artifactId>
- <version>4.2.0-SNAPSHOT</version>
- <relativePath>../../pom.xml</relativePath>
- </parent>
+ <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/a90affe4/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/a90affe4/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..62736b1
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapAddConfigurationCmd.java
@@ -0,0 +1,84 @@
+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.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@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 ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+ try {
+ final LdapConfigurationResponse response = _ldapManager.addConfiguration(getHostname(), getPort());
+ 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 0;
+ }
+
+ 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/a90affe4/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..364b260
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapDeleteConfigurationCmd.java
@@ -0,0 +1,74 @@
+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.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@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 ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+
+ try {
+ final LdapConfigurationResponse response = _ldapManager.deleteConfiguration(getHostname());
+ 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 0;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(final String hostname) {
+ this.hostname = hostname;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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..f261f74
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListAllUsersCmd.java
@@ -0,0 +1,73 @@
+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.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@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;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+ try {
+ final List<LdapUser> users = _ldapManager.getUsers();
+ final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
+ final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>();
+
+ for (final LdapUser user : users) {
+ final LdapUserResponse ldapResponse = _ldapManager.createLdapUserResponse(user);
+ ldapResponse.setObjectName("LdapUser");
+ ldapResponses.add(ldapResponse);
+ }
+
+ 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 0;
+ }
+}
\ 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/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..d3239e6
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapListConfigurationCmd.java
@@ -0,0 +1,96 @@
+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.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+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.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+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;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(this);
+ if (result.second() > 0) {
+ final ListResponse<LdapConfigurationResponse> response = new ListResponse<LdapConfigurationResponse>();
+ final List<LdapConfigurationResponse> responses = new ArrayList<LdapConfigurationResponse>();
+ for (final LdapConfigurationVO resource : result.first()) {
+ final LdapConfigurationResponse configurationResponse = _ldapManager.createLdapConfigurationResponse(resource);
+ configurationResponse.setObjectName("LdapConfiguration");
+ responses.add(configurationResponse);
+ }
+ response.setResponses(responses, result.second());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find any LDAP Configurations");
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return 0;
+ }
+
+ 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/a90affe4/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..a8d3308
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapUserSearchCmd.java
@@ -0,0 +1,86 @@
+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.Parameter;
+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.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+
+@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;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException {
+ try {
+ final List<LdapUser> users = _ldapManager.searchUsers(getQuery());
+
+ final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
+ final List<LdapUserResponse> ldapUserResponses = new ArrayList<LdapUserResponse>();
+
+ for (final LdapUser user : users) {
+ final LdapUserResponse ldapUserResponse = _ldapManager.createLdapUserResponse(user);
+ ldapUserResponse.setObjectName("LdapUser");
+ ldapUserResponses.add(ldapUserResponse);
+ }
+
+ response.setResponses(ldapUserResponses);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } catch (final NoLdapUserMatchingQueryException e) {
+ throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return 0;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public void setQuery(final String query) {
+ this.query = 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/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..12c6ed9
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapConfigurationResponse.java
@@ -0,0 +1,46 @@
+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) {
+ 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/a90affe4/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..24d8b4d
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/response/LdapUserResponse.java
@@ -0,0 +1,68 @@
+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("realname")
+ @Param(description = "The user's realname")
+ private String realname;
+
+ @SerializedName("username")
+ @Param(description = "The user's username")
+ private String username;
+
+ public LdapUserResponse() {
+ super();
+ }
+
+ public LdapUserResponse(final String username, final String email, final String realname, final String principal) {
+ this.username = username;
+ this.email = email;
+ this.realname = realname;
+ this.principal = principal;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getPrincipal() {
+ return principal;
+ }
+
+ public String getRealname() {
+ return realname;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ public void setPrincipal(final String principal) {
+ this.principal = principal;
+ }
+
+ public void setRealname(final String realname) {
+ this.realname = realname;
+ }
+
+ 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/a90affe4/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..74a15b6
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java
@@ -0,0 +1,53 @@
+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 (_ldapManager.listConfigurations(new LdapListConfigurationCmd(_ldapManager)).second() > 0) {
+ return _ldapManager.canAuthenticate(username, password);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public String encode(final String password) {
+ return password;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/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..07d4879
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfiguration.java
@@ -0,0 +1,102 @@
+package org.apache.cloudstack.ldap;
+
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.naming.directory.SearchControls;
+
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.ServerApiException;
+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 getProviderUrl() {
+ final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager
+ .listConfigurations(new LdapListConfigurationCmd(_ldapManager));
+ if (result.second() > 0) {
+ 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();
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to get Ldap Configuration(s)");
+ }
+ }
+
+ public String getRealnameAttribute() {
+ final String realnameAttribute = _configDao.getValue("ldap.realname.attribute");
+ return realnameAttribute == null ? "cn" : realnameAttribute;
+ }
+
+ public String[] getReturnAttributes() {
+ return new String[] {getUsernameAttribute(), getEmailAttribute(), getRealnameAttribute()};
+ }
+
+ 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
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
new file mode 100644
index 0000000..e7fe0a9
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapConfigurationVO.java
@@ -0,0 +1,58 @@
+package org.apache.cloudstack.ldap;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "ldap_configuration")
+public class LdapConfigurationVO implements InternalIdentity {
+ @Column(name = "hostname")
+ private String hostname;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "port")
+ private int port;
+
+ public LdapConfigurationVO() {
+ }
+
+ public LdapConfigurationVO(final String hostname, final int port) {
+ this.hostname = hostname;
+ this.port = port;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setHostname(final String hostname) {
+ this.hostname = hostname;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ 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/a90affe4/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
new file mode 100644
index 0000000..918fd20
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapContextFactory.java
@@ -0,0 +1,89 @@
+package org.apache.cloudstack.ldap;
+
+import java.util.Hashtable;
+
+import javax.inject.Inject;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.log4j.Logger;
+
+public class LdapContextFactory {
+ private static final Logger s_logger = Logger.getLogger(LdapContextFactory.class.getName());
+
+ @Inject
+ private LdapConfiguration _ldapConfiguration;
+
+ public LdapContextFactory() {
+ }
+
+ public LdapContextFactory(final LdapConfiguration ldapConfiguration) {
+ _ldapConfiguration = ldapConfiguration;
+ }
+
+ public LdapContext createBindContext() throws NamingException {
+ return createBindContext(null);
+ }
+
+ public LdapContext createBindContext(final String providerUrl) throws NamingException {
+ final String bindPrincipal = _ldapConfiguration.getBindPrincipal();
+ final String bindPassword = _ldapConfiguration.getBindPassword();
+ return createInitialDirContext(bindPrincipal, bindPassword, providerUrl, true);
+ }
+
+ private LdapContext createInitialDirContext(final String principal, final String password, final boolean isSystemContext)
+ throws NamingException {
+ return createInitialDirContext(principal, password, null, isSystemContext);
+ }
+
+ private LdapContext createInitialDirContext(final String principal, final String password, final String providerUrl, final boolean isSystemContext)
+ throws NamingException {
+ return new InitialLdapContext(getEnvironment(principal, password, providerUrl, isSystemContext), null);
+ }
+
+ public LdapContext createUserContext(final String principal, final String password) throws NamingException {
+ return createInitialDirContext(principal, password, false);
+ }
+
+ private Hashtable<String, String> getEnvironment(final String principal, final String password, final String providerUrl, final boolean isSystemContext) {
+ final String factory = _ldapConfiguration.getFactory();
+ final String url = providerUrl == null ? _ldapConfiguration.getProviderUrl() : providerUrl;
+ final String authentication = _ldapConfiguration.getAuthentication();
+
+ final Hashtable<String, String> environment = new Hashtable<String, String>();
+
+ environment.put(Context.INITIAL_CONTEXT_FACTORY, factory);
+ environment.put(Context.PROVIDER_URL, url);
+ environment.put("com.sun.jndi.ldap.read.timeout", "1000");
+ environment.put("com.sun.jndi.ldap.connect.pool", "true");
+
+ if ("none".equals(authentication) && !isSystemContext) {
+ environment.put(Context.SECURITY_AUTHENTICATION, "simple");
+ } else {
+ environment.put(Context.SECURITY_AUTHENTICATION, authentication);
+ }
+
+ if (principal != null) {
+ environment.put(Context.SECURITY_PRINCIPAL, principal);
+ }
+
+ if (password != null) {
+ environment.put(Context.SECURITY_CREDENTIALS, password);
+ }
+
+ return environment;
+ }
+
+ public void testConnection(final String providerUrl) throws NamingException {
+ try {
+ createBindContext(providerUrl);
+ s_logger.info("LDAP Connection was successful");
+ } catch (final NamingException e) {
+ s_logger.warn("LDAP Connection failed");
+ s_logger.error(e.getMessage(), e);
+ throw e;
+ }
+ }
+}
\ 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/LdapManager.java
----------------------------------------------------------------------
diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
new file mode 100644
index 0000000..980beb7
--- /dev/null
+++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapManager.java
@@ -0,0 +1,30 @@
+package org.apache.cloudstack.ldap;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
+import org.apache.cloudstack.api.response.LdapConfigurationResponse;
+import org.apache.cloudstack.api.response.LdapUserResponse;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.Pair;
+import com.cloud.utils.component.PluggableService;
+
+public interface LdapManager extends PluggableService {
+
+ LdapConfigurationResponse addConfiguration(String hostname, int port) throws InvalidParameterValueException;
+
+ boolean canAuthenticate(String username, String password);
+
+ LdapConfigurationResponse createLdapConfigurationResponse(LdapConfigurationVO configuration);
+
+ LdapUserResponse createLdapUserResponse(LdapUser user);
+
+ LdapConfigurationResponse deleteConfiguration(String hostname) throws InvalidParameterValueException;
+
+ List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
+
+ Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(LdapListConfigurationCmd cmd);
+
+ List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
+}
\ No newline at end of file