Skip to content

Commit 5881035

Browse files
committed
Merge pull request apache#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>
2 parents dd9ba48 + 53a441f commit 5881035

33 files changed

Lines changed: 1422 additions & 137 deletions

api/src/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,8 @@ public class ApiConstants {
628628
public static final String OVM3_CLUSTER = "ovm3cluster";
629629
public static final String OVM3_VIP = "ovm3vip";
630630

631+
public static final String ADMIN = "admin";
632+
631633
public enum HostDetails {
632634
all, capacity, events, stats, min;
633635
}

client/WEB-INF/classes/resources/messages.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,10 @@ label.every=Every
21332133
label.day=Day
21342134
label.of.month=of month
21352135
label.add.private.gateway=Add Private Gateway
2136+
label.link.domain.to.ldap=Link Domain to LDAP
2137+
message.link.domain.to.ldap=Enable autosync for this domain in LDAP
2138+
label.ldap.link.type=Type
2139+
label.account.type=Account Type
21362140
message.desc.created.ssh.key.pair=Created a SSH Key Pair.
21372141
message.please.confirm.remove.ssh.key.pair=Please confirm that you want to remove this SSH Key Pair
21382142
message.password.has.been.reset.to=Password has been reset to

client/tomcatconf/commands.properties.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ deleteLdapConfiguration=3
771771
listLdapUsers=3
772772
ldapCreateAccount=3
773773
importLdapUsers=3
774+
linkDomainToLdap=3
774775

775776

776777
#### juniper-contrail commands

plugins/user-authenticators/ldap/resources/META-INF/cloudstack/ldap/spring-ldap-context.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@
3535
<bean id="LdapConfigurationDao"
3636
class="org.apache.cloudstack.ldap.dao.LdapConfigurationDaoImpl" />
3737
<bean id="LdapConfiguration" class="org.apache.cloudstack.ldap.LdapConfiguration" />
38+
<bean id="LdapTrustMapDao" class="org.apache.cloudstack.ldap.dao.LdapTrustMapDaoImpl" />
3839

3940
</beans>
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.cloudstack.api.command;
20+
21+
import javax.inject.Inject;
22+
23+
import com.cloud.exception.InvalidParameterValueException;
24+
import com.cloud.user.User;
25+
import com.cloud.user.UserAccount;
26+
import org.apache.cloudstack.api.APICommand;
27+
import org.apache.cloudstack.api.ApiConstants;
28+
import org.apache.cloudstack.api.ApiErrorCode;
29+
import org.apache.cloudstack.api.BaseCmd;
30+
import org.apache.cloudstack.api.Parameter;
31+
import org.apache.cloudstack.api.ServerApiException;
32+
import org.apache.cloudstack.api.response.DomainResponse;
33+
import org.apache.cloudstack.api.response.LinkDomainToLdapResponse;
34+
import org.apache.cloudstack.ldap.LdapManager;
35+
import org.apache.cloudstack.ldap.LdapUser;
36+
import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException;
37+
import org.apache.log4j.Logger;
38+
39+
import com.cloud.user.Account;
40+
41+
import java.util.UUID;
42+
43+
@APICommand(name = "linkDomainToLdap", description = "link an existing cloudstack domain to group or OU in ldap", responseObject = LinkDomainToLdapResponse.class, since = "4.6.0",
44+
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
45+
public class LinkDomainToLdapCmd extends BaseCmd {
46+
public static final Logger s_logger = Logger.getLogger(LinkDomainToLdapCmd.class.getName());
47+
private static final String s_name = "linkdomaintoldapresponse";
48+
49+
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "The id of the domain which has to be "
50+
+ "linked to LDAP.")
51+
private Long domainId;
52+
53+
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "type of the ldap name. GROUP or OU")
54+
private String type;
55+
56+
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the group or OU in LDAP")
57+
private String name;
58+
59+
@Parameter(name = ApiConstants.ADMIN, type = CommandType.STRING, required = false, description = "domain admin username in LDAP ")
60+
private String admin;
61+
62+
@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 " +
63+
"domain admin")
64+
private short accountType;
65+
66+
@Inject
67+
private LdapManager _ldapManager;
68+
69+
@Override
70+
public void execute() throws ServerApiException {
71+
try {
72+
LinkDomainToLdapResponse response = _ldapManager.linkDomainToLdap(domainId, type, name, accountType);
73+
if(admin!=null) {
74+
LdapUser ldapUser = null;
75+
try {
76+
ldapUser = _ldapManager.getUser(admin, type, name);
77+
} catch (NoLdapUserMatchingQueryException e) {
78+
s_logger.debug("no ldap user matching username " + admin + " in the given group/ou", e);
79+
}
80+
if (ldapUser != null && !ldapUser.isDisabled()) {
81+
Account account = _accountService.getActiveAccountByName(admin, domainId);
82+
if (account == null) {
83+
try {
84+
UserAccount userAccount = _accountService.createUserAccount(admin, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null,
85+
admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId, admin, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
86+
response.setAdminId(String.valueOf(userAccount.getAccountId()));
87+
s_logger.info("created an account with name " + admin + " in the given domain " + domainId);
88+
} catch (Exception e) {
89+
s_logger.info("an exception occurred while creating account with name " + admin +" in domain " + domainId, e);
90+
}
91+
} else {
92+
s_logger.debug("an account with name " + admin + " already exists in the domain " + domainId);
93+
}
94+
} else {
95+
s_logger.debug("ldap user with username "+admin+" is disabled in the given group/ou");
96+
}
97+
}
98+
response.setObjectName("LinkDomainToLdap");
99+
response.setResponseName(getCommandName());
100+
setResponseObject(response);
101+
} catch (final InvalidParameterValueException e) {
102+
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.toString());
103+
}
104+
}
105+
106+
@Override
107+
public String getCommandName() {
108+
return s_name;
109+
}
110+
111+
@Override
112+
public long getEntityOwnerId() {
113+
return Account.ACCOUNT_ID_SYSTEM;
114+
}
115+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.cloudstack.api.response;
20+
21+
import com.cloud.serializer.Param;
22+
import com.google.gson.annotations.SerializedName;
23+
import org.apache.cloudstack.api.ApiConstants;
24+
import org.apache.cloudstack.api.BaseResponse;
25+
26+
public class LinkDomainToLdapResponse extends BaseResponse {
27+
28+
@SerializedName(ApiConstants.DOMAIN_ID)
29+
@Param(description = "id of the Domain which is linked to LDAP")
30+
private long domainId;
31+
32+
@SerializedName(ApiConstants.NAME)
33+
@Param(description = "name of the group or OU in LDAP which is linked to the domain")
34+
private String name;
35+
36+
@SerializedName(ApiConstants.TYPE)
37+
@Param(description = "type of the name in LDAP which is linke to the domain")
38+
private String type;
39+
40+
@SerializedName(ApiConstants.ACCOUNT_TYPE)
41+
@Param(description = "Type of the account to auto import")
42+
private short accountType;
43+
44+
@SerializedName(ApiConstants.ACCOUNT_ID)
45+
@Param(description = "Domain Admin accountId that is created")
46+
private String adminId;
47+
48+
public LinkDomainToLdapResponse(long domainId, String type, String name, short accountType) {
49+
this.domainId = domainId;
50+
this.name = name;
51+
this.type = type;
52+
this.accountType = accountType;
53+
}
54+
55+
public long getDomainId() {
56+
return domainId;
57+
}
58+
59+
public String getName() {
60+
return name;
61+
}
62+
63+
public String getType() {
64+
return type;
65+
}
66+
67+
public short getAccountType() {
68+
return accountType;
69+
}
70+
71+
public String getAdminId() {
72+
return adminId;
73+
}
74+
75+
public void setAdminId(String adminId) {
76+
this.adminId = adminId;
77+
}
78+
}

plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/ADLdapUserManagerImpl.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232

3333
public class ADLdapUserManagerImpl extends OpenLdapUserManagerImpl implements LdapUserManager {
3434
public static final Logger s_logger = Logger.getLogger(ADLdapUserManagerImpl.class.getName());
35-
private static final String MICROSOFT_AD_NESTED_MEMBERS_FILTER = "memberOf:1.2.840.113556.1.4.1941";
35+
private static final String MICROSOFT_AD_NESTED_MEMBERS_FILTER = "memberOf:1.2.840.113556.1.4.1941:";
36+
private static final String MICROSOFT_AD_MEMBERS_FILTER = "memberOf";
3637

3738
@Override
3839
public List<LdapUser> getUsersInGroup(String groupName, LdapContext context) throws NamingException {
@@ -66,7 +67,7 @@ private String generateADGroupSearchFilter(String groupName) {
6667

6768
final StringBuilder memberOfFilter = new StringBuilder();
6869
String groupCnName = _ldapConfiguration.getCommonNameAttribute() + "=" +groupName + "," + _ldapConfiguration.getBaseDn();
69-
memberOfFilter.append("(" + MICROSOFT_AD_NESTED_MEMBERS_FILTER + ":=");
70+
memberOfFilter.append("(").append(getMemberOfAttribute()).append("=");
7071
memberOfFilter.append(groupCnName);
7172
memberOfFilter.append(")");
7273

@@ -79,4 +80,25 @@ private String generateADGroupSearchFilter(String groupName) {
7980
s_logger.debug("group search filter = " + result);
8081
return result.toString();
8182
}
83+
84+
protected boolean isUserDisabled(SearchResult result) throws NamingException {
85+
boolean isDisabledUser = false;
86+
String userAccountControl = LdapUtils.getAttributeValue(result.getAttributes(), _ldapConfiguration.getUserAccountControlAttribute());
87+
if (userAccountControl != null) {
88+
int control = Integer.valueOf(userAccountControl);
89+
// second bit represents disabled user flag in AD
90+
if ((control & 2) > 0) {
91+
isDisabledUser = true;
92+
}
93+
}
94+
return isDisabledUser;
95+
}
96+
97+
protected String getMemberOfAttribute() {
98+
if(_ldapConfiguration.isNestedGroupsEnabled()) {
99+
return MICROSOFT_AD_NESTED_MEMBERS_FILTER;
100+
} else {
101+
return MICROSOFT_AD_MEMBERS_FILTER;
102+
}
103+
}
82104
}

plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
package org.apache.cloudstack.ldap;
1818

1919
import com.cloud.server.auth.DefaultUserAuthenticator;
20+
import com.cloud.user.Account;
21+
import com.cloud.user.AccountManager;
22+
import com.cloud.user.User;
2023
import com.cloud.user.UserAccount;
2124
import com.cloud.user.dao.UserAccountDao;
2225
import com.cloud.utils.Pair;
@@ -25,6 +28,7 @@
2528

2629
import javax.inject.Inject;
2730
import java.util.Map;
31+
import java.util.UUID;
2832

2933
public class LdapAuthenticator extends DefaultUserAuthenticator {
3034
private static final Logger s_logger = Logger.getLogger(LdapAuthenticator.class.getName());
@@ -33,6 +37,8 @@ public class LdapAuthenticator extends DefaultUserAuthenticator {
3337
private LdapManager _ldapManager;
3438
@Inject
3539
private UserAccountDao _userAccountDao;
40+
@Inject
41+
private AccountManager _accountManager;
3642

3743
public LdapAuthenticator() {
3844
super();
@@ -52,21 +58,71 @@ public Pair<Boolean, ActionOnFailedAuthentication> authenticate(final String use
5258
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
5359
}
5460

55-
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
61+
boolean result = false;
62+
ActionOnFailedAuthentication action = null;
5663

57-
if (user == null) {
58-
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
59-
return new Pair<Boolean, ActionOnFailedAuthentication>(false, null);
60-
} else if (_ldapManager.isLdapEnabled()) {
61-
boolean result = _ldapManager.canAuthenticate(username, password);
62-
ActionOnFailedAuthentication action = null;
63-
if (result == false) {
64+
if (_ldapManager.isLdapEnabled()) {
65+
final UserAccount user = _userAccountDao.getUserAccount(username, domainId);
66+
LdapTrustMapVO ldapTrustMapVO = _ldapManager.getDomainLinkedToLdap(domainId);
67+
if(ldapTrustMapVO != null) {
68+
try {
69+
LdapUser ldapUser = _ldapManager.getUser(username, ldapTrustMapVO.getType().toString(), ldapTrustMapVO.getName());
70+
if(!ldapUser.isDisabled()) {
71+
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
72+
if(result) {
73+
if(user == null) {
74+
// import user to cloudstack
75+
createCloudStackUserAccount(ldapUser, domainId, ldapTrustMapVO.getAccountType());
76+
} else {
77+
enableUserInCloudStack(user);
78+
}
79+
}
80+
} else {
81+
//disable user in cloudstack
82+
disableUserInCloudStack(user);
83+
}
84+
} catch (NoLdapUserMatchingQueryException e) {
85+
s_logger.debug(e.getMessage());
86+
}
87+
88+
} else {
89+
//domain is not linked to ldap follow normal authentication
90+
if(user != null ) {
91+
try {
92+
LdapUser ldapUser = _ldapManager.getUser(username);
93+
if(!ldapUser.isDisabled()) {
94+
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password);
95+
} else {
96+
s_logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
97+
}
98+
} catch (NoLdapUserMatchingQueryException e) {
99+
s_logger.debug(e.getMessage());
100+
}
101+
}
102+
}
103+
if (!result && user != null) {
64104
action = ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT;
65105
}
66-
return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
106+
}
107+
108+
return new Pair<Boolean, ActionOnFailedAuthentication>(result, action);
109+
}
110+
111+
private void enableUserInCloudStack(UserAccount user) {
112+
if(user != null && (user.getState().equalsIgnoreCase(Account.State.disabled.toString()))) {
113+
_accountManager.enableUser(user.getId());
114+
}
115+
}
116+
117+
private void createCloudStackUserAccount(LdapUser user, long domainId, short accountType) {
118+
String username = user.getUsername();
119+
_accountManager.createUserAccount(username, "", user.getFirstname(), user.getLastname(), user.getEmail(), null, username, accountType, domainId, username, null,
120+
UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP);
121+
}
67122

68-
} else {
69-
return new Pair<Boolean, ActionOnFailedAuthentication>(false, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
123+
private void disableUserInCloudStack(UserAccount user) {
124+
if (user != null) {
125+
_accountManager.disableUser(user.getId());
70126
}
71127
}
72128

0 commit comments

Comments
 (0)