mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge LDAPPlugin
Signed-off-by: Abhinandan Prateek <aprateek@apache.org>
This commit is contained in:
parent
1f64354ec8
commit
eaa4143371
@ -26,8 +26,6 @@ import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
|
||||
@ -272,12 +270,6 @@ public interface ConfigurationService {
|
||||
|
||||
DiskOffering getDiskOffering(long diskOfferingId);
|
||||
|
||||
boolean updateLDAP(LDAPConfigCmd cmd) throws NamingException;
|
||||
|
||||
boolean removeLDAP(LDAPRemoveCmd cmd);
|
||||
|
||||
LDAPConfigCmd listLDAPConfig(LDAPConfigCmd cmd);
|
||||
|
||||
/**
|
||||
* @param offering
|
||||
* @return
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -129,7 +129,6 @@ import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
|
||||
import org.apache.cloudstack.api.response.IsolationMethodResponse;
|
||||
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
|
||||
import org.apache.cloudstack.api.response.LBStickinessResponse;
|
||||
import org.apache.cloudstack.api.response.LDAPConfigResponse;
|
||||
import org.apache.cloudstack.api.response.LoadBalancerResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkACLItemResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkACLResponse;
|
||||
@ -363,8 +362,6 @@ public interface ResponseGenerator {
|
||||
|
||||
VirtualRouterProviderResponse createVirtualRouterProviderResponse(VirtualRouterProvider result);
|
||||
|
||||
LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String baseSearch, String dn);
|
||||
|
||||
StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result);
|
||||
|
||||
RegionResponse createRegionResponse(Region region);
|
||||
|
||||
@ -1,206 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.ldap;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.LDAPConfigResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "ldapConfig", description="Configure the LDAP context for this site.", responseObject=LDAPConfigResponse.class, since="3.0.0")
|
||||
public class LDAPConfigCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(LDAPConfigCmd.class.getName());
|
||||
|
||||
private static final String s_name = "ldapconfigresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Parameter(name=ApiConstants.LIST_ALL, type=CommandType.BOOLEAN, description="If true return current LDAP configuration")
|
||||
private Boolean listAll;
|
||||
|
||||
@Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, description="Hostname or ip address of the ldap server eg: my.ldap.com")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name=ApiConstants.PORT, type=CommandType.INTEGER, description="Specify the LDAP port if required, default is 389.")
|
||||
private Integer port=0;
|
||||
|
||||
@Parameter(name=ApiConstants.USE_SSL, type=CommandType.BOOLEAN, description="Check Use SSL if the external LDAP server is configured for LDAP over SSL.")
|
||||
private Boolean useSSL;
|
||||
|
||||
@Parameter(name=ApiConstants.SEARCH_BASE, type=CommandType.STRING, description="The search base defines the starting point for the search in the directory tree Example: dc=cloud,dc=com.")
|
||||
private String searchBase;
|
||||
|
||||
@Parameter(name=ApiConstants.QUERY_FILTER, type=CommandType.STRING, description="You specify a query filter here, which narrows down the users, who can be part of this domain.")
|
||||
private String queryFilter;
|
||||
|
||||
@Parameter(name=ApiConstants.BIND_DN, type=CommandType.STRING, description="Specify the distinguished name of a user with the search permission on the directory.")
|
||||
private String bindDN;
|
||||
|
||||
@Parameter(name=ApiConstants.BIND_PASSWORD, type=CommandType.STRING, description="Enter the password.")
|
||||
private String bindPassword;
|
||||
|
||||
@Parameter(name=ApiConstants.TRUST_STORE, type=CommandType.STRING, description="Enter the path to trust certificates store.")
|
||||
private String trustStore;
|
||||
|
||||
@Parameter(name=ApiConstants.TRUST_STORE_PASSWORD, type=CommandType.STRING, description="Enter the password for trust store.")
|
||||
private String trustStorePassword;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Boolean getListAll() {
|
||||
return listAll == null ? Boolean.FALSE : listAll;
|
||||
}
|
||||
|
||||
public String getBindPassword() {
|
||||
return bindPassword;
|
||||
}
|
||||
|
||||
public String getBindDN() {
|
||||
return bindDN;
|
||||
}
|
||||
|
||||
public void setBindDN(String bdn) {
|
||||
this.bindDN=bdn;
|
||||
}
|
||||
|
||||
public String getQueryFilter() {
|
||||
return queryFilter;
|
||||
}
|
||||
|
||||
public void setQueryFilter(String queryFilter) {
|
||||
this.queryFilter=StringEscapeUtils.unescapeHtml(queryFilter);
|
||||
}
|
||||
public String getSearchBase() {
|
||||
return searchBase;
|
||||
}
|
||||
|
||||
public void setSearchBase(String searchBase) {
|
||||
this.searchBase=searchBase;
|
||||
}
|
||||
|
||||
public Boolean getUseSSL() {
|
||||
return useSSL == null ? Boolean.FALSE : useSSL;
|
||||
}
|
||||
|
||||
public void setUseSSL(Boolean useSSL) {
|
||||
this.useSSL=useSSL;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname) {
|
||||
this.hostname=hostname;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port <= 0 ? 389 : port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port=port;
|
||||
}
|
||||
|
||||
public String getTrustStore() {
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void setTrustStore(String trustStore) {
|
||||
this.trustStore=trustStore;
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return trustStorePassword;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException,
|
||||
InsufficientCapacityException, ServerApiException,
|
||||
ConcurrentOperationException, ResourceAllocationException {
|
||||
try {
|
||||
if (getListAll()){
|
||||
// return the existing conf
|
||||
LDAPConfigCmd cmd = _configService.listLDAPConfig(this);
|
||||
ListResponse<LDAPConfigResponse> response = new ListResponse<LDAPConfigResponse>();
|
||||
List<LDAPConfigResponse> responses = new ArrayList<LDAPConfigResponse>();
|
||||
|
||||
if(!cmd.getHostname().equals("")) {
|
||||
responses.add(_responseGenerator.createLDAPConfigResponse(cmd.getHostname(), cmd.getPort(), cmd.getUseSSL(), cmd.getQueryFilter(), cmd.getSearchBase(), cmd.getBindDN()));
|
||||
}
|
||||
|
||||
response.setResponses(responses);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
}
|
||||
else if (getHostname()==null || getSearchBase() == null || getQueryFilter() == null) {
|
||||
throw new InvalidParameterValueException("You need to provide hostname, searchbase and queryfilter to configure your LDAP server");
|
||||
}
|
||||
else {
|
||||
boolean result = _configService.updateLDAP(this);
|
||||
if (result){
|
||||
LDAPConfigResponse lr = _responseGenerator.createLDAPConfigResponse(getHostname(), getPort(), getUseSSL(), getQueryFilter(), getSearchBase(), getBindDN());
|
||||
lr.setResponseName(getCommandName());
|
||||
this.setResponseObject(lr);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NamingException ne){
|
||||
ne.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -391,7 +391,7 @@
|
||||
<bean id="MD5UserAuthenticator" class="com.cloud.server.auth.MD5UserAuthenticator">
|
||||
<property name="name" value="MD5"/>
|
||||
</bean>
|
||||
<bean id="LDAPUserAuthenticator" class="com.cloud.server.auth.LDAPUserAuthenticator">
|
||||
<bean id="LdapAuthenticator" class="org.apache.cloudstack.ldap.LdapAuthenticator">
|
||||
<property name="name" value="LDAP"/>
|
||||
</bean>
|
||||
<bean id="SHA256SaltedUserAuthenticator" class="com.cloud.server.auth.SHA256SaltedUserAuthenticator">
|
||||
@ -400,6 +400,11 @@
|
||||
<bean id="PlainTextUserAuthenticator" class="com.cloud.server.auth.PlainTextUserAuthenticator">
|
||||
<property name="name" value="PLAINTEXT"/>
|
||||
</bean>
|
||||
<bean id="LdapManager" class="org.apache.cloudstack.ldap.LdapManagerImpl" />
|
||||
<bean id="LdapUserManager" class="org.apache.cloudstack.ldap.LdapUserManager" />
|
||||
<bean id="LdapContextFactory" class="org.apache.cloudstack.ldap.LdapContextFactory" />
|
||||
<bean id="LdapConfigurationDao" class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
|
||||
<bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
|
||||
|
||||
<!--
|
||||
Network Elements
|
||||
|
||||
@ -210,8 +210,6 @@ scaleSystemVm=1
|
||||
#### configuration commands
|
||||
updateConfiguration=1
|
||||
listConfigurations=1
|
||||
ldapConfig=1
|
||||
ldapRemove=1
|
||||
listCapabilities=15
|
||||
listDeploymentPlanners=1
|
||||
cleanVMReservations=1
|
||||
@ -666,3 +664,11 @@ listDedicatedZones=1
|
||||
listDedicatedPods=1
|
||||
listDedicatedClusters=1
|
||||
listDedicatedHosts=1
|
||||
|
||||
### LDAP
|
||||
searchLdap=3
|
||||
listLdapConfigurations=3
|
||||
addLdapConfiguration=3
|
||||
deleteLdapConfiguration=3
|
||||
listAllLdapUsers=3
|
||||
ldapCreateAccount=3
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -29,7 +29,6 @@ import net.sf.ehcache.CacheManager;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.acl.APIChecker;
|
||||
import org.apache.cloudstack.api.ApiConstants.LDAPParams;
|
||||
import org.apache.cloudstack.api.command.admin.ratelimit.ResetApiLimitCmd;
|
||||
import org.apache.cloudstack.api.command.user.ratelimit.GetApiLimitCmd;
|
||||
import org.apache.cloudstack.api.response.ApiLimitResponse;
|
||||
|
||||
@ -1,22 +1,14 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
license agreements. See the NOTICE file distributed with this work for additional
|
||||
information regarding copyright ownership. The ASF licenses this file to you under
|
||||
the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software distributed under
|
||||
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||
OF ANY KIND, either express or implied. See the License for the specific language
|
||||
governing permissions and limitations under the License. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-user-authenticator-ldap</artifactId>
|
||||
<name>Apache CloudStack Plugin - User Authenticator LDAP</name>
|
||||
@ -26,4 +18,93 @@
|
||||
<version>4.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmaven</groupId>
|
||||
<artifactId>gmaven-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
<configuration>
|
||||
<providerSelection>1.7</providerSelection>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<fileset>
|
||||
<directory>test/groovy</directory>
|
||||
<includes>
|
||||
<include>**/*.groovy</include>
|
||||
</includes>
|
||||
</fileset>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.gmaven.runtime</groupId>
|
||||
<artifactId>gmaven-runtime-1.7</artifactId>
|
||||
<version>1.3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>2.0.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Spec*</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.btmatthews.maven.plugins</groupId>
|
||||
<artifactId>ldap-maven-plugin</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<configuration>
|
||||
<monitorPort>11389</monitorPort>
|
||||
<monitorKey>ldap</monitorKey>
|
||||
<daemon>false</daemon>
|
||||
<rootDn>dc=cloudstack,dc=org</rootDn>
|
||||
<ldapPort>10389</ldapPort>
|
||||
<ldifFile>test/resources/cloudstack.org.ldif</ldifFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Mandatory dependencies for using Spock -->
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>0.7-groovy-2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional dependencies for using Spock -->
|
||||
<dependency> <!-- enables mocking of classes (in addition to interfaces) -->
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@ -1,173 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
// contributor license agreements. See the NOTICE file distributed with
|
||||
// this work for additional information regarding copyright ownership.
|
||||
// The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
// (the "License"); you may not use this file except in compliance with
|
||||
// the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package com.cloud.server.auth;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants.LDAPParams;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Local(value={UserAuthenticator.class})
|
||||
public class LDAPUserAuthenticator extends DefaultUserAuthenticator {
|
||||
public static final Logger s_logger = Logger.getLogger(LDAPUserAuthenticator.class);
|
||||
|
||||
@Inject private ConfigurationDao _configDao;
|
||||
@Inject private UserAccountDao _userAccountDao;
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String username, String password, Long domainId, Map<String, Object[]> requestParameters ) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Retrieving user: " + username);
|
||||
}
|
||||
UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||
if (user == null) {
|
||||
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = _configDao.getValue(LDAPParams.hostname.toString());
|
||||
if (url==null){
|
||||
s_logger.debug("LDAP authenticator is not configured.");
|
||||
return false;
|
||||
}
|
||||
String port = _configDao.getValue(LDAPParams.port.toString());
|
||||
String queryFilter = _configDao.getValue(LDAPParams.queryfilter.toString());
|
||||
String searchBase = _configDao.getValue(LDAPParams.searchbase.toString());
|
||||
Boolean useSSL = Boolean.valueOf(_configDao.getValue(LDAPParams.usessl.toString()));
|
||||
String bindDN = _configDao.getValue(LDAPParams.dn.toString());
|
||||
String bindPasswd = _configDao.getValue(LDAPParams.passwd.toString());
|
||||
String trustStore = _configDao.getValue(LDAPParams.truststore.toString());
|
||||
String trustStorePassword = _configDao.getValue(LDAPParams.truststorepass.toString());
|
||||
|
||||
try {
|
||||
// get all params
|
||||
Hashtable<String, String> env = new Hashtable<String, String>(11);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
|
||||
String protocol = "ldap://" ;
|
||||
if (useSSL){
|
||||
env.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
protocol="ldaps://" ;
|
||||
System.setProperty("javax.net.ssl.trustStore", trustStore);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
|
||||
}
|
||||
env.put(Context.PROVIDER_URL, protocol + url + ":" + port);
|
||||
|
||||
if (bindDN != null && bindPasswd != null){
|
||||
env.put(Context.SECURITY_PRINCIPAL, bindDN);
|
||||
env.put(Context.SECURITY_CREDENTIALS, bindPasswd);
|
||||
}
|
||||
else {
|
||||
// Use anonymous authentication
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "none");
|
||||
}
|
||||
// Create the initial context
|
||||
DirContext ctx = new InitialDirContext(env);
|
||||
// use this context to search
|
||||
|
||||
// substitute the queryFilter with this user info
|
||||
queryFilter = queryFilter.replaceAll("\\%u", username);
|
||||
queryFilter = queryFilter.replaceAll("\\%n", user.getFirstname() + " " + user.getLastname());
|
||||
queryFilter = queryFilter.replaceAll("\\%e", user.getEmail());
|
||||
|
||||
|
||||
SearchControls sc = new SearchControls();
|
||||
String[] searchFilter = { "dn" };
|
||||
sc.setReturningAttributes(new String[0]); //return no attributes
|
||||
sc.setReturningAttributes(searchFilter);
|
||||
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
sc.setCountLimit(1);
|
||||
|
||||
// Search for objects with those matching attributes
|
||||
NamingEnumeration<SearchResult> answer = ctx.search(searchBase, queryFilter, sc);
|
||||
SearchResult sr = answer.next();
|
||||
String cn = sr.getName();
|
||||
answer.close();
|
||||
ctx.close();
|
||||
|
||||
s_logger.info("DN from LDAP =" + cn);
|
||||
|
||||
// check the password
|
||||
env = new Hashtable<String, String>(11);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
|
||||
protocol = "ldap://" ;
|
||||
if (useSSL){
|
||||
env.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
protocol="ldaps://" ;
|
||||
}
|
||||
env.put(Context.PROVIDER_URL, protocol + url + ":" + port);
|
||||
env.put(Context.SECURITY_PRINCIPAL, cn + "," + searchBase);
|
||||
env.put(Context.SECURITY_CREDENTIALS, password);
|
||||
// Create the initial context
|
||||
ctx = new InitialDirContext(env);
|
||||
ctx.close();
|
||||
|
||||
} catch (NamingException ne) {
|
||||
s_logger.warn("Authentication Failed ! " + ne.getMessage() + (ne.getCause() != null ? ("; Caused by:" + ne.getCause().getMessage()) : ""));
|
||||
return false;
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
s_logger.warn("Unknown error encountered " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// authenticate
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
if (name == null) {
|
||||
name = "LDAP";
|
||||
}
|
||||
super.configure(name, params);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(String password) {
|
||||
// Password is not used, so set to a random string
|
||||
try {
|
||||
SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
|
||||
byte bytes[] = new byte[20];
|
||||
randomGen.nextBytes(bytes);
|
||||
return Base64.encode(bytes).toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Failed to generate random password",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.LdapConfigurationResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "addLdapConfiguration", description = "Add a new Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
|
||||
public class LdapAddConfigurationCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(LdapAddConfigurationCmd.class.getName());
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name = "port", type = CommandType.INTEGER, required = true, description = "Port")
|
||||
private int port;
|
||||
|
||||
public LdapAddConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapAddConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
try {
|
||||
final LdapConfigurationResponse response = _ldapManager.addConfiguration(hostname, port);
|
||||
response.setObjectName("LdapAddConfiguration");
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (final InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserAccount;
|
||||
|
||||
@APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0")
|
||||
public class LdapCreateAccount extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(LdapCreateAccount.class.getName());
|
||||
private static final String s_name = "createaccountresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.")
|
||||
private String accountName;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin")
|
||||
private Short accountType;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class,
|
||||
description = "Creates the user under the specified domain.")
|
||||
private Long domainId;
|
||||
|
||||
@Parameter(name = ApiConstants.TIMEZONE, type = CommandType.STRING, description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
|
||||
private String timeZone;
|
||||
|
||||
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Unique username.")
|
||||
private String userName;
|
||||
|
||||
@Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "Network domain for the account's networks")
|
||||
private String networkDomain;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
|
||||
private Map<String, String> details;
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.STRING, description = "Account UUID, required for adding account from external provisioning system")
|
||||
private String accountUUID;
|
||||
|
||||
@Parameter(name = ApiConstants.USER_ID, type = CommandType.STRING, description = "User UUID, required for adding account from external provisioning system")
|
||||
private String userUUID;
|
||||
|
||||
public LdapCreateAccount() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapCreateAccount(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
CallContext.current().setEventDetails("Account Name: " + accountName + ", Domain Id:" + domainId);
|
||||
try {
|
||||
LdapUser user = _ldapManager.getUser(userName);
|
||||
validateUser(user);
|
||||
UserAccount userAccount = _accountService.createUserAccount(userName, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timeZone,
|
||||
accountName, accountType, domainId, networkDomain, details, accountUUID, userUUID);
|
||||
if (userAccount != null) {
|
||||
AccountResponse response = _responseGenerator.createUserAccountResponse(userAccount);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a user account");
|
||||
}
|
||||
} catch (NamingException e) {
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, "No LDAP user exists with the username of " + userName);
|
||||
}
|
||||
}
|
||||
|
||||
private String generatePassword() throws ServerApiException {
|
||||
try {
|
||||
SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
|
||||
byte bytes[] = new byte[20];
|
||||
randomGen.nextBytes(bytes);
|
||||
return Base64.encode(bytes).toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate random password");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
private void validateUser(LdapUser user) throws ServerApiException {
|
||||
if (user.getEmail() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no email address set within LDAP");
|
||||
}
|
||||
if (user.getFirstname() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no firstname set within LDAP");
|
||||
}
|
||||
if (user.getLastname() == null) {
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, userName + " has no lastname set within LDAP");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.LdapConfigurationResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "deleteLdapConfiguration", description = "Remove an Ldap Configuration", responseObject = LdapConfigurationResponse.class, since = "4.2.0")
|
||||
public class LdapDeleteConfigurationCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(LdapDeleteConfigurationCmd.class.getName());
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = true, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
public LdapDeleteConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapDeleteConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
try {
|
||||
final LdapConfigurationResponse response = _ldapManager.deleteConfiguration(hostname);
|
||||
response.setObjectName("LdapDeleteConfiguration");
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (final InvalidParameterValueException e) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "listAllLdapUsers", responseObject = LdapUserResponse.class, description = "Lists all LDAP Users", since = "4.2.0")
|
||||
public class LdapListAllUsersCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(LdapListAllUsersCmd.class.getName());
|
||||
private static final String s_name = "ldapuserresponse";
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
public LdapListAllUsersCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapListAllUsersCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) {
|
||||
final List<LdapUserResponse> ldapResponses = new ArrayList<LdapUserResponse>();
|
||||
for (final LdapUser user : users) {
|
||||
final LdapUserResponse ldapResponse = _ldapManager.createLdapUserResponse(user);
|
||||
ldapResponse.setObjectName("LdapUser");
|
||||
ldapResponses.add(ldapResponse);
|
||||
}
|
||||
return ldapResponses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ServerApiException {
|
||||
try {
|
||||
final List<LdapUser> users = _ldapManager.getUsers();
|
||||
final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
|
||||
final List<LdapUserResponse> ldapResponses = createLdapUserResponse(users);
|
||||
response.setResponses(ldapResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
} catch (final NoLdapUserMatchingQueryException ex) {
|
||||
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.LdapConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@APICommand(name = "listLdapConfigurations", responseObject = LdapConfigurationResponse.class, description = "Lists all LDAP configurations", since = "4.2.0")
|
||||
public class LdapListConfigurationCmd extends BaseListCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(LdapListConfigurationCmd.class.getName());
|
||||
|
||||
private static final String s_name = "ldapconfigurationresponse";
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "hostname", type = CommandType.STRING, required = false, description = "Hostname")
|
||||
private String hostname;
|
||||
|
||||
@Parameter(name = "port", type = CommandType.INTEGER, required = false, description = "Port")
|
||||
private int port;
|
||||
|
||||
public LdapListConfigurationCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapListConfigurationCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
private List<LdapConfigurationResponse> createLdapConfigurationResponses(List<? extends LdapConfigurationVO> configurations) {
|
||||
final List<LdapConfigurationResponse> responses = new ArrayList<LdapConfigurationResponse>();
|
||||
for (final LdapConfigurationVO resource : configurations) {
|
||||
final LdapConfigurationResponse configurationResponse = _ldapManager.createLdapConfigurationResponse(resource);
|
||||
configurationResponse.setObjectName("LdapConfiguration");
|
||||
responses.add(configurationResponse);
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(this);
|
||||
final List<LdapConfigurationResponse> responses = createLdapConfigurationResponses(result.first());
|
||||
final ListResponse<LdapConfigurationResponse> response = new ListResponse<LdapConfigurationResponse>();
|
||||
response.setResponses(responses, result.second());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseListCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.ldap.LdapManager;
|
||||
import org.apache.cloudstack.ldap.LdapUser;
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "searchLdap", responseObject = LdapUserResponse.class, description = "Searches LDAP based on the username attribute", since = "4.2.0")
|
||||
public class LdapUserSearchCmd extends BaseListCmd {
|
||||
|
||||
public static final Logger s_logger = Logger.getLogger(LdapUserSearchCmd.class.getName());
|
||||
private static final String s_name = "ldapuserresponse";
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
@Parameter(name = "query", type = CommandType.STRING, entityType = LdapUserResponse.class, required = true, description = "query to search using")
|
||||
private String query;
|
||||
|
||||
public LdapUserSearchCmd() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapUserSearchCmd(final LdapManager ldapManager) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
private List<LdapUserResponse> createLdapUserResponse(List<LdapUser> users) {
|
||||
final List<LdapUserResponse> ldapUserResponses = new ArrayList<LdapUserResponse>();
|
||||
if (users != null) {
|
||||
for (final LdapUser user : users) {
|
||||
final LdapUserResponse ldapUserResponse = _ldapManager.createLdapUserResponse(user);
|
||||
ldapUserResponse.setObjectName("LdapUser");
|
||||
ldapUserResponses.add(ldapUserResponse);
|
||||
}
|
||||
}
|
||||
return ldapUserResponses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final ListResponse<LdapUserResponse> response = new ListResponse<LdapUserResponse>();
|
||||
List<LdapUser> users = null;
|
||||
|
||||
try {
|
||||
users = _ldapManager.searchUsers(query);
|
||||
} catch (final NoLdapUserMatchingQueryException e) {
|
||||
s_logger.debug(e.getMessage());
|
||||
}
|
||||
|
||||
final List<LdapUserResponse> ldapUserResponses = createLdapUserResponse(users);
|
||||
|
||||
response.setResponses(ldapUserResponses);
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class LdapConfigurationResponse extends BaseResponse {
|
||||
@SerializedName("hostname")
|
||||
@Param(description = "hostname")
|
||||
private String hostname;
|
||||
|
||||
@SerializedName("port")
|
||||
@Param(description = "port")
|
||||
private int port;
|
||||
|
||||
public LdapConfigurationResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapConfigurationResponse(final String hostname) {
|
||||
super();
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public LdapConfigurationResponse(final String hostname, final int port) {
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setHostname(final String hostname) {
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class LdapUserResponse extends BaseResponse {
|
||||
@SerializedName("email")
|
||||
@Param(description = "The user's email")
|
||||
private String email;
|
||||
|
||||
@SerializedName("principal")
|
||||
@Param(description = "The user's principle")
|
||||
private String principal;
|
||||
|
||||
@SerializedName("firstname")
|
||||
@Param(description = "The user's firstname")
|
||||
private String firstname;
|
||||
|
||||
@SerializedName("lastname")
|
||||
@Param(description = "The user's lastname")
|
||||
private String lastname;
|
||||
|
||||
@SerializedName("username")
|
||||
@Param(description = "The user's username")
|
||||
private String username;
|
||||
|
||||
public LdapUserResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapUserResponse(final String username, final String email, final String firstname, final String lastname, final String principal) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public String getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setEmail(final String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public void setFirstname(final String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public void setLastname(final String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public void setPrincipal(final String principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
|
||||
|
||||
import com.cloud.server.auth.DefaultUserAuthenticator;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
|
||||
public class LdapAuthenticator extends DefaultUserAuthenticator {
|
||||
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
@Inject
|
||||
private UserAccountDao _userAccountDao;
|
||||
|
||||
public LdapAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapAuthenticator(final LdapManager ldapManager, final UserAccountDao userAccountDao) {
|
||||
super();
|
||||
_ldapManager = ldapManager;
|
||||
_userAccountDao = userAccountDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(final String username, final String password, final Long domainId, final Map<String, Object[]> requestParameters) {
|
||||
|
||||
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||
|
||||
if (user == null) {
|
||||
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
||||
return false;
|
||||
} else if (isLdapConfigurationPresent()) {
|
||||
return _ldapManager.canAuthenticate(username, password);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(final String password) {
|
||||
return password;
|
||||
}
|
||||
|
||||
private boolean isLdapConfigurationPresent() {
|
||||
return _ldapManager.listConfigurations(new LdapListConfigurationCmd(_ldapManager)).second() > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.ldap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
|
||||
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public class LdapConfiguration {
|
||||
private final static String factory = "com.sun.jndi.ldap.LdapCtxFactory";
|
||||
|
||||
private final static int scope = SearchControls.SUBTREE_SCOPE;
|
||||
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
@Inject
|
||||
private LdapManager _ldapManager;
|
||||
|
||||
public LdapConfiguration() {
|
||||
}
|
||||
|
||||
public LdapConfiguration(final ConfigurationDao configDao, final LdapManager ldapManager) {
|
||||
_configDao = configDao;
|
||||
_ldapManager = ldapManager;
|
||||
}
|
||||
|
||||
public String getAuthentication() {
|
||||
if ((getBindPrincipal() == null) && (getBindPassword() == null)) {
|
||||
return "none";
|
||||
} else {
|
||||
return "simple";
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseDn() {
|
||||
return _configDao.getValue("ldap.basedn");
|
||||
}
|
||||
|
||||
public String getBindPassword() {
|
||||
return _configDao.getValue("ldap.bind.password");
|
||||
}
|
||||
|
||||
public String getBindPrincipal() {
|
||||
return _configDao.getValue("ldap.bind.principal");
|
||||
}
|
||||
|
||||
public String getEmailAttribute() {
|
||||
final String emailAttribute = _configDao.getValue("ldap.email.attribute");
|
||||
return emailAttribute == null ? "mail" : emailAttribute;
|
||||
}
|
||||
|
||||
public String getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public String getFirstnameAttribute() {
|
||||
final String firstnameAttribute = _configDao.getValue("ldap.firstname.attribute");
|
||||
return firstnameAttribute == null ? "givenname" : firstnameAttribute;
|
||||
}
|
||||
|
||||
public String getLastnameAttribute() {
|
||||
final String lastnameAttribute = _configDao.getValue("ldap.lastname.attribute");
|
||||
return lastnameAttribute == null ? "sn" : lastnameAttribute;
|
||||
}
|
||||
|
||||
public String getProviderUrl() {
|
||||
final Pair<List<? extends LdapConfigurationVO>, Integer> result = _ldapManager.listConfigurations(new LdapListConfigurationCmd(_ldapManager));
|
||||
final StringBuilder providerUrls = new StringBuilder();
|
||||
String delim = "";
|
||||
for (final LdapConfigurationVO resource : result.first()) {
|
||||
final String providerUrl = "ldap://" + resource.getHostname() + ":" + resource.getPort();
|
||||
providerUrls.append(delim).append(providerUrl);
|
||||
delim = " ";
|
||||
}
|
||||
return providerUrls.toString();
|
||||
}
|
||||
|
||||
public String[] getReturnAttributes() {
|
||||
return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute()};
|
||||
}
|
||||
|
||||
public int getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public String getUsernameAttribute() {
|
||||
final String usernameAttribute = _configDao.getValue("ldap.username.attribute");
|
||||
return usernameAttribute == null ? "uid" : usernameAttribute;
|
||||
}
|
||||
|
||||
public String getUserObject() {
|
||||
final String userObject = _configDao.getValue("ldap.user.object");
|
||||
return userObject == null ? "inetOrgPerson" : userObject;
|
||||
}
|
||||
}
|
||||
@ -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(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
// 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 Hashtable<String, String> getEnvironment(final String principal, final String password, final String providerUrl, final boolean isSystemContext) {
|
||||
final String factory = _ldapConfiguration.getFactory();
|
||||
final String url = providerUrl == null ? _ldapConfiguration.getProviderUrl() : providerUrl;
|
||||
final String authentication = _ldapConfiguration.getAuthentication();
|
||||
|
||||
final Hashtable<String, String> environment = new Hashtable<String, String>();
|
||||
|
||||
environment.put(Context.INITIAL_CONTEXT_FACTORY, factory);
|
||||
environment.put(Context.PROVIDER_URL, url);
|
||||
environment.put("com.sun.jndi.ldap.read.timeout", "500");
|
||||
environment.put("com.sun.jndi.ldap.connect.pool", "true");
|
||||
|
||||
if ("none".equals(authentication) && !isSystemContext) {
|
||||
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
} else {
|
||||
environment.put(Context.SECURITY_AUTHENTICATION, authentication);
|
||||
}
|
||||
|
||||
if (principal != null) {
|
||||
environment.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
environment.put(Context.SECURITY_CREDENTIALS, password);
|
||||
}
|
||||
|
||||
return environment;
|
||||
}
|
||||
|
||||
public void testConnection(final String providerUrl) throws NamingException {
|
||||
try {
|
||||
createBindContext(providerUrl);
|
||||
s_logger.info("LDAP Connection was successful");
|
||||
} catch (final NamingException e) {
|
||||
s_logger.warn("LDAP Connection failed");
|
||||
s_logger.error(e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
// 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;
|
||||
|
||||
Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(LdapListConfigurationCmd cmd);
|
||||
|
||||
List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
|
||||
}
|
||||
@ -0,0 +1,205 @@
|
||||
// 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.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.api.command.LdapAddConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapCreateAccount;
|
||||
import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapListAllUsersCmd;
|
||||
import org.apache.cloudstack.api.command.LdapListConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.LdapUserSearchCmd;
|
||||
import org.apache.cloudstack.api.response.LdapConfigurationResponse;
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse;
|
||||
import org.apache.cloudstack.ldap.dao.LdapConfigurationDao;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@Component
|
||||
@Local(value = LdapManager.class)
|
||||
public class LdapManagerImpl implements LdapManager {
|
||||
private static final Logger s_logger = Logger.getLogger(LdapManagerImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
private LdapConfigurationDao _ldapConfigurationDao;
|
||||
|
||||
@Inject
|
||||
private LdapContextFactory _ldapContextFactory;
|
||||
|
||||
@Inject
|
||||
private LdapUserManager _ldapUserManager;
|
||||
|
||||
public LdapManagerImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapManagerImpl(final LdapConfigurationDao ldapConfigurationDao, final LdapContextFactory ldapContextFactory, final LdapUserManager ldapUserManager) {
|
||||
super();
|
||||
_ldapConfigurationDao = ldapConfigurationDao;
|
||||
_ldapContextFactory = ldapContextFactory;
|
||||
_ldapUserManager = ldapUserManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LdapConfigurationResponse addConfiguration(final String hostname, final int port) throws InvalidParameterValueException {
|
||||
LdapConfigurationVO configuration = _ldapConfigurationDao.findByHostname(hostname);
|
||||
if (configuration == null) {
|
||||
try {
|
||||
final String providerUrl = "ldap://" + hostname + ":" + port;
|
||||
_ldapContextFactory.createBindContext(providerUrl);
|
||||
configuration = new LdapConfigurationVO(hostname, port);
|
||||
_ldapConfigurationDao.persist(configuration);
|
||||
s_logger.info("Added new ldap server with hostname: " + hostname);
|
||||
return new LdapConfigurationResponse(hostname, port);
|
||||
} catch (final NamingException e) {
|
||||
throw new InvalidParameterValueException("Unable to bind to the given LDAP server");
|
||||
}
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Duplicate configuration");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAuthenticate(final String username, final String password) {
|
||||
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
|
||||
try {
|
||||
final LdapUser user = getUser(escapedUsername);
|
||||
final String principal = user.getPrincipal();
|
||||
final 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(LdapListAllUsersCmd.class);
|
||||
cmdList.add(LdapAddConfigurationCmd.class);
|
||||
cmdList.add(LdapDeleteConfigurationCmd.class);
|
||||
cmdList.add(LdapListConfigurationCmd.class);
|
||||
cmdList.add(LdapCreateAccount.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 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,75 @@
|
||||
// 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,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.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);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
final String filter = "(&(objectClass=" + _ldapConfiguration.getUserObject() + ")" + "("
|
||||
+ _ldapConfiguration.getUsernameAttribute() + "=" + (username == null ? "*" : username) + "))";
|
||||
|
||||
return context.search(_ldapConfiguration.getBaseDn(), filter, controls);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
// 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 (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,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 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,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.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.SearchCriteria.Op;
|
||||
|
||||
@Component
|
||||
@Local(value = {LdapConfigurationDao.class})
|
||||
public class LdapConfigurationDaoImpl extends GenericDaoBase<LdapConfigurationVO, Long> implements LdapConfigurationDao {
|
||||
private final SearchBuilder<LdapConfigurationVO> hostnameSearch;
|
||||
private final SearchBuilder<LdapConfigurationVO> listAllConfigurationsSearch;
|
||||
|
||||
public LdapConfigurationDaoImpl() {
|
||||
super();
|
||||
hostnameSearch = createSearchBuilder();
|
||||
hostnameSearch.and("hostname", hostnameSearch.entity().getHostname(), SearchCriteria.Op.EQ);
|
||||
hostnameSearch.done();
|
||||
|
||||
listAllConfigurationsSearch = createSearchBuilder();
|
||||
listAllConfigurationsSearch.and("hostname", listAllConfigurationsSearch.entity().getHostname(), Op.EQ);
|
||||
listAllConfigurationsSearch.and("port", listAllConfigurationsSearch.entity().getPort(), Op.EQ);
|
||||
listAllConfigurationsSearch.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LdapConfigurationVO findByHostname(final String hostname) {
|
||||
final SearchCriteria<LdapConfigurationVO> sc = hostnameSearch.create();
|
||||
sc.setParameters("hostname", hostname);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<LdapConfigurationVO>, Integer> searchConfigurations(final String hostname, final int port) {
|
||||
final SearchCriteria<LdapConfigurationVO> sc = listAllConfigurationsSearch.create();
|
||||
if (hostname != null) {
|
||||
sc.setParameters("hostname", hostname);
|
||||
}
|
||||
return searchAndCount(sc, null);
|
||||
}
|
||||
}
|
||||
@ -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>();
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return items.size != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nextElement() {
|
||||
SearchResult result = items.getFirst();
|
||||
items.removeFirst();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws NamingException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMore() throws NamingException {
|
||||
return hasMoreElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() throws NamingException {
|
||||
return nextElement();
|
||||
}
|
||||
|
||||
public void add(SearchResult item) {
|
||||
items.add(item)
|
||||
}
|
||||
}
|
||||
@ -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 successful response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.addConfiguration(_, _) >> new LdapConfigurationResponse("localhost", 389)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapAddConfigurationCmd.execute()
|
||||
then:
|
||||
ldapAddConfigurationCmd.responseObject.hostname == "localhost"
|
||||
ldapAddConfigurationCmd.responseObject.port == 389
|
||||
}
|
||||
|
||||
def "Test failed response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.addConfiguration(_, _) >> { throw new InvalidParameterValueException() }
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapAddConfigurationCmd.execute()
|
||||
then:
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test successful setting of hostname"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapAddConfigurationCmd.setHostname("localhost")
|
||||
then:
|
||||
ldapAddConfigurationCmd.getHostname() == "localhost"
|
||||
}
|
||||
|
||||
def "Test successful setting of port"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapAddConfigurationCmd.setPort(389)
|
||||
then:
|
||||
ldapAddConfigurationCmd.getPort() == 389
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 0"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
long ownerId = ldapAddConfigurationCmd.getEntityOwnerId()
|
||||
then:
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapAddConfigurationCmd = new LdapAddConfigurationCmd(ldapManager)
|
||||
when:
|
||||
String commandName = ldapAddConfigurationCmd.getCommandName()
|
||||
then:
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
// 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:
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> null
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when:
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then:
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap not being configured"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapManager.listConfigurations(_) >> ldapConfigurations
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when:
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then:
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap bind being unsuccessful"() {
|
||||
given:
|
||||
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
|
||||
Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapManager.listConfigurations(_) >> ldapConfigurations
|
||||
ldapManager.canAuthenticate(_, _) >> false
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
|
||||
when:
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
|
||||
then:
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test that encode doesn't change the input"() {
|
||||
given:
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when:
|
||||
def result = ldapAuthenticator.encode("password")
|
||||
then:
|
||||
result == "password"
|
||||
}
|
||||
}
|
||||
@ -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:
|
||||
def ldapConfigurationDaoImpl = new LdapConfigurationDaoImpl();
|
||||
expect:
|
||||
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:
|
||||
LdapConfigurationResponse response = new LdapConfigurationResponse();
|
||||
when:
|
||||
response.setHostname("localhost");
|
||||
then:
|
||||
response.getHostname() == "localhost";
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapConfigurationResponse port"() {
|
||||
given:
|
||||
LdapConfigurationResponse response = new LdapConfigurationResponse()
|
||||
when:
|
||||
response.setPort(389)
|
||||
then:
|
||||
response.getPort() == 389
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapConfigurationResponse hostname and port via constructor"() {
|
||||
given:
|
||||
LdapConfigurationResponse response
|
||||
when:
|
||||
response = new LdapConfigurationResponse("localhost", 389)
|
||||
then:
|
||||
response.getHostname() == "localhost"
|
||||
response.getPort() == 389
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
// 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.configuration.dao.ConfigurationDao
|
||||
import com.cloud.utils.Pair
|
||||
import org.apache.cloudstack.api.ServerApiException
|
||||
import org.apache.cloudstack.ldap.LdapConfiguration
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO
|
||||
import org.apache.cloudstack.ldap.LdapManager
|
||||
|
||||
import javax.naming.directory.SearchControls
|
||||
|
||||
class LdapConfigurationSpec extends spock.lang.Specification {
|
||||
def "Test that providerUrl successfully returns a URL when a configuration is available"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
|
||||
Pair<List<LdapConfigurationVO>, Integer> result = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
result.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapManager.listConfigurations(_) >> result
|
||||
|
||||
LdapConfiguration ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
|
||||
when:
|
||||
String providerUrl = ldapConfiguration.getProviderUrl()
|
||||
|
||||
then:
|
||||
providerUrl == "ldap://localhost:389"
|
||||
}
|
||||
|
||||
def "Test that getAuthentication returns simple"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
configDao.getValue("ldap.bind.password") >> "password"
|
||||
configDao.getValue("ldap.bind.principal") >> "cn=rmurphy,dc=cloudstack,dc=org"
|
||||
when:
|
||||
String authentication = ldapConfiguration.getAuthentication()
|
||||
then:
|
||||
authentication == "simple"
|
||||
}
|
||||
|
||||
def "Test that getAuthentication returns none"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String authentication = ldapConfiguration.getAuthentication()
|
||||
then:
|
||||
authentication == "none"
|
||||
}
|
||||
|
||||
def "Test that getEmailAttribute returns mail"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.email.attribute") >> "mail"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String emailAttribute = ldapConfiguration.getEmailAttribute()
|
||||
then:
|
||||
emailAttribute == "mail"
|
||||
}
|
||||
|
||||
def "Test that getUsernameAttribute returns uid"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.username.attribute") >> "uid"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String usernameAttribute = ldapConfiguration.getUsernameAttribute()
|
||||
then:
|
||||
usernameAttribute == "uid"
|
||||
}
|
||||
|
||||
def "Test that getFirstnameAttribute returns givenname"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.firstname.attribute") >> "givenname"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String firstname = ldapConfiguration.getFirstnameAttribute()
|
||||
then:
|
||||
firstname == "givenname"
|
||||
}
|
||||
|
||||
def "Test that getLastnameAttribute returns givenname"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.lastname.attribute") >> "sn"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String lastname = ldapConfiguration.getLastnameAttribute()
|
||||
then:
|
||||
lastname == "sn"
|
||||
}
|
||||
|
||||
def "Test that getUserObject returns inetOrgPerson"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.user.object") >> "inetOrgPerson"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String userObject = ldapConfiguration.getUserObject()
|
||||
then:
|
||||
userObject == "inetOrgPerson"
|
||||
}
|
||||
|
||||
def "Test that getReturnAttributes returns the correct data"() {
|
||||
given:
|
||||
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:
|
||||
String[] returnAttributes = ldapConfiguration.getReturnAttributes()
|
||||
then:
|
||||
returnAttributes == ["uid", "mail", "givenname", "sn"]
|
||||
}
|
||||
|
||||
def "Test that getScope returns SearchControls.SUBTREE_SCOPE"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
int scope = ldapConfiguration.getScope()
|
||||
then:
|
||||
scope == SearchControls.SUBTREE_SCOPE;
|
||||
}
|
||||
|
||||
def "Test that getBaseDn returns dc=cloudstack,dc=org"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
configDao.getValue("ldap.basedn") >> "dc=cloudstack,dc=org"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String baseDn = ldapConfiguration.getBaseDn();
|
||||
then:
|
||||
baseDn == "dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test that getFactory returns com.sun.jndi.ldap.LdapCtxFactory"() {
|
||||
given:
|
||||
def configDao = Mock(ConfigurationDao)
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapConfiguration = new LdapConfiguration(configDao, ldapManager)
|
||||
when:
|
||||
String factory = ldapConfiguration.getFactory();
|
||||
then:
|
||||
factory == "com.sun.jndi.ldap.LdapCtxFactory"
|
||||
}
|
||||
}
|
||||
@ -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,134 @@
|
||||
// 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"
|
||||
|
||||
username = "rmurphy"
|
||||
principal = "cn=" + username + "," + ldapConfiguration.getBaseDn()
|
||||
password = "password"
|
||||
}
|
||||
|
||||
def "Test successfully creating a system environment with anon bind"() {
|
||||
given:
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = ldapContextFactory.getEnvironment(principal, password, null, false)
|
||||
|
||||
then:
|
||||
result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
|
||||
result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
|
||||
result['java.naming.security.principal'] == principal
|
||||
result['java.naming.security.authentication'] == "simple"
|
||||
result['java.naming.security.credentials'] == password
|
||||
}
|
||||
|
||||
def "Test successfully creating a environment with username and password"() {
|
||||
given:
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = ldapContextFactory.getEnvironment(null, null, null, true)
|
||||
|
||||
then:
|
||||
result['java.naming.provider.url'] == ldapConfiguration.getProviderUrl()
|
||||
result['java.naming.factory.initial'] == ldapConfiguration.getFactory()
|
||||
result['java.naming.security.principal'] == null
|
||||
result['java.naming.security.authentication'] == ldapConfiguration.getAuthentication()
|
||||
result['java.naming.security.credentials'] == null
|
||||
}
|
||||
|
||||
def "Test successfully binding as a user"() {
|
||||
given:
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when:
|
||||
ldapContextFactory.createUserContext(principal, password)
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successully binding as system"() {
|
||||
given:
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when:
|
||||
ldapContextFactory.createBindContext()
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test succcessfully creating a initial context"() {
|
||||
given:
|
||||
def ldapContextFactory = new LdapContextFactory(ldapConfiguration)
|
||||
when:
|
||||
ldapContextFactory.createInitialDirContext(null, null, true)
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successful failed connection"() {
|
||||
given:
|
||||
def ldapContextFactory = Spy(LdapContextFactory, constructorArgs: [ldapConfiguration])
|
||||
when:
|
||||
ldapContextFactory.testConnection(ldapConfiguration.getProviderUrl())
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successful connection"() {
|
||||
given:
|
||||
def ldapContextFactory = Spy(LdapContextFactory, constructorArgs: [ldapConfiguration])
|
||||
ldapContextFactory.createBindContext(_) >> Mock(LdapContext)
|
||||
when:
|
||||
ldapContextFactory.testConnection(ldapConfiguration.getProviderUrl())
|
||||
then:
|
||||
notThrown NamingException
|
||||
}
|
||||
}
|
||||
@ -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 successful response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.deleteConfiguration(_) >> new LdapConfigurationResponse("localhost")
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapDeleteConfigurationCmd.execute()
|
||||
then:
|
||||
ldapDeleteConfigurationCmd.responseObject.hostname == "localhost"
|
||||
}
|
||||
|
||||
def "Test failed response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.deleteConfiguration(_) >> { throw new InvalidParameterValueException() }
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapDeleteConfigurationCmd.execute()
|
||||
then:
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 0"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when:
|
||||
long ownerId = ldapDeleteConfigurationCmd.getEntityOwnerId()
|
||||
then:
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapDeleteConfigurationCmd = new LdapDeleteConfigurationCmd(ldapManager)
|
||||
when:
|
||||
String commandName = ldapDeleteConfigurationCmd.getCommandName()
|
||||
then:
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
}
|
||||
@ -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.LdapListAllUsersCmd
|
||||
import org.apache.cloudstack.api.response.LdapUserResponse
|
||||
import org.apache.cloudstack.ldap.LdapManager
|
||||
import org.apache.cloudstack.ldap.LdapUser
|
||||
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
|
||||
|
||||
class LdapListAllUsersCmdSpec extends spock.lang.Specification {
|
||||
def "Test successful response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapUser> users = new ArrayList()
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
ldapManager.getUsers() >> users
|
||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
ldapManager.createLdapUserResponse(_) >> response
|
||||
def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
|
||||
when:
|
||||
ldapListAllUsersCmd.execute()
|
||||
then:
|
||||
ldapListAllUsersCmd.responseObject.getResponses().size() != 0
|
||||
}
|
||||
|
||||
def "Test successful empty response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.getUsers() >> {throw new NoLdapUserMatchingQueryException()}
|
||||
def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
|
||||
when:
|
||||
ldapListAllUsersCmd.execute()
|
||||
then:
|
||||
thrown ServerApiException
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 1"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
|
||||
when:
|
||||
long ownerId = ldapListAllUsersCmd.getEntityOwnerId()
|
||||
then:
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListAllUsersCmd = new LdapListAllUsersCmd(ldapManager)
|
||||
when:
|
||||
String commandName = ldapListAllUsersCmd.getCommandName()
|
||||
then:
|
||||
commandName == "ldapuserresponse"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
// 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 successful response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
|
||||
Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapManager.listConfigurations(_) >> ldapConfigurations
|
||||
ldapManager.createLdapConfigurationResponse(_) >> new LdapConfigurationResponse("localhost", 389)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapListConfigurationCmd.execute()
|
||||
then:
|
||||
ldapListConfigurationCmd.getResponseObject().getResponses().size() != 0
|
||||
}
|
||||
|
||||
def "Test failed response from execute"() {
|
||||
given:
|
||||
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
Pair<List<LdapConfigurationVO>, Integer> ldapConfigurations = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
ldapConfigurations.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapManager.listConfigurations(_) >> ldapConfigurations
|
||||
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapListConfigurationCmd.execute()
|
||||
then:
|
||||
ldapListConfigurationCmd.getResponseObject().getResponses().size() == 0
|
||||
}
|
||||
|
||||
def "Test successful setting of hostname"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapListConfigurationCmd.setHostname("localhost")
|
||||
then:
|
||||
ldapListConfigurationCmd.getHostname() == "localhost"
|
||||
}
|
||||
|
||||
def "Test successful setting of Port"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
ldapListConfigurationCmd.setPort(389)
|
||||
then:
|
||||
ldapListConfigurationCmd.getPort() == 389
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 0"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
long ownerId = ldapListConfigurationCmd.getEntityOwnerId()
|
||||
then:
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapListConfigurationCmd = new LdapListConfigurationCmd(ldapManager)
|
||||
when:
|
||||
String commandName = ldapListConfigurationCmd.getCommandName()
|
||||
then:
|
||||
commandName == "ldapconfigurationresponse"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,319 @@
|
||||
// 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 that addConfiguration fails when a duplicate configuration exists"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapConfigurationDao.findByHostname(_) >> new LdapConfigurationVO("localhost", 389)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.addConfiguration("localhost", 389)
|
||||
then:
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test that addConfiguration fails when a binding fails"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext(_) >> { throw new NamingException() }
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.addConfiguration("localhost", 389)
|
||||
then:
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test successfully addConfiguration"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext(_) >> null
|
||||
ldapConfigurationDao.persist(_) >> null
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.addConfiguration("localhost", 389)
|
||||
then:
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test successful failed result from deleteConfiguration due to configuration not existing"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapConfigurationDao.findByHostname(_) >> null
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.deleteConfiguration("localhost")
|
||||
then:
|
||||
thrown InvalidParameterValueException
|
||||
}
|
||||
|
||||
def "Test successful result from deleteConfiguration"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapConfigurationDao.findByHostname(_) >> {
|
||||
def configuration = new LdapConfigurationVO("localhost", 389)
|
||||
configuration.setId(0);
|
||||
return configuration;
|
||||
}
|
||||
ldapConfigurationDao.remove(_) >> null
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.deleteConfiguration("localhost")
|
||||
then:
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test successful failed result from canAuthenticate due to user not found"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
|
||||
ldapManager.getUser(_) >> { throw new NamingException() }
|
||||
when:
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then:
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test successful failed result from canAuthenticate due to bad password"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
ldapContextFactory.createUserContext(_, _) >> { throw new NamingException() }
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
|
||||
ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org") }
|
||||
when:
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then:
|
||||
result == false
|
||||
}
|
||||
|
||||
def "Test successful result from canAuthenticate"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
ldapContextFactory.createUserContext(_, _) >> null
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManager])
|
||||
ldapManager.getUser(_) >> { new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org") }
|
||||
when:
|
||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
||||
then:
|
||||
result == true
|
||||
}
|
||||
|
||||
def "Test successful closing of context"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def context = Mock(InitialLdapContext)
|
||||
ldapManager.closeContext(context)
|
||||
then:
|
||||
context.defaultInitCtx == null
|
||||
}
|
||||
|
||||
def "Test successful failing to close of context"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def context = Mock(InitialLdapContext)
|
||||
context.close() >> { throw new NamingException() }
|
||||
ldapManager.closeContext(context)
|
||||
then:
|
||||
context.defaultInitCtx == null
|
||||
}
|
||||
|
||||
def "Test LdapConfigurationResponse generation"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.createLdapConfigurationResponse(new LdapConfigurationVO("localhost", 389))
|
||||
then:
|
||||
result.hostname == "localhost"
|
||||
result.port == 389
|
||||
}
|
||||
|
||||
def "Test LdapUserResponse generation"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
then:
|
||||
result.username == "rmurphy"
|
||||
result.email == "rmurphy@test.com"
|
||||
result.firstname == "Ryan"
|
||||
result.lastname == "Murphy"
|
||||
result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test that getCommands isn't empty"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.getCommands()
|
||||
then:
|
||||
result.size() > 0
|
||||
}
|
||||
|
||||
def "Test failing of getUser due to bind issue"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> { throw new NamingException() }
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.getUser("rmurphy")
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test success of getUser"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> null
|
||||
ldapUserManager.getUser(_, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.getUser("rmurphy")
|
||||
then:
|
||||
result.username == "rmurphy"
|
||||
result.email == "rmurphy@test.com"
|
||||
result.firstname == "Ryan"
|
||||
result.lastname == "Murphy"
|
||||
result.principal == "cn=rmurphy,dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Test failing of getUsers due to bind issue"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> { throw new NamingException() }
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.getUsers()
|
||||
then:
|
||||
thrown NoLdapUserMatchingQueryException
|
||||
}
|
||||
|
||||
def "Test success getUsers"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> null
|
||||
List<LdapUser> users = new ArrayList<>();
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
ldapUserManager.getUsers(_) >> users;
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.getUsers()
|
||||
then:
|
||||
result.size() > 0;
|
||||
}
|
||||
|
||||
def "Testing of listConfigurations"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
List<LdapConfigurationVO> ldapConfigurationList = new ArrayList()
|
||||
ldapConfigurationList.add(new LdapConfigurationVO("localhost", 389))
|
||||
Pair<List<LdapConfigurationVO>, Integer> configurations = new Pair<List<LdapConfigurationVO>, Integer>();
|
||||
configurations.set(ldapConfigurationList, ldapConfigurationList.size())
|
||||
ldapConfigurationDao.searchConfigurations(_, _) >> configurations
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.listConfigurations(new LdapListConfigurationCmd())
|
||||
then:
|
||||
result.second() > 0
|
||||
}
|
||||
|
||||
def "Test failing of searchUsers due to a failure to bind"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> { throw new NamingException() }
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
ldapManager.searchUsers("rmurphy")
|
||||
then:
|
||||
thrown NoLdapUserMatchingQueryException
|
||||
}
|
||||
|
||||
def "Test successful result from searchUsers"() {
|
||||
given:
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
def ldapContextFactory = Mock(LdapContextFactory)
|
||||
def ldapUserManager = Mock(LdapUserManager)
|
||||
ldapContextFactory.createBindContext() >> null;
|
||||
|
||||
List<LdapUser> users = new ArrayList<LdapUser>();
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
ldapUserManager.getUsers(_, _) >> users;
|
||||
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManager)
|
||||
when:
|
||||
def result = ldapManager.searchUsers("rmurphy");
|
||||
then:
|
||||
result.size() > 0;
|
||||
}
|
||||
}
|
||||
@ -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 successful response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapUser> users = new ArrayList()
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org"))
|
||||
ldapManager.searchUsers(_) >> users
|
||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org")
|
||||
ldapManager.createLdapUserResponse(_) >> response
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when:
|
||||
ldapUserSearchCmd.execute()
|
||||
then:
|
||||
ldapUserSearchCmd.responseObject.getResponses().size() != 0
|
||||
}
|
||||
|
||||
def "Test successful empty response from execute"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.searchUsers(_) >> {throw new NoLdapUserMatchingQueryException()}
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when:
|
||||
ldapUserSearchCmd.execute()
|
||||
then:
|
||||
ldapUserSearchCmd.responseObject.getResponses().size() == 0
|
||||
}
|
||||
|
||||
def "Test getEntityOwnerId is 0"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when:
|
||||
long ownerId = ldapUserSearchCmd.getEntityOwnerId()
|
||||
then:
|
||||
ownerId == 1
|
||||
}
|
||||
|
||||
def "Test successful return of getCommandName"() {
|
||||
given:
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUserSearchCmd = new LdapUserSearchCmd(ldapManager)
|
||||
when:
|
||||
String commandName = ldapUserSearchCmd.getCommandName()
|
||||
then:
|
||||
commandName == "ldapuserresponse"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,207 @@
|
||||
// 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
|
||||
|
||||
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 that a newly created Ldap User Manager is not null"() {
|
||||
given: "You have created a new Ldap user manager object"
|
||||
def result = new LdapUserManager();
|
||||
expect: "The result is not null"
|
||||
result != null
|
||||
}
|
||||
|
||||
def "Test successfully creating an Ldap User from Search result"() {
|
||||
given:
|
||||
def attributes = createUserAttributes(username, email, firstname, lastname)
|
||||
def search = createSearchResult(attributes)
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
def result = userManager.createUser(search)
|
||||
|
||||
expect:
|
||||
|
||||
result.username == username
|
||||
result.email == email
|
||||
result.firstname == firstname
|
||||
result.lastname == lastname
|
||||
result.principal == principal
|
||||
}
|
||||
|
||||
def "Test successfully returning an Ldap user from a get user request"() {
|
||||
given:
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = userManager.getUser(username, createContext())
|
||||
|
||||
then:
|
||||
result.username == username
|
||||
result.email == email
|
||||
result.firstname == firstname
|
||||
result.lastname == lastname
|
||||
result.principal == principal
|
||||
}
|
||||
|
||||
def "Test successfully returning a list from get users"() {
|
||||
given:
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = userManager.getUsers(username, createContext())
|
||||
|
||||
then:
|
||||
result.size() == 1
|
||||
}
|
||||
|
||||
def "Test successfully returning a list from get users when no username is given"() {
|
||||
given:
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = userManager.getUsers(createContext())
|
||||
|
||||
then:
|
||||
result.size() == 1
|
||||
}
|
||||
|
||||
def "Test successfully throwing an exception when no users are found with getUser"() {
|
||||
given:
|
||||
|
||||
def searchUsersResults = new BasicNamingEnumerationImpl()
|
||||
|
||||
def context = Mock(LdapContext)
|
||||
context.search(_, _, _) >> searchUsersResults;
|
||||
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = userManager.getUser(username, context)
|
||||
|
||||
then:
|
||||
thrown NamingException
|
||||
}
|
||||
|
||||
def "Test successfully returning a NamingEnumeration from searchUsers"() {
|
||||
given:
|
||||
def userManager = new LdapUserManager(ldapConfiguration)
|
||||
|
||||
when:
|
||||
def result = userManager.searchUsers(createContext())
|
||||
|
||||
then:
|
||||
result.next().getName() + "," + ldapConfiguration.getBaseDn() == principal
|
||||
}
|
||||
|
||||
private def createContext() {
|
||||
|
||||
Attributes attributes = createUserAttributes(username, email, 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
|
||||
}
|
||||
}
|
||||
@ -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:
|
||||
LdapUserResponse response = new LdapUserResponse();
|
||||
when:
|
||||
response.setEmail("rmurphy@test.com");
|
||||
then:
|
||||
response.getEmail() == "rmurphy@test.com";
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse principal"() {
|
||||
given:
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when:
|
||||
response.setPrincipal("dc=cloudstack,dc=org")
|
||||
then:
|
||||
response.getPrincipal() == "dc=cloudstack,dc=org"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse username"() {
|
||||
given:
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when:
|
||||
response.setUsername("rmurphy")
|
||||
then:
|
||||
response.getUsername() == "rmurphy"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse firstname"() {
|
||||
given:
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when:
|
||||
response.setFirstname("Ryan")
|
||||
then:
|
||||
response.getFirstname() == "Ryan"
|
||||
}
|
||||
|
||||
def "Testing successful setting of LdapUserResponse lastname"() {
|
||||
given:
|
||||
LdapUserResponse response = new LdapUserResponse()
|
||||
when:
|
||||
response.setLastname("Murphy")
|
||||
then:
|
||||
response.getLastname() == "Murphy"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
// 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 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"]
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
@ -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 that a Ldap Search Filter is correctly escaped"() {
|
||||
given: "You have some input from a user"
|
||||
|
||||
expect: "That the input is escaped"
|
||||
LdapUtils.escapeLDAPSearchFilter(input) == result
|
||||
|
||||
where: "The following inputs are given "
|
||||
input | result
|
||||
"Hi This is a test #çà" | "Hi This is a test #çà"
|
||||
"Hi (This) = is * a \\ test # ç à ô \u0000" | "Hi \\28This\\29 = is \\2a a \\5c test # ç à ô \\00"
|
||||
}
|
||||
|
||||
def "Testing than an attribute is successfully returned"() {
|
||||
given: "You have an attributes object with some attribute"
|
||||
def attributes = Mock(Attributes)
|
||||
def attribute = Mock(Attribute)
|
||||
attribute.getId() >> name
|
||||
attribute.get() >> value
|
||||
attributes.get(name) >> attribute
|
||||
|
||||
when: "You get the attribute"
|
||||
String foundValue = LdapUtils.getAttributeValue(attributes, name)
|
||||
|
||||
then: "Its value equals uid"
|
||||
foundValue == value
|
||||
|
||||
where:
|
||||
name | value
|
||||
"uid" | "rmurphy"
|
||||
"email" | "rmurphy@test.com"
|
||||
}
|
||||
|
||||
def "Testing than an attribute is not successfully returned"() {
|
||||
given: "You have an attributes object with some attribute"
|
||||
def attributes = Mock(Attributes)
|
||||
attributes.get("uid") >> null
|
||||
|
||||
when: "You get the attribute"
|
||||
String foundValue = LdapUtils.getAttributeValue(attributes, "uid")
|
||||
|
||||
then: "Its value equals uid"
|
||||
foundValue == null
|
||||
}
|
||||
}
|
||||
@ -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,19 @@
|
||||
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=
|
||||
@ -78,7 +78,6 @@ import org.apache.cloudstack.api.response.LBHealthCheckPolicyResponse;
|
||||
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
|
||||
import org.apache.cloudstack.api.response.LBStickinessPolicyResponse;
|
||||
import org.apache.cloudstack.api.response.LBStickinessResponse;
|
||||
import org.apache.cloudstack.api.response.LDAPConfigResponse;
|
||||
import org.apache.cloudstack.api.response.LoadBalancerResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkACLItemResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkACLResponse;
|
||||
@ -2807,20 +2806,6 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
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();
|
||||
|
||||
@ -424,6 +424,16 @@ 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),
|
||||
|
||||
// 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),
|
||||
|
||||
@ -43,10 +43,7 @@ import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
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;
|
||||
@ -1542,175 +1539,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)
|
||||
|
||||
@ -87,8 +87,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;
|
||||
@ -2504,8 +2502,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);
|
||||
|
||||
@ -26,8 +26,6 @@ import javax.naming.ConfigurationException;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
|
||||
@ -87,8 +85,6 @@ import com.cloud.user.Account;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd;
|
||||
import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd;
|
||||
@ -383,33 +379,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)
|
||||
*/
|
||||
|
||||
@ -2142,11 +2142,26 @@ CREATE VIEW `cloud`.`project_view` AS
|
||||
left join
|
||||
`cloud`.`project_account` pacct ON projects.id = pacct.project_id;
|
||||
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.bind.principal', NULL, 'Specifies the bind principal to use for bind to LDAP');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.bind.password', NULL, 'Specifies the password to use for binding to LDAP');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.username.attribute', 'uid', 'Sets the username attribute used within LDAP');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.email.attribute', 'mail', 'Sets the email attribute used within LDAP');
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ldap.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');
|
||||
|
||||
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;
|
||||
|
||||
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'network.loadbalancer.haproxy.max.conn', '4096', 'Load Balancer(haproxy) maximum number of concurrent connections(global max)');
|
||||
|
||||
ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `concurrent_connections` int(10) unsigned COMMENT 'Load Balancer(haproxy) maximum number of concurrent connections(global max)';
|
||||
|
||||
|
||||
ALTER TABLE `cloud`.`sync_queue` MODIFY `queue_size` smallint(6) NOT NULL DEFAULT '0' COMMENT 'number of items being processed by the queue';
|
||||
ALTER TABLE `cloud`.`sync_queue` MODIFY `queue_size_limit` smallint(6) NOT NULL DEFAULT '1' COMMENT 'max number of items the queue can process concurrently';
|
||||
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -5834,7 +5834,7 @@ label.error {
|
||||
.multi-wizard .buttons {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 519px;
|
||||
bottom: 10px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
@ -12267,3 +12267,85 @@ 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 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 .select-container {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.accounts-wizard .input-area{
|
||||
width: 320px;
|
||||
font-size: 15px;
|
||||
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 .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: 10px;
|
||||
width: 278px;
|
||||
}
|
||||
|
||||
.manual-account-details select, .manual-account-details input {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.manual-account-details > *:nth-child(even) {
|
||||
background: #DFE1E3;
|
||||
}
|
||||
|
||||
.manual-account-details > *:nth-child(odd) {
|
||||
background: #F2F0F0;
|
||||
}
|
||||
|
||||
.manual-account-details .value {
|
||||
display: inline-block;
|
||||
}
|
||||
33
ui/index.jsp
33
ui/index.jsp
@ -469,6 +469,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">
|
||||
<div class="select-container ldap-account-choice">
|
||||
<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">
|
||||
<div class="button cancel"><span><fmt:message key="label.cancel"/></span></div>
|
||||
<div class="button next"><span><fmt:message key="label.add"/></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Zone wizard -->
|
||||
<div class="multi-wizard zone-wizard">
|
||||
<div class="progress">
|
||||
@ -1687,6 +1718,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,7 +76,7 @@
|
||||
return 'label.add.account';
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
createForm: {
|
||||
title: 'label.add.account',
|
||||
desc: 'label.add.account',
|
||||
@ -284,14 +284,21 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
*/
|
||||
notification: {
|
||||
poll: function(args) {
|
||||
args.complete({
|
||||
actionFilter: accountActionfilter
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
action: {
|
||||
custom: cloudStack.uiCustom.accountsWizard(
|
||||
cloudStack.accountsWizard
|
||||
)
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
158
ui/scripts/accountsWizard.js
Normal file
158
ui/scripts/accountsWizard.js
Normal file
@ -0,0 +1,158 @@
|
||||
// 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 = {
|
||||
|
||||
manuallyInputtedAccountInformation: {
|
||||
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: true
|
||||
},
|
||||
},
|
||||
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 = [];
|
||||
|
||||
array1.push("&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);
|
||||
}
|
||||
|
||||
console.log(array1.join(""));
|
||||
console.log(args.data);
|
||||
|
||||
$.ajax({
|
||||
url: createURL("ldapCreateAccount" + array1.join("")),
|
||||
dataType: "json",
|
||||
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).replace('&', '%26'));
|
||||
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',
|
||||
|
||||
116
ui/scripts/ui-custom/accountsWizard.js
Normal file
116
ui/scripts/ui-custom/accountsWizard.js
Normal file
@ -0,0 +1,116 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
(function($, cloudStack) {
|
||||
cloudStack.uiCustom.accountsWizard = function(args) {
|
||||
return function(listViewArgs) {
|
||||
var context = listViewArgs.context;
|
||||
|
||||
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);
|
||||
args.action({
|
||||
context: context,
|
||||
data: data,
|
||||
response: {
|
||||
success: function(args) {
|
||||
$('.list-view').listView('refresh');
|
||||
close();
|
||||
},
|
||||
error: function(message) {
|
||||
close();
|
||||
if(message) {
|
||||
cloudStack.dialog.notice({
|
||||
message: message
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$wizard.click(function(event) {
|
||||
var $target = $(event.target);
|
||||
if ($target.closest('div.button.next').size()) {
|
||||
$form.validate();
|
||||
if ($form.valid()) {
|
||||
completeAction();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($target.closest('div.button.cancel').size()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
var form = cloudStack.dialog.createForm({
|
||||
context: context,
|
||||
noDialog: true,
|
||||
form: {
|
||||
title: '',
|
||||
fields: args.manuallyInputtedAccountInformation
|
||||
}
|
||||
});
|
||||
|
||||
var $manualDetails = form.$formContainer.find('form .form-item');
|
||||
$wizard.find('.manual-account-details').append($manualDetails);
|
||||
|
||||
var $table = $wizard.find('.ldap-account-choice tbody');
|
||||
|
||||
$.ajax({
|
||||
url: createURL("listAllLdapUsers"),
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(json) {
|
||||
$(json.ldapuserresponse.LdapUser).each(function() {
|
||||
var result = $("<tr>");
|
||||
result.append("<td><input type=\"radio\" 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);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
return $wizard.dialog({
|
||||
title: _l('label.add.account'),
|
||||
width: 800,
|
||||
height: 500,
|
||||
closeOnEscape: false,
|
||||
zIndex: 5000
|
||||
}).closest('.ui-dialog').overlay();
|
||||
}
|
||||
|
||||
accountsWizard(args);
|
||||
};
|
||||
};
|
||||
})(jQuery, cloudStack);
|
||||
Loading…
x
Reference in New Issue
Block a user