mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge pull request #755 from karuturi/CLOUDSTACK-8647-2
Cloudstack:8647 LDAP Trust AD and AutoimportToday, CloudStack can automatically import LDAP users based on the configuration to a domain or an account. However, any new users in LDAP aren't automatically reflected. The admin has to manually import them again. This feature enables admin to map LDAP group/OU to a CloudStack domain and any changes are reflected in ACS as well. FS: https://cwiki.apache.org/confluence/display/CLOUDSTACK/WIP%3A+LDAP%3A+Trust+AD+and+Auto+Import testcases output: ``` ------------------------------------------------------- T E S T S ------------------------------------------------------- Running groovy.org.apache.cloudstack.ldap.NoLdapUserMatchingQueryExceptionSpec Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.216 sec - in groovy.org.apache.cloudstack.ldap.NoLdapUserMatchingQueryExceptionSpec Running groovy.org.apache.cloudstack.ldap.LdapManagerImplSpec log4j:WARN No appenders could be found for logger (org.apache.cloudstack.ldap.LdapManagerImpl). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. using type: using type: null using type: TEST using type: TEST TEST using name: using name: null using accountType: -1 using accountType: 1 using accountType: 3 using accountType: 4 using accountType: 5 using accountType: 6 using accountType: 20000 using accountType: -500000 Tests run: 29, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.387 sec - in groovy.org.apache.cloudstack.ldap.LdapManagerImplSpec Running groovy.org.apache.cloudstack.ldap.LdapListUsersCmdSpec Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.041 sec - in groovy.org.apache.cloudstack.ldap.LdapListUsersCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapAddConfigurationCmdSpec Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 sec - in groovy.org.apache.cloudstack.ldap.LdapAddConfigurationCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapUserSpec Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.021 sec - in groovy.org.apache.cloudstack.ldap.LdapUserSpec Running groovy.org.apache.cloudstack.ldap.LdapAuthenticatorSpec Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.082 sec - in groovy.org.apache.cloudstack.ldap.LdapAuthenticatorSpec Running groovy.org.apache.cloudstack.ldap.LdapConfigurationVOSpec Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 sec - in groovy.org.apache.cloudstack.ldap.LdapConfigurationVOSpec Running groovy.org.apache.cloudstack.ldap.OpenLdapUserManagerSpec Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.094 sec - in groovy.org.apache.cloudstack.ldap.OpenLdapUserManagerSpec Running groovy.org.apache.cloudstack.ldap.LdapDeleteConfigurationCmdSpec Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.008 sec - in groovy.org.apache.cloudstack.ldap.LdapDeleteConfigurationCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapUserResponseSpec Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec - in groovy.org.apache.cloudstack.ldap.LdapUserResponseSpec Running groovy.org.apache.cloudstack.ldap.LdapUserManagerFactorySpec Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 sec - in groovy.org.apache.cloudstack.ldap.LdapUserManagerFactorySpec Running groovy.org.apache.cloudstack.ldap.ADLdapUserManagerImplSpec Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 sec - in groovy.org.apache.cloudstack.ldap.ADLdapUserManagerImplSpec Running groovy.org.apache.cloudstack.ldap.LdapCreateAccountCmdSpec Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.168 sec - in groovy.org.apache.cloudstack.ldap.LdapCreateAccountCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapImportUsersCmdSpec Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.063 sec - in groovy.org.apache.cloudstack.ldap.LdapImportUsersCmdSpec Running groovy.org.apache.cloudstack.ldap.LinkDomainToLdapCmdSpec Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 sec - in groovy.org.apache.cloudstack.ldap.LinkDomainToLdapCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapSearchUserCmdSpec Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 sec - in groovy.org.apache.cloudstack.ldap.LdapSearchUserCmdSpec Running groovy.org.apache.cloudstack.ldap.LdapListConfigurationCmdSpec Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec - in groovy.org.apache.cloudstack.ldap.LdapListConfigurationCmdSpec Running groovy.org.apache.cloudstack.ldap.NoSuchLdapUserExceptionSpec Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec - in groovy.org.apache.cloudstack.ldap.NoSuchLdapUserExceptionSpec Running groovy.org.apache.cloudstack.ldap.LdapConfigurationResponseSpec Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 sec - in groovy.org.apache.cloudstack.ldap.LdapConfigurationResponseSpec Running groovy.org.apache.cloudstack.ldap.LdapConfigurationSpec asserting for provider configuration: openldap asserting for provider configuration: microsoftad asserting for provider configuration: asserting for provider configuration: asserting for provider configuration: xyz asserting for provider configuration: MicrosoftAd asserting for provider configuration: OpenLdap asserting for provider configuration: MicrosoftAD Tests run: 19, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.053 sec - in groovy.org.apache.cloudstack.ldap.LdapConfigurationSpec Running groovy.org.apache.cloudstack.ldap.LdapContextFactorySpec Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.099 sec - in groovy.org.apache.cloudstack.ldap.LdapContextFactorySpec Running groovy.org.apache.cloudstack.ldap.LdapConfigurationDaoImplSpec Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 sec - in groovy.org.apache.cloudstack.ldap.LdapConfigurationDaoImplSpec Running groovy.org.apache.cloudstack.ldap.LdapUtilsSpec Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec - in groovy.org.apache.cloudstack.ldap.LdapUtilsSpec Results : Tests run: 156, Failures: 0, Errors: 0, Skipped: 0 ``` * pr/755: CLOUDSTACK-8647: linkdomaintoldap shouldnt fail when createuseraccount fails CLOUDSTACK-8647 removed duplicate key in create sql of ldap_trust_map CLOUDSTACK-8647: string formatting CLOUDSTACK-8647: updated with review comments CLOUDSTACK-8647: unittests for LdapAuthenticatorSpec CLOUDSTACK-8647: formatted LdapAuthenticatorSpec CLOUDSTACK-8647: UI for trust AD feature CLOUDSTACK-8647 added unittests for new methods in ldapmanager CLOUDSTACK-8647 unittests for LinkDomainToLdap api command CLOUDSTACK-8647: fixed unittests CLOUDSTACK-8647 support for assigning and admin to linked ldap domain CLOUDSTACK-8647 added nested group enabled config in ldap CLOUDSTACK-8647 added account_type to the linkDomainToLdap API CLOUDSTACK-8647 changed the authentication flow CLOUDSTACK-8647 added new api linkLdapToDomain CLOUDSTACK-8647: added cmd and response class for the new api Signed-off-by: Rajani Karuturi <rajani.karuturi@citrix.com>
This commit is contained in:
commit
5881035e7b
@ -628,6 +628,8 @@ public class ApiConstants {
|
|||||||
public static final String OVM3_CLUSTER = "ovm3cluster";
|
public static final String OVM3_CLUSTER = "ovm3cluster";
|
||||||
public static final String OVM3_VIP = "ovm3vip";
|
public static final String OVM3_VIP = "ovm3vip";
|
||||||
|
|
||||||
|
public static final String ADMIN = "admin";
|
||||||
|
|
||||||
public enum HostDetails {
|
public enum HostDetails {
|
||||||
all, capacity, events, stats, min;
|
all, capacity, events, stats, min;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2133,6 +2133,10 @@ label.every=Every
|
|||||||
label.day=Day
|
label.day=Day
|
||||||
label.of.month=of month
|
label.of.month=of month
|
||||||
label.add.private.gateway=Add Private Gateway
|
label.add.private.gateway=Add Private Gateway
|
||||||
|
label.link.domain.to.ldap=Link Domain to LDAP
|
||||||
|
message.link.domain.to.ldap=Enable autosync for this domain in LDAP
|
||||||
|
label.ldap.link.type=Type
|
||||||
|
label.account.type=Account Type
|
||||||
message.desc.created.ssh.key.pair=Created a SSH Key Pair.
|
message.desc.created.ssh.key.pair=Created a SSH Key Pair.
|
||||||
message.please.confirm.remove.ssh.key.pair=Please confirm that you want to remove this SSH Key Pair
|
message.please.confirm.remove.ssh.key.pair=Please confirm that you want to remove this SSH Key Pair
|
||||||
message.password.has.been.reset.to=Password has been reset to
|
message.password.has.been.reset.to=Password has been reset to
|
||||||
|
|||||||
@ -771,6 +771,7 @@ deleteLdapConfiguration=3
|
|||||||
listLdapUsers=3
|
listLdapUsers=3
|
||||||
ldapCreateAccount=3
|
ldapCreateAccount=3
|
||||||
importLdapUsers=3
|
importLdapUsers=3
|
||||||
|
linkDomainToLdap=3
|
||||||
|
|
||||||
|
|
||||||
#### juniper-contrail commands
|
#### juniper-contrail commands
|
||||||
|
|||||||
@ -35,5 +35,6 @@
|
|||||||
<bean id="LdapConfigurationDao"
|
<bean id="LdapConfigurationDao"
|
||||||
class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
|
class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
|
||||||
<bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
|
<bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
|
||||||
|
<bean id="LdapTrustMapDao" class="org.apache.cloudstack.ldap.dao.LdapTrustMapDaoImpl" />
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.cloud.exception.InvalidParameterValueException;
|
||||||
|
import com.cloud.user.User;
|
||||||
|
import com.cloud.user.UserAccount;
|
||||||
|
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.DomainResponse;
|
||||||
|
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
|
||||||
|
import org.apache.cloudstack.ldap.LdapManager;
|
||||||
|
import org.apache.cloudstack.ldap.LdapUser;
|
||||||
|
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@APICommand(name = "linkDomainToLdap", description = "link an existing cloudstack domain to group or OU in ldap", responseObject = LinkDomainToLdapResponse.class, since = "4.6.0",
|
||||||
|
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||||
|
public class LinkDomainToLdapCmd extends BaseCmd {
|
||||||
|
public static final Logger s_logger = Logger.getLogger(LinkDomainToLdapCmd.class.getName());
|
||||||
|
private static final String s_name = "linkdomaintoldapresponse";
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "The id of the domain which has to be "
|
||||||
|
+ "linked to LDAP.")
|
||||||
|
private Long domainId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "type of the ldap name. GROUP or OU")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ADMIN, type = CommandType.STRING, required = false, description = "domain admin username in LDAP ")
|
||||||
|
private String admin;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account to auto import. Specify 0 for user and 2 for " +
|
||||||
|
"domain admin")
|
||||||
|
private short accountType;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private LdapManager _ldapManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws ServerApiException {
|
||||||
|
try {
|
||||||
|
LinkDomainToLdapResponse response = _ldapManager.linkDomainToLdap(domainId, type, name, accountType);
|
||||||
|
if(admin!=null) {
|
||||||
|
LdapUser ldapUser = null;
|
||||||
|
try {
|
||||||
|
ldapUser = _ldapManager.getUser(admin, type, name);
|
||||||
|
} catch (NoLdapUserMatchingQueryException e) {
|
||||||
|
s_logger.debug("no ldap user matching username " + admin + " in the given group/ou", e);
|
||||||
|
}
|
||||||
|
if (ldapUser != null && !ldapUser.isDisabled()) {
|
||||||
|
Account account = _accountService.getActiveAccountByName(admin, domainId);
|
||||||
|
if (account == null) {
|
||||||
|
try {
|
||||||
|
UserAccount userAccount = _accountService.createUserAccount(admin, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null,
|
||||||
|
admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId, admin, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
|
||||||
|
response.setAdminId(String.valueOf(userAccount.getAccountId()));
|
||||||
|
s_logger.info("created an account with name " + admin + " in the given domain " + domainId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.info("an exception occurred while creating account with name " + admin +" in domain " + domainId, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_logger.debug("an account with name " + admin + " already exists in the domain " + domainId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s_logger.debug("ldap user with username "+admin+" is disabled in the given group/ou");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.setObjectName("LinkDomainToLdap");
|
||||||
|
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,78 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cloudstack.api.response;
|
||||||
|
|
||||||
|
import com.cloud.serializer.Param;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
|
import org.apache.cloudstack.api.BaseResponse;
|
||||||
|
|
||||||
|
public class LinkDomainToLdapResponse extends BaseResponse {
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.DOMAIN_ID)
|
||||||
|
@Param(description = "id of the Domain which is linked to LDAP")
|
||||||
|
private long domainId;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.NAME)
|
||||||
|
@Param(description = "name of the group or OU in LDAP which is linked to the domain")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.TYPE)
|
||||||
|
@Param(description = "type of the name in LDAP which is linke to the domain")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ACCOUNT_TYPE)
|
||||||
|
@Param(description = "Type of the account to auto import")
|
||||||
|
private short accountType;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ACCOUNT_ID)
|
||||||
|
@Param(description = "Domain Admin accountId that is created")
|
||||||
|
private String adminId;
|
||||||
|
|
||||||
|
public LinkDomainToLdapResponse(long domainId, String type, String name, short accountType) {
|
||||||
|
this.domainId = domainId;
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.accountType = accountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDomainId() {
|
||||||
|
return domainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getAccountType() {
|
||||||
|
return accountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAdminId() {
|
||||||
|
return adminId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdminId(String adminId) {
|
||||||
|
this.adminId = adminId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,7 +32,8 @@ import org.apache.log4j.Logger;
|
|||||||
|
|
||||||
public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements LdapUserManager {
|
public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements LdapUserManager {
|
||||||
public static final Logger s_logger = Logger.getLogger(ADLdapUserManagerImpl.class.getName());
|
public static final Logger s_logger = Logger.getLogger(ADLdapUserManagerImpl.class.getName());
|
||||||
private static final String MICROSOFT_AD_NESTED_MEMBERS_FILTER = "memberOf:1.2.840.113556.1.4.1941";
|
private static final String MICROSOFT_AD_NESTED_MEMBERS_FILTER = "memberOf:1.2.840.113556.1.4.1941:";
|
||||||
|
private static final String MICROSOFT_AD_MEMBERS_FILTER = "memberOf";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException {
|
public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException {
|
||||||
@ -66,7 +67,7 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld
|
|||||||
|
|
||||||
final StringBuilder memberOfFilter = new StringBuilder();
|
final StringBuilder memberOfFilter = new StringBuilder();
|
||||||
String groupCnName = _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," + _ldapConfiguration.getBaseDn();
|
String groupCnName = _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," + _ldapConfiguration.getBaseDn();
|
||||||
memberOfFilter.append("(" + MICROSOFT_AD_NESTED_MEMBERS_FILTER + ":=");
|
memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
|
||||||
memberOfFilter.append(groupCnName);
|
memberOfFilter.append(groupCnName);
|
||||||
memberOfFilter.append(")");
|
memberOfFilter.append(")");
|
||||||
|
|
||||||
@ -79,4 +80,25 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld
|
|||||||
s_logger.debug("group search filter = " + result);
|
s_logger.debug("group search filter = " + result);
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isUserDisabled(SearchResult result) throws NamingException {
|
||||||
|
boolean isDisabledUser = false;
|
||||||
|
String userAccountControl = LdapUtils.getAttributeValue(result.getAttributes(), _ldapConfiguration.getUserAccountControlAttribute());
|
||||||
|
if (userAccountControl != null) {
|
||||||
|
int control = Integer.valueOf(userAccountControl);
|
||||||
|
// second bit represents disabled user flag in AD
|
||||||
|
if ((control & 2) > 0) {
|
||||||
|
isDisabledUser = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isDisabledUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getMemberOfAttribute() {
|
||||||
|
if(_ldapConfiguration.isNestedGroupsEnabled()) {
|
||||||
|
return MICROSOFT_AD_NESTED_MEMBERS_FILTER;
|
||||||
|
} else {
|
||||||
|
return MICROSOFT_AD_MEMBERS_FILTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,9 @@
|
|||||||
package org.apache.cloudstack.ldap;
|
package org.apache.cloudstack.ldap;
|
||||||
|
|
||||||
import com.cloud.server.auth.DefaultUserAuthenticator;
|
import com.cloud.server.auth.DefaultUserAuthenticator;
|
||||||
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.user.AccountManager;
|
||||||
|
import com.cloud.user.User;
|
||||||
import com.cloud.user.UserAccount;
|
import com.cloud.user.UserAccount;
|
||||||
import com.cloud.user.dao.UserAccountDao;
|
import com.cloud.user.dao.UserAccountDao;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
@ -25,6 +28,7 @@ import org.apache.log4j.Logger;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class LdapAuthenticator extends DefaultUserAuthenticator {
|
public class LdapAuthenticator extends DefaultUserAuthenticator {
|
||||||
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
|
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
|
||||||
@ -33,6 +37,8 @@ public class LdapAuthenticator extends DefaultUserAuthenticator {
|
|||||||
private LdapManager _ldapManager;
|
private LdapManager _ldapManager;
|
||||||
@Inject
|
@Inject
|
||||||
private UserAccountDao _userAccountDao;
|
private UserAccountDao _userAccountDao;
|
||||||
|
@Inject
|
||||||
|
private AccountManager _accountManager;
|
||||||
|
|
||||||
public LdapAuthenticator() {
|
public LdapAuthenticator() {
|
||||||
super();
|
super();
|
||||||
@ -52,21 +58,71 @@ public class LdapAuthenticator extends DefaultUserAuthenticator {
|
|||||||
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
|
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
boolean result = false;
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
|
||||||
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
|
|
||||||
} else if (_ldapManager.isLdapEnabled()) {
|
|
||||||
boolean result = _ldapManager.canAuthenticate(username, password);
|
|
||||||
ActionOnFailedAuthentication action = null;
|
ActionOnFailedAuthentication action = null;
|
||||||
if (result == false) {
|
|
||||||
action = ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT;
|
if (_ldapManager.isLdapEnabled()) {
|
||||||
|
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||||
|
LdapTrustMapVO ldapTrustMapVO = _ldapManager.getDomainLinkedToLdap(domainId);
|
||||||
|
if(ldapTrustMapVO != null) {
|
||||||
|
try {
|
||||||
|
LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName());
|
||||||
|
if(!ldapUser.isDisabled()) {
|
||||||
|
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
|
||||||
|
if(result) {
|
||||||
|
if(user == null) {
|
||||||
|
// import user to cloudstack
|
||||||
|
createCloudStackUserAccount(ldapUser, domainId, ldapTrustMapVO.getAccountType());
|
||||||
|
} else {
|
||||||
|
enableUserInCloudStack(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//disable user in cloudstack
|
||||||
|
disableUserInCloudStack(user);
|
||||||
|
}
|
||||||
|
} catch (NoLdapUserMatchingQueryException e) {
|
||||||
|
s_logger.debug(e.getMessage());
|
||||||
}
|
}
|
||||||
return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return new Pair<Boolean, ActionOnFailedAuthentication>(false, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
|
//domain is not linked to ldap follow normal authentication
|
||||||
|
if(user != null ) {
|
||||||
|
try {
|
||||||
|
LdapUser ldapUser = _ldapManager.getUser(username);
|
||||||
|
if(!ldapUser.isDisabled()) {
|
||||||
|
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
|
||||||
|
} else {
|
||||||
|
s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
|
||||||
|
}
|
||||||
|
} catch (NoLdapUserMatchingQueryException e) {
|
||||||
|
s_logger.debug(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!result && user != null) {
|
||||||
|
action = ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableUserInCloudStack(UserAccount user) {
|
||||||
|
if(user != null && (user.getState().equalsIgnoreCase(Account.State.disabled.toString()))) {
|
||||||
|
_accountManager.enableUser(user.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCloudStackUserAccount(LdapUser user, long domainId, short accountType) {
|
||||||
|
String username = user.getUsername();
|
||||||
|
_accountManager.createUserAccount(username, "", user.getFirstname(), user.getLastname(), user.getEmail(), null, username, accountType, domainId, username, null,
|
||||||
|
UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableUserInCloudStack(UserAccount user) {
|
||||||
|
if (user != null) {
|
||||||
|
_accountManager.disableUser(user.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,9 @@ public class LdapConfiguration implements Configurable{
|
|||||||
private static final ConfigKey<String> ldapProvider = new ConfigKey<String>(String.class, "ldap.provider", "Advanced", "openldap", "ldap provider ex:openldap, microsoftad",
|
private static final ConfigKey<String> ldapProvider = new ConfigKey<String>(String.class, "ldap.provider", "Advanced", "openldap", "ldap provider ex:openldap, microsoftad",
|
||||||
true, ConfigKey.Scope.Global, null);
|
true, ConfigKey.Scope.Global, null);
|
||||||
|
|
||||||
|
private static final ConfigKey<Boolean> ldapEnableNestedGroups = new ConfigKey<Boolean>(Boolean.class, "ldap.nested.groups.enable", "Advanced", "true",
|
||||||
|
"if true, nested groups will also be queried", true, ConfigKey.Scope.Global, null);
|
||||||
|
|
||||||
private final static int scope = SearchControls.SUBTREE_SCOPE;
|
private final static int scope = SearchControls.SUBTREE_SCOPE;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@ -108,7 +111,8 @@ public class LdapConfiguration implements Configurable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String[] getReturnAttributes() {
|
public String[] getReturnAttributes() {
|
||||||
return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute()};
|
return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute(),
|
||||||
|
getUserAccountControlAttribute()};
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScope() {
|
public int getScope() {
|
||||||
@ -159,6 +163,10 @@ public class LdapConfiguration implements Configurable{
|
|||||||
return "cn";
|
return "cn";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUserAccountControlAttribute() {
|
||||||
|
return "userAccountControl";
|
||||||
|
}
|
||||||
|
|
||||||
public Long getReadTimeout() {
|
public Long getReadTimeout() {
|
||||||
return ldapReadTimeout.value();
|
return ldapReadTimeout.value();
|
||||||
}
|
}
|
||||||
@ -178,6 +186,10 @@ public class LdapConfiguration implements Configurable{
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isNestedGroupsEnabled() {
|
||||||
|
return ldapEnableNestedGroups.value();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigComponentName() {
|
public String getConfigComponentName() {
|
||||||
return LdapConfiguration.class.getSimpleName();
|
return LdapConfiguration.class.getSimpleName();
|
||||||
@ -185,6 +197,6 @@ public class LdapConfiguration implements Configurable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigKey<?>[] getConfigKeys() {
|
public ConfigKey<?>[] getConfigKeys() {
|
||||||
return new ConfigKey<?>[] {ldapReadTimeout, ldapPageSize, ldapProvider};
|
return new ConfigKey<?>[] {ldapReadTimeout, ldapPageSize, ldapProvider, ldapEnableNestedGroups};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,12 +25,15 @@ import org.apache.cloudstack.api.response.LdapUserResponse;
|
|||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.component.PluggableService;
|
import com.cloud.utils.component.PluggableService;
|
||||||
|
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
|
||||||
|
|
||||||
public interface LdapManager extends PluggableService {
|
public interface LdapManager extends PluggableService {
|
||||||
|
|
||||||
|
enum LinkType { GROUP, OU;}
|
||||||
|
|
||||||
LdapConfigurationResponse addConfiguration(String hostname, int port) throws InvalidParameterValueException;
|
LdapConfigurationResponse addConfiguration(String hostname, int port) throws InvalidParameterValueException;
|
||||||
|
|
||||||
boolean canAuthenticate(String username, String password);
|
boolean canAuthenticate(String principal, String password);
|
||||||
|
|
||||||
LdapConfigurationResponse createLdapConfigurationResponse(LdapConfigurationVO configuration);
|
LdapConfigurationResponse createLdapConfigurationResponse(LdapConfigurationVO configuration);
|
||||||
|
|
||||||
@ -40,6 +43,8 @@ public interface LdapManager extends PluggableService {
|
|||||||
|
|
||||||
LdapUser getUser(final String username) throws NoLdapUserMatchingQueryException;
|
LdapUser getUser(final String username) throws NoLdapUserMatchingQueryException;
|
||||||
|
|
||||||
|
LdapUser getUser(String username, String type, String name) throws NoLdapUserMatchingQueryException;
|
||||||
|
|
||||||
List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
|
List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException;
|
||||||
|
|
||||||
List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException;
|
List<LdapUser> getUsersInGroup(String groupName) throws NoLdapUserMatchingQueryException;
|
||||||
@ -49,4 +54,8 @@ public interface LdapManager extends PluggableService {
|
|||||||
Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(LdapListConfigurationCmd cmd);
|
Pair<List<? extends LdapConfigurationVO>, Integer> listConfigurations(LdapListConfigurationCmd cmd);
|
||||||
|
|
||||||
List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
|
List<LdapUser> searchUsers(String query) throws NoLdapUserMatchingQueryException;
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType);
|
||||||
|
|
||||||
|
public LdapTrustMapVO getDomainLinkedToLdap(long domainId);
|
||||||
}
|
}
|
||||||
@ -25,6 +25,10 @@ import javax.inject.Inject;
|
|||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.naming.ldap.LdapContext;
|
import javax.naming.ldap.LdapContext;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.command.LinkDomainToLdapCmd;
|
||||||
|
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
|
||||||
|
import org.apache.cloudstack.ldap.dao.LdapTrustMapDao;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -61,6 +65,9 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
|
|
||||||
@Inject LdapUserManagerFactory _ldapUserManagerFactory;
|
@Inject LdapUserManagerFactory _ldapUserManagerFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LdapTrustMapDao _ldapTrustMapDao;
|
||||||
|
|
||||||
|
|
||||||
public LdapManagerImpl() {
|
public LdapManagerImpl() {
|
||||||
super();
|
super();
|
||||||
@ -99,17 +106,14 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canAuthenticate(final String username, final String password) {
|
public boolean canAuthenticate(final String principal, final String password) {
|
||||||
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
|
|
||||||
try {
|
try {
|
||||||
final LdapUser user = getUser(escapedUsername);
|
|
||||||
final String principal = user.getPrincipal();
|
|
||||||
final LdapContext context = _ldapContextFactory.createUserContext(principal, password);
|
final LdapContext context = _ldapContextFactory.createUserContext(principal, password);
|
||||||
closeContext(context);
|
closeContext(context);
|
||||||
return true;
|
return true;
|
||||||
} catch (NamingException | IOException | NoLdapUserMatchingQueryException e) {
|
} catch (NamingException | IOException e) {
|
||||||
s_logger.debug("Exception while doing an LDAP bind for user "+" "+username, e);
|
s_logger.debug("Exception while doing an LDAP bind for user "+" "+principal, e);
|
||||||
s_logger.info("Failed to authenticate user: " + username + ". incorrect password.");
|
s_logger.info("Failed to authenticate user: " + principal + ". incorrect password.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +124,7 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
} catch (final NamingException e) {
|
} catch (final NamingException e) {
|
||||||
s_logger.warn(e.getMessage(),e);
|
s_logger.warn(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +172,7 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
cmdList.add(LdapImportUsersCmd.class);
|
cmdList.add(LdapImportUsersCmd.class);
|
||||||
cmdList.add(LDAPConfigCmd.class);
|
cmdList.add(LDAPConfigCmd.class);
|
||||||
cmdList.add(LDAPRemoveCmd.class);
|
cmdList.add(LDAPRemoveCmd.class);
|
||||||
|
cmdList.add(LinkDomainToLdapCmd.class);
|
||||||
return cmdList;
|
return cmdList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +193,21 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LdapUser getUser(final String username, final String type, final String name) throws NoLdapUserMatchingQueryException {
|
||||||
|
LdapContext context = null;
|
||||||
|
try {
|
||||||
|
context = _ldapContextFactory.createBindContext();
|
||||||
|
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
|
||||||
|
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider()).getUser(escapedUsername, type, name, context);
|
||||||
|
} catch (NamingException | IOException e) {
|
||||||
|
s_logger.debug("ldap Exception: ",e);
|
||||||
|
throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username + "name: " + name + "of type: " + type);
|
||||||
|
} finally {
|
||||||
|
closeContext(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException {
|
public List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException {
|
||||||
LdapContext context = null;
|
LdapContext context = null;
|
||||||
@ -243,4 +263,22 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
|||||||
closeContext(context);
|
closeContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LinkDomainToLdapResponse linkDomainToLdap(Long domainId, String type, String name, short accountType) {
|
||||||
|
Validate.notNull(type, "type cannot be null. It should either be GROUP or OU");
|
||||||
|
Validate.notNull(domainId, "domainId cannot be null.");
|
||||||
|
Validate.notEmpty(name, "GROUP or OU name cannot be empty");
|
||||||
|
//Account type should be 0 or 2. check the constants in com.cloud.user.Account
|
||||||
|
Validate.isTrue(accountType==0 || accountType==2, "accountype should be either 0(normal user) or 2(domain admin)");
|
||||||
|
LinkType linkType = LdapManager.LinkType.valueOf(type.toUpperCase());
|
||||||
|
LdapTrustMapVO vo = _ldapTrustMapDao.persist(new LdapTrustMapVO(domainId, linkType, name, accountType));
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(vo.getDomainId(), vo.getType().toString(), vo.getName(), vo.getAccountType());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LdapTrustMapVO getDomainLinkedToLdap(long domainId){
|
||||||
|
return _ldapTrustMapDao.findByDomainId(domainId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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_trust_map")
|
||||||
|
public class LdapTrustMapVO implements InternalIdentity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "type")
|
||||||
|
private LdapManager.LinkType type;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "domain_id")
|
||||||
|
private long domainId;
|
||||||
|
|
||||||
|
@Column(name = "account_type")
|
||||||
|
private short accountType;
|
||||||
|
|
||||||
|
|
||||||
|
public LdapTrustMapVO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LdapTrustMapVO(long domainId, LdapManager.LinkType type, String name, short accountType) {
|
||||||
|
this.domainId = domainId;
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.accountType = accountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LdapManager.LinkType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDomainId() {
|
||||||
|
return domainId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getAccountType() {
|
||||||
|
return accountType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LdapTrustMapVO that = (LdapTrustMapVO) o;
|
||||||
|
|
||||||
|
if (domainId != that.domainId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (accountType != that.accountType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type != that.type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return name.equals(that.name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = type.hashCode();
|
||||||
|
result = 31 * result + name.hashCode();
|
||||||
|
result = 31 * result + (int) (domainId ^ (domainId >>> 32));
|
||||||
|
result = 31 * result + (int) accountType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,14 +23,16 @@ public class LdapUser implements Comparable<LdapUser> {
|
|||||||
private final String lastname;
|
private final String lastname;
|
||||||
private final String username;
|
private final String username;
|
||||||
private final String domain;
|
private final String domain;
|
||||||
|
private final boolean disabled;
|
||||||
|
|
||||||
public LdapUser(final String username, final String email, final String firstname, final String lastname, final String principal, String domain) {
|
public LdapUser(final String username, final String email, final String firstname, final String lastname, final String principal, String domain, boolean disabled) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.firstname = firstname;
|
this.firstname = firstname;
|
||||||
this.lastname = lastname;
|
this.lastname = lastname;
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
|
this.disabled = disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,6 +76,11 @@ public class LdapUser implements Comparable<LdapUser> {
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return getUsername().hashCode();
|
return getUsername().hashCode();
|
||||||
|
|||||||
@ -32,6 +32,8 @@ public interface LdapUserManager {
|
|||||||
|
|
||||||
public LdapUser getUser(final String username, final LdapContext context) throws NamingException, IOException;
|
public LdapUser getUser(final String username, final LdapContext context) throws NamingException, IOException;
|
||||||
|
|
||||||
|
public LdapUser getUser(final String username, final String type, final String name, final LdapContext context) throws NamingException, IOException;
|
||||||
|
|
||||||
public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException;
|
public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException;
|
||||||
|
|
||||||
public List<LdapUser> getUsers(final String username, final LdapContext context) throws NamingException, IOException;
|
public List<LdapUser> getUsers(final String username, final LdapContext context) throws NamingException, IOException;
|
||||||
|
|||||||
@ -63,7 +63,9 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
|||||||
domain = domain.replace("," + _ldapConfiguration.getBaseDn(), "");
|
domain = domain.replace("," + _ldapConfiguration.getBaseDn(), "");
|
||||||
domain = domain.replace("ou=", "");
|
domain = domain.replace("ou=", "");
|
||||||
|
|
||||||
return new LdapUser(username, email, firstname, lastname, principal, domain);
|
boolean disabled = isUserDisabled(result);
|
||||||
|
|
||||||
|
return new LdapUser(username, email, firstname, lastname, principal, domain, disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateSearchFilter(final String username) {
|
private String generateSearchFilter(final String username) {
|
||||||
@ -128,6 +130,48 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LdapUser getUser(final String username, final String type, final String name, final LdapContext context) throws NamingException, IOException {
|
||||||
|
String basedn;
|
||||||
|
if("OU".equals(type)) {
|
||||||
|
basedn = name;
|
||||||
|
} else {
|
||||||
|
basedn = _ldapConfiguration.getBaseDn();
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder userObjectFilter = new StringBuilder();
|
||||||
|
userObjectFilter.append("(objectClass=");
|
||||||
|
userObjectFilter.append(_ldapConfiguration.getUserObject());
|
||||||
|
userObjectFilter.append(")");
|
||||||
|
|
||||||
|
final StringBuilder usernameFilter = new StringBuilder();
|
||||||
|
usernameFilter.append("(");
|
||||||
|
usernameFilter.append(_ldapConfiguration.getUsernameAttribute());
|
||||||
|
usernameFilter.append("=");
|
||||||
|
usernameFilter.append((username == null ? "*" : username));
|
||||||
|
usernameFilter.append(")");
|
||||||
|
|
||||||
|
final StringBuilder memberOfFilter = new StringBuilder();
|
||||||
|
if ("GROUP".equals(type)) {
|
||||||
|
memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
|
||||||
|
memberOfFilter.append(name);
|
||||||
|
memberOfFilter.append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder searchQuery = new StringBuilder();
|
||||||
|
searchQuery.append("(&");
|
||||||
|
searchQuery.append(userObjectFilter);
|
||||||
|
searchQuery.append(usernameFilter);
|
||||||
|
searchQuery.append(memberOfFilter);
|
||||||
|
searchQuery.append(")");
|
||||||
|
|
||||||
|
return searchUser(basedn, searchQuery.toString(), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getMemberOfAttribute() {
|
||||||
|
return "memberof";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException {
|
public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException {
|
||||||
return getUsers(null, context);
|
return getUsers(null, context);
|
||||||
@ -191,6 +235,30 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
|||||||
return searchUsers(null, context);
|
return searchUsers(null, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isUserDisabled(SearchResult result) throws NamingException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LdapUser searchUser(final String basedn, final String searchString, final LdapContext context) throws NamingException, IOException {
|
||||||
|
final SearchControls searchControls = new SearchControls();
|
||||||
|
|
||||||
|
searchControls.setSearchScope(_ldapConfiguration.getScope());
|
||||||
|
searchControls.setReturningAttributes(_ldapConfiguration.getReturnAttributes());
|
||||||
|
|
||||||
|
NamingEnumeration<SearchResult> results = context.search(basedn, searchString, searchControls);
|
||||||
|
final List<LdapUser> users = new ArrayList<LdapUser>();
|
||||||
|
while (results.hasMoreElements()) {
|
||||||
|
final SearchResult result = results.nextElement();
|
||||||
|
users.add(createUser(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (users.size() == 1) {
|
||||||
|
return users.get(0);
|
||||||
|
} else {
|
||||||
|
throw new NamingException("No user found for basedn " + basedn + " and searchString " + searchString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<LdapUser> searchUsers(final String username, final LdapContext context) throws NamingException, IOException {
|
public List<LdapUser> searchUsers(final String username, final LdapContext context) throws NamingException, IOException {
|
||||||
|
|
||||||
@ -212,8 +280,10 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
|||||||
results = context.search(basedn, generateSearchFilter(username), searchControls);
|
results = context.search(basedn, generateSearchFilter(username), searchControls);
|
||||||
while (results.hasMoreElements()) {
|
while (results.hasMoreElements()) {
|
||||||
final SearchResult result = results.nextElement();
|
final SearchResult result = results.nextElement();
|
||||||
|
if (!isUserDisabled(result)) {
|
||||||
users.add(createUser(result));
|
users.add(createUser(result));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Control[] contextControls = context.getResponseControls();
|
Control[] contextControls = context.getResponseControls();
|
||||||
if (contextControls != null) {
|
if (contextControls != null) {
|
||||||
for (Control control : contextControls) {
|
for (Control control : contextControls) {
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.apache.cloudstack.ldap.LdapTrustMapVO;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface LdapTrustMapDao extends GenericDao<LdapTrustMapVO, Long> {
|
||||||
|
LdapTrustMapVO findByDomainId(long domainId);
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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 javax.ejb.Local;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import org.apache.cloudstack.ldap.LdapTrustMapVO;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Local(value = {LdapTrustMapDao.class})
|
||||||
|
public class LdapTrustMapDaoImpl extends GenericDaoBase<LdapTrustMapVO, Long> implements LdapTrustMapDao {
|
||||||
|
private final SearchBuilder<LdapTrustMapVO> domainIdSearch;
|
||||||
|
|
||||||
|
public LdapTrustMapDaoImpl() {
|
||||||
|
super();
|
||||||
|
domainIdSearch = createSearchBuilder();
|
||||||
|
domainIdSearch.and("domainId", domainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ);
|
||||||
|
domainIdSearch.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LdapTrustMapVO findByDomainId(long domainId) {
|
||||||
|
final SearchCriteria<LdapTrustMapVO> sc = domainIdSearch.create();
|
||||||
|
sc.setParameters("domainId", domainId);
|
||||||
|
return findOneBy(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,10 +39,11 @@ class ADLdapUserManagerImplSpec extends spock.lang.Specification {
|
|||||||
adLdapUserManager._ldapConfiguration = ldapConfiguration;
|
adLdapUserManager._ldapConfiguration = ldapConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
def "test generate AD search filter"() {
|
def "test generate AD search filter with nested groups enabled"() {
|
||||||
ldapConfiguration.getUserObject() >> "user"
|
ldapConfiguration.getUserObject() >> "user"
|
||||||
ldapConfiguration.getCommonNameAttribute() >> "CN"
|
ldapConfiguration.getCommonNameAttribute() >> "CN"
|
||||||
ldapConfiguration.getBaseDn() >> "DC=cloud,DC=citrix,DC=com"
|
ldapConfiguration.getBaseDn() >> "DC=cloud,DC=citrix,DC=com"
|
||||||
|
ldapConfiguration.isNestedGroupsEnabled() >> true
|
||||||
|
|
||||||
def result = adLdapUserManager.generateADGroupSearchFilter(group);
|
def result = adLdapUserManager.generateADGroupSearchFilter(group);
|
||||||
expect:
|
expect:
|
||||||
@ -52,6 +53,20 @@ class ADLdapUserManagerImplSpec extends spock.lang.Specification {
|
|||||||
group << ["dev", "dev-hyd"]
|
group << ["dev", "dev-hyd"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "test generate AD search filter with nested groups disabled"() {
|
||||||
|
ldapConfiguration.getUserObject() >> "user"
|
||||||
|
ldapConfiguration.getCommonNameAttribute() >> "CN"
|
||||||
|
ldapConfiguration.getBaseDn() >> "DC=cloud,DC=citrix,DC=com"
|
||||||
|
ldapConfiguration.isNestedGroupsEnabled() >> false
|
||||||
|
|
||||||
|
def result = adLdapUserManager.generateADGroupSearchFilter(group);
|
||||||
|
expect:
|
||||||
|
assert result.contains("memberOf=")
|
||||||
|
result == "(&(objectClass=user)(memberOf=CN=" + group + ",DC=cloud,DC=citrix,DC=com))"
|
||||||
|
where:
|
||||||
|
group << ["dev", "dev-hyd"]
|
||||||
|
}
|
||||||
|
|
||||||
def "test getUsersInGroup null group"() {
|
def "test getUsersInGroup null group"() {
|
||||||
ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
|
ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
|
||||||
ldapConfiguration.getReturnAttributes() >> ["username", "firstname", "lastname", "email"]
|
ldapConfiguration.getReturnAttributes() >> ["username", "firstname", "lastname", "email"]
|
||||||
|
|||||||
@ -16,12 +16,18 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package groovy.org.apache.cloudstack.ldap
|
package groovy.org.apache.cloudstack.ldap
|
||||||
|
|
||||||
|
import com.cloud.server.auth.UserAuthenticator
|
||||||
|
import com.cloud.user.Account
|
||||||
|
import com.cloud.user.AccountManager
|
||||||
|
import com.cloud.user.User
|
||||||
|
import com.cloud.user.UserAccount
|
||||||
import com.cloud.user.UserAccountVO
|
import com.cloud.user.UserAccountVO
|
||||||
import com.cloud.user.dao.UserAccountDao
|
import com.cloud.user.dao.UserAccountDao
|
||||||
import com.cloud.utils.Pair
|
import com.cloud.utils.Pair
|
||||||
import org.apache.cloudstack.ldap.LdapAuthenticator
|
import org.apache.cloudstack.ldap.LdapAuthenticator
|
||||||
import org.apache.cloudstack.ldap.LdapConfigurationVO
|
|
||||||
import org.apache.cloudstack.ldap.LdapManager
|
import org.apache.cloudstack.ldap.LdapManager
|
||||||
|
import org.apache.cloudstack.ldap.LdapTrustMapVO
|
||||||
|
import org.apache.cloudstack.ldap.LdapUser
|
||||||
|
|
||||||
class LdapAuthenticatorSpec extends spock.lang.Specification {
|
class LdapAuthenticatorSpec extends spock.lang.Specification {
|
||||||
|
|
||||||
@ -40,7 +46,10 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
|
|||||||
def "Test failed authentication due to ldap bind being unsuccessful"() {
|
def "Test failed authentication due to ldap bind being unsuccessful"() {
|
||||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
|
def ldapUser = Mock(LdapUser)
|
||||||
|
ldapUser.isDisabled() >> false
|
||||||
ldapManager.isLdapEnabled() >> true
|
ldapManager.isLdapEnabled() >> true
|
||||||
|
ldapManager.getUser("rmurphy") >> ldapUser
|
||||||
ldapManager.canAuthenticate(_, _) >> false
|
ldapManager.canAuthenticate(_, _) >> false
|
||||||
|
|
||||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
@ -72,8 +81,11 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
|
|||||||
def "Test successful authentication"() {
|
def "Test successful authentication"() {
|
||||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
|
def ldapUser = Mock(LdapUser)
|
||||||
|
ldapUser.isDisabled() >> false
|
||||||
ldapManager.isLdapEnabled() >> true
|
ldapManager.isLdapEnabled() >> true
|
||||||
ldapManager.canAuthenticate(_, _) >> true
|
ldapManager.canAuthenticate(_, _) >> true
|
||||||
|
ldapManager.getUser("rmurphy") >> ldapUser
|
||||||
|
|
||||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||||
@ -96,4 +108,142 @@ class LdapAuthenticatorSpec extends spock.lang.Specification {
|
|||||||
then: "it doesn't change"
|
then: "it doesn't change"
|
||||||
result == "password"
|
result == "password"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "test authentication when ldap is disabled"(){
|
||||||
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
|
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||||
|
ldapManager.isLdapEnabled() >> false
|
||||||
|
|
||||||
|
when:
|
||||||
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate("rajanik", "password", 1, null)
|
||||||
|
then:
|
||||||
|
result.first() == false
|
||||||
|
result.second() == null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// tests when domain is linked to LDAP
|
||||||
|
def "test authentication when domain is linked and user disabled in ldap"(){
|
||||||
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
|
AccountManager accountManager = Mock(AccountManager)
|
||||||
|
|
||||||
|
def ldapAuthenticator = new LdapAuthenticator()
|
||||||
|
ldapAuthenticator._ldapManager = ldapManager
|
||||||
|
ldapAuthenticator._userAccountDao = userAccountDao
|
||||||
|
ldapAuthenticator._accountManager = accountManager
|
||||||
|
|
||||||
|
long domainId = 1;
|
||||||
|
String username = "rajanik"
|
||||||
|
LdapManager.LinkType type = LdapManager.LinkType.GROUP
|
||||||
|
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapManager.isLdapEnabled() >> true
|
||||||
|
UserAccount userAccount = Mock(UserAccount)
|
||||||
|
userAccountDao.getUserAccount(username, domainId) >> userAccount
|
||||||
|
userAccount.getId() >> 1
|
||||||
|
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
|
||||||
|
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true)
|
||||||
|
//user should be disabled in cloudstack
|
||||||
|
accountManager.disableUser(1) >> userAccount
|
||||||
|
|
||||||
|
when:
|
||||||
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
|
||||||
|
then:
|
||||||
|
result.first() == false
|
||||||
|
result.second() == UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test authentication when domain is linked and first time user can authenticate in ldap"(){
|
||||||
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
|
AccountManager accountManager = Mock(AccountManager)
|
||||||
|
|
||||||
|
def ldapAuthenticator = new LdapAuthenticator()
|
||||||
|
ldapAuthenticator._ldapManager = ldapManager
|
||||||
|
ldapAuthenticator._userAccountDao = userAccountDao
|
||||||
|
ldapAuthenticator._accountManager = accountManager
|
||||||
|
|
||||||
|
long domainId = 1;
|
||||||
|
String username = "rajanik"
|
||||||
|
LdapManager.LinkType type = LdapManager.LinkType.GROUP
|
||||||
|
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapManager.isLdapEnabled() >> true
|
||||||
|
userAccountDao.getUserAccount(username, domainId) >> null
|
||||||
|
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)0)
|
||||||
|
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
|
||||||
|
ldapManager.canAuthenticate(_,_) >> true
|
||||||
|
//user should be created in cloudstack
|
||||||
|
accountManager.createUserAccount(username, "", "firstname", "lastname", "email", null, username, (short) 2, domainId, username, null, _, _, User.Source.LDAP) >> Mock(UserAccount)
|
||||||
|
|
||||||
|
when:
|
||||||
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
|
||||||
|
then:
|
||||||
|
result.first() == true
|
||||||
|
result.second() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test authentication when domain is linked and existing user can authenticate in ldap"(){
|
||||||
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
|
AccountManager accountManager = Mock(AccountManager)
|
||||||
|
|
||||||
|
def ldapAuthenticator = new LdapAuthenticator()
|
||||||
|
ldapAuthenticator._ldapManager = ldapManager
|
||||||
|
ldapAuthenticator._userAccountDao = userAccountDao
|
||||||
|
ldapAuthenticator._accountManager = accountManager
|
||||||
|
|
||||||
|
long domainId = 1;
|
||||||
|
String username = "rajanik"
|
||||||
|
LdapManager.LinkType type = LdapManager.LinkType.GROUP
|
||||||
|
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapManager.isLdapEnabled() >> true
|
||||||
|
UserAccount userAccount = Mock(UserAccount)
|
||||||
|
userAccountDao.getUserAccount(username, domainId) >> userAccount
|
||||||
|
userAccount.getId() >> 1
|
||||||
|
userAccount.getState() >> Account.State.disabled.toString()
|
||||||
|
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
|
||||||
|
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
|
||||||
|
ldapManager.canAuthenticate(_,_) >> true
|
||||||
|
//user should be enabled in cloudstack if disabled
|
||||||
|
accountManager.enableUser(1) >> userAccount
|
||||||
|
|
||||||
|
when:
|
||||||
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
|
||||||
|
then:
|
||||||
|
result.first() == true
|
||||||
|
result.second() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test authentication when domain is linked and user cannot authenticate in ldap"(){
|
||||||
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
|
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||||
|
AccountManager accountManager = Mock(AccountManager)
|
||||||
|
|
||||||
|
def ldapAuthenticator = new LdapAuthenticator()
|
||||||
|
ldapAuthenticator._ldapManager = ldapManager
|
||||||
|
ldapAuthenticator._userAccountDao = userAccountDao
|
||||||
|
ldapAuthenticator._accountManager = accountManager
|
||||||
|
|
||||||
|
long domainId = 1;
|
||||||
|
String username = "rajanik"
|
||||||
|
LdapManager.LinkType type = LdapManager.LinkType.GROUP
|
||||||
|
String name = "CN=test,DC=ccp,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapManager.isLdapEnabled() >> true
|
||||||
|
UserAccount userAccount = Mock(UserAccount)
|
||||||
|
userAccountDao.getUserAccount(username, domainId) >> userAccount
|
||||||
|
ldapManager.getDomainLinkedToLdap(domainId) >> new LdapTrustMapVO(domainId, type, name, (short)2)
|
||||||
|
ldapManager.getUser(username, type.toString(), name) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
|
||||||
|
ldapManager.canAuthenticate(_,_) >> false
|
||||||
|
|
||||||
|
when:
|
||||||
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> result = ldapAuthenticator.authenticate(username, "password", domainId, null)
|
||||||
|
then:
|
||||||
|
result.first() == false
|
||||||
|
result.second() == UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -127,7 +127,7 @@ class LdapConfigurationSpec extends spock.lang.Specification {
|
|||||||
when: "Get return attributes is called"
|
when: "Get return attributes is called"
|
||||||
String[] returnAttributes = ldapConfiguration.getReturnAttributes()
|
String[] returnAttributes = ldapConfiguration.getReturnAttributes()
|
||||||
then: "An array containing uid, mail, givenname, sn and cn is returned"
|
then: "An array containing uid, mail, givenname, sn and cn is returned"
|
||||||
returnAttributes == ["uid", "mail", "givenname", "sn", "cn"]
|
returnAttributes == ["uid", "mail", "givenname", "sn", "cn", "userAccountControl"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def "Test that getScope returns SearchControls.SUBTREE_SCOPE"() {
|
def "Test that getScope returns SearchControls.SUBTREE_SCOPE"() {
|
||||||
|
|||||||
@ -53,7 +53,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
|||||||
def "Test failed creation due to a null response from cloudstack account creater"() {
|
def "Test failed creation due to a null response from cloudstack account creater"() {
|
||||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||||
LdapManager ldapManager = Mock(LdapManager)
|
LdapManager ldapManager = Mock(LdapManager)
|
||||||
ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false)
|
||||||
AccountService accountService = Mock(AccountService)
|
AccountService accountService = Mock(AccountService)
|
||||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||||
ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
|
ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
|
||||||
@ -105,7 +105,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
|||||||
AccountService accountService = Mock(AccountService)
|
AccountService accountService = Mock(AccountService)
|
||||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
|
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
|
||||||
when: "a user with an username, email, firstname and lastname is validated"
|
when: "a user with an username, email, firstname and lastname is validated"
|
||||||
def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain"))
|
def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain", false))
|
||||||
then: "the result is true"
|
then: "the result is true"
|
||||||
result == true
|
result == true
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
|||||||
AccountService accountService = Mock(AccountService)
|
AccountService accountService = Mock(AccountService)
|
||||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||||
when: "A user with no email address attempts to validate"
|
when: "A user with no email address attempts to validate"
|
||||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain"))
|
ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain", false))
|
||||||
then: "An exception is thrown"
|
then: "An exception is thrown"
|
||||||
thrown Exception
|
thrown Exception
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
|||||||
AccountService accountService = Mock(AccountService)
|
AccountService accountService = Mock(AccountService)
|
||||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||||
when: "A user with no firstname attempts to validate"
|
when: "A user with no firstname attempts to validate"
|
||||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", null, "lastname", "principal"))
|
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", null, "lastname", "principal", false))
|
||||||
then: "An exception is thrown"
|
then: "An exception is thrown"
|
||||||
thrown Exception
|
thrown Exception
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
|||||||
AccountService accountService = Mock(AccountService)
|
AccountService accountService = Mock(AccountService)
|
||||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||||
when: "A user with no lastname attempts to validate"
|
when: "A user with no lastname attempts to validate"
|
||||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain"))
|
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain", false))
|
||||||
then: "An exception is thown"
|
then: "An exception is thown"
|
||||||
thrown Exception
|
thrown Exception
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,8 +53,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
def accountService = Mock(AccountService)
|
def accountService = Mock(AccountService)
|
||||||
|
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
@ -81,8 +81,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
def accountService = Mock(AccountService)
|
def accountService = Mock(AccountService)
|
||||||
|
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsersInGroup("TestGroup") >> users
|
ldapManager.getUsersInGroup("TestGroup") >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
@ -110,8 +110,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
def accountService = Mock(AccountService)
|
def accountService = Mock(AccountService)
|
||||||
|
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsersInGroup("TestGroup") >> users
|
ldapManager.getUsersInGroup("TestGroup") >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
@ -139,8 +139,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
def accountService = Mock(AccountService)
|
def accountService = Mock(AccountService)
|
||||||
|
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response2 = new LdapUserResponse("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
@ -169,8 +169,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
ldapImportUsersCmd.domainId = varDomainId
|
ldapImportUsersCmd.domainId = varDomainId
|
||||||
ldapImportUsersCmd.groupName = varGroupName
|
ldapImportUsersCmd.groupName = varGroupName
|
||||||
|
|
||||||
def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false)
|
||||||
def ldapUser2 = new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering");
|
def ldapUser2 = new LdapUser("bob", "bob@test.com", "Robert", "Young", "cn=bob,ou=engineering,dc=cloudstack,dc=org", "engineering", false);
|
||||||
|
|
||||||
Domain domain = new DomainVO(expectedDomainName, 1L, 1L, expectedDomainName, UUID.randomUUID().toString());
|
Domain domain = new DomainVO(expectedDomainName, 1L, 1L, expectedDomainName, UUID.randomUUID().toString());
|
||||||
if (varDomainId != null) {
|
if (varDomainId != null) {
|
||||||
@ -204,7 +204,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
ldapManager.createLdapUserResponse(_) >>> response1
|
ldapManager.createLdapUserResponse(_) >>> response1
|
||||||
@ -234,7 +234,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
ldapManager.createLdapUserResponse(_) >>> response1
|
ldapManager.createLdapUserResponse(_) >>> response1
|
||||||
@ -263,7 +263,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
|||||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||||
ldapManager.createLdapUserResponse(_) >>> response1
|
ldapManager.createLdapUserResponse(_) >>> response1
|
||||||
|
|||||||
@ -53,7 +53,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
|||||||
given: "We have an LdapManager, one user, QueryService and a LdapListUsersCmd"
|
given: "We have an LdapManager, one user, QueryService and a LdapListUsersCmd"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||||
ldapManager.getUsers() >> users
|
ldapManager.getUsers() >> users
|
||||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
||||||
ldapManager.createLdapUserResponse(_) >> response
|
ldapManager.createLdapUserResponse(_) >> response
|
||||||
@ -92,7 +92,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
queryService.searchForUsers(_) >> queryServiceResponse
|
queryService.searchForUsers(_) >> queryServiceResponse
|
||||||
|
|
||||||
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
|
||||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
||||||
|
|
||||||
when: "isACloudstackUser is executed"
|
when: "isACloudstackUser is executed"
|
||||||
@ -109,7 +109,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
queryService.searchForUsers(_) >> new ListResponse<UserResponse>()
|
queryService.searchForUsers(_) >> new ListResponse<UserResponse>()
|
||||||
|
|
||||||
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
def ldapUser = new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
|
||||||
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
def ldapListUsersCmd = new LdapListUsersCmd(ldapManager,queryService)
|
||||||
|
|
||||||
when: "isACloudstackUser is executed"
|
when: "isACloudstackUser is executed"
|
||||||
|
|||||||
@ -24,6 +24,9 @@ import org.apache.cloudstack.api.command.LdapDeleteConfigurationCmd
|
|||||||
import org.apache.cloudstack.api.command.LdapImportUsersCmd
|
import org.apache.cloudstack.api.command.LdapImportUsersCmd
|
||||||
import org.apache.cloudstack.api.command.LdapListUsersCmd
|
import org.apache.cloudstack.api.command.LdapListUsersCmd
|
||||||
import org.apache.cloudstack.api.command.LdapUserSearchCmd
|
import org.apache.cloudstack.api.command.LdapUserSearchCmd
|
||||||
|
import org.apache.cloudstack.api.command.LinkDomainToLdapCmd
|
||||||
|
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse
|
||||||
|
import org.apache.cloudstack.ldap.dao.LdapTrustMapDao
|
||||||
|
|
||||||
import javax.naming.NamingException
|
import javax.naming.NamingException
|
||||||
import javax.naming.ldap.InitialLdapContext
|
import javax.naming.ldap.InitialLdapContext
|
||||||
@ -35,6 +38,8 @@ import org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl
|
|||||||
import com.cloud.exception.InvalidParameterValueException
|
import com.cloud.exception.InvalidParameterValueException
|
||||||
import com.cloud.utils.Pair
|
import com.cloud.utils.Pair
|
||||||
|
|
||||||
|
import javax.naming.ldap.LdapContext
|
||||||
|
|
||||||
class LdapManagerImplSpec extends spock.lang.Specification {
|
class LdapManagerImplSpec extends spock.lang.Specification {
|
||||||
def "Test failing of getUser due to bind issue"() {
|
def "Test failing of getUser due to bind issue"() {
|
||||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||||
@ -111,7 +116,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||||
when: "A ldap user response is generated"
|
when: "A ldap user response is generated"
|
||||||
def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org",
|
def result = ldapManager.createLdapUserResponse(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org",
|
||||||
"engineering"))
|
"engineering", false))
|
||||||
then: "The result of the response should match the given ldap user"
|
then: "The result of the response should match the given ldap user"
|
||||||
result.username == "rmurphy"
|
result.username == "rmurphy"
|
||||||
result.email == "rmurphy@test.com"
|
result.email == "rmurphy@test.com"
|
||||||
@ -131,7 +136,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
ldapContextFactory.createBindContext() >> null
|
ldapContextFactory.createBindContext() >> null
|
||||||
List<LdapUser> users = new ArrayList<>();
|
List<LdapUser> users = new ArrayList<>();
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||||
ldapUserManager.getUsers(_) >> users;
|
ldapUserManager.getUsers(_) >> users;
|
||||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||||
when: "We search for a group of users"
|
when: "We search for a group of users"
|
||||||
@ -149,7 +154,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
def ldapConfiguration = Mock(LdapConfiguration)
|
def ldapConfiguration = Mock(LdapConfiguration)
|
||||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
ldapContextFactory.createBindContext() >> null
|
ldapContextFactory.createBindContext() >> null
|
||||||
ldapUserManager.getUser(_, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
ldapUserManager.getUser(_, _) >> new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false)
|
||||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||||
when: "We search for a user"
|
when: "We search for a user"
|
||||||
def result = ldapManager.getUser("rmurphy")
|
def result = ldapManager.getUser("rmurphy")
|
||||||
@ -194,22 +199,6 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
result == false
|
result == false
|
||||||
}
|
}
|
||||||
|
|
||||||
def "Test successful failed result from canAuthenticate due to user not found"() {
|
|
||||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
|
||||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
|
||||||
def ldapContextFactory = Mock(LdapContextFactory)
|
|
||||||
def ldapUserManager = Mock(LdapUserManager)
|
|
||||||
def ldapUserManagerFactory = Mock(LdapUserManagerFactory)
|
|
||||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
|
||||||
def ldapConfiguration = Mock(LdapConfiguration)
|
|
||||||
def ldapManager = Spy(LdapManagerImpl, constructorArgs: [ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration])
|
|
||||||
ldapManager.getUser(_) >> { throw new NamingException() }
|
|
||||||
when: "The user attempts to authenticate and the user is not found"
|
|
||||||
def result = ldapManager.canAuthenticate("rmurphy", "password")
|
|
||||||
then: "the authentication fails"
|
|
||||||
result == false
|
|
||||||
}
|
|
||||||
|
|
||||||
def "Test successful failed result from deleteConfiguration due to configuration not existing"() {
|
def "Test successful failed result from deleteConfiguration due to configuration not existing"() {
|
||||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||||
@ -293,7 +282,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
ldapContextFactory.createBindContext() >> null;
|
ldapContextFactory.createBindContext() >> null;
|
||||||
|
|
||||||
List<LdapUser> users = new ArrayList<LdapUser>();
|
List<LdapUser> users = new ArrayList<LdapUser>();
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapUserManager.getUsers(_, _) >> users;
|
ldapUserManager.getUsers(_, _) >> users;
|
||||||
|
|
||||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||||
@ -364,6 +353,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
cmdList.add(LdapImportUsersCmd.class);
|
cmdList.add(LdapImportUsersCmd.class);
|
||||||
cmdList.add(LDAPConfigCmd.class);
|
cmdList.add(LDAPConfigCmd.class);
|
||||||
cmdList.add(LDAPRemoveCmd.class);
|
cmdList.add(LDAPRemoveCmd.class);
|
||||||
|
cmdList.add(LinkDomainToLdapCmd.class)
|
||||||
return cmdList
|
return cmdList
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +424,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
ldapContextFactory.createBindContext() >> null
|
ldapContextFactory.createBindContext() >> null
|
||||||
List<LdapUser> users = new ArrayList<>();
|
List<LdapUser> users = new ArrayList<>();
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering"))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering", false))
|
||||||
ldapUserManager.getUsersInGroup("engineering", _) >> users;
|
ldapUserManager.getUsersInGroup("engineering", _) >> users;
|
||||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||||
when: "We search for a group of users"
|
when: "We search for a group of users"
|
||||||
@ -442,4 +432,154 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
|||||||
then: "A list greater of size one is returned"
|
then: "A list greater of size one is returned"
|
||||||
result.size() == 1;
|
result.size() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "test linkDomainToLdap invalid ldap group type"() {
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
LdapTrustMapDao ldapTrustMapDao = Mock(LdapTrustMapDao)
|
||||||
|
ldapManager._ldapTrustMapDao = ldapTrustMapDao
|
||||||
|
|
||||||
|
def domainId = 1
|
||||||
|
when:
|
||||||
|
println("using type: " + type)
|
||||||
|
LinkDomainToLdapResponse response = ldapManager.linkDomainToLdap(domainId, type, "CN=test,DC=CCP,DC=Citrix,DC=Com", (short)2)
|
||||||
|
then:
|
||||||
|
thrown(IllegalArgumentException)
|
||||||
|
where:
|
||||||
|
type << ["", null, "TEST", "TEST TEST"]
|
||||||
|
}
|
||||||
|
def "test linkDomainToLdap invalid domain"() {
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
LdapTrustMapDao ldapTrustMapDao = Mock(LdapTrustMapDao)
|
||||||
|
ldapManager._ldapTrustMapDao = ldapTrustMapDao
|
||||||
|
|
||||||
|
when:
|
||||||
|
LinkDomainToLdapResponse response = ldapManager.linkDomainToLdap(null, "GROUP", "CN=test,DC=CCP,DC=Citrix,DC=Com", (short)2)
|
||||||
|
then:
|
||||||
|
thrown(IllegalArgumentException)
|
||||||
|
}
|
||||||
|
def "test linkDomainToLdap invalid ldap name"() {
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
LdapTrustMapDao ldapTrustMapDao = Mock(LdapTrustMapDao)
|
||||||
|
ldapManager._ldapTrustMapDao = ldapTrustMapDao
|
||||||
|
|
||||||
|
def domainId = 1
|
||||||
|
when:
|
||||||
|
println("using name: " + name)
|
||||||
|
LinkDomainToLdapResponse response = ldapManager.linkDomainToLdap(domainId, "GROUP", name, (short)2)
|
||||||
|
then:
|
||||||
|
thrown(IllegalArgumentException)
|
||||||
|
where:
|
||||||
|
name << ["", null]
|
||||||
|
}
|
||||||
|
def "test linkDomainToLdap invalid accountType"(){
|
||||||
|
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
LdapTrustMapDao ldapTrustMapDao = Mock(LdapTrustMapDao)
|
||||||
|
ldapManager._ldapTrustMapDao = ldapTrustMapDao
|
||||||
|
|
||||||
|
def domainId = 1
|
||||||
|
when:
|
||||||
|
println("using accountType: " + accountType)
|
||||||
|
LinkDomainToLdapResponse response = ldapManager.linkDomainToLdap(domainId, "GROUP", "TEST", (short)accountType)
|
||||||
|
then:
|
||||||
|
thrown(IllegalArgumentException)
|
||||||
|
where:
|
||||||
|
accountType << [-1, 1, 3, 4, 5, 6, 20000, -500000]
|
||||||
|
}
|
||||||
|
def "test linkDomainToLdap when all is well"(){
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
LdapTrustMapDao ldapTrustMapDao = Mock(LdapTrustMapDao)
|
||||||
|
ldapManager._ldapTrustMapDao = ldapTrustMapDao
|
||||||
|
|
||||||
|
def domainId=1
|
||||||
|
def type=LdapManager.LinkType.GROUP
|
||||||
|
def name="CN=test,DC=CCP, DC=citrix,DC=com"
|
||||||
|
short accountType=2
|
||||||
|
|
||||||
|
1 * ldapTrustMapDao.persist(new LdapTrustMapVO(domainId, type, name, accountType)) >> new LdapTrustMapVO(domainId, type, name, accountType)
|
||||||
|
|
||||||
|
when:
|
||||||
|
LinkDomainToLdapResponse response = ldapManager.linkDomainToLdap(domainId, type.toString(), name, accountType)
|
||||||
|
then:
|
||||||
|
response.getDomainId() == domainId
|
||||||
|
response.getType() == type.toString()
|
||||||
|
response.getName() == name
|
||||||
|
response.getAccountType() == accountType
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test getUser(username,type,group) when username disabled in ldap"(){
|
||||||
|
def ldapUserManager = Mock(LdapUserManager)
|
||||||
|
def ldapUserManagerFactory = Mock(LdapUserManagerFactory)
|
||||||
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
|
def ldapContextFactory = Mock(LdapContextFactory)
|
||||||
|
ldapContextFactory.createBindContext() >> Mock(LdapContext)
|
||||||
|
def ldapConfiguration = Mock(LdapConfiguration)
|
||||||
|
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
ldapManager._ldapUserManagerFactory = ldapUserManagerFactory
|
||||||
|
ldapManager._ldapContextFactory = ldapContextFactory
|
||||||
|
ldapManager._ldapConfiguration = ldapConfiguration
|
||||||
|
|
||||||
|
def username = "admin"
|
||||||
|
def type = "GROUP"
|
||||||
|
def name = "CN=test,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", true)
|
||||||
|
|
||||||
|
when:
|
||||||
|
LdapUser user = ldapManager.getUser(username, type, name)
|
||||||
|
then:
|
||||||
|
user.getUsername() == username
|
||||||
|
user.isDisabled() == true
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test getUser(username,type,group) when username doesnt exist in ldap"(){
|
||||||
|
def ldapUserManager = Mock(LdapUserManager)
|
||||||
|
def ldapUserManagerFactory = Mock(LdapUserManagerFactory)
|
||||||
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
|
def ldapContextFactory = Mock(LdapContextFactory)
|
||||||
|
ldapContextFactory.createBindContext() >> Mock(LdapContext)
|
||||||
|
def ldapConfiguration = Mock(LdapConfiguration)
|
||||||
|
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
ldapManager._ldapUserManagerFactory = ldapUserManagerFactory
|
||||||
|
ldapManager._ldapContextFactory = ldapContextFactory
|
||||||
|
ldapManager._ldapConfiguration = ldapConfiguration
|
||||||
|
|
||||||
|
def username = "admin"
|
||||||
|
def type = "GROUP"
|
||||||
|
def name = "CN=test,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapUserManager.getUser(username, type, name, _) >> { throw new NamingException("Test naming exception") }
|
||||||
|
|
||||||
|
when:
|
||||||
|
LdapUser user = ldapManager.getUser(username, type, name)
|
||||||
|
then:
|
||||||
|
thrown(NoLdapUserMatchingQueryException)
|
||||||
|
}
|
||||||
|
def "test getUser(username,type,group) when username is an active member of the group in ldap"(){
|
||||||
|
def ldapUserManager = Mock(LdapUserManager)
|
||||||
|
def ldapUserManagerFactory = Mock(LdapUserManagerFactory)
|
||||||
|
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||||
|
def ldapContextFactory = Mock(LdapContextFactory)
|
||||||
|
ldapContextFactory.createBindContext() >> Mock(LdapContext)
|
||||||
|
def ldapConfiguration = Mock(LdapConfiguration)
|
||||||
|
|
||||||
|
def ldapManager = new LdapManagerImpl()
|
||||||
|
ldapManager._ldapUserManagerFactory = ldapUserManagerFactory
|
||||||
|
ldapManager._ldapContextFactory = ldapContextFactory
|
||||||
|
ldapManager._ldapConfiguration = ldapConfiguration
|
||||||
|
|
||||||
|
def username = "admin"
|
||||||
|
def type = "GROUP"
|
||||||
|
def name = "CN=test,DC=citrix,DC=com"
|
||||||
|
|
||||||
|
ldapUserManager.getUser(username, type, name, _) >> new LdapUser(username, "email", "firstname", "lastname", "principal", "domain", false)
|
||||||
|
|
||||||
|
when:
|
||||||
|
LdapUser user = ldapManager.getUser(username, type, name)
|
||||||
|
then:
|
||||||
|
user.getUsername() == username
|
||||||
|
user.isDisabled() == false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class LdapSearchUserCmdSpec extends spock.lang.Specification {
|
|||||||
given: "We have an Ldap manager and ldap user search cmd"
|
given: "We have an Ldap manager and ldap user search cmd"
|
||||||
def ldapManager = Mock(LdapManager)
|
def ldapManager = Mock(LdapManager)
|
||||||
List<LdapUser> users = new ArrayList()
|
List<LdapUser> users = new ArrayList()
|
||||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||||
ldapManager.searchUsers(_) >> users
|
ldapManager.searchUsers(_) >> users
|
||||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
||||||
ldapManager.createLdapUserResponse(_) >> response
|
ldapManager.createLdapUserResponse(_) >> response
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing LdapUsers hashCode generation"() {
|
def "Testing LdapUsers hashCode generation"() {
|
||||||
given:
|
given:
|
||||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||||
expect:
|
expect:
|
||||||
userA.hashCode() == usernameA.hashCode()
|
userA.hashCode() == usernameA.hashCode()
|
||||||
where:
|
where:
|
||||||
@ -31,8 +31,8 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing that LdapUser successfully gives the correct result for a compare to"() {
|
def "Testing that LdapUser successfully gives the correct result for a compare to"() {
|
||||||
given: "You have created two LDAP user objects"
|
given: "You have created two LDAP user objects"
|
||||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||||
def userB = new LdapUser(usernameB, "", "", "", "", "")
|
def userB = new LdapUser(usernameB, "", "", "", "", "", false)
|
||||||
expect: "That when compared the result is less than or equal to 0"
|
expect: "That when compared the result is less than or equal to 0"
|
||||||
userA.compareTo(userB) <= 0
|
userA.compareTo(userB) <= 0
|
||||||
where: "The following values are used"
|
where: "The following values are used"
|
||||||
@ -43,8 +43,8 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing that LdapUsers equality"() {
|
def "Testing that LdapUsers equality"() {
|
||||||
given:
|
given:
|
||||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||||
def userB = new LdapUser(usernameB, "", "", "", "", "")
|
def userB = new LdapUser(usernameB, "", "", "", "", "", false)
|
||||||
expect:
|
expect:
|
||||||
userA.equals(userA) == true
|
userA.equals(userA) == true
|
||||||
userA.equals(new Object()) == false
|
userA.equals(new Object()) == false
|
||||||
@ -56,7 +56,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing that the username is correctly set with the ldap object"() {
|
def "Testing that the username is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a username"
|
given: "You have created a LDAP user object with a username"
|
||||||
def user = new LdapUser(username, "", "", "", "", "")
|
def user = new LdapUser(username, "", "", "", "", "", false)
|
||||||
expect: "The username is equal to the given data source"
|
expect: "The username is equal to the given data source"
|
||||||
user.getUsername() == username
|
user.getUsername() == username
|
||||||
where: "The username is set to "
|
where: "The username is set to "
|
||||||
@ -65,7 +65,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing the email is correctly set with the ldap object"() {
|
def "Testing the email is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a email"
|
given: "You have created a LDAP user object with a email"
|
||||||
def user = new LdapUser("", email, "", "", "", "")
|
def user = new LdapUser("", email, "", "", "", "", false)
|
||||||
expect: "The email is equal to the given data source"
|
expect: "The email is equal to the given data source"
|
||||||
user.getEmail() == email
|
user.getEmail() == email
|
||||||
where: "The email is set to "
|
where: "The email is set to "
|
||||||
@ -74,7 +74,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing the firstname is correctly set with the ldap object"() {
|
def "Testing the firstname is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a firstname"
|
given: "You have created a LDAP user object with a firstname"
|
||||||
def user = new LdapUser("", "", firstname, "", "", "")
|
def user = new LdapUser("", "", firstname, "", "", "", false)
|
||||||
expect: "The firstname is equal to the given data source"
|
expect: "The firstname is equal to the given data source"
|
||||||
user.getFirstname() == firstname
|
user.getFirstname() == firstname
|
||||||
where: "The firstname is set to "
|
where: "The firstname is set to "
|
||||||
@ -83,7 +83,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing the lastname is correctly set with the ldap object"() {
|
def "Testing the lastname is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a lastname"
|
given: "You have created a LDAP user object with a lastname"
|
||||||
def user = new LdapUser("", "", "", lastname, "", "")
|
def user = new LdapUser("", "", "", lastname, "", "", false)
|
||||||
expect: "The lastname is equal to the given data source"
|
expect: "The lastname is equal to the given data source"
|
||||||
user.getLastname() == lastname
|
user.getLastname() == lastname
|
||||||
where: "The lastname is set to "
|
where: "The lastname is set to "
|
||||||
@ -92,7 +92,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing the principal is correctly set with the ldap object"() {
|
def "Testing the principal is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a principal"
|
given: "You have created a LDAP user object with a principal"
|
||||||
def user = new LdapUser("", "", "", "", principal, "")
|
def user = new LdapUser("", "", "", "", principal, "", false)
|
||||||
expect: "The principal is equal to the given data source"
|
expect: "The principal is equal to the given data source"
|
||||||
user.getPrincipal() == principal
|
user.getPrincipal() == principal
|
||||||
where: "The principal is set to "
|
where: "The principal is set to "
|
||||||
@ -101,7 +101,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
|||||||
|
|
||||||
def "Testing the domain is correctly set with the ldap object"() {
|
def "Testing the domain is correctly set with the ldap object"() {
|
||||||
given: "You have created a LDAP user object with a principal"
|
given: "You have created a LDAP user object with a principal"
|
||||||
def user = new LdapUser("", "", "", "", "", domain)
|
def user = new LdapUser("", "", "", "", "", domain, false)
|
||||||
expect: "The principal is equal to the given data source"
|
expect: "The principal is equal to the given data source"
|
||||||
user.getDomain() == domain
|
user.getDomain() == domain
|
||||||
where: "The username is set to "
|
where: "The username is set to "
|
||||||
|
|||||||
@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package groovy.org.apache.cloudstack.ldap
|
||||||
|
|
||||||
|
import com.cloud.exception.InvalidParameterValueException
|
||||||
|
import com.cloud.user.Account
|
||||||
|
import com.cloud.user.AccountService
|
||||||
|
import com.cloud.user.User
|
||||||
|
import com.cloud.user.UserAccount
|
||||||
|
import org.apache.cloudstack.api.ServerApiException
|
||||||
|
import org.apache.cloudstack.api.command.LinkDomainToLdapCmd
|
||||||
|
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse
|
||||||
|
import org.apache.cloudstack.ldap.LdapManager
|
||||||
|
import org.apache.cloudstack.ldap.LdapUser
|
||||||
|
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException
|
||||||
|
import spock.lang.Shared
|
||||||
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
class LinkDomainToLdapCmdSpec extends Specification {
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
private LdapManager _ldapManager;
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
public AccountService _accountService;
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
public LinkDomainToLdapCmd linkDomainToLdapCmd;
|
||||||
|
|
||||||
|
def setup() {
|
||||||
|
_ldapManager = Mock(LdapManager)
|
||||||
|
_accountService = Mock(AccountService)
|
||||||
|
|
||||||
|
linkDomainToLdapCmd = new LinkDomainToLdapCmd()
|
||||||
|
linkDomainToLdapCmd._accountService = _accountService
|
||||||
|
linkDomainToLdapCmd._ldapManager = _ldapManager
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test invalid params"() {
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> {throw new InvalidParameterValueException("invalid param")}
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute();
|
||||||
|
then:
|
||||||
|
thrown(ServerApiException)
|
||||||
|
}
|
||||||
|
def "test valid params without admin"(){
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(1, "GROUP", "CN=test,DC=ccp,DC=citrix,DC=com", (short)2)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test with valid params and with disabled admin"() {
|
||||||
|
def domainId = 1;
|
||||||
|
def type = "GROUP";
|
||||||
|
def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
|
||||||
|
def accountType = 2;
|
||||||
|
def username = "admin"
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
_ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", true)
|
||||||
|
|
||||||
|
linkDomainToLdapCmd.admin = username
|
||||||
|
linkDomainToLdapCmd.type = type
|
||||||
|
linkDomainToLdapCmd.name = name
|
||||||
|
linkDomainToLdapCmd.domainId = domainId
|
||||||
|
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
result.getDomainId() == domainId
|
||||||
|
result.getType() == type
|
||||||
|
result.getName() == name
|
||||||
|
result.getAdminId() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test with valid params and with admin who exist in cloudstack already"() {
|
||||||
|
def domainId = 1;
|
||||||
|
def type = "GROUP";
|
||||||
|
def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
|
||||||
|
def accountType = 2;
|
||||||
|
def username = "admin"
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
_ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false)
|
||||||
|
|
||||||
|
_accountService.getActiveAccountByName(username, domainId) >> Mock(Account)
|
||||||
|
|
||||||
|
linkDomainToLdapCmd.admin = username
|
||||||
|
linkDomainToLdapCmd.type = type
|
||||||
|
linkDomainToLdapCmd.name = name
|
||||||
|
linkDomainToLdapCmd.domainId = domainId
|
||||||
|
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
result.getDomainId() == domainId
|
||||||
|
result.getType() == type
|
||||||
|
result.getName() == name
|
||||||
|
result.getAdminId() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test with valid params and with admin who doesnt exist in cloudstack"() {
|
||||||
|
def domainId = 1;
|
||||||
|
def type = "GROUP";
|
||||||
|
def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
|
||||||
|
def accountType = 2;
|
||||||
|
def username = "admin"
|
||||||
|
def accountId = 24
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
_ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false)
|
||||||
|
|
||||||
|
_accountService.getActiveAccountByName(username, domainId) >> null
|
||||||
|
UserAccount userAccount = Mock(UserAccount)
|
||||||
|
userAccount.getAccountId() >> 24
|
||||||
|
_accountService.createUserAccount(username, "", "Admin", "Admin", "admin@ccp.citrix.com", null, username, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId,
|
||||||
|
username, null, _, _, User.Source.LDAP) >> userAccount
|
||||||
|
|
||||||
|
linkDomainToLdapCmd.admin = username
|
||||||
|
linkDomainToLdapCmd.type = type
|
||||||
|
linkDomainToLdapCmd.name = name
|
||||||
|
linkDomainToLdapCmd.domainId = domainId
|
||||||
|
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
result.getDomainId() == domainId
|
||||||
|
result.getType() == type
|
||||||
|
result.getName() == name
|
||||||
|
result.getAdminId() == String.valueOf(accountId)
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test when admin doesnt exist in ldap"() {
|
||||||
|
def domainId = 1;
|
||||||
|
def type = "GROUP";
|
||||||
|
def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
|
||||||
|
def accountType = 2;
|
||||||
|
def username = "admin"
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
_ldapManager.getUser(username, type, name) >> {throw new NoLdapUserMatchingQueryException("get ldap user failed from mock")}
|
||||||
|
|
||||||
|
linkDomainToLdapCmd.admin = username
|
||||||
|
linkDomainToLdapCmd.type = type
|
||||||
|
linkDomainToLdapCmd.name = name
|
||||||
|
linkDomainToLdapCmd.domainId = domainId
|
||||||
|
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
result.getDomainId() == domainId
|
||||||
|
result.getType() == type
|
||||||
|
result.getName() == name
|
||||||
|
result.getAdminId() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api should not fail in this case as link domain to ldap is successful
|
||||||
|
*/
|
||||||
|
def "test when create user account throws a run time exception"() {
|
||||||
|
def domainId = 1;
|
||||||
|
def type = "GROUP";
|
||||||
|
def name = "CN=test,DC=ccp,DC=Citrix,DC=com"
|
||||||
|
def accountType = 2;
|
||||||
|
def username = "admin"
|
||||||
|
def accountId = 24
|
||||||
|
|
||||||
|
LinkDomainToLdapResponse response = new LinkDomainToLdapResponse(domainId, type, name, (short)accountType)
|
||||||
|
_ldapManager.linkDomainToLdap(_,_,_,_) >> response
|
||||||
|
_ldapManager.getUser(username, type, name) >> new LdapUser(username, "admin@ccp.citrix.com", "Admin", "Admin", name, "ccp", false)
|
||||||
|
|
||||||
|
_accountService.getActiveAccountByName(username, domainId) >> null
|
||||||
|
UserAccount userAccount = Mock(UserAccount)
|
||||||
|
userAccount.getAccountId() >> 24
|
||||||
|
_accountService.createUserAccount(username, "", "Admin", "Admin", "admin@ccp.citrix.com", null, username, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId,
|
||||||
|
username, null, _, _, User.Source.LDAP) >> { throw new RuntimeException("created failed from mock") }
|
||||||
|
|
||||||
|
linkDomainToLdapCmd.admin = username
|
||||||
|
linkDomainToLdapCmd.type = type
|
||||||
|
linkDomainToLdapCmd.name = name
|
||||||
|
linkDomainToLdapCmd.domainId = domainId
|
||||||
|
|
||||||
|
when:
|
||||||
|
linkDomainToLdapCmd.execute()
|
||||||
|
then:
|
||||||
|
LinkDomainToLdapResponse result = (LinkDomainToLdapResponse)linkDomainToLdapCmd.getResponseObject()
|
||||||
|
result.getObjectName() == "LinkDomainToLdap"
|
||||||
|
result.getResponseName() == linkDomainToLdapCmd.getCommandName()
|
||||||
|
result.getDomainId() == domainId
|
||||||
|
result.getType() == type
|
||||||
|
result.getName() == name
|
||||||
|
result.getAdminId() == null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2145,14 +2145,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
|
s_logger.debug("Attempting to log in user: " + username + " in domain " + domainId);
|
||||||
}
|
}
|
||||||
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
|
UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId);
|
||||||
if (userAccount == null) {
|
|
||||||
s_logger.warn("Unable to find an user with username " + username + " in domain " + domainId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean authenticated = false;
|
boolean authenticated = false;
|
||||||
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<ActionOnFailedAuthentication>();
|
HashSet<ActionOnFailedAuthentication> actionsOnFailedAuthenticaion = new HashSet<ActionOnFailedAuthentication>();
|
||||||
User.Source userSource = userAccount.getSource();
|
User.Source userSource = userAccount != null ? userAccount.getSource(): User.Source.UNKNOWN;
|
||||||
for (UserAuthenticator authenticator : _userAuthenticators) {
|
for (UserAuthenticator authenticator : _userAuthenticators) {
|
||||||
if(userSource != User.Source.UNKNOWN) {
|
if(userSource != User.Source.UNKNOWN) {
|
||||||
if(!authenticator.getName().equalsIgnoreCase(userSource.name())){
|
if(!authenticator.getName().equalsIgnoreCase(userSource.name())){
|
||||||
@ -2177,6 +2173,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
if (domain != null) {
|
if (domain != null) {
|
||||||
domainName = domain.getName();
|
domainName = domain.getName();
|
||||||
}
|
}
|
||||||
|
userAccount = _userAccountDao.getUserAccount(username, domainId);
|
||||||
|
|
||||||
if (!userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString()) ||
|
if (!userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString()) ||
|
||||||
!userAccount.getAccountState().equalsIgnoreCase(Account.State.enabled.toString())) {
|
!userAccount.getAccountState().equalsIgnoreCase(Account.State.enabled.toString())) {
|
||||||
@ -2196,6 +2193,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
s_logger.debug("Unable to authenticate user with username " + username + " in domain " + domainId);
|
s_logger.debug("Unable to authenticate user with username " + username + " in domain " + domainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userAccount == null) {
|
||||||
|
s_logger.warn("Unable to find an user with username " + username + " in domain " + domainId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString())) {
|
if (userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString())) {
|
||||||
if (!isInternalAccount(userAccount.getId())) {
|
if (!isInternalAccount(userAccount.getId())) {
|
||||||
// Internal accounts are not disabled
|
// Internal accounts are not disabled
|
||||||
|
|||||||
@ -399,3 +399,13 @@ CREATE TABLE `cloud`.`external_bigswitch_bcf_devices` (
|
|||||||
CONSTRAINT `fk_external_bigswitch_bcf_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE
|
CONSTRAINT `fk_external_bigswitch_bcf_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`ldap_trust_map` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`domain_id` bigint unsigned NOT NULL,
|
||||||
|
`type` varchar(10) NOT NULL,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`account_type` int(1) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uk_ldap_trust_map__domain_id` (`domain_id`),
|
||||||
|
CONSTRAINT `fk_ldap_trust_map__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain` (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|||||||
@ -12853,6 +12853,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
|
|||||||
background-position: -230px -677px;
|
background-position: -230px -677px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.linktoldap .icon {
|
||||||
|
background-position: -197px -65px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linktoldap:hover .icon {
|
||||||
|
background-position: -197px -647px;
|
||||||
|
}
|
||||||
|
|
||||||
.label-hovered {
|
.label-hovered {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #0000FF !important;
|
color: #0000FF !important;
|
||||||
|
|||||||
@ -1066,6 +1066,10 @@ under the License.
|
|||||||
'label.ovm3.vip': '<fmt:message key="label.ovm3.vip" />',
|
'label.ovm3.vip': '<fmt:message key="label.ovm3.vip" />',
|
||||||
'label.local.file': '<fmt:message key="label.local.file" />',
|
'label.local.file': '<fmt:message key="label.local.file" />',
|
||||||
'label.local.storage.enabled.system.vms': '<fmt:message key="label.local.storage.enabled.system.vms" />',
|
'label.local.storage.enabled.system.vms': '<fmt:message key="label.local.storage.enabled.system.vms" />',
|
||||||
|
'label.link.domain.to.ldap': '<fmt:message key="label.link.domain.to.ldap" />',
|
||||||
|
'message.link.domain.to.ldap': '<fmt:message key="message.link.domain.to.ldap" />',
|
||||||
|
'label.ldap.link.type': '<fmt:message key="label.ldap.link.type" />',
|
||||||
|
'label.account.type': '<fmt:message key="label.account.type" />'
|
||||||
'label.create.ssh.key.pair': '<fmt:message key="label.create.ssh.key.pair" />',
|
'label.create.ssh.key.pair': '<fmt:message key="label.create.ssh.key.pair" />',
|
||||||
'label.fingerprint': '<fmt:message key="label.fingerprint" />',
|
'label.fingerprint': '<fmt:message key="label.fingerprint" />',
|
||||||
'label.host.tag': '<fmt:message key="label.host.tag" />',
|
'label.host.tag': '<fmt:message key="label.host.tag" />',
|
||||||
|
|||||||
@ -1317,5 +1317,16 @@ cloudStack.docs = {
|
|||||||
helpOvm3Vip: {
|
helpOvm3Vip: {
|
||||||
desc: 'The VIP used by the pool and cluster',
|
desc: 'The VIP used by the pool and cluster',
|
||||||
externalLink: ''
|
externalLink: ''
|
||||||
|
},
|
||||||
|
helpLdapGroupName: {
|
||||||
|
desc: 'Fully qualified name of OU/GROUP in LDAP',
|
||||||
|
externalLink: ''
|
||||||
|
},
|
||||||
|
helpLdapGroupType: {
|
||||||
|
desc: 'Type of LDAP name provided. Can be either GROUP/OU',
|
||||||
|
externalLink: ''
|
||||||
|
},
|
||||||
|
helpLdapLinkDomainAdmin: {
|
||||||
|
desc: 'domain admin of the linked domain. Specify a username in GROUP/OU of LDAP'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -313,6 +313,109 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
linktoldap: {
|
||||||
|
label: 'label.link.domain.to.ldap',
|
||||||
|
|
||||||
|
action: function(args) {
|
||||||
|
var data = {
|
||||||
|
domainid: args.context.domains[0].id,
|
||||||
|
type: args.data.type,
|
||||||
|
name: args.data.name,
|
||||||
|
accounttype: args.data.accounttype
|
||||||
|
};
|
||||||
|
|
||||||
|
if (args.data.admin != null && args.data.admin.length > 0) {
|
||||||
|
$.extend(data, {
|
||||||
|
admin: args.data.admin
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: createURL('linkDomainToLdap'),
|
||||||
|
data: data,
|
||||||
|
success: function(json) {
|
||||||
|
var item = json.linkdomaintoldapresponse.LinkDomainToLdap.domainid;
|
||||||
|
args.response.success({
|
||||||
|
data: item
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function(XMLHttpResponse) {
|
||||||
|
var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
|
||||||
|
args.response.error(errorMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
messages: {
|
||||||
|
notification: function(args) {
|
||||||
|
return 'label.link.domain.to.ldap';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createForm: {
|
||||||
|
title: 'label.link.domain.to.ldap',
|
||||||
|
desc: 'message.link.domain.to.ldap',
|
||||||
|
fields: {
|
||||||
|
type: {
|
||||||
|
label: 'label.ldap.link.type',
|
||||||
|
docID: 'helpLdapGroupType',
|
||||||
|
validation: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
select: function(args) {
|
||||||
|
var items = [];
|
||||||
|
items.push({
|
||||||
|
id: "GROUP",
|
||||||
|
description: "GROUP"
|
||||||
|
}); //regular-user
|
||||||
|
items.push({
|
||||||
|
id: "OU",
|
||||||
|
description: "OU"
|
||||||
|
}); //root-admin
|
||||||
|
args.response.success({
|
||||||
|
data: items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
label: 'label.name',
|
||||||
|
docID: 'helpLdapGroupName',
|
||||||
|
validation: {
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
accounttype: {
|
||||||
|
label: 'label.account.type',
|
||||||
|
docID: 'helpAccountType',
|
||||||
|
validation: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
select: function(args) {
|
||||||
|
var items = [];
|
||||||
|
items.push({
|
||||||
|
id: 0,
|
||||||
|
description: "Normal User"
|
||||||
|
}); //regular-user
|
||||||
|
items.push({
|
||||||
|
id: 2,
|
||||||
|
description: "Domain Admin"
|
||||||
|
}); //root-admin
|
||||||
|
args.response.success({
|
||||||
|
data: items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
label: 'label.domain.admin',
|
||||||
|
docID: 'helpLdapLinkDomainAdmin',
|
||||||
|
validation: {
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
updateResourceCount: {
|
updateResourceCount: {
|
||||||
label: 'label.action.update.resource.count',
|
label: 'label.action.update.resource.count',
|
||||||
messages: {
|
messages: {
|
||||||
@ -652,6 +755,9 @@
|
|||||||
if (jsonObj.level != 0) { //ROOT domain (whose level is 0) is not allowed to delete
|
if (jsonObj.level != 0) { //ROOT domain (whose level is 0) is not allowed to delete
|
||||||
allowedActions.push("delete");
|
allowedActions.push("delete");
|
||||||
}
|
}
|
||||||
|
if(isLdapEnabled()) {
|
||||||
|
allowedActions.push("linktoldap")
|
||||||
|
}
|
||||||
} else if (isDomainAdmin()) {
|
} else if (isDomainAdmin()) {
|
||||||
if (args.context.domains[0].id != g_domainid) {
|
if (args.context.domains[0].id != g_domainid) {
|
||||||
allowedActions.push("edit"); //merge updateResourceLimit into edit
|
allowedActions.push("edit"); //merge updateResourceLimit into edit
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user