Mark LDAP user query timeout as incorrect login instead of disabling user immediately (#11220)

* Mark LDAP user query timeout as incorrect login instead of disabling user immediately

* code improvements
This commit is contained in:
Suresh Kumar Anaparti 2025-07-25 19:31:43 +05:30 committed by GitHub
parent 890386e949
commit ed6ee6b704
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 35 deletions

View File

@ -143,7 +143,8 @@ public class LdapListUsersCmd extends BaseListCmd {
// now filter and annotate // now filter and annotate
ldapResponses = applyUserFilter(ldapResponses); ldapResponses = applyUserFilter(ldapResponses);
} catch (final NoLdapUserMatchingQueryException ex) { } catch (final NoLdapUserMatchingQueryException ex) {
// ok, we'll make do with the empty list ldapResponses = new ArrayList<LdapUserResponse>(); logger.debug(ex.getMessage());
// ok, we'll make do with the empty list
} finally { } finally {
response.setResponses(ldapResponses); response.setResponses(ldapResponses);
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());

View File

@ -45,6 +45,8 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
@Inject @Inject
private AccountManager _accountManager; private AccountManager _accountManager;
private static final String LDAP_READ_TIMED_OUT_MESSAGE = "LDAP response read timed out";
public LdapAuthenticator() { public LdapAuthenticator() {
super(); super();
} }
@ -174,12 +176,21 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
} }
} catch (NoLdapUserMatchingQueryException e) { } catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage()); logger.debug(e.getMessage());
disableUserInCloudStack(userAccount); processLdapUserErrorMessage(userAccount, e.getMessage(), rc);
} }
return rc; return rc;
} }
private void processLdapUserErrorMessage(UserAccount user, String errorMessage, Pair<Boolean, ActionOnFailedAuthentication> rc) {
if (StringUtils.isNotEmpty(errorMessage) && errorMessage.contains(LDAP_READ_TIMED_OUT_MESSAGE) && !rc.first()) {
rc.second(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
} else {
// no user in ldap ==>> disable user in cloudstack
disableUserInCloudStack(user);
}
}
private void tracelist(String msg, List<String> listToTrace) { private void tracelist(String msg, List<String> listToTrace) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
StringBuilder logMsg = new StringBuilder(); StringBuilder logMsg = new StringBuilder();
@ -229,8 +240,7 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
processLdapUser(password, domainId, user, rc, ldapUser, accountType); processLdapUser(password, domainId, user, rc, ldapUser, accountType);
} catch (NoLdapUserMatchingQueryException e) { } catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage()); logger.debug(e.getMessage());
// no user in ldap ==>> disable user in cloudstack processLdapUserErrorMessage(user, e.getMessage(), rc);
disableUserInCloudStack(user);
} }
return rc; return rc;
} }
@ -264,6 +274,7 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
*/ */
Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount user) { Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount user) {
boolean result = false; boolean result = false;
boolean timedOut = false;
if (user != null ) { if (user != null ) {
try { try {
@ -275,13 +286,16 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
} }
} catch (NoLdapUserMatchingQueryException e) { } catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage()); logger.debug(e.getMessage());
if (e.getMessage().contains(LDAP_READ_TIMED_OUT_MESSAGE)) {
timedOut = true;
} }
} }
return processResultAndAction(user, result); }
return processResultAndAction(user, result, timedOut);
} }
private Pair<Boolean, ActionOnFailedAuthentication> processResultAndAction(UserAccount user, boolean result) { private Pair<Boolean, ActionOnFailedAuthentication> processResultAndAction(UserAccount user, boolean result, boolean timedOut) {
return (!result && user != null) ? return (!result && (user != null || timedOut)) ?
new Pair<Boolean, ActionOnFailedAuthentication>(result, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT): new Pair<Boolean, ActionOnFailedAuthentication>(result, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT):
new Pair<Boolean, ActionOnFailedAuthentication>(result, null); new Pair<Boolean, ActionOnFailedAuthentication>(result, null);
} }

View File

@ -303,8 +303,8 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUser(escapedUsername, context, domainId); return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUser(escapedUsername, context, domainId);
} catch (NamingException | IOException e) { } catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e); logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username); throw new NoLdapUserMatchingQueryException("Unable to find LDAP User for username: " + username + ", due to " + e.getMessage());
} finally { } finally {
closeContext(context); closeContext(context);
} }
@ -324,8 +324,8 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
LdapUserManager userManagerFactory = _ldapUserManagerFactory.getInstance(ldapProvider); LdapUserManager userManagerFactory = _ldapUserManagerFactory.getInstance(ldapProvider);
return userManagerFactory.getUser(escapedUsername, type, name, context, domainId); return userManagerFactory.getUser(escapedUsername, type, name, context, domainId);
} catch (NamingException | IOException e) { } catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e); logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username + " in group: " + name + " of type: " + type); throw new NoLdapUserMatchingQueryException("Unable to find LDAP User for username: " + username + " in group: " + name + " of type: " + type + ", due to " + e.getMessage());
} finally { } finally {
closeContext(context); closeContext(context);
} }
@ -338,7 +338,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
context = _ldapContextFactory.createBindContext(domainId); context = _ldapContextFactory.createBindContext(domainId);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsers(context, domainId); return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsers(context, domainId);
} catch (NamingException | IOException e) { } catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e); logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("*"); throw new NoLdapUserMatchingQueryException("*");
} finally { } finally {
closeContext(context); closeContext(context);
@ -352,7 +352,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
context = _ldapContextFactory.createBindContext(domainId); context = _ldapContextFactory.createBindContext(domainId);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsersInGroup(groupName, context, domainId); return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsersInGroup(groupName, context, domainId);
} catch (NamingException | IOException e) { } catch (NamingException | IOException e) {
logger.debug("ldap NamingException: ",e); logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("groupName=" + groupName); throw new NoLdapUserMatchingQueryException("groupName=" + groupName);
} finally { } finally {
closeContext(context); closeContext(context);
@ -390,7 +390,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username); final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUsers("*" + escapedUsername + "*", context, null); return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUsers("*" + escapedUsername + "*", context, null);
} catch (NamingException | IOException e) { } catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e); logger.debug("LDAP Exception: ",e);
throw new NoLdapUserMatchingQueryException(username); throw new NoLdapUserMatchingQueryException(username);
} finally { } finally {
closeContext(context); closeContext(context);