This is an automated email from the ASF dual-hosted git repository.

madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 943a3a0  RANGER-2362: lockout login after too many failure attempts
943a3a0 is described below

commit 943a3a0bb02e7897c7b621994c244733c9dc0d2b
Author: ZhouTianling <[email protected]>
AuthorDate: Thu Mar 17 20:01:04 2022 +0800

    RANGER-2362: lockout login after too many failure attempts
    
    Signed-off-by: Madhan Neethiraj <[email protected]>
---
 .../java/org/apache/ranger/biz/SessionMgr.java     | 29 +++++++++++++++++++++-
 .../org/apache/ranger/db/XXAuthSessionDao.java     | 13 ++++++++++
 .../handler/RangerAuthenticationProvider.java      | 15 +++++++++++
 .../security/listener/SpringEventListener.java     | 16 +++++++++++-
 .../main/resources/META-INF/jpa_named_queries.xml  | 12 +++++++++
 .../conf.dist/ranger-admin-default-site.xml        | 13 ++++++++++
 6 files changed, 96 insertions(+), 2 deletions(-)

diff --git a/security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java 
b/security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java
index 6b002cf..3f56448 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java
@@ -44,6 +44,7 @@ import org.apache.ranger.common.SearchCriteria;
 import org.apache.ranger.common.StringUtil;
 import org.apache.ranger.common.UserSessionBase;
 import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXAuthSessionDao;
 import org.apache.ranger.entity.XXAuthSession;
 import org.apache.ranger.entity.XXPortalUser;
 import org.apache.ranger.entity.XXPortalUserRole;
@@ -453,7 +454,33 @@ public class SessionMgr {
                VXAuthSession vXAuthSession = 
authSessionService.populateViewBean(xXAuthSession);
                return vXAuthSession;
        }
-       
+
+       /**
+        * Check whether the user failed to log in so many times that we need 
to lock it for
+        * a while. The current limit of is to fail at most n times in a 
sliding time window,
+        * otherwise the login verification will not be performed in the future.
+        * @param loginId
+        * @return
+        */
+       public boolean isLoginIdLocked(String loginId) {
+               boolean ret             = false;
+               boolean autoLockEnabled = 
PropertiesUtil.getBooleanProperty("ranger.admin.login.autolock.enabled", true);
+
+               if (autoLockEnabled) {
+                       int  windowSeconds    = 
PropertiesUtil.getIntProperty("ranger.admin.login.autolock.window.seconds", 
300);
+                       int  maxFailuresCount = 
PropertiesUtil.getIntProperty("ranger.admin.login.autolock.maxfailure", 5);
+                       long failuresCount    = 
daoManager.getXXAuthSession().getRecentAuthFailureCountByLoginId(loginId, 
windowSeconds);
+
+                       ret = failuresCount >= maxFailuresCount;
+
+                       if (logger.isDebugEnabled()) {
+                               logger.debug("isLoginIdLocked(loginId={}): 
windowSeconds={}, maxFailuresCount={}, failuresCount={}, ret={}", loginId, 
windowSeconds, maxFailuresCount, failuresCount, ret);
+                       }
+               }
+
+               return ret;
+       }
+
        public boolean isValidXAUser(String loginId) {
                XXPortalUser pUser = 
daoManager.getXXPortalUser().findByLoginId(loginId);
                if (pUser == null) {
diff --git 
a/security-admin/src/main/java/org/apache/ranger/db/XXAuthSessionDao.java 
b/security-admin/src/main/java/org/apache/ranger/db/XXAuthSessionDao.java
index b0270e9..934d258 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXAuthSessionDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXAuthSessionDao.java
@@ -19,10 +19,12 @@
 
  package org.apache.ranger.db;
 
+import java.util.Date;
 import java.util.List;
 
 import javax.persistence.NoResultException;
 
+import org.apache.ranger.common.DateUtil;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXAuthSession;
 import org.springframework.stereotype.Service;
@@ -63,5 +65,16 @@ public class XXAuthSessionDao extends BaseDao<XXAuthSession> 
{
                        return null;
                }
        }
+
+       public long getRecentAuthFailureCountByLoginId(String loginId, int 
timeRangezSecond){
+               Date authWindowStartTime = new 
Date(DateUtil.getUTCDate().getTime() - timeRangezSecond * 1000);
+
+               return getEntityManager()
+                               
.createNamedQuery("XXAuthSession.getRecentAuthFailureCountByLoginId", 
Long.class)
+                               .setParameter("loginId", loginId)
+                               .setParameter("authWindowStartTime", 
authWindowStartTime)
+                               .getSingleResult();
+       }
+
 }
 
diff --git 
a/security-admin/src/main/java/org/apache/ranger/security/handler/RangerAuthenticationProvider.java
 
b/security-admin/src/main/java/org/apache/ranger/security/handler/RangerAuthenticationProvider.java
index 8f7abbe..efd5417 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/security/handler/RangerAuthenticationProvider.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/security/handler/RangerAuthenticationProvider.java
@@ -41,6 +41,7 @@ import 
org.springframework.ldap.core.support.LdapContextSource;
 import org.springframework.security.authentication.AuthenticationProvider;
 import 
org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.LockedException;
 import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import 
org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider;
 import 
org.springframework.security.authentication.jaas.memory.InMemoryConfiguration;
@@ -62,6 +63,7 @@ import 
org.springframework.security.authentication.dao.DaoAuthenticationProvider
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.apache.ranger.biz.UserMgr;
+import org.apache.ranger.biz.SessionMgr;
 
 
 
