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_VIP = "ovm3vip";
|
||||
|
||||
public static final String ADMIN = "admin";
|
||||
|
||||
public enum HostDetails {
|
||||
all, capacity, events, stats, min;
|
||||
}
|
||||
|
||||
@ -2133,6 +2133,10 @@ label.every=Every
|
||||
label.day=Day
|
||||
label.of.month=of month
|
||||
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.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
|
||||
|
||||
@ -771,6 +771,7 @@ deleteLdapConfiguration=3
|
||||
listLdapUsers=3
|
||||
ldapCreateAccount=3
|
||||
importLdapUsers=3
|
||||
linkDomainToLdap=3
|
||||
|
||||
|
||||
#### juniper-contrail commands
|
||||
|
||||
@ -35,5 +35,6 @@
|
||||
<bean id="LdapConfigurationDao"
|
||||
class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
|
||||
<bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
|
||||
<bean id="LdapTrustMapDao" class="org.apache.cloudstack.ldap.dao.LdapTrustMapDaoImpl" />
|
||||
|
||||
</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 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
|
||||
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();
|
||||
String groupCnName = _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," + _ldapConfiguration.getBaseDn();
|
||||
memberOfFilter.append("(" + MICROSOFT_AD_NESTED_MEMBERS_FILTER + ":=");
|
||||
memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
|
||||
memberOfFilter.append(groupCnName);
|
||||
memberOfFilter.append(")");
|
||||
|
||||
@ -79,4 +80,25 @@ public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements Ld
|
||||
s_logger.debug("group search filter = " + result);
|
||||
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;
|
||||
|
||||
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.dao.UserAccountDao;
|
||||
import com.cloud.utils.Pair;
|
||||
@ -25,6 +28,7 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LdapAuthenticator extends DefaultUserAuthenticator {
|
||||
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
|
||||
@ -33,6 +37,8 @@ public class LdapAuthenticator extends DefaultUserAuthenticator {
|
||||
private LdapManager _ldapManager;
|
||||
@Inject
|
||||
private UserAccountDao _userAccountDao;
|
||||
@Inject
|
||||
private AccountManager _accountManager;
|
||||
|
||||
public LdapAuthenticator() {
|
||||
super();
|
||||
@ -52,21 +58,71 @@ public class LdapAuthenticator extends DefaultUserAuthenticator {
|
||||
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
|
||||
}
|
||||
|
||||
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||
boolean result = false;
|
||||
ActionOnFailedAuthentication action = null;
|
||||
|
||||
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;
|
||||
if (result == false) {
|
||||
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());
|
||||
}
|
||||
|
||||
} else {
|
||||
//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);
|
||||
}
|
||||
|
||||
} else {
|
||||
return new Pair<Boolean, ActionOnFailedAuthentication>(false, 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",
|
||||
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;
|
||||
|
||||
@Inject
|
||||
@ -108,7 +111,8 @@ public class LdapConfiguration implements Configurable{
|
||||
}
|
||||
|
||||
public String[] getReturnAttributes() {
|
||||
return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute()};
|
||||
return new String[] {getUsernameAttribute(), getEmailAttribute(), getFirstnameAttribute(), getLastnameAttribute(), getCommonNameAttribute(),
|
||||
getUserAccountControlAttribute()};
|
||||
}
|
||||
|
||||
public int getScope() {
|
||||
@ -159,6 +163,10 @@ public class LdapConfiguration implements Configurable{
|
||||
return "cn";
|
||||
}
|
||||
|
||||
public String getUserAccountControlAttribute() {
|
||||
return "userAccountControl";
|
||||
}
|
||||
|
||||
public Long getReadTimeout() {
|
||||
return ldapReadTimeout.value();
|
||||
}
|
||||
@ -178,6 +186,10 @@ public class LdapConfiguration implements Configurable{
|
||||
return provider;
|
||||
}
|
||||
|
||||
public boolean isNestedGroupsEnabled() {
|
||||
return ldapEnableNestedGroups.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return LdapConfiguration.class.getSimpleName();
|
||||
@ -185,6 +197,6 @@ public class LdapConfiguration implements Configurable{
|
||||
|
||||
@Override
|
||||
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.utils.Pair;
|
||||
import com.cloud.utils.component.PluggableService;
|
||||
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
|
||||
|
||||
public interface LdapManager extends PluggableService {
|
||||
|
||||
enum LinkType { GROUP, OU;}
|
||||
|
||||
LdapConfigurationResponse addConfiguration(String hostname, int port) throws InvalidParameterValueException;
|
||||
|
||||
boolean canAuthenticate(String username, String password);
|
||||
boolean canAuthenticate(String principal, String password);
|
||||
|
||||
LdapConfigurationResponse createLdapConfigurationResponse(LdapConfigurationVO configuration);
|
||||
|
||||
@ -40,6 +43,8 @@ public interface LdapManager extends PluggableService {
|
||||
|
||||
LdapUser getUser(final String username) throws NoLdapUserMatchingQueryException;
|
||||
|
||||
LdapUser getUser(String username, String type, String name) throws NoLdapUserMatchingQueryException;
|
||||
|
||||
List<LdapUser> getUsers() 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);
|
||||
|
||||
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.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.springframework.stereotype.Component;
|
||||
|
||||
@ -61,6 +65,9 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
||||
|
||||
@Inject LdapUserManagerFactory _ldapUserManagerFactory;
|
||||
|
||||
@Inject
|
||||
LdapTrustMapDao _ldapTrustMapDao;
|
||||
|
||||
|
||||
public LdapManagerImpl() {
|
||||
super();
|
||||
@ -99,17 +106,14 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAuthenticate(final String username, final String password) {
|
||||
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
|
||||
public boolean canAuthenticate(final String principal, final String password) {
|
||||
try {
|
||||
final LdapUser user = getUser(escapedUsername);
|
||||
final String principal = user.getPrincipal();
|
||||
final LdapContext context = _ldapContextFactory.createUserContext(principal, password);
|
||||
closeContext(context);
|
||||
return true;
|
||||
} catch (NamingException | IOException | NoLdapUserMatchingQueryException e) {
|
||||
s_logger.debug("Exception while doing an LDAP bind for user "+" "+username, e);
|
||||
s_logger.info("Failed to authenticate user: " + username + ". incorrect password.");
|
||||
} catch (NamingException | IOException e) {
|
||||
s_logger.debug("Exception while doing an LDAP bind for user "+" "+principal, e);
|
||||
s_logger.info("Failed to authenticate user: " + principal + ". incorrect password.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -120,7 +124,7 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
||||
context.close();
|
||||
}
|
||||
} 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(LDAPConfigCmd.class);
|
||||
cmdList.add(LDAPRemoveCmd.class);
|
||||
cmdList.add(LinkDomainToLdapCmd.class);
|
||||
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
|
||||
public List<LdapUser> getUsers() throws NoLdapUserMatchingQueryException {
|
||||
LdapContext context = null;
|
||||
@ -243,4 +263,22 @@ public class LdapManagerImpl implements LdapManager, LdapValidator {
|
||||
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 username;
|
||||
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.email = email;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.principal = principal;
|
||||
this.domain = domain;
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,6 +76,11 @@ public class LdapUser implements Comparable<LdapUser> {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int 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 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 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("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) {
|
||||
@ -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
|
||||
public List<LdapUser> getUsers(final LdapContext context) throws NamingException, IOException {
|
||||
return getUsers(null, context);
|
||||
@ -191,6 +235,30 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
||||
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
|
||||
public List<LdapUser> searchUsers(final String username, final LdapContext context) throws NamingException, IOException {
|
||||
|
||||
@ -212,7 +280,9 @@ public class OpenLdapUserManagerImpl implements LdapUserManager {
|
||||
results = context.search(basedn, generateSearchFilter(username), searchControls);
|
||||
while (results.hasMoreElements()) {
|
||||
final SearchResult result = results.nextElement();
|
||||
users.add(createUser(result));
|
||||
if (!isUserDisabled(result)) {
|
||||
users.add(createUser(result));
|
||||
}
|
||||
}
|
||||
Control[] contextControls = context.getResponseControls();
|
||||
if (contextControls != null) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
def "test generate AD search filter"() {
|
||||
def "test generate AD search filter with nested groups enabled"() {
|
||||
ldapConfiguration.getUserObject() >> "user"
|
||||
ldapConfiguration.getCommonNameAttribute() >> "CN"
|
||||
ldapConfiguration.getBaseDn() >> "DC=cloud,DC=citrix,DC=com"
|
||||
ldapConfiguration.isNestedGroupsEnabled() >> true
|
||||
|
||||
def result = adLdapUserManager.generateADGroupSearchFilter(group);
|
||||
expect:
|
||||
@ -52,6 +53,20 @@ class ADLdapUserManagerImplSpec extends spock.lang.Specification {
|
||||
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"() {
|
||||
ldapConfiguration.getScope() >> SearchControls.SUBTREE_SCOPE
|
||||
ldapConfiguration.getReturnAttributes() >> ["username", "firstname", "lastname", "email"]
|
||||
|
||||
@ -16,84 +16,234 @@
|
||||
// under the License.
|
||||
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.dao.UserAccountDao
|
||||
import com.cloud.utils.Pair
|
||||
import org.apache.cloudstack.ldap.LdapAuthenticator
|
||||
import org.apache.cloudstack.ldap.LdapConfigurationVO
|
||||
import org.apache.cloudstack.ldap.LdapManager
|
||||
import org.apache.cloudstack.ldap.LdapTrustMapVO
|
||||
import org.apache.cloudstack.ldap.LdapUser
|
||||
|
||||
class LdapAuthenticatorSpec extends spock.lang.Specification {
|
||||
|
||||
def "Test a failed authentication due to user not being found within cloudstack"() {
|
||||
given: "We have an LdapManager, userAccountDao and ldapAuthenticator and the user doesn't exist within cloudstack."
|
||||
given: "We have an LdapManager, userAccountDao and ldapAuthenticator and the user doesn't exist within cloudstack."
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> null
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "A user authentications"
|
||||
when: "A user authentications"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap bind being unsuccessful"() {
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.canAuthenticate(_, _) >> false
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUser = Mock(LdapUser)
|
||||
ldapUser.isDisabled() >> false
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.getUser("rmurphy") >> ldapUser
|
||||
ldapManager.canAuthenticate(_, _) >> false
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
}
|
||||
|
||||
def "Test failed authentication due to ldap not being configured"() {
|
||||
given: "We have an LdapManager, A configured LDAP server, a userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> false
|
||||
given: "We have an LdapManager, A configured LDAP server, a userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> false
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "The user authenticates"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "The user authenticates"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
then: "their authentication fails"
|
||||
result.first() == false
|
||||
}
|
||||
|
||||
def "Test successful authentication"() {
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.canAuthenticate(_, _) >> true
|
||||
def "Test successful authentication"() {
|
||||
given: "We have an LdapManager, LdapConfiguration, userAccountDao and LdapAuthenticator"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
def ldapUser = Mock(LdapUser)
|
||||
ldapUser.isDisabled() >> false
|
||||
ldapManager.isLdapEnabled() >> true
|
||||
ldapManager.canAuthenticate(_, _) >> true
|
||||
ldapManager.getUser("rmurphy") >> ldapUser
|
||||
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
userAccountDao.getUserAccount(_, _) >> new UserAccountVO()
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
when: "The user authenticates with an incorrect password"
|
||||
def result = ldapAuthenticator.authenticate("rmurphy", "password", 0, null)
|
||||
|
||||
then: "their authentication passes"
|
||||
result.first() == true
|
||||
}
|
||||
then: "their authentication passes"
|
||||
result.first() == true
|
||||
}
|
||||
|
||||
def "Test that encode doesn't change the input"() {
|
||||
given: "We have an LdapManager, userAccountDao and LdapAuthenticator"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "a users password is encoded"
|
||||
def result = ldapAuthenticator.encode("password")
|
||||
then: "it doesn't change"
|
||||
result == "password"
|
||||
given: "We have an LdapManager, userAccountDao and LdapAuthenticator"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
UserAccountDao userAccountDao = Mock(UserAccountDao)
|
||||
def ldapAuthenticator = new LdapAuthenticator(ldapManager, userAccountDao)
|
||||
when: "a users password is encoded"
|
||||
def result = ldapAuthenticator.encode("password")
|
||||
then: "it doesn't change"
|
||||
result == "password"
|
||||
}
|
||||
|
||||
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"
|
||||
String[] returnAttributes = ldapConfiguration.getReturnAttributes()
|
||||
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"() {
|
||||
|
||||
@ -53,7 +53,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
def "Test failed creation due to a null response from cloudstack account creater"() {
|
||||
given: "We have an LdapManager, AccountService and LdapCreateAccountCmd"
|
||||
LdapManager ldapManager = Mock(LdapManager)
|
||||
ldapManager.getUser(_) >> new LdapUser("rmurphy", "rmurphy@cloudstack.org", "Ryan", "Murphy", "cn=rmurphy,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)
|
||||
def ldapCreateAccountCmd = Spy(LdapCreateAccountCmd, constructorArgs: [ldapManager, accountService])
|
||||
ldapCreateAccountCmd.getCurrentContext() >> Mock(CallContext)
|
||||
@ -105,7 +105,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService);
|
||||
when: "a user with an username, email, firstname and lastname is validated"
|
||||
def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain"))
|
||||
def result = ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", "lastname", "principal", "domain", false))
|
||||
then: "the result is true"
|
||||
result == true
|
||||
}
|
||||
@ -116,7 +116,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no email address attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain"))
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", null, "firstname", "lastname", "principal", "domain", false))
|
||||
then: "An exception is thrown"
|
||||
thrown Exception
|
||||
}
|
||||
@ -127,7 +127,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no firstname attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", null, "lastname", "principal"))
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", null, "lastname", "principal", false))
|
||||
then: "An exception is thrown"
|
||||
thrown Exception
|
||||
}
|
||||
@ -138,7 +138,7 @@ class LdapCreateAccountCmdSpec extends spock.lang.Specification {
|
||||
AccountService accountService = Mock(AccountService)
|
||||
def ldapCreateAccountCmd = new LdapCreateAccountCmd(ldapManager, accountService)
|
||||
when: "A user with no lastname attempts to validate"
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain"))
|
||||
ldapCreateAccountCmd.validateUser(new LdapUser("username", "email", "firstname", null, "principal", "domain", false))
|
||||
then: "An exception is thown"
|
||||
thrown Exception
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
def accountService = Mock(AccountService)
|
||||
|
||||
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("bob", "bob@test.com", "Robert", "Young", "cn=bob,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", false))
|
||||
ldapManager.getUsers() >> users
|
||||
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")
|
||||
@ -81,8 +81,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
def accountService = Mock(AccountService)
|
||||
|
||||
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("bob", "bob@test.com", "Robert", "Young", "cn=bob,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", false))
|
||||
ldapManager.getUsersInGroup("TestGroup") >> users
|
||||
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")
|
||||
@ -110,8 +110,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
def accountService = Mock(AccountService)
|
||||
|
||||
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("bob", "bob@test.com", "Robert", "Young", "cn=bob,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", false))
|
||||
ldapManager.getUsersInGroup("TestGroup") >> users
|
||||
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")
|
||||
@ -139,8 +139,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
def accountService = Mock(AccountService)
|
||||
|
||||
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("bob", "bob@test.com", "Robert", "Young", "cn=bob,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", false))
|
||||
ldapManager.getUsers() >> users
|
||||
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")
|
||||
@ -169,8 +169,8 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
ldapImportUsersCmd.domainId = varDomainId
|
||||
ldapImportUsersCmd.groupName = varGroupName
|
||||
|
||||
def ldapUser1 = new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,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");
|
||||
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", false);
|
||||
|
||||
Domain domain = new DomainVO(expectedDomainName, 1L, 1L, expectedDomainName, UUID.randomUUID().toString());
|
||||
if (varDomainId != null) {
|
||||
@ -204,7 +204,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
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
|
||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||
ldapManager.createLdapUserResponse(_) >>> response1
|
||||
@ -234,7 +234,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
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
|
||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||
ldapManager.createLdapUserResponse(_) >>> response1
|
||||
@ -263,7 +263,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification {
|
||||
given: "We have an LdapManager, DomainService, two users and a LdapImportUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
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
|
||||
LdapUserResponse response1 = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,ou=engineering,dc=cloudstack,dc=org", "engineering")
|
||||
ldapManager.createLdapUserResponse(_) >>> response1
|
||||
|
||||
@ -53,7 +53,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
||||
given: "We have an LdapManager, one user, QueryService and a LdapListUsersCmd"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapUser> users = new ArrayList()
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||
ldapManager.getUsers() >> users
|
||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
||||
ldapManager.createLdapUserResponse(_) >> response
|
||||
@ -92,7 +92,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
||||
|
||||
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)
|
||||
|
||||
when: "isACloudstackUser is executed"
|
||||
@ -109,7 +109,7 @@ class LdapListUsersCmdSpec extends spock.lang.Specification {
|
||||
|
||||
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)
|
||||
|
||||
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.LdapListUsersCmd
|
||||
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.ldap.InitialLdapContext
|
||||
@ -35,6 +38,8 @@ import org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl
|
||||
import com.cloud.exception.InvalidParameterValueException
|
||||
import com.cloud.utils.Pair
|
||||
|
||||
import javax.naming.ldap.LdapContext
|
||||
|
||||
class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
def "Test failing of getUser due to bind issue"() {
|
||||
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)
|
||||
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",
|
||||
"engineering"))
|
||||
"engineering", false))
|
||||
then: "The result of the response should match the given ldap user"
|
||||
result.username == "rmurphy"
|
||||
result.email == "rmurphy@test.com"
|
||||
@ -131,7 +136,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||
ldapContextFactory.createBindContext() >> null
|
||||
List<LdapUser> users = new ArrayList<>();
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||
ldapUserManager.getUsers(_) >> users;
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||
when: "We search for a group of users"
|
||||
@ -149,7 +154,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
def ldapConfiguration = Mock(LdapConfiguration)
|
||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||
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)
|
||||
when: "We search for a user"
|
||||
def result = ldapManager.getUser("rmurphy")
|
||||
@ -194,22 +199,6 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
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"() {
|
||||
given: "We have an LdapConfigurationDao, LdapContextFactory, LdapUserManager and LdapManager"
|
||||
def ldapConfigurationDao = Mock(LdapConfigurationDaoImpl)
|
||||
@ -293,7 +282,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
ldapContextFactory.createBindContext() >> null;
|
||||
|
||||
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;
|
||||
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||
@ -364,6 +353,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
cmdList.add(LdapImportUsersCmd.class);
|
||||
cmdList.add(LDAPConfigCmd.class);
|
||||
cmdList.add(LDAPRemoveCmd.class);
|
||||
cmdList.add(LinkDomainToLdapCmd.class)
|
||||
return cmdList
|
||||
}
|
||||
|
||||
@ -434,7 +424,7 @@ class LdapManagerImplSpec extends spock.lang.Specification {
|
||||
ldapUserManagerFactory.getInstance(_) >> ldapUserManager
|
||||
ldapContextFactory.createBindContext() >> null
|
||||
List<LdapUser> users = new ArrayList<>();
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering"))
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", "engineering", false))
|
||||
ldapUserManager.getUsersInGroup("engineering", _) >> users;
|
||||
def ldapManager = new LdapManagerImpl(ldapConfigurationDao, ldapContextFactory, ldapUserManagerFactory, ldapConfiguration)
|
||||
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"
|
||||
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"
|
||||
def ldapManager = Mock(LdapManager)
|
||||
List<LdapUser> users = new ArrayList()
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null))
|
||||
users.add(new LdapUser("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null, false))
|
||||
ldapManager.searchUsers(_) >> users
|
||||
LdapUserResponse response = new LdapUserResponse("rmurphy", "rmurphy@test.com", "Ryan", "Murphy", "cn=rmurphy,dc=cloudstack,dc=org", null)
|
||||
ldapManager.createLdapUserResponse(_) >> response
|
||||
|
||||
@ -22,7 +22,7 @@ class LdapUserSpec extends spock.lang.Specification {
|
||||
|
||||
def "Testing LdapUsers hashCode generation"() {
|
||||
given:
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||
expect:
|
||||
userA.hashCode() == usernameA.hashCode()
|
||||
where:
|
||||
@ -31,8 +31,8 @@ class LdapUserSpec extends spock.lang.Specification {
|
||||
|
||||
def "Testing that LdapUser successfully gives the correct result for a compare to"() {
|
||||
given: "You have created two LDAP user objects"
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
||||
def userB = new LdapUser(usernameB, "", "", "", "", "")
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||
def userB = new LdapUser(usernameB, "", "", "", "", "", false)
|
||||
expect: "That when compared the result is less than or equal to 0"
|
||||
userA.compareTo(userB) <= 0
|
||||
where: "The following values are used"
|
||||
@ -43,8 +43,8 @@ class LdapUserSpec extends spock.lang.Specification {
|
||||
|
||||
def "Testing that LdapUsers equality"() {
|
||||
given:
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "")
|
||||
def userB = new LdapUser(usernameB, "", "", "", "", "")
|
||||
def userA = new LdapUser(usernameA, "", "", "", "", "", false)
|
||||
def userB = new LdapUser(usernameB, "", "", "", "", "", false)
|
||||
expect:
|
||||
userA.equals(userA) == true
|
||||
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"() {
|
||||
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"
|
||||
user.getUsername() == username
|
||||
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"() {
|
||||
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"
|
||||
user.getEmail() == email
|
||||
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"() {
|
||||
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"
|
||||
user.getFirstname() == firstname
|
||||
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"() {
|
||||
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"
|
||||
user.getLastname() == lastname
|
||||
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"() {
|
||||
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"
|
||||
user.getPrincipal() == principal
|
||||
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"() {
|
||||
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"
|
||||
user.getDomain() == domain
|
||||
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);
|
||||
}
|
||||
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;
|
||||
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) {
|
||||
if(userSource != User.Source.UNKNOWN) {
|
||||
if(!authenticator.getName().equalsIgnoreCase(userSource.name())){
|
||||
@ -2177,6 +2173,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
||||
if (domain != null) {
|
||||
domainName = domain.getName();
|
||||
}
|
||||
userAccount = _userAccountDao.getUserAccount(username, domainId);
|
||||
|
||||
if (!userAccount.getState().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);
|
||||
}
|
||||
|
||||
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 (!isInternalAccount(userAccount.getId())) {
|
||||
// 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
|
||||
) 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;
|
||||
}
|
||||
|
||||
.linktoldap .icon {
|
||||
background-position: -197px -65px;
|
||||
}
|
||||
|
||||
.linktoldap:hover .icon {
|
||||
background-position: -197px -647px;
|
||||
}
|
||||
|
||||
.label-hovered {
|
||||
cursor: pointer;
|
||||
color: #0000FF !important;
|
||||
|
||||
@ -1066,6 +1066,10 @@ under the License.
|
||||
'label.ovm3.vip': '<fmt:message key="label.ovm3.vip" />',
|
||||
'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.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.fingerprint': '<fmt:message key="label.fingerprint" />',
|
||||
'label.host.tag': '<fmt:message key="label.host.tag" />',
|
||||
|
||||
@ -1317,5 +1317,16 @@ cloudStack.docs = {
|
||||
helpOvm3Vip: {
|
||||
desc: 'The VIP used by the pool and cluster',
|
||||
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: {
|
||||
label: 'label.action.update.resource.count',
|
||||
messages: {
|
||||
@ -652,6 +755,9 @@
|
||||
if (jsonObj.level != 0) { //ROOT domain (whose level is 0) is not allowed to delete
|
||||
allowedActions.push("delete");
|
||||
}
|
||||
if(isLdapEnabled()) {
|
||||
allowedActions.push("linktoldap")
|
||||
}
|
||||
} else if (isDomainAdmin()) {
|
||||
if (args.context.domains[0].id != g_domainid) {
|
||||
allowedActions.push("edit"); //merge updateResourceLimit into edit
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user