mirror of https://github.com/apache/cloudstack.git
Cloudstack-2014 [GSoC] Add support for ldap user provisioning
This commit is contained in:
commit
f80ecfe4b0
|
|
@ -81,4 +81,5 @@ debian/*.debhelper
|
|||
replace.properties.tmp
|
||||
build-indep-stamp
|
||||
configure-stamp
|
||||
*_flymake.js
|
||||
*_flymake.js
|
||||
engine/storage/integration-test/test-output
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ import java.util.List;
|
|||
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;
|
||||
|
|
@ -261,12 +259,6 @@ public interface ConfigurationService {
|
|||
|
||||
Long getDefaultPageSize();
|
||||
|
||||
boolean updateLDAP(LDAPConfigCmd cmd) throws NamingException;
|
||||
|
||||
boolean removeLDAP(LDAPRemoveCmd cmd);
|
||||
|
||||
LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd);
|
||||
|
||||
PortableIpRange createPortableIpRange(CreatePortableIpRangeCmd cmd) throws ConcurrentOperationException;
|
||||
|
||||
boolean deletePortableIpRange(DeletePortableIpRangeCmd cmd);
|
||||
|
|
|
|||
|
|
@ -525,15 +525,4 @@ public class ApiConstants {
|
|||
public enum VMDetails {
|
||||
all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp;
|
||||
}
|
||||
|
||||
public enum LDAPParams {
|
||||
hostname, port, usessl, queryfilter, searchbase, dn, passwd, truststore, truststorepass;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ldap." + name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.cloudstack.api;
|
||||
|
||||
public interface LdapValidator {
|
||||
boolean isLdapEnabled();
|
||||
}
|
||||
|
|
@ -60,7 +60,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;
|
||||
|
|
@ -354,8 +353,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ message.action.delete.nic=Please confirm that want to remove this NIC, which wil
|
|||
changed.item.properties=Changed item properties
|
||||
confirm.enable.s3=Please fill in the following information to enable support for S3-backed Secondary Storage
|
||||
confirm.enable.swift=Please fill in the following information to enable support for Swift
|
||||
error.could.not.change.your.password.because.ldap.is.enabled=Error cloud not change your password because LDAP is enabled.
|
||||
error.could.not.enable.zone=Could not enable zone
|
||||
error.installWizard.message=Something went wrong; you may go back and correct any errors
|
||||
error.invalid.username.password=Invalid username or password
|
||||
|
|
|
|||
|
|
@ -387,7 +387,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">
|
||||
|
|
@ -396,6 +396,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
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
|
@ -210,8 +210,6 @@ scaleSystemVm=1
|
|||
#### configuration commands
|
||||
updateConfiguration=1
|
||||
listConfigurations=1
|
||||
ldapConfig=1
|
||||
ldapRemove=1
|
||||
listCapabilities=15
|
||||
listDeploymentPlanners=1
|
||||
cleanVMReservations=1
|
||||
|
|
@ -386,12 +384,12 @@ listProjectInvitations=15
|
|||
updateProjectInvitation=15
|
||||
deleteProjectInvitation=15
|
||||
|
||||
####
|
||||
####
|
||||
createFirewallRule=15
|
||||
deleteFirewallRule=15
|
||||
listFirewallRules=15
|
||||
|
||||
####
|
||||
####
|
||||
createEgressFirewallRule=15
|
||||
deleteEgressFirewallRule=15
|
||||
listEgressFirewallRules=15
|
||||
|
|
@ -673,3 +671,10 @@ listDedicatedZones=1
|
|||
listDedicatedPods=1
|
||||
listDedicatedClusters=1
|
||||
listDedicatedHosts=1
|
||||
|
||||
### LDAP
|
||||
listLdapConfigurations=15
|
||||
addLdapConfiguration=3
|
||||
deleteLdapConfiguration=3
|
||||
listLdapUsers=3
|
||||
ldapCreateAccount=3
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@
|
|||
<list>
|
||||
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||
<ref bean="MD5UserAuthenticator"/>
|
||||
<ref bean="LDAPUserAuthenticator"/>
|
||||
<ref bean="LdapAuthenticator"/>
|
||||
<ref bean="PlainTextUserAuthenticator"/>
|
||||
</list>
|
||||
</property>
|
||||
|
|
@ -234,7 +234,7 @@
|
|||
<list>
|
||||
<ref bean="SHA256SaltedUserAuthenticator"/>
|
||||
<ref bean="MD5UserAuthenticator"/>
|
||||
<ref bean="LDAPUserAuthenticator"/>
|
||||
<ref bean="LdapAuthenticator"/>
|
||||
<ref bean="PlainTextUserAuthenticator"/>
|
||||
</list>
|
||||
</property>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -24,19 +24,28 @@
|
|||
<section id="LDAP-for-user-authentication">
|
||||
<title>Using an LDAP Server for User Authentication</title>
|
||||
<para>You can use an external LDAP server such as Microsoft Active Directory or OpenLDAP to authenticate &PRODUCT; end-users.</para>
|
||||
<para>To set up LDAP authentication in &PRODUCT;, open the global settings page and set:</para>
|
||||
<para>In order to do this you must:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>ldap.basedn - The base directory you want to search within for uses</para></listitem>
|
||||
<listitem><para>ldap.bind.password - The password you wish to use to bind, this can be blank if the server supports anonymous binding</para></listitem>
|
||||
<listitem><para>ldap.bind.principal - The account you wish to use to bind, this can be blank if the server supports anonymous binding</para></listitem>
|
||||
<listitem><para>ldap.email.attribute - The attribute within your LDAP server that holds a value for users email address</para></listitem>
|
||||
<listitem><para>ldap.realname.attribute - The attribute within your LDAP server that holds a value users realname</para></listitem>
|
||||
<listitem><para>ldap.user.object - The object class that identifies a user</para></listitem>
|
||||
<listitem><para>ldap.username.attribute - The attribute within your LDAP server that has a value that will match the cloudstack accounts username field</para></listitem>
|
||||
<listitem><para>Set your LDAP configuration within &PRODUCT;</para></listitem>
|
||||
<listitem><para>Create &PRODUCT; accounts for LDAP users</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Finally you can add LDAP servers from Global Settings -> Select View -> LDAP Configuration. This requires a hostname and port</para>
|
||||
<para>To set up LDAP authentication in &PRODUCT;, open the global settings page and search for LDAP</para>
|
||||
<para>Set ldap.basedn to match your sever's base directory.</para>
|
||||
<para>Review the defaults for the following, ensure that they match your schema.</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>ldap.email.attribute</para></listitem>
|
||||
<listitem><para>ldap.firstname.attribute</para></listitem>
|
||||
<listitem><para>ldap.lastname.attribute</para></listitem>
|
||||
<listitem><para>ldap.username.attribute</para></listitem>
|
||||
<listitem><para>ldap.user.object</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Optionally you can set the following:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>If you do not want to use anonymous binding you can set ldap.bind.principle and ldap.bind.password as credentials for your LDAP server that will grant &PRODUCT; permission to perform a search on the LDAP server.</para></listitem>
|
||||
<listitem><para>For SSL support set ldap.truststore to a path on the file system where your trusted store is located. Along with this set ldap.truststore.password as the password that unlocks the truststore.</para></listitem>
|
||||
<listitem><para>If you wish to filter down the user set that is granted access to &PRODUCT; via the LDAP attribute memberof you can do so using ldap.search.group.principle.</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Finally, you can add your LDAP server. To do so select LDAP Configuration from the views section within global settings. Click on "Configure LDAP" and fill in your server's hostname and port.</para>
|
||||
<xi:include href="example-activedirectory-configuration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="example-openldap-configuration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<!-- Support for SSL has been removed but will be back shortly. -->
|
||||
<!-- <xi:include href="SSL-keystore-path-and-password.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> -->
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@
|
|||
|
||||
<section id="example-activedirectory-configuration">
|
||||
<title>Example LDAP Configuration for Active Directory</title>
|
||||
<para>This shows the configuration settings required for using ActiveDirectory</para>
|
||||
<para>This shows the configuration settings required for using ActiveDirectory.</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>samAccountName - Logon name</para></listitem>
|
||||
<listitem><para>mail - Email Address</para></listitem>
|
||||
<listitem><para>cn - Real name</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Along with this the ldap.user.object name needs to be modified, by default ActiveDirectory uses the value "user" for this.</para>
|
||||
<para>Map the following attributes accordingly as shown below within the cloudstack ldap configuration:</para>
|
||||
<para>Map the following attributes accordingly as shown below:</para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="./images/add-ldap-configuration-ad.png"/>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
|
||||
<section id="example-openldap-configuration">
|
||||
<title>Example LDAP Configuration for OpenLdap</title>
|
||||
<para>This shows the configuration settings required for using OpenLDAP</para>
|
||||
<para>The default values supplied are suited for OpenLDAP</para>
|
||||
<para>This shows the configuration settings required for using OpenLDAP.</para>
|
||||
<para>The default values supplied are suited for OpenLDAP.</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>uid - Logon name</para></listitem>
|
||||
<listitem><para>mail - Email Address</para></listitem>
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 64 KiB |
|
|
@ -30,7 +30,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;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,14 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
license agreements. See the NOTICE file distributed with this work for additional
|
||||
information regarding copyright ownership. The ASF licenses this file to you under
|
||||
the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software distributed under
|
||||
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||
OF ANY KIND, either express or implied. See the License for the specific language
|
||||
governing permissions and limitations under the License. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-user-authenticator-ldap</artifactId>
|
||||
<name>Apache CloudStack Plugin - User Authenticator LDAP</name>
|
||||
|
|
@ -26,4 +18,93 @@
|
|||
<version>4.3.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmaven</groupId>
|
||||
<artifactId>gmaven-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
<configuration>
|
||||
<providerSelection>1.7</providerSelection>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<fileset>
|
||||
<directory>test/groovy</directory>
|
||||
<includes>
|
||||
<include>**/*.groovy</include>
|
||||
</includes>
|
||||
</fileset>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.gmaven.runtime</groupId>
|
||||
<artifactId>gmaven-runtime-1.7</artifactId>
|
||||
<version>1.3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>2.0.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Spec*</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.btmatthews.maven.plugins</groupId>
|
||||
<artifactId>ldap-maven-plugin</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<configuration>
|
||||
<monitorPort>11389</monitorPort>
|
||||
<monitorKey>ldap</monitorKey>
|
||||
<daemon>false</daemon>
|
||||
<rootDn>dc=cloudstack,dc=org</rootDn>
|
||||
<ldapPort>10389</ldapPort>
|
||||
<ldifFile>test/resources/cloudstack.org.ldif</ldifFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Mandatory dependencies for using Spock -->
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional dependencies for using Spock -->
|
||||
<dependency> <!-- enables mocking of classes (in addition to interfaces) -->
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1,174 +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.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
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 org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "addLdapConfiguration", description = "Add a new Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
|
||||
public class LdapAddConfigurationCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapAddConfigurationCmd.class.getName());
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name = "port", type = CommandType.INTEGER, required = true, description = "Port")
|
||||
private int port;
|
||||
|
||||
public LdapAddConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapAddConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
try {
|
||||
final LdapConfigurationResponse response = _ldapManager
|
||||
.addConfiguration(hostname, port);
|
||||
response.setObjectName("LdapAddConfiguration");
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (final InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
|
||||
e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.UserAccount;
|
||||
|
||||
@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0")
|
||||
public class LdapCreateAccountCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapCreateAccountCmd.class.getName());
|
||||
private static final String s_name = "createaccountresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin")
|
||||
private Short accountType;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Creates the user under the specified domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.TIMEZONE, type = CommandType.STRING, description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
||||
private String timezone;
|
||||
|
||||
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Unique username.")
|
||||
private String username;
|
||||
|
||||
@Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "Network domain for the account's networks")
|
||||
private String networkDomain;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
|
||||
private Map<String, String> details;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.STRING, description = "Account UUID, required for adding account from external provisioning system")
|
||||
private String accountUUID;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_ID, type = CommandType.STRING, description = "User UUID, required for adding account from external provisioning system")
|
||||
private String userUUID;
|
||||
|
||||
public LdapCreateAccountCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapCreateAccountCmd(final LdapManager ldapManager,
|
||||
final AccountService accountService) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
_accountService = accountService;
|
||||
}
|
||||
|
||||
UserAccount createCloudstackUserAccount(final LdapUser user) {
|
||||
return _accountService.createUserAccount(username, generatePassword(),
|
||||
user.getFirstname(), user.getLastname(), user.getEmail(),
|
||||
timezone, accountName, accountType, domainId, networkDomain,
|
||||
details, accountUUID, userUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
final CallContext callContext = getCurrentContext();
|
||||
callContext.setEventDetails("Account Name: " + accountName
|
||||
+ ", Domain Id:" + domainId);
|
||||
try {
|
||||
final LdapUser user = _ldapManager.getUser(username);
|
||||
validateUser(user);
|
||||
final UserAccount userAccount = createCloudstackUserAccount(user);
|
||||
if (userAccount != null) {
|
||||
final AccountResponse response = _responseGenerator
|
||||
.createUserAccountResponse(userAccount);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
|
||||
"Failed to create a user account");
|
||||
}
|
||||
} catch (final NamingException e) {
|
||||
throw new ServerApiException(
|
||||
ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR,
|
||||
"No LDAP user exists with the username of " + username);
|
||||
}
|
||||
}
|
||||
|
||||
private String generatePassword() throws ServerApiException {
|
||||
try {
|
||||
final SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
|
||||
final byte bytes[] = new byte[20];
|
||||
randomGen.nextBytes(bytes);
|
||||
return Base64.encode(bytes).toString();
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
|
||||
"Failed to generate random password");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
CallContext getCurrentContext() {
|
||||
return CallContext.current();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
private boolean validateUser(final LdapUser user) throws ServerApiException {
|
||||
if (user.getEmail() == null) {
|
||||
throw new ServerApiException(
|
||||
ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, username
|
||||
+ " has no email address set within LDAP");
|
||||
}
|
||||
if (user.getFirstname() == null) {
|
||||
throw new ServerApiException(
|
||||
ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, username
|
||||
+ " has no firstname set within LDAP");
|
||||
}
|
||||
if (user.getLastname() == null) {
|
||||
throw new ServerApiException(
|
||||
ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, username
|
||||
+ " has no lastname set within LDAP");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.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 org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteLdapConfiguration", description = "Remove an Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
|
||||
public class LdapDeleteConfigurationCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapDeleteConfigurationCmd.class.getName());
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
public LdapDeleteConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapDeleteConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
try {
|
||||
final LdapConfigurationResponse response = _ldapManager
|
||||
.deleteConfiguration(hostname);
|
||||
response.setObjectName("LdapDeleteConfiguration");
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (final InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
|
||||
e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.LdapConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@APICommand(name = "listLdapConfigurations", responseObject = LdapConfigurationResponse.class, description = "Lists all LDAP configurations", since = "4.2.0")
|
||||
public class LdapListConfigurationCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapListConfigurationCmd.class.getName());
|
||||
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = false, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name = "port", type = CommandType.INTEGER, required = false, description = "Port")
|
||||
private int port;
|
||||
|
||||
public LdapListConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapListConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
private List<LdapConfigurationResponse> createLdapConfigurationResponses(
|
||||
final List<? extends LdapConfigurationVO> configurations) {
|
||||
final List<LdapConfigurationResponse> responses = new ArrayList<LdapConfigurationResponse>();
|
||||
for (final LdapConfigurationVO resource : configurations) {
|
||||
final LdapConfigurationResponse configurationResponse = _ldapManager
|
||||
.createLdapConfigurationResponse(resource);
|
||||
configurationResponse.setObjectName("LdapConfiguration");
|
||||
responses.add(configurationResponse);
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager
|
||||
.listConfigurations(this);
|
||||
final List<LdapConfigurationResponse> responses = createLdapConfigurationResponses(result
|
||||
.first());
|
||||
final ListResponse<LdapConfigurationResponse> response = new ListResponse<LdapConfigurationResponse>();
|
||||
response.setResponses(responses, result.second());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.UserResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
|
||||
import org.apache.cloudstack.query.QueryService;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "listLdapUsers", responseObject = LdapUserResponse.class, description = "Lists all LDAP Users", since = "4.2.0")
|
||||
public class LdapListUsersCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapListUsersCmd.class.getName());
|
||||
private static final String s_name = "ldapuserresponse";
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Inject
|
||||
private QueryService _queryService;
|
||||
|
||||
@Parameter(name = "listtype", type = CommandType.STRING, required = false, description = "Determines whether all ldap users are returned or just non-cloudstack users")
|
||||
private String listType;
|
||||
|
||||
public LdapListUsersCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapListUsersCmd(final LdapManager ldapManager,
|
||||
final QueryService queryService) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
_queryService = queryService;
|
||||
}
|
||||
|
||||
private List<LdapUserResponse> createLdapUserResponse(
|
||||
final List<LdapUser> users) {
|
||||
final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>();
|
||||
for (final LdapUser user : users) {
|
||||
if (getListType().equals("all") || !isACloudstackUser(user)) {
|
||||
final LdapUserResponse ldapResponse = _ldapManager
|
||||
.createLdapUserResponse(user);
|
||||
ldapResponse.setObjectName("LdapUser");
|
||||
ldapResponses.add(ldapResponse);
|
||||
}
|
||||
}
|
||||
return ldapResponses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
List<LdapUserResponse> ldapResponses = null;
|
||||
final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
|
||||
try {
|
||||
final List<LdapUser> users = _ldapManager.getUsers();
|
||||
ldapResponses = createLdapUserResponse(users);
|
||||
} catch (final NoLdapUserMatchingQueryException ex) {
|
||||
ldapResponses = new ArrayList<LdapUserResponse>();
|
||||
} finally {
|
||||
response.setResponses(ldapResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
private String getListType() {
|
||||
return listType == null ? "all" : listType;
|
||||
}
|
||||
|
||||
private boolean isACloudstackUser(final LdapUser ldapUser) {
|
||||
final ListResponse<UserResponse> response = _queryService
|
||||
.searchForUsers(new ListUsersCmd());
|
||||
final List<UserResponse> cloudstackUsers = response.getResponses();
|
||||
if (cloudstackUsers != null && cloudstackUsers.size() != 0) {
|
||||
for (final UserResponse cloudstackUser : response.getResponses()) {
|
||||
if (ldapUser.getUsername().equals(cloudstackUser.getUsername())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "searchLdap", responseObject = LdapUserResponse.class, description = "Searches LDAP based on the username attribute", since = "4.2.0")
|
||||
public class LdapUserSearchCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger
|
||||
.getLogger(LdapUserSearchCmd.class.getName());
|
||||
private static final String s_name = "ldapuserresponse";
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "query", type = CommandType.STRING, entityType = LdapUserResponse.class, required = true, description = "query to search using")
|
||||
private String query;
|
||||
|
||||
public LdapUserSearchCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapUserSearchCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
private List<LdapUserResponse> createLdapUserResponse(
|
||||
final List<LdapUser> users) {
|
||||
final List<LdapUserResponse> ldapUserResponses = new ArrayList<LdapUserResponse>();
|
||||
if (users != null) {
|
||||
for (final LdapUser user : users) {
|
||||
final LdapUserResponse ldapUserResponse = _ldapManager
|
||||
.createLdapUserResponse(user);
|
||||
ldapUserResponse.setObjectName("LdapUser");
|
||||
ldapUserResponses.add(ldapUserResponse);
|
||||
}
|
||||
}
|
||||
return ldapUserResponses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
|
||||
List<LdapUser> users = null;
|
||||
|
||||
try {
|
||||
users = _ldapManager.searchUsers(query);
|
||||
} catch (final NoLdapUserMatchingQueryException e) {
|
||||
s_logger.debug(e.getMessage());
|
||||
}
|
||||
|
||||
final List<LdapUserResponse> ldapUserResponses = createLdapUserResponse(users);
|
||||
|
||||
response.setResponses(ldapUserResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class LdapConfigurationResponse extends BaseResponse {
|
||||
@SerializedName("hostname")
|
||||
@Param(description = "hostname")
|
||||
private String hostname;
|
||||
|
||||
@SerializedName("port")
|
||||
@Param(description = "port")
|
||||
private int port;
|
||||
|
||||
public LdapConfigurationResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapConfigurationResponse(final String hostname) {
|
||||
super();
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public LdapConfigurationResponse(final String hostname, final int port) {
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// 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;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class LdapUserResponse extends BaseResponse {
|
||||
@SerializedName("email")
|
||||
@Param(description = "The user's email")
|
||||
private String email;
|
||||
|
||||
@SerializedName("principal")
|
||||
@Param(description = "The user's principle")
|
||||
private String principal;
|
||||
|
||||
@SerializedName("firstname")
|
||||
@Param(description = "The user's firstname")
|
||||
private String firstname;
|
||||
|
||||
@SerializedName("lastname")
|
||||
@Param(description = "The user's lastname")
|
||||
private String lastname;
|
||||
|
||||
@SerializedName("username")
|
||||
@Param(description = "The user's username")
|
||||
private String username;
|
||||
|
||||
public LdapUserResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapUserResponse(final String username, final String email,
|
||||
final String firstname, final String lastname,
|
||||
final String principal) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public String getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setEmail(final String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public void setFirstname(final String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public void setLastname(final String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public void setPrincipal(final String principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import 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.isLdapEnabled()) {
|
||||
return _ldapManager.canAuthenticate(username, password);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(final String password) {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public class LdapConfiguration {
|
||||
private final static String factory = "com.sun.jndi.ldap.LdapCtxFactory";
|
||||
|
||||
private final static int scope = SearchControls.SUBTREE_SCOPE;
|
||||
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
public LdapConfiguration() {
|
||||
}
|
||||
|
||||
public LdapConfiguration(final ConfigurationDao configDao,
|
||||
final LdapManager ldapManager) {
|
||||
_configDao = configDao;
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
public String getAuthentication() {
|
||||
if ((getBindPrincipal() == null) && (getBindPassword() == null)) {
|
||||
return "none";
|
||||
} else {
|
||||
return "simple";
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseDn() {
|
||||
return _configDao.getValue("ldap.basedn");
|
||||
}
|
||||
|
||||
public String getBindPassword() {
|
||||
return _configDao.getValue("ldap.bind.password");
|
||||
}
|
||||
|
||||
public String getBindPrincipal() {
|
||||
return _configDao.getValue("ldap.bind.principal");
|
||||
}
|
||||
|
||||
public String getEmailAttribute() {
|
||||
final String emailAttribute = _configDao
|
||||
.getValue("ldap.email.attribute");
|
||||
return emailAttribute == null ? "mail" : emailAttribute;
|
||||
}
|
||||
|
||||
public String getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public String getFirstnameAttribute() {
|
||||
final String firstnameAttribute = _configDao
|
||||
.getValue("ldap.firstname.attribute");
|
||||
return firstnameAttribute == null ? "givenname" : firstnameAttribute;
|
||||
}
|
||||
|
||||
public String getLastnameAttribute() {
|
||||
final String lastnameAttribute = _configDao
|
||||
.getValue("ldap.lastname.attribute");
|
||||
return lastnameAttribute == null ? "sn" : lastnameAttribute;
|
||||
}
|
||||
|
||||
public String getProviderUrl() {
|
||||
final String protocol = getSSLStatus() == true ? "ldaps://" : "ldap://";
|
||||
final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager
|
||||
.listConfigurations(new LdapListConfigurationCmd(_ldapManager));
|
||||
final StringBuilder providerUrls = new StringBuilder();
|
||||
String delim = "";
|
||||
for (final LdapConfigurationVO resource : result.first()) {
|
||||
final String providerUrl = protocol + resource.getHostname() + ":"
|
||||
+ resource.getPort();
|
||||
providerUrls.append(delim).append(providerUrl);
|
||||
delim = " ";
|
||||
}
|
||||
return providerUrls.toString();
|
||||
}
|
||||
|
||||
public String[] getReturnAttributes() {
|
||||
return new String[] { getUsernameAttribute(), getEmailAttribute(),
|
||||
getFirstnameAttribute(), getLastnameAttribute() };
|
||||
}
|
||||
|
||||
public int getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public String getSearchGroupPrinciple() {
|
||||
return _configDao.getValue("ldap.search.group.principle");
|
||||
}
|
||||
|
||||
public boolean getSSLStatus() {
|
||||
boolean sslStatus = false;
|
||||
if (getTrustStore() != null && getTrustStorePassword() != null) {
|
||||
sslStatus = true;
|
||||
}
|
||||
return sslStatus;
|
||||
}
|
||||
|
||||
public String getTrustStore() {
|
||||
return _configDao.getValue("ldap.truststore");
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return _configDao.getValue("ldap.truststore.password");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import 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 setId(final long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
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 DirContext createBindContext() throws NamingException {
|
||||
return createBindContext(null);
|
||||
}
|
||||
|
||||
public DirContext createBindContext(final String providerUrl)
|
||||
throws NamingException {
|
||||
final String bindPrincipal = _ldapConfiguration.getBindPrincipal();
|
||||
final String bindPassword = _ldapConfiguration.getBindPassword();
|
||||
return createInitialDirContext(bindPrincipal, bindPassword,
|
||||
providerUrl, true);
|
||||
}
|
||||
|
||||
private DirContext createInitialDirContext(final String principal,
|
||||
final String password, final boolean isSystemContext)
|
||||
throws NamingException {
|
||||
return createInitialDirContext(principal, password, null,
|
||||
isSystemContext);
|
||||
}
|
||||
|
||||
private DirContext createInitialDirContext(final String principal,
|
||||
final String password, final String providerUrl,
|
||||
final boolean isSystemContext) throws NamingException {
|
||||
return new InitialDirContext(getEnvironment(principal, password,
|
||||
providerUrl, isSystemContext));
|
||||
}
|
||||
|
||||
public DirContext createUserContext(final String principal,
|
||||
final String password) throws NamingException {
|
||||
return createInitialDirContext(principal, password, false);
|
||||
}
|
||||
|
||||
private void enableSSL(final Hashtable<String, String> environment) {
|
||||
final boolean sslStatus = _ldapConfiguration.getSSLStatus();
|
||||
|
||||
if (sslStatus) {
|
||||
s_logger.info("LDAP SSL enabled.");
|
||||
environment.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
System.setProperty("javax.net.ssl.trustStore",
|
||||
_ldapConfiguration.getTrustStore());
|
||||
System.setProperty("javax.net.ssl.trustStorePassword",
|
||||
_ldapConfiguration.getTrustStorePassword());
|
||||
}
|
||||
}
|
||||
|
||||
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 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", "500");
|
||||
environment.put("com.sun.jndi.ldap.connect.pool", "true");
|
||||
|
||||
enableSSL(environment);
|
||||
setAuthentication(environment, isSystemContext);
|
||||
|
||||
if (principal != null) {
|
||||
environment.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
environment.put(Context.SECURITY_CREDENTIALS, password);
|
||||
}
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
private void setAuthentication(final Hashtable<String, String> environment,
|
||||
final boolean isSystemContext) {
|
||||
final String authentication = _ldapConfiguration.getAuthentication();
|
||||
|
||||
if ("none".equals(authentication) && !isSystemContext) {
|
||||
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
} else {
|
||||
environment.put(Context.SECURITY_AUTHENTICATION, authentication);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
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;
|
||||
|
||||
LdapUser getUser(final String username) throws NamingException;
|
||||
|
||||
List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
|
||||
|
||||
boolean isLdapEnabled();
|
||||
|
||||
Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(
|
||||
LdapListConfigurationCmd cmd);
|
||||
|
||||
List<LdapUser> searchUsers(String query)
|
||||
throws NoLdapUserMatchingQueryException;
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
|
||||
import org.apache.cloudstack.api.LdapValidator;
|
||||
import org.apache.cloudstack.api.command.LdapAddConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapCreateAccountCmd;
|
||||
import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapListUsersCmd;
|
||||
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 org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@Component
|
||||
@Local(value = LdapManager.class)
|
||||
public class LdapManagerImpl implements LdapManager, LdapValidator {
|
||||
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 DirContext context = _ldapContextFactory.createUserContext(
|
||||
principal, password);
|
||||
closeContext(context);
|
||||
return true;
|
||||
} catch (final NamingException e) {
|
||||
s_logger.info("Failed to authenticate user: " + username
|
||||
+ ". incorrect password.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void closeContext(final DirContext 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.setFirstname(user.getFirstname());
|
||||
response.setLastname(user.getLastname());
|
||||
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(LdapListUsersCmd.class);
|
||||
cmdList.add(LdapAddConfigurationCmd.class);
|
||||
cmdList.add(LdapDeleteConfigurationCmd.class);
|
||||
cmdList.add(LdapListConfigurationCmd.class);
|
||||
cmdList.add(LdapCreateAccountCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LdapUser getUser(final String username) throws NamingException {
|
||||
DirContext 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 {
|
||||
DirContext context = null;
|
||||
try {
|
||||
context = _ldapContextFactory.createBindContext();
|
||||
return _ldapUserManager.getUsers(context);
|
||||
} catch (final NamingException e) {
|
||||
throw new NoLdapUserMatchingQueryException("*");
|
||||
} finally {
|
||||
closeContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLdapEnabled() {
|
||||
return listConfigurations(new LdapListConfigurationCmd(this)).second() > 0;
|
||||
}
|
||||
|
||||
@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 {
|
||||
DirContext 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
public class LdapUser implements Comparable<LdapUser> {
|
||||
private final String email;
|
||||
private final String principal;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
private final String username;
|
||||
|
||||
public LdapUser(final String username, final String email,
|
||||
final String firstname, final String lastname,
|
||||
final String principal) {
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
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 getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public String getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getUsername().hashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.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.DirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
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 firstname = LdapUtils.getAttributeValue(attributes,
|
||||
_ldapConfiguration.getFirstnameAttribute());
|
||||
final String lastname = LdapUtils.getAttributeValue(attributes,
|
||||
_ldapConfiguration.getLastnameAttribute());
|
||||
final String principal = result.getName() + ","
|
||||
+ _ldapConfiguration.getBaseDn();
|
||||
|
||||
return new LdapUser(username, email, firstname, lastname, principal);
|
||||
}
|
||||
|
||||
private String generateSearchFilter(final String username) {
|
||||
final StringBuilder userObjectFilter = new StringBuilder();
|
||||
userObjectFilter.append("(objectClass=");
|
||||
userObjectFilter.append(_ldapConfiguration.getUserObject());
|
||||
userObjectFilter.append(")");
|
||||
|
||||
final StringBuilder usernameFilter = new StringBuilder();
|
||||
usernameFilter.append("(");
|
||||
usernameFilter.append(_ldapConfiguration.getUsernameAttribute());
|
||||
usernameFilter.append("=");
|
||||
usernameFilter.append((username == null ? "*" : username));
|
||||
usernameFilter.append(")");
|
||||
|
||||
final StringBuilder memberOfFilter = new StringBuilder();
|
||||
if (_ldapConfiguration.getSearchGroupPrinciple() != null) {
|
||||
memberOfFilter.append("(memberof=");
|
||||
memberOfFilter.append(_ldapConfiguration.getSearchGroupPrinciple());
|
||||
memberOfFilter.append(")");
|
||||
}
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append("(&");
|
||||
result.append(userObjectFilter);
|
||||
result.append(usernameFilter);
|
||||
result.append(memberOfFilter);
|
||||
result.append(")");
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public LdapUser getUser(final String username, final DirContext context)
|
||||
throws NamingException {
|
||||
final NamingEnumeration<SearchResult> result = searchUsers(username,
|
||||
context);
|
||||
if (result.hasMoreElements()) {
|
||||
return createUser(result.nextElement());
|
||||
} else {
|
||||
throw new NamingException("No user found for username " + username);
|
||||
}
|
||||
}
|
||||
|
||||
public List<LdapUser> getUsers(final DirContext context)
|
||||
throws NamingException {
|
||||
return getUsers(null, context);
|
||||
}
|
||||
|
||||
public List<LdapUser> getUsers(final String username,
|
||||
final DirContext 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 DirContext context)
|
||||
throws NamingException {
|
||||
return searchUsers(null, context);
|
||||
}
|
||||
|
||||
public NamingEnumeration<SearchResult> searchUsers(final String username,
|
||||
final DirContext context) throws NamingException {
|
||||
final SearchControls controls = new SearchControls();
|
||||
|
||||
controls.setSearchScope(_ldapConfiguration.getScope());
|
||||
controls.setReturningAttributes(_ldapConfiguration
|
||||
.getReturnAttributes());
|
||||
|
||||
return context.search(_ldapConfiguration.getBaseDn(),
|
||||
generateSearchFilter(username), controls);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import 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 (final 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() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,13 +14,18 @@
|
|||
// 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;
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
public class NoSuchLdapUserException extends Exception {
|
||||
private static final long serialVersionUID = 6782938919658010900L;
|
||||
private final String username;
|
||||
|
||||
public class LDAPRemoveResponse extends BaseResponse {
|
||||
public NoSuchLdapUserException(final String username) {
|
||||
super("No such user: " + username);
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public LDAPRemoveResponse(){
|
||||
super();
|
||||
}
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap.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);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// 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 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>();
|
||||
|
||||
public void add(SearchResult item) {
|
||||
items.add(item)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws NamingException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMore() throws NamingException {
|
||||
return hasMoreElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return items.size != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() throws NamingException {
|
||||
return nextElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nextElement() {
|
||||
SearchResult result = items.getFirst();
|
||||
items.removeFirst();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// 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 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 failed response from execute"() {
|
||||
given: "We have an LDAP manager, no configuration and a LdapAddConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.addConfiguration(_, _) >> { throw new InvalidParameterValueException() }
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "LdapAddCofnigurationCmd is executed"
|
||||
ldapAddConfigurationCmd.execute()
|
||||
then: "an exception is thrown"
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given: "We have an LdapManager and LdapConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "Get Entity Owner Id is called"
|
||||
long ownerId = ldapAddConfigurationCmd.getEntityOwnerId()
|
||||
then: "1 is returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful response from execute"() {
|
||||
given: "We have an LDAP Manager that has a configuration and a LdapAddConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.addConfiguration(_, _) >> new LdapConfigurationResponse("localhost", 389)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "LdapAddConfigurationCmd is executed"
|
||||
ldapAddConfigurationCmd.execute()
|
||||
then: "the responseObject should have the hostname localhost and port 389"
|
||||
ldapAddConfigurationCmd.responseObject.hostname == "localhost"
|
||||
ldapAddConfigurationCmd.responseObject.port == 389
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given: "We have an LdapManager and LdapConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "Get Command Name is called"
|
||||
String commandName = ldapAddConfigurationCmd.getCommandName()
|
||||
then: "ldapconfigurationresponse is returned"
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
|
||||
def "Test successful setting of hostname"() {
|
||||
given: "We have an LdapManager and LdapAddConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "The hostname is set"
|
||||
ldapAddConfigurationCmd.setHostname("localhost")
|
||||
then: "Get hostname returns the set hostname"
|
||||
ldapAddConfigurationCmd.getHostname() == "localhost"
|
||||
}
|
||||
|
||||
def "Test successful setting of port"() {
|
||||
given: "We have an LdapManager and LdapAddConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when: "The port is set"
|
||||
ldapAddConfigurationCmd.setPort(389)
|
||||
then: "Get port returns the port"
|
||||
ldapAddConfigurationCmd.getPort() == 389
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
// 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 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: "We have an LdapManager, userAccountDao and ldapAuthenticator and the user doesn't exist within cloudstack."
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> null
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "A user authentications"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then: "their authentication fails"
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap bind being unsuccessful"() {
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.canAuthenticate(_, _) >> false
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
|
||||
then: "their authentication fails"
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap not being configured"() {
|
||||
given: "We have an LdapManager, A configured LDAP server, a userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> false
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "The user authenticates"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then: "their authentication fails"
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test successful authentication"() {
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.canAuthenticate(_, _) >> true
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
|
||||
then: "their authentication passes"
|
||||
result == true
|
||||
}
|
||||
|
||||
def "Test that encode doesn't change the input"() {
|
||||
given: "We have an LdapManager, userAccountDao and LdapAuthenticator"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "a users password is encoded"
|
||||
def result = ldapAuthenticator.encode("password")
|
||||
then: "it doesn't change"
|
||||
result == "password"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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 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: "We have an LdapConfigurationDao implementation"
|
||||
def ldapConfigurationDaoImpl = new LdapConfigurationDaoImpl();
|
||||
expect: "that hostnameSearch and listAllConfigurationsSearch is configured"
|
||||
ldapConfigurationDaoImpl.hostnameSearch != null;
|
||||
ldapConfigurationDaoImpl.listAllConfigurationsSearch != null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// 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 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: "We have a LdapConfigurationResponse"
|
||||
LdapConfigurationResponse response = new LdapConfigurationResponse();
|
||||
when: "The hostname is set"
|
||||
response.setHostname("localhost");
|
||||
then: "Get hostname should return the set value"
|
||||
response.getHostname() == "localhost";
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapConfigurationResponse hostname and port via constructor"() {
|
||||
given: "We have a LdapConfiguration response"
|
||||
LdapConfigurationResponse response
|
||||
when: "both hostname and port are set by constructor"
|
||||
response = new LdapConfigurationResponse("localhost", 389)
|
||||
then: "Get hostname and port should return the set values."
|
||||
response.getHostname() == "localhost"
|
||||
response.getPort() == 389
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapConfigurationResponse port"() {
|
||||
given: "We have a LdapConfigurationResponse"
|
||||
LdapConfigurationResponse response = new LdapConfigurationResponse()
|
||||
when: "The port is set"
|
||||
response.setPort(389)
|
||||
then: "Get port should return the set value"
|
||||
response.getPort() == 389
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
// 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 groovy.org.apache.cloudstack.ldap
|
||||
|
||||
import org.apache.cloudstack.framework.config.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 getAuthentication returns none"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get authentication is called"
|
||||
String authentication = ldapConfiguration.getAuthentication()
|
||||
then: "none should be returned"
|
||||
authentication == "none"
|
||||
}
|
||||
|
||||
def "Test that getAuthentication returns simple"() {
|
||||
given: "We have a configDao, LdapManager and LdapConfiguration with bind principle and password set"
|
||||
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: "Get authentication is called"
|
||||
String authentication = ldapConfiguration.getAuthentication()
|
||||
then: "authentication should be set to simple"
|
||||
authentication == "simple"
|
||||
}
|
||||
|
||||
def "Test that getBaseDn returns dc=cloudstack,dc=org"() {
|
||||
given: "We have a ConfigDao, LdapManager and ldapConfiguration with a baseDn value set."
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.basedn") >> "dc=cloudstack,dc=org"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get basedn is called"
|
||||
String baseDn = ldapConfiguration.getBaseDn();
|
||||
then: "The set baseDn should be returned"
|
||||
baseDn == "dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test that getEmailAttribute returns mail"() {
|
||||
given: "Given that we have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.email.attribute") >> "mail"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get Email Attribute is called"
|
||||
String emailAttribute = ldapConfiguration.getEmailAttribute()
|
||||
then: "mail should be returned"
|
||||
emailAttribute == "mail"
|
||||
}
|
||||
|
||||
def "Test that getFactory returns com.sun.jndi.ldap.LdapCtxFactory"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get Factory is scalled"
|
||||
String factory = ldapConfiguration.getFactory();
|
||||
then: "com.sun.jndi.ldap.LdapCtxFactory is returned"
|
||||
factory == "com.sun.jndi.ldap.LdapCtxFactory"
|
||||
}
|
||||
|
||||
def "Test that getFirstnameAttribute returns givenname"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.firstname.attribute") >> "givenname"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get firstname attribute is called"
|
||||
String firstname = ldapConfiguration.getFirstnameAttribute()
|
||||
then: "givennam should be returned"
|
||||
firstname == "givenname"
|
||||
}
|
||||
|
||||
def "Test that getLastnameAttribute returns givenname"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.lastname.attribute") >> "sn"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get Lastname Attribute is scalled "
|
||||
String lastname = ldapConfiguration.getLastnameAttribute()
|
||||
then: "sn should be returned"
|
||||
lastname == "sn"
|
||||
}
|
||||
|
||||
def "Test that getReturnAttributes returns the correct data"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.firstname.attribute") >> "givenname"
|
||||
configDao.getValue("ldap.lastname.attribute") >> "sn"
|
||||
configDao.getValue("ldap.username.attribute") >> "uid"
|
||||
configDao.getValue("ldap.email.attribute") >> "mail"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get return attributes is called"
|
||||
String[] returnAttributes = ldapConfiguration.getReturnAttributes()
|
||||
then: "An array containing uid, mail, givenname and sn is returned"
|
||||
returnAttributes == ["uid", "mail", "givenname", "sn"]
|
||||
}
|
||||
|
||||
def "Test that getScope returns SearchControls.SUBTREE_SCOPE"() {
|
||||
given: "We have ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get scope is called"
|
||||
int scope = ldapConfiguration.getScope()
|
||||
then: "SearchControls.SUBTRE_SCOPE should be returned"
|
||||
scope == SearchControls.SUBTREE_SCOPE;
|
||||
}
|
||||
|
||||
def "Test that getUsernameAttribute returns uid"() {
|
||||
given: "We have ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.username.attribute") >> "uid"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get Username Attribute is called"
|
||||
String usernameAttribute = ldapConfiguration.getUsernameAttribute()
|
||||
then: "uid should be returned"
|
||||
usernameAttribute == "uid"
|
||||
}
|
||||
|
||||
def "Test that getUserObject returns inetOrgPerson"() {
|
||||
given: "We have a ConfigDao, LdapManager and LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.user.object") >> "inetOrgPerson"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when: "Get user object is called"
|
||||
String userObject = ldapConfiguration.getUserObject()
|
||||
then: "inetOrgPerson is returned"
|
||||
userObject == "inetOrgPerson"
|
||||
}
|
||||
|
||||
def "Test that providerUrl successfully returns a URL when a configuration is available"() {
|
||||
given: "We have a ConfigDao, LdapManager, LdapConfiguration"
|
||||
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: "A request is made to get the providerUrl"
|
||||
String providerUrl = ldapConfiguration.getProviderUrl()
|
||||
|
||||
then: "The providerUrl should be given."
|
||||
providerUrl == "ldap://localhost:389"
|
||||
}
|
||||
|
||||
def "Test that get search group principle returns successfully"() {
|
||||
given: "We have a ConfigDao with a value for ldap.search.group.principle and an LdapConfiguration"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.search.group.principle") >> "cn=cloudstack,cn=users,dc=cloudstack,dc=org"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
|
||||
when: "A request is made to get the search group principle"
|
||||
String result = ldapConfiguration.getSearchGroupPrinciple();
|
||||
|
||||
then: "The result holds the same value configDao did"
|
||||
result == "cn=cloudstack,cn=users,dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test that getTrustStorePassword resopnds"() {
|
||||
given: "We have a ConfigDao with a value for truststore password"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.truststore.password") >> "password"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
|
||||
when: "A request is made to get the truststore password"
|
||||
String result = ldapConfiguration.getTrustStorePassword()
|
||||
|
||||
then: "The result is password"
|
||||
result == "password";
|
||||
}
|
||||
|
||||
def "Test that getSSLStatus can be true"() {
|
||||
given: "We have a ConfigDao with values for truststore and truststore password set"
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.truststore") >> "/tmp/ldap.ts"
|
||||
configDao.getValue("ldap.truststore.password") >> "password"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
|
||||
when: "A request is made to get the status of SSL"
|
||||
boolean result = ldapConfiguration.getSSLStatus();
|
||||
|
||||
then: "The response should be true"
|
||||
result == true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// 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 groovy.org.apache.cloudstack.ldap
|
||||
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO
|
||||
|
||||
|
||||
class LdapConfigurationVOSpec extends spock.lang.Specification {
|
||||
def "Testing that the ID hostname and port is correctly set within the LDAP configuration VO"() {
|
||||
given: "You have created an LDAP Configuration VO"
|
||||
def configuration = new LdapConfigurationVO(hostname, port)
|
||||
configuration.setId(id)
|
||||
expect: "The id hostname and port is equal to the given data source"
|
||||
configuration.getId() == id
|
||||
configuration.getHostname() == hostname
|
||||
configuration.getPort() == port
|
||||
where: "The id, hostname and port is set to "
|
||||
hostname << ["", null, "localhost"]
|
||||
id << [0, 1000, -1000]
|
||||
port << [0, 1000, -1000]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
// 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 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.getFirstnameAttribute() >> "givenname"
|
||||
ldapConfiguration.getLastnameAttribute() >> "sn"
|
||||
ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
|
||||
ldapConfiguration.getSSLStatus() >> true
|
||||
ldapConfiguration.getTrustStore() >> "/tmp/ldap.ts"
|
||||
ldapConfiguration.getTrustStorePassword() >> "password"
|
||||
|
||||
username = "rmurphy"
|
||||
principal = "cn=" + username + "," + ldapConfiguration.getBaseDn()
|
||||
password = "password"
|
||||
}
|
||||
|
||||
def "Test succcessfully creating a initial context"() {
|
||||
given: "We have a LdapContextFactory"
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when: "A context attempts to bind and no Ldap server is avaiable"
|
||||
ldapContextFactory.createInitialDirContext(null, null, true)
|
||||
then: "An expection is thrown"
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successful failed connection"() {
|
||||
given: "We have a LdapContextFactory"
|
||||
def ldapContextFactory = Spy(LdapContextFactory, constructorArgs: [ldapConfiguration])
|
||||
when: "Test connection is executed"
|
||||
ldapContextFactory.testConnection(ldapConfiguration.getProviderUrl())
|
||||
then: "An exception is thrown"
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successfully binding as a user"() {
|
||||
given: "We have a LdapContextFactory"
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when: "A user attempts to bind and no LDAP server is avaiable"
|
||||
ldapContextFactory.createUserContext(principal, password)
|
||||
then: "An exception is thrown"
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successfully creating a environment with username and password"() {
|
||||
given: "We have an LdapContextFactory"
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
|
||||
when: "A request for an environment is made"
|
||||
def result = ldapContextFactory.getEnvironment(null, null, null, true)
|
||||
|
||||
then: "The resulting values should be set"
|
||||
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 creating a system environment with anon bind"() {
|
||||
given: "We have an LdapContext Factory"
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
|
||||
when: "A request for an environment is made"
|
||||
def result = ldapContextFactory.getEnvironment(principal, password, null, false)
|
||||
|
||||
then: "The resulting values should be set"
|
||||
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 successully binding as system"() {
|
||||
given: "We have a LdapContextFactory"
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when: "A bind context attempts to bind and no Ldap server is avaiable"
|
||||
ldapContextFactory.createBindContext()
|
||||
then: "An exception is thrown"
|
||||
thrown NamingException
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
// 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 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.LdapUser;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapCreateAccountCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.user.AccountService;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.UserAccountVO;
|
||||
|
||||
import javax.naming.NamingException
|
||||
|
||||
class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
|
||||
def "Test failure to retrive LDAP user"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd and LDAP user that doesn't exist"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
ldapManager.getUser(_) >> { throw new NamingException() }
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||
ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
|
||||
CallContext context = ldapCreateAccountCmd.getCurrentContext()
|
||||
when: "An an account is created"
|
||||
ldapCreateAccountCmd.execute()
|
||||
then: "It fails and an exception is thrown"
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test failed creation due to a null response from cloudstack account creater"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||
ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
|
||||
ldapCreateAccountCmd.createCloudstackUserAccount(_) >> null
|
||||
when: "Cloudstack fail to create the user"
|
||||
ldapCreateAccountCmd.execute()
|
||||
then: "An exception is thrown"
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test command name"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "Get command name is called"
|
||||
def result = ldapCreateAccountCmd.getCommandName()
|
||||
then: "createaccountresponse is returned"
|
||||
result == "createaccountresponse"
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given: "We have an LdapManager, AccountService andL dapCreateAccount"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
|
||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||
when: "Get entity owner id is called"
|
||||
long ownerId = ldapCreateAccountCmd.getEntityOwnerId()
|
||||
then: "1 is returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test password generation"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A password is generated"
|
||||
def result = ldapCreateAccountCmd.generatePassword()
|
||||
then: "The result shouldn't be null or empty"
|
||||
result != ""
|
||||
result != null
|
||||
}
|
||||
|
||||
def "Test validate User"() {
|
||||
given: "We have an LdapManager, AccountService andL dapCreateAccount"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
|
||||
when: "a user with an username, email, firstname and lastname is validated"
|
||||
def result = ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname","lastname","principal"))
|
||||
then: "the result is true"
|
||||
result == true
|
||||
}
|
||||
|
||||
def "Test validate User empty email"() {
|
||||
given: "We have an LdapManager, AccountService andL dapCreateAccount"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no email address attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username",null,"firstname","lastname","principal"))
|
||||
then: "An exception is thrown"
|
||||
thrown Exception
|
||||
}
|
||||
|
||||
def "Test validate User empty firstname"() {
|
||||
given: "We have an LdapManager, AccountService andL dapCreateAccount"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no firstname attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username","email",null,"lastname","principal"))
|
||||
then: "An exception is thrown"
|
||||
thrown Exception
|
||||
}
|
||||
|
||||
def "Test validate User empty lastname"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no lastname attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username","email","firstname",null,"principal"))
|
||||
then: "An exception is thown"
|
||||
thrown Exception
|
||||
}
|
||||
|
||||
def "Test validation of a user"() {
|
||||
given: "We have an LdapManager, AccountService andL dapCreateAccount"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||
when: "Get command name is called"
|
||||
def commandName = ldapCreateAccountCmd.getCommandName()
|
||||
then: "createaccountresponse is returned"
|
||||
commandName == "createaccountresponse"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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 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 failed response from execute"() {
|
||||
given: "We have an LdapManager and LdapDeleteConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.deleteConfiguration(_) >> { throw new InvalidParameterValueException() }
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when:"LdapDeleteConfigurationCmd is executed and no configuration exists"
|
||||
ldapDeleteConfigurationCmd.execute()
|
||||
then: "An exception is thrown"
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given: "We have an LdapManager and LdapDeleteConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when: "Get entity owner id is called"
|
||||
long ownerId = ldapDeleteConfigurationCmd.getEntityOwnerId()
|
||||
then: "1 is returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful response from execute"() {
|
||||
given: "We have an LdapManager and LdapDeleteConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.deleteConfiguration(_) >> new LdapConfigurationResponse("localhost")
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when: "LdapDeleteConfigurationCmd is executed"
|
||||
ldapDeleteConfigurationCmd.execute()
|
||||
then: "The given configuration should be deleted and returned"
|
||||
ldapDeleteConfigurationCmd.responseObject.hostname == "localhost"
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given: "We have an LdapManager and LdapDeleteConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when: "Get Command name is called"
|
||||
String commandName = ldapDeleteConfigurationCmd.getCommandName()
|
||||
then: "ldapconfigurationresponse is returned"
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package 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 failed response from execute"() {
|
||||
given: "We have an LdapManager and a LdapListConfigurationsCmd"
|
||||
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 is executed"
|
||||
ldapListConfigurationCmd.execute()
|
||||
then: "Its response object contains an array that is 0"
|
||||
ldapListConfigurationCmd.getResponseObject().getResponses().size() == 0
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given: "We have an LdapManager and ListLdapConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when: "Get entity owner id is called"
|
||||
long ownerId = ldapListConfigurationCmd.getEntityOwnerId()
|
||||
then: "a 1 is returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful response from execute"() {
|
||||
given: "We have an LdapManager with a configuration and a LdapListConfigurationsCmd"
|
||||
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: "LdapListConfigurationsCmd is executed"
|
||||
ldapListConfigurationCmd.execute()
|
||||
then: "Its response object contains an array that is not 0 in size"
|
||||
ldapListConfigurationCmd.getResponseObject().getResponses().size() != 0
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given: "We have an LdapManager and LdapListConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when: "Get command name is called"
|
||||
String commandName = ldapListConfigurationCmd.getCommandName()
|
||||
then: "ldapconfigurationresponse is returned"
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
|
||||
def "Test successful setting of hostname"() {
|
||||
given: "We have an LdapManager and LdapListConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when: "The hostname is set"
|
||||
ldapListConfigurationCmd.setHostname("localhost")
|
||||
then: "Get hostname returns the set value"
|
||||
ldapListConfigurationCmd.getHostname() == "localhost"
|
||||
}
|
||||
|
||||
def "Test successful setting of Port"() {
|
||||
given: "We have an LdapManager and LdapListConfigurationCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when: "The port is set"
|
||||
ldapListConfigurationCmd.setPort(389)
|
||||
then: "Get port returns the set value"
|
||||
ldapListConfigurationCmd.getPort() == 389
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// 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 groovy.org.apache.cloudstack.ldap
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapListUsersCmd
|
||||
import org.apache.cloudstack.api.ServerApiException
|
||||
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse
|
||||
import org.apache.cloudstack.api.response.ListResponse
|
||||
import org.apache.cloudstack.api.response.UserResponse
|
||||
import org.apache.cloudstack.ldap.LdapManager
|
||||
import org.apache.cloudstack.ldap.LdapUser
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
|
||||
import org.apache.cloudstack.query.QueryService
|
||||
|
||||
class LdapListUsersCmdSpec extends spock.lang.Specification {
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given: "We have an LdapManager, QueryService and LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def queryService = Mock(QueryService)
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager, queryService)
|
||||
when: "Get entity owner id is called"
|
||||
long ownerId = ldapListUsersCmd.getEntityOwnerId()
|
||||
then: "a 1 should be returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful empty response from execute"() {
|
||||
given: "We have a LdapManager with no users, QueryService and a LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.getUsers() >> {throw new NoLdapUserMatchingQueryException()}
|
||||
def queryService = Mock(QueryService)
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager, queryService)
|
||||
when: "LdapListUsersCmd is executed"
|
||||
ldapListUsersCmd.execute()
|
||||
then: "An array of size 0 is returned"
|
||||
ldapListUsersCmd.responseObject.getResponses().size() == 0
|
||||
}
|
||||
|
||||
def "Test successful response from execute"() {
|
||||
given: "We have an LdapManager, one user, QueryService and a LdapListUsersCmd"
|
||||
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 queryService = Mock(QueryService)
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager, queryService)
|
||||
when: "LdapListUsersCmd is executed"
|
||||
ldapListUsersCmd.execute()
|
||||
then: "a list of size not 0 is returned"
|
||||
ldapListUsersCmd.responseObject.getResponses().size() != 0
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given: "We have an LdapManager, QueryService and a LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def queryService = Mock(QueryService)
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager, queryService)
|
||||
when: "Get command name is called"
|
||||
String commandName = ldapListUsersCmd.getCommandName()
|
||||
then: "ldapuserresponse is returned"
|
||||
commandName == "ldapuserresponse"
|
||||
}
|
||||
|
||||
def "Test successful result from isACloudstackUser"() {
|
||||
given: "We have an LdapManager and a LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def queryService = Mock(QueryService)
|
||||
|
||||
UserResponse userResponse = new UserResponse()
|
||||
userResponse.setUsername("rmurphy")
|
||||
|
||||
ArrayList<UserResponse> responses = new ArrayList<UserResponse>()
|
||||
responses.add(userResponse);
|
||||
|
||||
ListResponse<UserResponse> queryServiceResponse = new ListResponse<UserResponse>()
|
||||
queryServiceResponse.setResponses(responses)
|
||||
|
||||
queryService.searchForUsers(_) >> queryServiceResponse
|
||||
|
||||
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
||||
|
||||
when: "isACloudstackUser is executed"
|
||||
def result = ldapListUsersCmd.isACloudstackUser(ldapUser);
|
||||
|
||||
then: "The result is true"
|
||||
result == true;
|
||||
}
|
||||
|
||||
def "Test failed result from isACloudstackUser"() {
|
||||
given: "We have an LdapManager and a LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def queryService = Mock(QueryService)
|
||||
|
||||
queryService.searchForUsers(_) >> new ListResponse<UserResponse>()
|
||||
|
||||
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
||||
|
||||
when: "isACloudstackUser is executed"
|
||||
def result = ldapListUsersCmd.isACloudstackUser(ldapUser);
|
||||
|
||||
then: "The result is true"
|
||||
result == false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
// 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 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 failing of getUser due to bind issue"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "We search for a user but there is a bind issue"
|
||||
ldapManager.getUser("rmurphy")
|
||||
then: "an exception is thrown"
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test failing of getUsers due to bind issue"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "We search for a group of users but there is a bind issue"
|
||||
ldapManager.getUsers()
|
||||
then: "An exception is thrown"
|
||||
thrown NoLdapUserMatchingQueryException
|
||||
}
|
||||
|
||||
def "Test failing of searchUsers due to a failure to bind"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "We search for users"
|
||||
ldapManager.searchUsers("rmurphy")
|
||||
then: "An exception is thrown"
|
||||
thrown NoLdapUserMatchingQueryException
|
||||
}
|
||||
|
||||
def "Test LdapConfigurationResponse generation"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "A ldap configuration response is generated"
|
||||
def result = ldapManager.createLdapConfigurationResponse(new LdapConfigurationVO("localhost", 389))
|
||||
then: "the result of the response should match the given LdapConfigurationVO"
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test LdapUserResponse generation"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "A ldap user response is generated"
|
||||
def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
then: "The result of the response should match the given ldap user"
|
||||
result.username == "rmurphy"
|
||||
result.email == "rmurphy@test.com"
|
||||
result.firstname == "Ryan"
|
||||
result.lastname == "Murphy"
|
||||
result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test success getUsers"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> null
|
||||
List<LdapUser> users = new ArrayList<>();
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
ldapUserManager.getUsers(_) >> users;
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "We search for a group of users"
|
||||
def result = ldapManager.getUsers()
|
||||
then: "A list greater than 0 is returned"
|
||||
result.size() > 0;
|
||||
}
|
||||
|
||||
def "Test success of getUser"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "We search for a user"
|
||||
def result = ldapManager.getUser("rmurphy")
|
||||
then: "The user is returned"
|
||||
result.username == "rmurphy"
|
||||
result.email == "rmurphy@test.com"
|
||||
result.firstname == "Ryan"
|
||||
result.lastname == "Murphy"
|
||||
result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test successful closing of context"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "The context is closed"
|
||||
def context = Mock(InitialLdapContext)
|
||||
ldapManager.closeContext(context)
|
||||
then: "The context is null"
|
||||
context.defaultInitCtx == null
|
||||
}
|
||||
|
||||
def "Test successful failed result from canAuthenticate due to bad password"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "The user attempts to authenticate with a bad password"
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then: "The authentication fails"
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test successful failed result from canAuthenticate due to user not found"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "The user attempts to authenticate and the user is not found"
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then: "the authentication fails"
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test successful failed result from deleteConfiguration due to configuration not existing"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapConfigurationDao.findByHostname(_) >> null
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "A ldap configuration that doesn't exist is deleted"
|
||||
ldapManager.deleteConfiguration("localhost")
|
||||
then: "A exception is thrown"
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test successful failing to close of context"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "The context is closed"
|
||||
def context = Mock(InitialLdapContext)
|
||||
context.close() >> { throw new NamingException() }
|
||||
ldapManager.closeContext(context)
|
||||
then: "An exception is thrown"
|
||||
context.defaultInitCtx == null
|
||||
}
|
||||
|
||||
def "Test successful result from canAuthenticate"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A user authenticates"
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then: "The result is true"
|
||||
result == true
|
||||
}
|
||||
|
||||
def "Test successful result from deleteConfiguration"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A ldap configuration is deleted"
|
||||
def result = ldapManager.deleteConfiguration("localhost")
|
||||
then: "The deleted configuration is returned"
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test successful result from searchUsers"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> null;
|
||||
|
||||
List<LdapUser> users = new ArrayList<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: "We search for users"
|
||||
def result = ldapManager.searchUsers("rmurphy");
|
||||
then: "A list of atleast 1 is returned"
|
||||
result.size() > 0;
|
||||
}
|
||||
|
||||
def "Test successfully addConfiguration"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A ldap configuration is added"
|
||||
def result = ldapManager.addConfiguration("localhost", 389)
|
||||
then: "the resulting object contain the given hostname and port"
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test that addConfiguration fails when a binding fails"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A configuration is added that can not be binded"
|
||||
ldapManager.addConfiguration("localhost", 389)
|
||||
then: "An exception is thrown"
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test that addConfiguration fails when a duplicate configuration exists"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "a configuration that already exists is added"
|
||||
ldapManager.addConfiguration("localhost", 389)
|
||||
then: "An exception is thrown"
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test that getCommands isn't empty"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when: "Get commands is called"
|
||||
def result = ldapManager.getCommands()
|
||||
then: "it must have atleast 1 command"
|
||||
result.size() > 0
|
||||
}
|
||||
|
||||
def "Testing of listConfigurations"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A request for configurations is made"
|
||||
def result = ldapManager.listConfigurations(new LdapListConfigurationCmd())
|
||||
then: "Then atleast 1 ldap configuration is returned"
|
||||
result.second() > 0
|
||||
}
|
||||
|
||||
def "Testing of isLdapEnabled"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
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: "A request to find out is ldap enabled"
|
||||
def result = ldapManager.isLdapEnabled();
|
||||
then: "true is returned because a configuration was found"
|
||||
result == true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// 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 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 getEntityOwnerId is 1"() {
|
||||
given: "We have an Ldap manager and ldap user search cmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when: "getEntityOwnerId is called"
|
||||
long ownerId = ldapUserSearchCmd.getEntityOwnerId()
|
||||
then: "1 is returned"
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful empty response from execute"() {
|
||||
given: "We have an Ldap manager and ldap user search cmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.searchUsers(_) >> {throw new NoLdapUserMatchingQueryException()}
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when: "The command is executed with no users found"
|
||||
ldapUserSearchCmd.execute()
|
||||
then: "An empty array is returned"
|
||||
ldapUserSearchCmd.responseObject.getResponses().size() == 0
|
||||
}
|
||||
|
||||
def "Test successful response from execute"() {
|
||||
given: "We have an Ldap manager and ldap user search cmd"
|
||||
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: "The command is executed"
|
||||
ldapUserSearchCmd.execute()
|
||||
then: "A array with length of atleast 1 is returned"
|
||||
ldapUserSearchCmd.responseObject.getResponses().size() > 0
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given: "We have an Ldap manager and ldap user search cmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when: "When a request for the command name is made"
|
||||
String commandName = ldapUserSearchCmd.getCommandName()
|
||||
then: "ldapuserresponse is returned"
|
||||
commandName == "ldapuserresponse"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
// 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 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 firstname
|
||||
|
||||
@Shared
|
||||
private def lastname
|
||||
|
||||
@Shared
|
||||
private def principal
|
||||
|
||||
private def createContext() {
|
||||
Attributes attributes = createUserAttributes(username, email, firstname, lastname)
|
||||
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 firstname, String lastname) {
|
||||
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 givennameAttribute = Mock(Attribute)
|
||||
givennameAttribute.getId() >> "givenname"
|
||||
givennameAttribute.get() >> firstname
|
||||
attributes.get("givenname") >> givennameAttribute
|
||||
|
||||
def snAttribute = Mock(Attribute)
|
||||
snAttribute.getId() >> "sn"
|
||||
snAttribute.get() >> lastname
|
||||
attributes.get("sn") >> snAttribute
|
||||
|
||||
return attributes
|
||||
}
|
||||
|
||||
def setupSpec() {
|
||||
ldapConfiguration = Mock(LdapConfiguration)
|
||||
|
||||
ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
|
||||
ldapConfiguration.getReturnAttributes() >> ["uid", "mail", "cn"]
|
||||
ldapConfiguration.getUsernameAttribute() >> "uid"
|
||||
ldapConfiguration.getEmailAttribute() >> "mail"
|
||||
ldapConfiguration.getFirstnameAttribute() >> "givenname"
|
||||
ldapConfiguration.getLastnameAttribute() >> "sn"
|
||||
ldapConfiguration.getBaseDn() >> "dc=cloudstack,dc=org"
|
||||
|
||||
username = "rmurphy"
|
||||
email = "rmurphy@test.com"
|
||||
firstname = "Ryan"
|
||||
lastname = "Murphy"
|
||||
principal = "cn=" + username + "," + ldapConfiguration.getBaseDn()
|
||||
}
|
||||
|
||||
def "Test successfully creating an Ldap User from Search result"() {
|
||||
given: "We have attributes, a search and a user manager"
|
||||
def attributes = createUserAttributes(username, email, firstname, lastname)
|
||||
def search = createSearchResult(attributes)
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
def result = userManager.createUser(search)
|
||||
|
||||
expect: "The crated user the data supplied from LDAP"
|
||||
|
||||
result.username == username
|
||||
result.email == email
|
||||
result.firstname == firstname
|
||||
result.lastname == lastname
|
||||
result.principal == principal
|
||||
}
|
||||
|
||||
def "Test successfully returning a list from get users"() {
|
||||
given: "We have a LdapUserManager"
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when: "A request for users is made"
|
||||
def result = userManager.getUsers(username, createContext())
|
||||
|
||||
then: "A list of users is returned"
|
||||
result.size() == 1
|
||||
}
|
||||
|
||||
def "Test successfully returning a list from get users when no username is given"() {
|
||||
given: "We have a LdapUserManager"
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when: "Get users is called without a username"
|
||||
def result = userManager.getUsers(createContext())
|
||||
|
||||
then: "All users are returned"
|
||||
result.size() == 1
|
||||
}
|
||||
|
||||
def "Test successfully returning a NamingEnumeration from searchUsers"() {
|
||||
given: "We have a LdapUserManager"
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when: "We search for users"
|
||||
def result = userManager.searchUsers(createContext())
|
||||
|
||||
then: "A list of users are returned."
|
||||
result.next().getName() + "," + ldapConfiguration.getBaseDn() == principal
|
||||
}
|
||||
|
||||
def "Test successfully returning an Ldap user from a get user request"() {
|
||||
given: "We have a LdapUserMaanger"
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when: "A request for a user is made"
|
||||
def result = userManager.getUser(username, createContext())
|
||||
|
||||
then: "The user is returned"
|
||||
result.username == username
|
||||
result.email == email
|
||||
result.firstname == firstname
|
||||
result.lastname == lastname
|
||||
result.principal == principal
|
||||
}
|
||||
|
||||
def "Test successfully throwing an exception when no users are found with getUser"() {
|
||||
given: "We have a seachResult of users and a User Manager"
|
||||
|
||||
def searchUsersResults = new BasicNamingEnumerationImpl()
|
||||
|
||||
def context = Mock(LdapContext)
|
||||
context.search(_, _, _) >> searchUsersResults;
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when: "a get user request is made and no user is found"
|
||||
def result = userManager.getUser(username, context)
|
||||
|
||||
then: "An exception is thrown."
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// 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 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: "We have an LdapResponse"
|
||||
LdapUserResponse response = new LdapUserResponse();
|
||||
when: "An email address is set"
|
||||
response.setEmail("rmurphy@test.com");
|
||||
then: "Get email should return that set email"
|
||||
response.getEmail() == "rmurphy@test.com";
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse firstname"() {
|
||||
given: "We have an LdapUserResponse"
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when: "A firstname is set"
|
||||
response.setFirstname("Ryan")
|
||||
then: "gGet Firstname returns the set value"
|
||||
response.getFirstname() == "Ryan"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse lastname"() {
|
||||
given: "We have an LdapUserResponse"
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when: "A lastname is set"
|
||||
response.setLastname("Murphy")
|
||||
then: "Get lastname is returned"
|
||||
response.getLastname() == "Murphy"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse principal"() {
|
||||
given: "We have an LdapResponse"
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when: "A principal is set"
|
||||
response.setPrincipal("dc=cloudstack,dc=org")
|
||||
then: "Get principled returns the set value"
|
||||
response.getPrincipal() == "dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse username"() {
|
||||
given: "We have an LdapUserResponse"
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when: "A username is set"
|
||||
response.setUsername("rmurphy")
|
||||
then: "Get username returns the set value."
|
||||
response.getUsername() == "rmurphy"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// 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 groovy.org.apache.cloudstack.ldap
|
||||
|
||||
import org.apache.cloudstack.ldap.LdapUser
|
||||
|
||||
class LdapUserSpec extends spock.lang.Specification {
|
||||
|
||||
def "Testing LdapUsers hashCode generation"() {
|
||||
given:
|
||||
def userA = new LdapUser(usernameA, "", "", "", "")
|
||||
expect:
|
||||
userA.hashCode() == usernameA.hashCode()
|
||||
where:
|
||||
usernameA = "A"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
def "Testing that LdapUsers equality"() {
|
||||
given:
|
||||
def userA = new LdapUser(usernameA, "", "", "", "")
|
||||
def userB = new LdapUser(usernameB, "", "", "", "")
|
||||
expect:
|
||||
userA.equals(userA) == true
|
||||
userA.equals(new Object()) == false
|
||||
userA.equals(userB) == false
|
||||
where:
|
||||
usernameA | usernameB
|
||||
"A" | "B"
|
||||
}
|
||||
|
||||
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 email"
|
||||
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 firstname is correctly set with the ldap object"() {
|
||||
given: "You have created a LDAP user object with a firstname"
|
||||
def user = new LdapUser("", "", firstname, "", "")
|
||||
expect: "The firstname is equal to the given data source"
|
||||
user.getFirstname() == firstname
|
||||
where: "The firstname is set to "
|
||||
firstname << ["", null, "Ryan"]
|
||||
}
|
||||
|
||||
def "Testing the lastname is correctly set with the ldap object"() {
|
||||
given: "You have created a LDAP user object with a lastname"
|
||||
def user = new LdapUser("", "", "", lastname, "")
|
||||
expect: "The lastname is equal to the given data source"
|
||||
user.getLastname() == lastname
|
||||
where: "The lastname is set to "
|
||||
lastname << ["", null, "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"]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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 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 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
|
||||
}
|
||||
|
||||
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 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"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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 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*"]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// 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 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"]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,295 @@
|
|||
version: 1
|
||||
|
||||
dn: dc=cloudstack,dc=org
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
dc: cloudstack
|
||||
o: cloudstack
|
||||
|
||||
dn: cn=Ryan Murphy,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Ryan Murphy
|
||||
sn: Murphy
|
||||
givenName: Ryan
|
||||
mail: rmurphy@cloudstack.org
|
||||
uid: rmurphy
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Barbara Brewer,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Barbara Brewer
|
||||
sn: Brewer
|
||||
mail: bbrewer@cloudstack.org
|
||||
uid: bbrewer
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Zak Wilkinson,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Zak Wilkinson
|
||||
givenname: Zak
|
||||
sn: Wilkinson
|
||||
uid: zwilkinson
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Archie Shingleton,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Archie Shingleton
|
||||
sn: Shingleton
|
||||
givenName: Archie
|
||||
mail: ashingleton@cloudstack.org
|
||||
uid: ashingleton
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Cletus Pears,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Cletus Pears
|
||||
sn: Pears
|
||||
givenName: Cletus
|
||||
mail: cpears@cloudstack.org
|
||||
uid: cpears
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Teisha Milewski,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Teisha Milewski
|
||||
sn: Milewski
|
||||
givenName: Teisha
|
||||
mail: tmilewski@cloudstack.org
|
||||
uid: tmilewski
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Eloy Para,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Eloy Para
|
||||
sn: Para
|
||||
givenName: Eloy
|
||||
mail: epara@cloudstack.org
|
||||
uid: epara
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Elaine Lamb,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Elaine Lamb
|
||||
sn: Lamb
|
||||
givenName: Elaine
|
||||
mail: elamb@cloudstack.org
|
||||
uid: elamb
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Soon Griffen,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Soon Griffen
|
||||
sn: Griffen
|
||||
givenName: Soon
|
||||
mail: sgriffen@cloudstack.org
|
||||
uid: sgriffen
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Tran Neisler,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Tran Neisler
|
||||
sn: Neisler
|
||||
givenName: Tran
|
||||
mail: tneisler@cloudstack.org
|
||||
uid: tneisler
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Mirella Zeck,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Mirella Zeck
|
||||
sn: Zeck
|
||||
givenName: Mirella
|
||||
mail: mzeck@cloudstack.org
|
||||
uid: mzeck
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Greg Hoskin,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Greg Hoskin
|
||||
sn: Hoskin
|
||||
givenName: Greg
|
||||
mail: ghoskin@cloudstack.org
|
||||
uid: ghoskin
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Johanne Runyon,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Johanne Runyon
|
||||
sn: Runyon
|
||||
givenName: Johanne
|
||||
mail: jrunyon@cloudstack.org
|
||||
uid: jrunyon
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Mabelle Waiters,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Mabelle Waiters
|
||||
sn: Waiters
|
||||
givenName: Mabelle
|
||||
mail: mwaiters@cloudstack.org
|
||||
uid: mwaiters
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Phillip Fruge,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Phillip Fruge
|
||||
sn: Fruge
|
||||
givenName: Phillip
|
||||
mail: pfruge@cloudstack.org
|
||||
uid: pfruge
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Jayna Ridenhour,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Jayna Ridenhour
|
||||
sn: Ridenhour
|
||||
givenName: Jayna
|
||||
mail: jridenhour@cloudstack.org
|
||||
uid: jridenhour
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Marlyn Mandujano,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Marlyn Mandujano
|
||||
sn: Mandujano
|
||||
givenName: Marlyn
|
||||
mail: mmandujano@cloudstack.org
|
||||
uid: mmandujano
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Shaunna Scherer,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Shaunna Scherer
|
||||
sn: Scherer
|
||||
givenName: Shaunna
|
||||
mail: sscherer@cloudstack.org
|
||||
uid: sscherer
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Adriana Bozek,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Adriana Bozek
|
||||
sn: Bozek
|
||||
givenName: Adriana
|
||||
mail: abozek@cloudstack.org
|
||||
uid: abozek
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Silvana Chipman,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Silvana Chipman
|
||||
sn: Chipman
|
||||
givenName: Silvana
|
||||
mail: schipman@cloudstack.org
|
||||
uid: schipman
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Marion Wasden,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Marion Wasden
|
||||
sn: Wasden
|
||||
givenName: Marion
|
||||
mail: mwasden@cloudstack.org
|
||||
uid: mwasden
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Anisa Casson,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Anisa Casson
|
||||
sn: Casson
|
||||
givenName: Anisa
|
||||
mail: acasson@cloudstack.org
|
||||
uid: acasson
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
dn: cn=Noel King,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Noel King
|
||||
sn: King
|
||||
givenName: Noel
|
||||
mail: nking@cloudstack.org
|
||||
uid: nking
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
|
||||
dn: cn=Cammy Petri,dc=cloudstack,dc=org
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: organizationalPerson
|
||||
objectClass: person
|
||||
objectClass: top
|
||||
cn: Cammy Petri
|
||||
sn: Petri
|
||||
givenName: Cammy
|
||||
mail: cpetri@cloudstack.org
|
||||
uid: cpetri
|
||||
userpassword:: cGFzc3dvcmQ=
|
||||
|
||||
|
|
@ -81,7 +81,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;
|
||||
|
|
@ -2804,20 +2803,6 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
return hcResponse;
|
||||
}
|
||||
|
||||
@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();
|
||||
|
|
|
|||
|
|
@ -415,6 +415,19 @@ 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),
|
||||
LdapFirstnameAttribute("Advanced", ManagementServer.class, String.class, "ldap.firstname.attribute", "givenname", "Sets the firstname attribute used within LDAP", null),
|
||||
LdapLastnameAttribute("Advanced", ManagementServer.class, String.class, "ldap.lastname.attribute", "sn", "Sets the lastname 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),
|
||||
LdapSearchGroupPrinciple("Advanced", ManagementServer.class, String.class, "ldap.search.group.principle", null, "Sets the principle of the group that users must be a member of", null),
|
||||
LdapTrustStore("Advanced", ManagementServer.class, String.class, "ldap.truststore", null, "Sets the path to the truststore to use for SSL", null),
|
||||
LdapTrustStorePassword("Advanced", ManagementServer.class, String.class, "ldap.truststore.password", null, "Sets the password for the truststore", null),
|
||||
|
||||
// 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),
|
||||
|
|
@ -423,15 +436,15 @@ public enum Config {
|
|||
|
||||
BlacklistedRoutes("Advanced", VpcManager.class, String.class, "blacklisted.routes", null, "Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway",
|
||||
"routes", ConfigurationParameterScope.zone.toString()),
|
||||
|
||||
|
||||
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, CopyCommand 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." +
|
||||
" If set to false, these commands become asynchronous. Default value is false.", null),
|
||||
|
||||
|
||||
UCSSyncBladeInterval("Advanced", ManagementServer.class, Integer.class, "ucs.sync.blade.interval", "3600", "the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack", null);
|
||||
|
||||
|
||||
private final String _category;
|
||||
private final Class<?> _componentClass;
|
||||
private final Class<?> _type;
|
||||
|
|
|
|||
|
|
@ -41,10 +41,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;
|
||||
|
|
@ -1547,175 +1544,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)
|
||||
|
|
|
|||
|
|
@ -90,8 +90,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;
|
||||
|
|
@ -2521,8 +2519,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);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ import javax.naming.NamingException;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
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;
|
||||
|
|
@ -318,33 +316,6 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
|||
return null;
|
||||
}
|
||||
|
||||
/* (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)
|
||||
*/
|
||||
|
|
@ -576,4 +547,4 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2307,3 +2307,23 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Storage', 'DEFAULT', 'manage
|
|||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Storage', 'DEFAULT', 'management-server', 'storage.cache.replacement.interval', '86400', 'time interval between cache replacement threads (in seconds).');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ("Advanced", 'DEFAULT', 'management-server', 'vmware.nested.virtualization', 'false', 'When set to true this will enable nested virtualization when this is supported by the hypervisor');
|
||||
|
||||
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.firstname.attribute', 'givenname', 'Sets the firstname attribute used within LDAP');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.lastname.attribute', 'sn', 'Sets the lastname 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');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.search.group.principle', NULL, 'Sets the principle of the group that users must be a member of');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.truststore', NULL, 'Sets the path to the truststore to use for LDAP SSL');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.truststore.password', NULL, 'Sets the password for the truststore');
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,78 +44,30 @@ class Services:
|
|||
def __init__(self):
|
||||
self.services = {
|
||||
"account": {
|
||||
"email": "test@test.com",
|
||||
"firstname": "test",
|
||||
"lastname": "t",
|
||||
"username": "test",
|
||||
"password": "password",
|
||||
"email": "rmurphy@cloudstack.org",
|
||||
"firstname": "Ryan",
|
||||
"lastname": "Murphy",
|
||||
"username": "rmurphy",
|
||||
"password": "internalcloudstackpassword",
|
||||
},
|
||||
"ldapCon_1":#valid values&Query filter as email.
|
||||
"ldapConfiguration_1":
|
||||
{
|
||||
"ldapHostname": "10.147.38.163",
|
||||
"port": "389",
|
||||
"binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com",
|
||||
"bindpass": "aaaa_1111",
|
||||
"queryfilter": "(&(mail=%e))",
|
||||
"searchbase": "CN=Users,DC=hyd-qa,DC=com",
|
||||
"ldapusername": "test",
|
||||
"ldappasswd": "aaaa_1111"
|
||||
},
|
||||
"ldapCon_2": ##valid values&Query filter as displayName.
|
||||
{
|
||||
"ldapHostname": "10.147.38.163",
|
||||
"port": "389",
|
||||
"binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com",
|
||||
"bindpass": "aaaa_1111",
|
||||
"queryfilter": "(&(displayName=%u))",
|
||||
"searchbase": "CN=Users,DC=hyd-qa,DC=com",
|
||||
"ldapusername": "test",
|
||||
"ldappasswd": "aaaa_1111"
|
||||
},
|
||||
"ldapCon_3": #Configuration with missing parameters value(queryfilter)
|
||||
{
|
||||
"ldapHostname": "10.147.38.163",
|
||||
"port": "389",
|
||||
"binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com",
|
||||
"bindpass": "aaaa_1111",
|
||||
"queryfilter": "",
|
||||
"searchbase": "CN=Users,DC=hyd-qa,DC=com",
|
||||
"ldapusername": "test",
|
||||
"ldappasswd": "aaaa_1111"
|
||||
},
|
||||
|
||||
"ldapCon_4": #invalid configuration-wrong query filter
|
||||
{
|
||||
"ldapHostname": "10.147.38.163",
|
||||
"port": "389",
|
||||
"binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com",
|
||||
"bindpass": "aaaa_1111",
|
||||
"queryfilter": "(&(displayName=%p))",
|
||||
"searchbase":"CN=Users,DC=hyd-qa,DC=com",
|
||||
"ldapusername": "test",
|
||||
"ldappasswd": "aaaa_1111"
|
||||
},
|
||||
"ldapCon_5": #Configuration with invalid ldap credentials
|
||||
{
|
||||
"ldapHostname": "10.147.38.163",
|
||||
"port": "389",
|
||||
"binddn": "CN=test,CN=Users,DC=hyd-qa,DC=com",
|
||||
"bindpass": "aaaa_1111",
|
||||
"queryfilter": "(&(displayName=%u))",
|
||||
"searchbase": "CN=Users,DC=hyd-qa,DC=com",
|
||||
"ldapusername": "test",
|
||||
"ldappasswd": "aaaa"
|
||||
"basedn": "dc=cloudstack,dc=org",
|
||||
"emailAttribute": "mail",
|
||||
"realnameAttribute": "cn",
|
||||
"userObject": "inetOrgPerson",
|
||||
"usernameAttribute": "uid",
|
||||
"hostname": "localhost",
|
||||
"port": "10389",
|
||||
"ldapUsername": "rmurphy",
|
||||
"ldapPassword": "password"
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class TestLdap(cloudstackTestCase):
|
||||
"""
|
||||
This test perform registering ldap configuration details in CS and create a user[ldap user] in CS
|
||||
and validate user credentials against LDAP server:AD
|
||||
This tests attempts to register a LDAP server and authenticate as an LDAP user.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
|
|
@ -134,8 +86,6 @@ class TestLdap(cloudstackTestCase):
|
|||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
try:
|
||||
#Cleanup resources used
|
||||
#print "tear down class"
|
||||
cleanup_resources(cls.api_client, cls._cleanup)
|
||||
|
||||
except Exception as tde:
|
||||
|
|
@ -144,10 +94,10 @@ class TestLdap(cloudstackTestCase):
|
|||
|
||||
def setUp(self):
|
||||
|
||||
self.apiclient = self.testClient.getApiClient()
|
||||
self.apiClient = self.testClient.getApiClient()
|
||||
|
||||
self.acct = createAccount.createAccountCmd()
|
||||
self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1
|
||||
self.acct.accounttype = 0
|
||||
self.acct.firstname = self.services["account"]["firstname"]
|
||||
self.acct.lastname = self.services["account"]["lastname"]
|
||||
self.acct.password = self.services["account"]["password"]
|
||||
|
|
@ -155,208 +105,153 @@ class TestLdap(cloudstackTestCase):
|
|||
self.acct.email = self.services["account"]["email"]
|
||||
self.acct.account = self.services["account"]["username"]
|
||||
self.acct.domainid = 1
|
||||
# mapping ldap user by creating same user in cloudstack
|
||||
|
||||
self.acctRes = self.apiclient.createAccount(self.acct)
|
||||
|
||||
self.acctRes = self.apiClient.createAccount(self.acct)
|
||||
|
||||
return
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
try:
|
||||
#Clean up, terminate the created accounts, domains etc
|
||||
|
||||
deleteAcct = deleteAccount.deleteAccountCmd()
|
||||
deleteAcct.id = self.acctRes.id
|
||||
|
||||
acct_name=self.acctRes.name
|
||||
|
||||
self.apiclient.deleteAccount(deleteAcct)
|
||||
self.apiClient.deleteAccount(deleteAcct)
|
||||
|
||||
self.debug("Deleted the the following account name %s:" %acct_name)
|
||||
#delete only if ldapconfig registered in CS
|
||||
if(self.ldapconfRes):
|
||||
deleteldapconfg=ldapRemove.ldapRemoveCmd()
|
||||
res=self.apiclient.ldapRemove(deleteldapconfg)
|
||||
|
||||
if(self.ldapconfRes==1):
|
||||
self._deleteLdapConfiguration(self.services["ldapConfiguration_1"])
|
||||
|
||||
except Exception as e:
|
||||
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||
return
|
||||
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_01_configLDAP(self):
|
||||
'''
|
||||
This test is to verify ldapConfig API with valid values.(i.e query fileter as email)
|
||||
'''
|
||||
# 1. This test covers ldapConfig & login API with valid ldap credentials..
|
||||
# require ldap configuration:ldapCon_1
|
||||
def test_01_addLdapConfiguration(self):
|
||||
"""
|
||||
This test configures LDAP and attempts to authenticate as a user.
|
||||
"""
|
||||
|
||||
|
||||
self.debug("start test")
|
||||
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_1"])
|
||||
self.ldapconfRes=self._addLdapConfiguration(self.services["ldapConfiguration_1"])
|
||||
|
||||
if(self.ldapconfRes==1):
|
||||
|
||||
self.debug("Ldap Configuration was succcessful")
|
||||
|
||||
self.debug("configure ldap successful")
|
||||
|
||||
#validating the user credentials with ldap Server
|
||||
loginRes = self.chkLogin(self.services["ldapCon_1"]["ldapusername"], self.services["ldapCon_1"]["ldappasswd"])
|
||||
self.assertEquals(loginRes,1,"ldap Authentication failed")
|
||||
loginRes = self._checkLogin(self.services["ldapConfiguration_1"]["ldapUsername"],self.services["ldapConfiguration_1"]["ldapPassword"])
|
||||
self.debug(loginRes)
|
||||
self.assertEquals(loginRes,1,"Ldap Authentication")
|
||||
|
||||
else:
|
||||
|
||||
self.debug("LDAP Configuration failed with exception")
|
||||
|
||||
self.assertEquals(self.ldapconfRes,1,"ldapConfig API failed")
|
||||
self.assertEquals(self.ldapconfRes,1,"addLdapConfiguration failed")
|
||||
|
||||
|
||||
self.debug("end test")
|
||||
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_02_configLDAP(self):
|
||||
'''
|
||||
This test is to verify ldapConfig API with valid values.(i.e query fileter as displayName)
|
||||
'''
|
||||
|
||||
# 1. This test covers ldapConfig & login API with valid ldap credentials.
|
||||
# 2. require ldap configuration:ldapCon_2
|
||||
|
||||
self.debug("start test")
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_2"])
|
||||
self.assertEquals(self.ldapconfRes,1,"ldapConfig API failed")
|
||||
if(self.ldapconfRes==1):
|
||||
self.debug("configure ldap successful")
|
||||
#validating the user credentials with ldap Server
|
||||
loginRes = self.chkLogin(self.services["ldapCon_2"]["ldapusername"], self.services["ldapCon_2"]["ldappasswd"])
|
||||
self.assertEquals(loginRes,1,"ldap Authentication failed")
|
||||
else:
|
||||
self.debug("LDAP Configuration failed with exception")
|
||||
self.debug("end test")
|
||||
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_03_configLDAP(self):
|
||||
|
||||
'''
|
||||
This test is to verify ldapConfig API with missing config parameters value(i.queryfilter)
|
||||
'''
|
||||
|
||||
# 1. Issue ldapConfig API with no ldap config parameter value and check behavior
|
||||
# 2. require ldap configuration:ldapCon_3
|
||||
|
||||
self.debug("start test...")
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_3"])
|
||||
self.assertEquals(self.ldapconfRes,0,"LDAP configuration successful with invalid value.API failed")
|
||||
self.debug("end test")
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_04_configLDAP(self):
|
||||
'''
|
||||
This test is to verify ldapConfig API with invalid configuration values(by passing wrong query filter)
|
||||
'''
|
||||
# 1. calling ldapConfig API with invalid query filter value and check behavior
|
||||
# 2. require ldap configuration:ldapCon_4
|
||||
|
||||
self.debug("start test...")
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_4"])
|
||||
self.assertEquals(self.ldapconfRes,0,"API failed")
|
||||
|
||||
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_05_configLDAP(self):
|
||||
|
||||
'''
|
||||
This test is to verify login API functionality by passing wrong ldap credentials
|
||||
'''
|
||||
# 1.This script first configure the ldap and validates the user credentials using login API
|
||||
# 2. require ldap configuration:ldapCon_5
|
||||
|
||||
|
||||
self.debug("start test")
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_5"])
|
||||
self.assertEquals(self.ldapconfRes,1,"API failed")
|
||||
#validating the cloudstack user credentials with ldap Server
|
||||
loginRes = self.chkLogin(self.services["ldapCon_5"]["ldapusername"], self.services["ldapCon_5"]["ldappasswd"])
|
||||
self.assertNotEqual(loginRes,1,"login API failed")
|
||||
self.debug("end test")
|
||||
|
||||
@attr(tags=["advanced", "basic"])
|
||||
def test_06_removeLDAP(self):
|
||||
'''
|
||||
This test is to verify ldapRemove API functionality
|
||||
'''
|
||||
# 1. This script fist configures ldap and removes the configured ldap values
|
||||
# 2. require ldap configuration:ldapCon_1
|
||||
|
||||
|
||||
self.debug("start test")
|
||||
self.ldapconfRes=self._testldapConfig(self.services["ldapCon_1"])
|
||||
if(self.ldapconfRes==1):
|
||||
self.debug("ldap configured successfully")
|
||||
deleteldapconfg=ldapRemove.ldapRemoveCmd()
|
||||
res=self.apiclient.ldapRemove(deleteldapconfg)
|
||||
self.debug("ldap removed successfully")
|
||||
self.ldapconfRes=0
|
||||
else:
|
||||
|
||||
self.debug("LDAP Configuration failed with exception")
|
||||
self.assertEquals(self.ldapconfRes,0,"ldapconfig API failed")
|
||||
self.debug("end test")
|
||||
|
||||
def _testldapConfig(self,ldapSrvD):
|
||||
def _addLdapConfiguration(self,ldapConfiguration):
|
||||
|
||||
"""
|
||||
|
||||
:param ldapSrvD
|
||||
|
||||
:param ldapConfiguration
|
||||
|
||||
"""
|
||||
#This Method takes dictionary as parameter,
|
||||
# reads the ldap configuration values from the passed dictionary and
|
||||
# register the ldapconfig detail in cloudstack
|
||||
# & return true or false based on ldapconfig API response
|
||||
|
||||
self.debug("start ldapconfig test")
|
||||
#creating the ldapconfig cmd object
|
||||
lpconfig = ldapConfig.ldapConfigCmd()
|
||||
#Config the ldap server by assigning the ldapconfig dict variable values to ldapConfig object
|
||||
lpconfig.hostname = ldapSrvD["ldapHostname"]
|
||||
lpconfig.port = ldapSrvD["port"]
|
||||
lpconfig.binddn = ldapSrvD["binddn"]
|
||||
lpconfig.bindpass = ldapSrvD["bindpass"]
|
||||
lpconfig.searchbase = ldapSrvD["searchbase"]
|
||||
lpconfig.queryfilter = ldapSrvD["queryfilter"]
|
||||
# Setup Global settings
|
||||
|
||||
#end of assigning the variables
|
||||
updateConfigurationCmd = updateConfiguration.updateConfigurationCmd()
|
||||
updateConfigurationCmd.name = "ldap.basedn"
|
||||
updateConfigurationCmd.value = ldapConfiguration['basedn']
|
||||
updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value))
|
||||
|
||||
#calling the ldapconfig Api
|
||||
self.debug("calling ldapconfig API")
|
||||
updateConfigurationCmd = updateConfiguration.updateConfigurationCmd()
|
||||
updateConfigurationCmd.name = "ldap.email.attribute"
|
||||
updateConfigurationCmd.value = ldapConfiguration['emailAttribute']
|
||||
updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value))
|
||||
|
||||
|
||||
updateConfigurationCmd = updateConfiguration.updateConfigurationCmd()
|
||||
updateConfigurationCmd.name = "ldap.realname.attribute"
|
||||
updateConfigurationCmd.value = ldapConfiguration['realnameAttribute']
|
||||
updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value))
|
||||
|
||||
|
||||
updateConfigurationCmd = updateConfiguration.updateConfigurationCmd()
|
||||
updateConfigurationCmd.name = "ldap.user.object"
|
||||
updateConfigurationCmd.value = ldapConfiguration['userObject']
|
||||
updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value))
|
||||
|
||||
|
||||
updateConfigurationCmd = updateConfiguration.updateConfigurationCmd()
|
||||
updateConfigurationCmd.name = "ldap.username.attribute"
|
||||
updateConfigurationCmd.value = ldapConfiguration['usernameAttribute']
|
||||
updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd)
|
||||
self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value))
|
||||
|
||||
self.debug("start addLdapConfiguration test")
|
||||
|
||||
ldapServer = addLdapConfiguration.addLdapConfigurationCmd()
|
||||
ldapServer.hostname = ldapConfiguration['hostname']
|
||||
ldapServer.port = ldapConfiguration['port']
|
||||
|
||||
self.debug("calling addLdapConfiguration API command")
|
||||
try:
|
||||
lpconfig1 = self.apiclient.ldapConfig(lpconfig)
|
||||
self.debug("ldapconfig API succesfful")
|
||||
self.apiClient.addLdapConfiguration(ldapServer)
|
||||
self.debug("addLdapConfiguration was successful")
|
||||
return 1
|
||||
except Exception, e:
|
||||
self.debug("ldapconfig API failed %s" %e)
|
||||
self.debug("addLdapConfiguration failed %s" %e)
|
||||
return 0
|
||||
|
||||
def chkLogin(self, username, password):
|
||||
def _deleteLdapConfiguration(self,ldapConfiguration):
|
||||
|
||||
"""
|
||||
|
||||
:param ldapConfiguration
|
||||
|
||||
"""
|
||||
|
||||
ldapServer = deleteLdapConfiguration.deleteLdapConfigurationCmd()
|
||||
ldapServer.hostname = ldapConfiguration["hostname"]
|
||||
|
||||
try:
|
||||
self.apiClient.deleteLdapConfiguration(ldapServer)
|
||||
self.debug("deleteLdapConfiguration was successful")
|
||||
return 1
|
||||
except Exception, e:
|
||||
self.debug("deleteLdapConfiguration failed %s" %e)
|
||||
return 0
|
||||
|
||||
def _checkLogin(self, username, password):
|
||||
"""
|
||||
|
||||
:param username:
|
||||
:param password:
|
||||
|
||||
"""
|
||||
self.debug("login test")
|
||||
self.debug("Attempting to login.")
|
||||
|
||||
try:
|
||||
login1 = login.loginCmd()
|
||||
login1.username = username
|
||||
login1.password = password
|
||||
loginRes = self.apiclient.login(login1)
|
||||
loginParams = login.loginCmd()
|
||||
loginParams.username = username
|
||||
loginParams.password = password
|
||||
loginRes = self.apiClient.login(loginParams)
|
||||
self.debug("login response %s" % loginRes)
|
||||
if loginRes is None:
|
||||
self.debug("login not successful")
|
||||
return 0
|
||||
else:
|
||||
self.debug("login successful")
|
||||
return 1
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ known_categories = {
|
|||
'TrafficType': 'Usage',
|
||||
'Product': 'Product',
|
||||
'LB': 'Load Balancer',
|
||||
'ldap': 'LDAP',
|
||||
'Ldap': 'LDAP',
|
||||
'Swift': 'Swift',
|
||||
'S3' : 'S3',
|
||||
'SecondaryStorage': 'Host',
|
||||
|
|
|
|||
|
|
@ -5830,7 +5830,7 @@ label.error {
|
|||
.multi-wizard .buttons {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 519px;
|
||||
bottom: 10px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
|
|
@ -12267,3 +12267,98 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
|
|||
color: #0000FF !important;
|
||||
}
|
||||
|
||||
.accounts-wizard table {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.accounts-wizard .ui-button {
|
||||
display: inline-block !important;
|
||||
float: none !important;
|
||||
}
|
||||
.accounts-wizard td:last-child {
|
||||
border: none;
|
||||
}
|
||||
.accounts-wizard tbody tr:nth-child(even) {
|
||||
background: #DFE1E3;
|
||||
}
|
||||
.accounts-wizard tbody tr:nth-child(odd) {
|
||||
background: #F2F0F0;
|
||||
}
|
||||
.accounts-wizard .content {
|
||||
display: inline-block;
|
||||
}
|
||||
.accounts-wizard .content:last-child {
|
||||
margin-left: 14px;
|
||||
}
|
||||
.accounts-wizard .input-area {
|
||||
width: 320px;
|
||||
font-size: 13px;
|
||||
color: #485867;
|
||||
text-shadow: 0px 2px 1px #FFFFFF;
|
||||
}
|
||||
.ldap-account-choice {
|
||||
border: none !important;
|
||||
border-radius: 0 0 0 0 !important;
|
||||
}
|
||||
.manual-account-details .name {
|
||||
margin-top: 2px;
|
||||
width: 100px;
|
||||
float: left;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
.manual-account-details {
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
overflow-x: visible !important;
|
||||
}
|
||||
.manual-account-details label.error {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
}
|
||||
.manual-account-details .value {
|
||||
float: left;
|
||||
}
|
||||
.manual-account-details .form-item:after {
|
||||
content:".";
|
||||
display: block;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
.manual-account-details .form-item {
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.manual-account-details select, .manual-account-details input {
|
||||
width: 150px;
|
||||
}
|
||||
.manual-account-details input {
|
||||
background: #F6F6F6;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
border: 1px solid #AFAFAF;
|
||||
-moz-box-shadow: inset 0px 1px #727272;
|
||||
-webkit-box-shadow: inset 0px 1px #727272;
|
||||
-o-box-shadow: inset 0px 1px #727272;
|
||||
box-shadow: inset 0px 1px #727272;
|
||||
-moz-box-shadow: inset 0px 1px 0px #727272;
|
||||
-webkit-box-shadow: inset 0px 1px 0px #727272;
|
||||
-o-box-shadow: inset 0px 1px 0px #727272;
|
||||
}
|
||||
.manual-account-details > *:nth-child(even) {
|
||||
background: #DFE1E3;
|
||||
}
|
||||
.manual-account-details > *:nth-child(odd) {
|
||||
background: #F2F0F0;
|
||||
}
|
||||
.manual-account-details .value {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ dictionary = {
|
|||
'changed.item.properties': '<fmt:message key="changed.item.properties" />',
|
||||
'confirm.enable.s3': '<fmt:message key="confirm.enable.s3" />',
|
||||
'confirm.enable.swift': '<fmt:message key="confirm.enable.swift" />',
|
||||
'error.could.not.change.your.password.because.ldap.is.enabled': '<fmt:message key="error.could.not.change.your.password.because.ldap.is.enabled" />',
|
||||
'error.could.not.enable.zone': '<fmt:message key="error.could.not.enable.zone" />',
|
||||
'error.installWizard.message': '<fmt:message key="error.installWizard.message" />',
|
||||
'error.invalid.username.password': '<fmt:message key="error.invalid.username.password" />',
|
||||
|
|
@ -526,7 +527,7 @@ dictionary = {
|
|||
'label.edit.lb.rule': '<fmt:message key="label.edit.lb.rule" />',
|
||||
'label.edit.network.details': '<fmt:message key="label.edit.network.details" />',
|
||||
'label.edit.project.details': '<fmt:message key="label.edit.project.details" />',
|
||||
'label.edit.tags': '<fmt:message key="label.edit.tags" />',
|
||||
'label.edit.tags': '<fmt:message key="label.edit.tags" />',
|
||||
'label.edit.traffic.type': '<fmt:message key="label.edit.traffic.type" />',
|
||||
'label.edit.vpc': '<fmt:message key="label.edit.vpc" />',
|
||||
'label.egress.rule': '<fmt:message key="label.egress.rule" />',
|
||||
|
|
|
|||
61
ui/index.jsp
61
ui/index.jsp
|
|
@ -238,10 +238,10 @@ under the License.
|
|||
<!-- Step 6: Network -->
|
||||
<div class="step network always-load" wizard-step-id="network">
|
||||
<!-- 5a: Network description -->
|
||||
<div class="wizard-step-conditional nothing-to-select">
|
||||
<div class="wizard-step-conditional nothing-to-select">
|
||||
<p id="from_instance_page_1"><fmt:message key="message.zone.no.network.selection"/></p>
|
||||
<p id="from_instance_page_2"><fmt:message key="message.please.proceed"/></p>
|
||||
<p id="from_vpc_tier"></p>
|
||||
<p id="from_vpc_tier"></p>
|
||||
</div>
|
||||
|
||||
<!-- 5b: Select network -->
|
||||
|
|
@ -446,7 +446,7 @@ under the License.
|
|||
<a href="6"><fmt:message key="label.edit"/></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Security groups -->
|
||||
<div class="select odd">
|
||||
<div class="name">
|
||||
|
|
@ -483,6 +483,37 @@ under the License.
|
|||
<div class="button next"><span><fmt:message key="label.next"/></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Accounts wizard -->
|
||||
<div class="multi-wizard accounts-wizard">
|
||||
<form>
|
||||
<div class="steps">
|
||||
<div class="content ldap-account-choice">
|
||||
<div class="select-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">Select</th>
|
||||
<th style="width:110px">Realname</th>
|
||||
<th style="width:70px">Username</th>
|
||||
<th>Email</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content input-area">
|
||||
<div class="select-container manual-account-details">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="buttons">
|
||||
<button class="cancel ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span><fmt:message key="label.cancel"/></span></button>
|
||||
<button class="next ok ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span><fmt:message key="label.add"/></span></button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Zone wizard -->
|
||||
<div class="multi-wizard zone-wizard">
|
||||
<div class="progress">
|
||||
|
|
@ -519,7 +550,7 @@ under the License.
|
|||
</div>
|
||||
<div class="select-area advanced-zone disabled">
|
||||
<div class="desc">
|
||||
<fmt:message key="message.desc.advanced.zone"/>
|
||||
<fmt:message key="message.desc.advanced.zone"/>
|
||||
</div>
|
||||
<input type="radio" name="network-model" value="Advanced" />
|
||||
<label><fmt:message key="label.advanced"/></label>
|
||||
|
|
@ -547,7 +578,7 @@ under the License.
|
|||
<div class="setup-zone" zone-wizard-form="zone"
|
||||
zone-wizard-step-id="addZone">
|
||||
<div class="info-desc">
|
||||
<fmt:message key="message.desc.zone"/>
|
||||
<fmt:message key="message.desc.zone"/>
|
||||
</div>
|
||||
<div class="content input-area">
|
||||
<div class="select-container"></div>
|
||||
|
|
@ -766,7 +797,7 @@ under the License.
|
|||
<li class="secondary-storage"><fmt:message key="label.secondary.storage"/></li>
|
||||
</ul>
|
||||
<div class="info-desc">
|
||||
<fmt:message key="message.desc.host"/>
|
||||
<fmt:message key="message.desc.host"/>
|
||||
</div>
|
||||
<div class="content input-area">
|
||||
<div class="select-container"></div>
|
||||
|
|
@ -990,7 +1021,7 @@ under the License.
|
|||
<span><fmt:message key="label.refresh"/></span>
|
||||
</div>
|
||||
<div id="update_ssl_button" class="button action main-action reduced-hide lock" title="Updates your Console Proxy SSL Certificate">
|
||||
<span class="icon"> </span>
|
||||
<span class="icon"> </span>
|
||||
<span><fmt:message key="label.update.ssl.cert"/></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1064,7 +1095,7 @@ under the License.
|
|||
<span class="button view-all hosts"
|
||||
view-all-title="<fmt:message key="label.virtual.routers"/>"
|
||||
view-all-target="virtualRouters"><fmt:message key="label.view.all"/></span>
|
||||
</li>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1239,7 +1270,7 @@ under the License.
|
|||
<div class="title">
|
||||
<span></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="button fetch-latest">
|
||||
<span><fmt:message key="label.fetch.latest"/></span>
|
||||
</div>
|
||||
|
|
@ -1632,7 +1663,7 @@ under the License.
|
|||
<script src="lib/jquery.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery.easing.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery.validate.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery-ui/js/jquery-ui.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery-ui/js/jquery-ui.js" type="text/javascript"></script>
|
||||
<script src="lib/date.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery.cookies.js" type="text/javascript"></script>
|
||||
<script src="lib/jquery.md5.js" type="text/javascript" ></script>
|
||||
|
|
@ -1656,7 +1687,7 @@ under the License.
|
|||
<script type="text/javascript" src="scripts/ui/utils.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/events.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/dialog.js?t=<%=now%>"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="scripts/ui/widgets/multiEdit.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/overlay.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/dataTable.js?t=<%=now%>"></script>
|
||||
|
|
@ -1664,7 +1695,7 @@ under the License.
|
|||
<script type="text/javascript" src="scripts/ui/widgets/listView.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/detailView.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/treeView.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/notifications.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/notifications.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/tagger.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui/widgets/toolTip.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/cloud.core.callbacks.js?t=<%=now%>"></script>
|
||||
|
|
@ -1685,8 +1716,8 @@ under the License.
|
|||
<script type="text/javascript" src="scripts/dashboard.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui-custom/instanceWizard.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/instanceWizard.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/affinity.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui-custom/affinity.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/affinity.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui-custom/affinity.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/instances.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/events.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/regions.js?t=<%=now%>"></script>
|
||||
|
|
@ -1701,6 +1732,8 @@ under the License.
|
|||
<script type="text/javascript" src="scripts/ui-custom/uploadVolume.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/storage.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/templates.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/accountsWizard.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/ui-custom/accountsWizard.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/accounts.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/configuration.js?t=<%=now%>"></script>
|
||||
<script type="text/javascript" src="scripts/globalSettings.js?t=<%=now%>"></script>
|
||||
|
|
|
|||
|
|
@ -76,222 +76,20 @@
|
|||
return 'label.add.account';
|
||||
}
|
||||
},
|
||||
|
||||
createForm: {
|
||||
title: 'label.add.account',
|
||||
desc: 'label.add.account',
|
||||
fields: {
|
||||
username: {
|
||||
label: 'label.username',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountUsername'
|
||||
},
|
||||
password: {
|
||||
label: 'label.password',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
isPassword: true,
|
||||
id: 'password',
|
||||
docID: 'helpAccountPassword'
|
||||
},
|
||||
'password-confirm': {
|
||||
label: 'label.confirm.password',
|
||||
validation: {
|
||||
required: true,
|
||||
equalTo: '#password'
|
||||
},
|
||||
isPassword: true,
|
||||
docID: 'helpAccountConfirmPassword'
|
||||
},
|
||||
email: {
|
||||
label: 'label.email',
|
||||
validation: {
|
||||
required: true,
|
||||
email: true
|
||||
},
|
||||
docID: 'helpAccountEmail'
|
||||
},
|
||||
firstname: {
|
||||
label: 'label.first.name',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountFirstName'
|
||||
},
|
||||
lastname: {
|
||||
label: 'label.last.name',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountLastName'
|
||||
},
|
||||
domainid: {
|
||||
label: 'label.domain',
|
||||
docID: 'helpAccountDomain',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
var data = {};
|
||||
|
||||
if (args.context.users) { // In accounts section
|
||||
data.listAll = true;
|
||||
} else if (args.context.domains) { // In domain section (use specific domain)
|
||||
data.id = args.context.domains[0].id;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL("listDomains"),
|
||||
data: data,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var items = [];
|
||||
domainObjs = json.listdomainsresponse.domain;
|
||||
$(domainObjs).each(function() {
|
||||
items.push({
|
||||
id: this.id,
|
||||
description: this.path
|
||||
});
|
||||
|
||||
if (this.level == 0)
|
||||
rootDomainId = this.id;
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
account: {
|
||||
label: 'label.account',
|
||||
docID: 'helpAccountAccount'
|
||||
},
|
||||
accounttype: {
|
||||
label: 'label.type',
|
||||
docID: 'helpAccountType',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
var items = [];
|
||||
items.push({
|
||||
id: 0,
|
||||
description: "User"
|
||||
}); //regular-user
|
||||
items.push({
|
||||
id: 1,
|
||||
description: "Admin"
|
||||
}); //root-admin
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
},
|
||||
timezone: {
|
||||
label: 'label.timezone',
|
||||
docID: 'helpAccountTimezone',
|
||||
select: function(args) {
|
||||
var items = [];
|
||||
items.push({
|
||||
id: "",
|
||||
description: ""
|
||||
});
|
||||
for (var p in timezoneMap)
|
||||
items.push({
|
||||
id: p,
|
||||
description: timezoneMap[p]
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
},
|
||||
networkdomain: {
|
||||
label: 'label.network.domain',
|
||||
docID: 'helpAccountNetworkDomain',
|
||||
validation: {
|
||||
required: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
action: function(args) {
|
||||
var data = {
|
||||
username: args.data.username,
|
||||
};
|
||||
|
||||
var password = args.data.password;
|
||||
if (md5Hashed) {
|
||||
password = $.md5(password);
|
||||
}
|
||||
$.extend(data, {
|
||||
password: password
|
||||
});
|
||||
|
||||
$.extend(data, {
|
||||
email: args.data.email,
|
||||
firstname: args.data.firstname,
|
||||
lastname: args.data.lastname,
|
||||
domainid: args.data.domainid
|
||||
});
|
||||
|
||||
var account = args.data.account;
|
||||
if (account == null || account.length == 0) {
|
||||
account = args.data.username;
|
||||
}
|
||||
$.extend(data, {
|
||||
account: account
|
||||
});
|
||||
|
||||
var accountType = args.data.accounttype;
|
||||
if (args.data.accounttype == "1" && args.data.domainid != rootDomainId) { //if account type is admin, but domain is not Root domain
|
||||
accountType = "2"; // Change accounttype from root-domain("1") to domain-admin("2")
|
||||
}
|
||||
$.extend(data, {
|
||||
accounttype: accountType
|
||||
});
|
||||
|
||||
if (args.data.timezone != null && args.data.timezone.length > 0) {
|
||||
$.extend(data, {
|
||||
timezone: args.data.timezone
|
||||
});
|
||||
}
|
||||
|
||||
if (args.data.networkdomain != null && args.data.networkdomain.length > 0) {
|
||||
$.extend(data, {
|
||||
networkdomain: args.data.networkdomain
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL('createAccount'),
|
||||
type: "POST",
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var item = json.createaccountresponse.account;
|
||||
args.response.success({
|
||||
data: item
|
||||
});
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
notification: {
|
||||
poll: function(args) {
|
||||
args.complete({
|
||||
actionFilter: accountActionfilter
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
action: {
|
||||
custom: cloudStack.uiCustom.accountsWizard(
|
||||
cloudStack.accountsWizard
|
||||
)
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -1254,47 +1052,56 @@
|
|||
return 'label.action.change.password';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.action.change.password',
|
||||
fields: {
|
||||
newPassword: {
|
||||
label: 'label.new.password',
|
||||
isPassword: true,
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
id: 'newPassword'
|
||||
},
|
||||
'password-confirm': {
|
||||
label: 'label.confirm.password',
|
||||
validation: {
|
||||
required: true,
|
||||
equalTo: '#newPassword'
|
||||
},
|
||||
isPassword: true
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var password = args.data.newPassword;
|
||||
if (md5Hashed)
|
||||
password = $.md5(password);
|
||||
|
||||
var data = {
|
||||
id: args.context.users[0].id,
|
||||
password: password
|
||||
};
|
||||
action: function(args) {
|
||||
if (isLdapEnabled()) {
|
||||
alert(dictionary["error.could.not.change.your.password.because.ldap.is.enabled"]);
|
||||
args.response.error({});
|
||||
} else {
|
||||
cloudStack.dialog.createForm({
|
||||
noDialog: false,
|
||||
form: {
|
||||
title: 'label.action.change.password',
|
||||
fields: {
|
||||
newPassword: {
|
||||
label: 'label.new.password',
|
||||
isPassword: true,
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
id: 'newPassword'
|
||||
},
|
||||
'password-confirm': {
|
||||
label: 'label.confirm.password',
|
||||
validation: {
|
||||
required: true,
|
||||
equalTo: '#newPassword'
|
||||
},
|
||||
isPassword: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
var password = args.data.newPassword;
|
||||
if (md5Hashed)
|
||||
password = $.md5(password);
|
||||
|
||||
$.ajax({
|
||||
url: createURL('updateUser'),
|
||||
data: data,
|
||||
type: "POST",
|
||||
success: function(json) {
|
||||
args.response.success({
|
||||
data: json.updateuserresponse.user
|
||||
});
|
||||
}
|
||||
});
|
||||
var data = {
|
||||
id: args.context.users[0].id,
|
||||
password: password
|
||||
};
|
||||
$.ajax({
|
||||
url: createURL('updateUser'),
|
||||
data: data,
|
||||
type: "POST",
|
||||
success: function(json) {
|
||||
args.response.success({
|
||||
data: json.updateuserresponse.user
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: function(args) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,288 @@
|
|||
// 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.
|
||||
|
||||
(function(cloudStack, $) {
|
||||
cloudStack.accountsWizard = {
|
||||
|
||||
informationWithinLdap: {
|
||||
username: {
|
||||
label: 'label.username',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountUsername'
|
||||
},
|
||||
password: {
|
||||
label: 'label.password',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
isPassword: true,
|
||||
id: 'password',
|
||||
docID: 'helpAccountPassword'
|
||||
},
|
||||
'password-confirm': {
|
||||
label: 'label.confirm.password',
|
||||
validation: {
|
||||
required: true,
|
||||
equalTo: '#password'
|
||||
},
|
||||
isPassword: true,
|
||||
docID: 'helpAccountConfirmPassword'
|
||||
},
|
||||
email: {
|
||||
label: 'label.email',
|
||||
validation: {
|
||||
required: true,
|
||||
email: true
|
||||
},
|
||||
docID: 'helpAccountEmail'
|
||||
},
|
||||
firstname: {
|
||||
label: 'label.first.name',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountFirstName'
|
||||
},
|
||||
lastname: {
|
||||
label: 'label.last.name',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
docID: 'helpAccountLastName'
|
||||
}
|
||||
},
|
||||
|
||||
informationNotInLdap: {
|
||||
domainid: {
|
||||
label: 'label.domain',
|
||||
docID: 'helpAccountDomain',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
var data = {};
|
||||
|
||||
if (args.context.users) { // In accounts section
|
||||
data.listAll = true;
|
||||
} else if (args.context.domains) { // In domain section (use specific domain)
|
||||
data.id = args.context.domains[0].id;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL("listDomains"),
|
||||
data: data,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var items = [];
|
||||
domainObjs = json.listdomainsresponse.domain;
|
||||
$(domainObjs).each(function() {
|
||||
items.push({
|
||||
id: this.id,
|
||||
description: this.path
|
||||
});
|
||||
|
||||
if (this.level === 0)
|
||||
rootDomainId = this.id;
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
account: {
|
||||
label: 'label.account',
|
||||
docID: 'helpAccountAccount',
|
||||
validation: {
|
||||
required: false
|
||||
}
|
||||
},
|
||||
accounttype: {
|
||||
label: 'label.type',
|
||||
docID: 'helpAccountType',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
var items = [];
|
||||
items.push({
|
||||
id: 0,
|
||||
description: "User"
|
||||
}); //regular-user
|
||||
items.push({
|
||||
id: 1,
|
||||
description: "Admin"
|
||||
}); //root-admin
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
},
|
||||
timezone: {
|
||||
label: 'label.timezone',
|
||||
docID: 'helpAccountTimezone',
|
||||
select: function(args) {
|
||||
var items = [];
|
||||
items.push({
|
||||
id: "",
|
||||
description: ""
|
||||
});
|
||||
for (var p in timezoneMap)
|
||||
items.push({
|
||||
id: p,
|
||||
description: timezoneMap[p]
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
}
|
||||
},
|
||||
networkdomain: {
|
||||
label: 'label.network.domain',
|
||||
docID: 'helpAccountNetworkDomain',
|
||||
validation: {
|
||||
required: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
action: function(args) {
|
||||
var array1 = [];
|
||||
var ldapStatus = isLdapEnabled();
|
||||
console.log("creating user: " + args.username);
|
||||
array1.push("&username=" + args.username);
|
||||
|
||||
if (!ldapStatus) {
|
||||
var password = args.data.password;
|
||||
if (md5Hashed) {
|
||||
password = $.md5(password);
|
||||
}
|
||||
array1.push("&email=" + args.data.email);
|
||||
array1.push("&firstname=" + args.data.firstname);
|
||||
array1.push("&lastname=" + args.data.lastname);
|
||||
|
||||
var password = args.data.password;
|
||||
if (md5Hashed) {
|
||||
password = $.md5(password);
|
||||
}
|
||||
array1.push("&password=" + password);
|
||||
}
|
||||
|
||||
array1.push("&domainid=" + args.data.domainid);
|
||||
|
||||
var account = args.data.account;
|
||||
if (account === null || account.length === 0) {
|
||||
account = args.username;
|
||||
}
|
||||
array1.push("&account=" + account);
|
||||
|
||||
var accountType = args.data.accounttype;
|
||||
if (args.data.accounttype == "1" && args.data.domainid != rootDomainId) { //if account type is admin, but domain is not Root domain
|
||||
accountType = "2"; // Change accounttype from root-domain("1") to domain-admin("2")
|
||||
}
|
||||
array1.push("&accounttype=" + accountType);
|
||||
|
||||
if (args.data.timezone !== null && args.data.timezone.length > 0) {
|
||||
array1.push("&timezone=" + args.data.timezone);
|
||||
}
|
||||
|
||||
if (args.data.networkdomain !== null && args.data.networkdomain.length > 0) {
|
||||
array1.push("&networkdomain=" + args.data.networkdomain);
|
||||
}
|
||||
|
||||
if (ldapStatus) {
|
||||
console.log("doing an ldap add");
|
||||
$.ajax({
|
||||
url: createURL('ldapCreateAccount' + array1.join("")),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var item = json.createaccountresponse.account;
|
||||
args.response.success({
|
||||
data: item
|
||||
});
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("doing normal user add");
|
||||
$.ajax({
|
||||
url: createURL('createAccount' + array1.join("")),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var item = json.createaccountresponse.account;
|
||||
args.response.success({
|
||||
data: item
|
||||
});
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
action: function(args) {
|
||||
var array1 = [];
|
||||
|
||||
var username = args.data.username;
|
||||
|
||||
array1.push("&domainid=" + args.data.domainid);
|
||||
|
||||
if (args.data.account != null && args.data.account.length != 0) {
|
||||
array1.push("&account=" + args.data.account);
|
||||
}
|
||||
|
||||
if (args.data.accounttype == "1" && args.data.domainid != rootDomainId) {
|
||||
args.data.accounttype = "2";
|
||||
}
|
||||
array1.push("&accountType=" + args.data.accounttype);
|
||||
|
||||
if (args.data.timezone != null && args.data.timezone.length != 0) {
|
||||
array1.push("&timezone=" + args.data.timezone);
|
||||
}
|
||||
if (args.data.networkdomain != null && args.data.networkdomain != 0) {
|
||||
array1.push("&networkDomain=" + args.data.networkdomain);
|
||||
}
|
||||
|
||||
for (var i = 0; i < username.length; i++) {
|
||||
$.ajax({
|
||||
url: createURL("ldapCreateAccount&username=" + username[i] + array1.join("")),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
var item = json.createaccountresponse.account;
|
||||
args.response.success({
|
||||
data: item
|
||||
});
|
||||
},
|
||||
error: function(XMLHttpResponse) {
|
||||
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
*/
|
||||
};
|
||||
}(cloudStack, jQuery));
|
||||
|
|
@ -99,7 +99,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
ldapConfiguration: {
|
||||
type: 'select',
|
||||
title: 'LDAP Configuration',
|
||||
|
|
@ -110,29 +109,18 @@
|
|||
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
|
||||
url: createURL('listLdapConfigurations'),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var items = json.ldapconfigresponse.ldapconfig;
|
||||
var items = json.ldapconfigurationresponse.LdapConfiguration;
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
|
|
@ -142,12 +130,9 @@
|
|||
}
|
||||
});
|
||||
},
|
||||
|
||||
detailView: {
|
||||
name: 'label.details',
|
||||
actions: {
|
||||
|
||||
// Remove LDAP
|
||||
remove: {
|
||||
label: 'Remove LDAP',
|
||||
messages: {
|
||||
|
|
@ -159,192 +144,96 @@
|
|||
}
|
||||
},
|
||||
action: function(args) {
|
||||
|
||||
$.ajax({
|
||||
url: createURL("ldapRemove"),
|
||||
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'
|
||||
},
|
||||
description: {
|
||||
label: 'label.description'
|
||||
},
|
||||
ssl: {
|
||||
label: 'SSL'
|
||||
port: {
|
||||
label: 'Port'
|
||||
}
|
||||
}],
|
||||
dataProvider: function(args) {
|
||||
var items = [];
|
||||
console.log(args);
|
||||
$.ajax({
|
||||
url: createURL("ldapConfig&listAll=true"),
|
||||
url: createURL("listLdapConfigurations&hostname=" + args.context.ldapConfiguration[0].hostname),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var item = json.ldapconfigresponse.ldapconfig;
|
||||
var item = json.ldapconfigurationresponse.LdapConfiguration;
|
||||
args.response.success({
|
||||
data: item
|
||||
data: item[0]
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
|
||||
label: 'Configure LDAP',
|
||||
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Do you really want to configure LDAP ? ';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'LDAP configured';
|
||||
console.log(args);
|
||||
return 'Successfully added a new LDAP server';
|
||||
}
|
||||
},
|
||||
|
||||
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
|
||||
|
||||
},
|
||||
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));
|
||||
|
||||
} else
|
||||
array.push("&ssl=false");
|
||||
|
||||
array.push("&port=" + todb(args.data.port));;
|
||||
$.ajax({
|
||||
url: createURL("ldapConfig" + array.join("")),
|
||||
url: createURL("addLdapConfiguration" + array.join("")),
|
||||
dataType: "json",
|
||||
type: "POST",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var items = json.ldapconfigresponse.ldapconfig;
|
||||
var items = json.ldapconfigurationresponse.LdapAddConfiguration;
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
error: function(json) {
|
||||
args.response.error(parseXMLHttpResponse(json));
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
hypervisorCapabilities: {
|
||||
type: 'select',
|
||||
|
|
@ -440,4 +329,4 @@
|
|||
}
|
||||
}
|
||||
};
|
||||
})(cloudStack);
|
||||
})(cloudStack);
|
||||
|
|
@ -699,7 +699,23 @@ var addGuestNetworkDialog = {
|
|||
}
|
||||
|
||||
|
||||
// Role Functions
|
||||
function isLdapEnabled() {
|
||||
var result;
|
||||
$.ajax({
|
||||
url: createURL("listLdapConfigurations"),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
result = (json.ldapconfigurationresponse.count > 0);
|
||||
},
|
||||
error: function(json) {
|
||||
result = false;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// Role Functions
|
||||
|
||||
function isAdmin() {
|
||||
return (g_role == 1);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
// 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.
|
||||
|
||||
(function($, cloudStack) {
|
||||
cloudStack.uiCustom.accountsWizard = function(args) {
|
||||
return function(listViewArgs) {
|
||||
var context = listViewArgs.context;
|
||||
var ldapStatus = isLdapEnabled();
|
||||
var accountsWizard = function(data) {
|
||||
var $wizard = $('#template').find('div.accounts-wizard').clone();
|
||||
var $form = $wizard.find('form');
|
||||
|
||||
var close = function() {
|
||||
$wizard.dialog('destroy');
|
||||
$('div.overlay').fadeOut(function() {
|
||||
$('div.overlay').remove();
|
||||
});
|
||||
};
|
||||
|
||||
var completeAction = function() {
|
||||
var data = cloudStack.serializeForm($form);
|
||||
var username = data.username;
|
||||
var bulkAdd = (username instanceof Array);
|
||||
if (bulkAdd) {
|
||||
console.log("doing bulk add");
|
||||
for (var i = 0; i < username.length; i++) {
|
||||
console.log("creating user " + username[i]);
|
||||
args.action({
|
||||
context: context,
|
||||
data: data,
|
||||
username: username[i],
|
||||
response: {
|
||||
error: function(message) {
|
||||
if (message) {
|
||||
cloudStack.dialog.notice({
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
args.action({
|
||||
context: context,
|
||||
data: data,
|
||||
username: username,
|
||||
response: {
|
||||
error: function(message) {
|
||||
if (message) {
|
||||
cloudStack.dialog.notice({
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$wizard.click(function(event) {
|
||||
var $target = $(event.target);
|
||||
if ($target.closest('button.next').size()) {
|
||||
$form.validate();
|
||||
if ($form.valid()) {
|
||||
completeAction();
|
||||
$(window).trigger('cloudStack.fullRefresh');
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($target.closest('button.cancel').size()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (ldapStatus) {
|
||||
var $table = $wizard.find('.ldap-account-choice tbody');
|
||||
$.ajax({
|
||||
url: createURL("listLdapUsers&listtype=new"),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
if (json.ldapuserresponse.count > 0) {
|
||||
$(json.ldapuserresponse.LdapUser).each(function() {
|
||||
var result = $("<tr>");
|
||||
result.append("<td><input type=\"checkbox\" class=\"required\" name=\"username\" value=\"" + this.username + "\"></td>");
|
||||
result.append("<td>" + this.firstname + " " + this.lastname + "</td>");
|
||||
result.append("<td>" + this.username + "</td>");
|
||||
result.append("<td>" + this.email + "</td>");
|
||||
$table.append(result);
|
||||
});
|
||||
} else {
|
||||
var result = $("<tr>");
|
||||
result.append("<td colspan=\"4\">No data to show</td>");
|
||||
$table.append(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var informationWithinLdap = cloudStack.dialog.createForm({
|
||||
context: context,
|
||||
noDialog: true,
|
||||
form: {
|
||||
title: '',
|
||||
fields: args.informationWithinLdap
|
||||
}
|
||||
});
|
||||
|
||||
//console.log(informationWithinLdap.$formContainer);
|
||||
var informationWithinLdapForm = informationWithinLdap.$formContainer.find('form .form-item');
|
||||
informationWithinLdapForm.find('.value #label_username').addClass('required');
|
||||
informationWithinLdapForm.find('.value #password').addClass('required');
|
||||
informationWithinLdapForm.find('.value #label_confirm_password').addClass('required');
|
||||
informationWithinLdapForm.find('.value #label_confirm_password').attr('equalTo', '#password');
|
||||
informationWithinLdapForm.find('.value #label_email').addClass('required');
|
||||
informationWithinLdapForm.find('.value #label_first_name').addClass('required');
|
||||
informationWithinLdapForm.find('.value #label_last_name').addClass('required');
|
||||
$wizard.find('.manual-account-details').append(informationWithinLdapForm).children().css('background', 'none');
|
||||
$wizard.find('.ldap-account-choice').css('display', 'none');
|
||||
$wizard.removeClass('multi-wizard');
|
||||
}
|
||||
|
||||
var informationNotInLdap = cloudStack.dialog.createForm({
|
||||
context: context,
|
||||
noDialog: true,
|
||||
form: {
|
||||
title: '',
|
||||
fields: args.informationNotInLdap
|
||||
}
|
||||
});
|
||||
|
||||
var informationNotInLdapForm = informationNotInLdap.$formContainer.find('form .form-item');
|
||||
informationNotInLdapForm.find('.value #label_domain').addClass('required');
|
||||
informationNotInLdapForm.find('.value #label_type').addClass('required');
|
||||
if (!ldapStatus) {
|
||||
informationNotInLdapForm.css('background', 'none');
|
||||
}
|
||||
$wizard.find('.manual-account-details').append(informationNotInLdapForm);
|
||||
|
||||
return $wizard.dialog({
|
||||
title: _l('label.add.account'),
|
||||
width: ldapStatus ? 800 : 330,
|
||||
height: ldapStatus ? 500 : 500,
|
||||
closeOnEscape: false,
|
||||
zIndex: 5000
|
||||
}).closest('.ui-dialog').overlay();
|
||||
};
|
||||
|
||||
accountsWizard(args);
|
||||
};
|
||||
};
|
||||
})(jQuery, cloudStack);
|
||||
Loading…
Reference in New Issue