@@ -73,7 +75,12 @@ public class RangerAuthenticationProvider implements 
AuthenticationProvider {
 
        @Autowired
        UserMgr userMgr;
+
+       @Autowired
+       SessionMgr sessionMgr;
+
        private static final Logger logger = 
LoggerFactory.getLogger(RangerAuthenticationProvider.class);
+
        private String rangerAuthenticationMethod;
 
        private LdapAuthenticator authenticator;
@@ -137,6 +144,14 @@ public class RangerAuthenticationProvider implements 
AuthenticationProvider {
                                        return authentication;
                                }
                        }
+
+                       // Following are JDBC
+                       if 
(sessionMgr.isLoginIdLocked(authentication.getName())) {
+                               logger.debug("Failed to authenticate since user 
account is locked");
+
+                               throw new LockedException(String.format("User 
account {} is locked", authentication.getName()));
+                       }
+
                        if (this.isFipsEnabled) {
                                try {
                                        authentication = 
getJDBCAuthentication(authentication,"");
diff --git 
a/security-admin/src/main/java/org/apache/ranger/security/listener/SpringEventListener.java
 
b/security-admin/src/main/java/org/apache/ranger/security/listener/SpringEventListener.java
index af5622a..9b048a0 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/security/listener/SpringEventListener.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/security/listener/SpringEventListener.java
@@ -30,6 +30,7 @@ import 
org.springframework.security.authentication.event.AbstractAuthenticationE
 import 
org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
 import 
org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
 import 
org.springframework.security.authentication.event.AuthenticationSuccessEvent;
+import 
org.springframework.security.authentication.event.AuthenticationFailureLockedEvent;
 import org.springframework.security.core.Authentication;
 import 
org.springframework.security.web.authentication.WebAuthenticationDetails;
 
@@ -49,6 +50,8 @@ public class SpringEventListener implements
                process((AuthenticationSuccessEvent) event);
            } else if (event instanceof 
AuthenticationFailureBadCredentialsEvent) {
                process((AuthenticationFailureBadCredentialsEvent) event);
+           } else if (event instanceof AuthenticationFailureLockedEvent) {
+               process((AuthenticationFailureLockedEvent) event);
            } else if (event instanceof AuthenticationFailureDisabledEvent) {
                process((AuthenticationFailureDisabledEvent) event);
            }
@@ -93,6 +96,17 @@ public class SpringEventListener implements
                remoteAddress, sessionId);
     }
 
+    protected void process(AuthenticationFailureLockedEvent authFailEvent) {
+               Authentication           auth          = 
authFailEvent.getAuthentication();
+               WebAuthenticationDetails details       = 
(WebAuthenticationDetails) auth.getDetails();
+               String                   remoteAddress = details != null ? 
details.getRemoteAddress() : "";
+               String                   sessionId     = details != null ? 
details.getSessionId() : "";
+
+               logger.info("Login Unsuccessful:" + auth.getName() + " | Ip 
Address:" + remoteAddress + " | User Locked");
+
+               
sessionMgr.processFailureLogin(XXAuthSession.AUTH_STATUS_LOCKED, 
XXAuthSession.AUTH_TYPE_PASSWORD, auth.getName(), remoteAddress, sessionId);
+       }
+
     protected void process(AuthenticationFailureDisabledEvent authFailEvent) {
        Authentication auth = authFailEvent.getAuthentication();
        WebAuthenticationDetails details = (WebAuthenticationDetails) auth
@@ -102,7 +116,7 @@ public class SpringEventListener implements
        String sessionId = details != null ? details.getSessionId() : "";
 
        logger.info("Login Unsuccessful:" + auth.getName() + " | Ip Address:"
-               + remoteAddress);
+               + remoteAddress + " | User Disabled");
 
        sessionMgr.processFailureLogin(XXAuthSession.AUTH_STATUS_DISABLED,
                XXAuthSession.AUTH_TYPE_PASSWORD, auth.getName(),
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml 
b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index b56cd26..2f50d71 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -24,6 +24,18 @@
                           WHERE obj.extSessionId = :sessionId
                </query>
        </named-query>
+       <named-query name="XXAuthSession.getRecentAuthFailureCountByLoginId">
+               <query>SELECT COUNT(1) FROM XXAuthSession obj
+                       WHERE obj.loginId = :loginId
+                         AND obj.authStatus != 1
+                         AND obj.createTime &gt; COALESCE(
+                           (SELECT MAX(obj2.createTime) FROM XXAuthSession obj2
+                             WHERE obj2.loginId = :loginId
+                               AND obj2.authStatus = 1
+                               AND obj2.createTime &gt; :authWindowStartTime),
+                           :authWindowStartTime)
+               </query>
+       </named-query>
 
        <!-- XXPortalUser -->
        <named-query name="XXPortalUser.findByEmailAddress">
diff --git 
a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml 
b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
index 2471f6a..e2bfc8f 100644
--- a/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
+++ b/security-admin/src/main/resources/conf.dist/ranger-admin-default-site.xml
@@ -157,6 +157,19 @@
                <value>1</value>
        </property>
 
+<!-- #auto lock when too many failed logon attempts -->
+       <property>
+               <name>ranger.admin.login.autolock.enabled</name>
+               <value>true</value>
+       </property>
+       <property>
+               <name>ranger.admin.login.autolock.window.seconds</name>
+               <value>300</value>
+       </property>
+       <property>
+               <name>ranger.admin.login.autolock.maxfailure</name>
+               <value>5</value>
+       </property>
 
 <!-- #hacks -->
        <property>

Reply via email to