/* * 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.ranger.biz; import java.util.ArrayList; import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.Logger; import org.apache.ranger.common.DateUtil; import org.apache.ranger.common.HTTPUtil; import org.apache.ranger.common.MessageEnums; import org.apache.ranger.common.PropertiesUtil; import org.apache.ranger.common.RESTErrorUtil; import org.apache.ranger.common.RangerCommonEnums; import org.apache.ranger.common.RangerConstants; 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.entity.XXAuthSession; import org.apache.ranger.entity.XXPortalUser; import org.apache.ranger.entity.XXPortalUserRole; import org.apache.ranger.entity.XXUser; import org.apache.ranger.security.context.RangerContextHolder; import org.apache.ranger.security.context.RangerSecurityContext; import org.apache.ranger.security.listener.RangerHttpSessionListener; import org.apache.ranger.security.web.filter.RangerSecurityContextFormationFilter; import org.apache.ranger.service.AuthSessionService; import org.apache.ranger.util.RestUtil; import org.apache.ranger.view.VXAuthSession; import org.apache.ranger.view.VXAuthSessionList; import org.apache.ranger.view.VXLong; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Component @Transactional public class SessionMgr { static final Logger logger = Logger.getLogger(SessionMgr.class); @Autowired RESTErrorUtil restErrorUtil; @Autowired RangerDaoManager daoManager; @Autowired XUserMgr xUserMgr; @Autowired AuthSessionService authSessionService; @Autowired HTTPUtil httpUtil; @Autowired StringUtil stringUtil; public SessionMgr() { logger.debug("SessionManager created"); } private static final Long SESSION_UPDATE_INTERVAL_IN_MILLIS = 30 * DateUtils.MILLIS_PER_MINUTE; public UserSessionBase processSuccessLogin(int authType, String userAgent, HttpServletRequest httpRequest) { boolean newSessionCreation = true; UserSessionBase userSession = null; RangerSecurityContext context = RangerContextHolder.getSecurityContext(); if (context != null) { userSession = context.getUserSession(); } Authentication authentication = SecurityContextHolder.getContext() .getAuthentication(); WebAuthenticationDetails details = (WebAuthenticationDetails) authentication .getDetails(); String currentLoginId = authentication.getName(); if (userSession != null) { if (validateUserSession(userSession, currentLoginId)) { newSessionCreation = false; } } if (newSessionCreation) { getSSOSpnegoAuthCheckForAPI(currentLoginId, httpRequest); // Need to build the UserSession XXPortalUser gjUser = daoManager.getXXPortalUser().findByLoginId(currentLoginId); if (gjUser == null) { logger.error( "Error getting user for loginId=" + currentLoginId, new Exception()); return null; } XXAuthSession gjAuthSession = new XXAuthSession(); gjAuthSession.setLoginId(currentLoginId); gjAuthSession.setUserId(gjUser.getId()); gjAuthSession.setAuthTime(DateUtil.getUTCDate()); gjAuthSession.setAuthStatus(XXAuthSession.AUTH_STATUS_SUCCESS); gjAuthSession.setAuthType(authType); if (details != null) { gjAuthSession.setExtSessionId(details.getSessionId()); gjAuthSession.setRequestIP(details.getRemoteAddress()); } if (userAgent != null) { gjAuthSession.setRequestUserAgent(userAgent); } gjAuthSession.setDeviceType(httpUtil.getDeviceType(userAgent)); HttpSession session = httpRequest.getSession(); if (session != null) { if (session.getAttribute("auditLoginId") == null) { synchronized (session) { if (session.getAttribute("auditLoginId") == null) { boolean isDownloadLogEnabled = PropertiesUtil.getBooleanProperty("ranger.downloadpolicy.session.log.enabled", false); if (isDownloadLogEnabled){ gjAuthSession = storeAuthSession(gjAuthSession); session.setAttribute("auditLoginId", gjAuthSession.getId()); } else if (!StringUtils.isEmpty(httpRequest.getRequestURI()) && !(httpRequest.getRequestURI().contains("/secure/policies/download/") || httpRequest.getRequestURI().contains("/secure/download/"))){ gjAuthSession = storeAuthSession(gjAuthSession); session.setAttribute("auditLoginId", gjAuthSession.getId()); }else if (StringUtils.isEmpty(httpRequest.getRequestURI())){ gjAuthSession = storeAuthSession(gjAuthSession); session.setAttribute("auditLoginId", gjAuthSession.getId()); }else{ //NOPMD //do not log the details for download policy and tag } } } } } userSession = new UserSessionBase(); userSession.setXXPortalUser(gjUser); userSession.setXXAuthSession(gjAuthSession); if(httpRequest.getAttribute("spnegoEnabled") != null && (boolean)httpRequest.getAttribute("spnegoEnabled")){ userSession.setSpnegoEnabled(true); } resetUserSessionForProfiles(userSession); resetUserModulePermission(userSession); Calendar cal = Calendar.getInstance(); if (details != null) { logger.info("Login Success: loginId=" + currentLoginId + ", sessionId=" + gjAuthSession.getId() + ", sessionId=" + details.getSessionId() + ", requestId=" + details.getRemoteAddress() + ", epoch=" + cal.getTimeInMillis()); } else { logger.info("Login Success: loginId=" + currentLoginId + ", sessionId=" + gjAuthSession.getId() + ", details is null" + ", epoch=" + cal.getTimeInMillis()); } } return userSession; } private void getSSOSpnegoAuthCheckForAPI(String currentLoginId, HttpServletRequest request) { RangerSecurityContext context = RangerContextHolder.getSecurityContext(); UserSessionBase session = context != null ? context.getUserSession() : null; boolean ssoEnabled = session != null ? session.isSSOEnabled() : PropertiesUtil.getBooleanProperty("ranger.sso.enabled", false); XXPortalUser gjUser = daoManager.getXXPortalUser().findByLoginId(currentLoginId); if (gjUser == null && ((request.getAttribute("spnegoEnabled") != null && (boolean)request.getAttribute("spnegoEnabled")) || (ssoEnabled))) { if(logger.isDebugEnabled()){ logger.debug("User : "+currentLoginId+" doesn't exist in Ranger DB So creating user as it's SSO or Spnego authenticated"); } xUserMgr.createServiceConfigUser(currentLoginId); } } public void resetUserModulePermission(UserSessionBase userSession) { XXUser xUser = daoManager.getXXUser().findByUserName(userSession.getLoginId()); if (xUser != null) { List<String> permissionList = daoManager.getXXModuleDef().findAccessibleModulesByUserId(userSession.getUserId(), xUser.getId()); CopyOnWriteArraySet<String> userPermissions = new CopyOnWriteArraySet<String>(permissionList); UserSessionBase.RangerUserPermission rangerUserPermission = userSession.getRangerUserPermission(); if (rangerUserPermission == null) { rangerUserPermission = new UserSessionBase.RangerUserPermission(); } rangerUserPermission.setUserPermissions(userPermissions); rangerUserPermission.setLastUpdatedTime(Calendar.getInstance().getTimeInMillis()); userSession.setRangerUserPermission(rangerUserPermission); logger.info("UserSession Updated to set new Permissions to User: " + userSession.getLoginId()); } else { logger.error("No XUser found with username: " + userSession.getLoginId() + "So Permission is not set for the user"); } } public void resetUserSessionForProfiles(UserSessionBase userSession) { if (userSession == null) { // Nothing to reset return; } // Let's get the Current User Again String currentLoginId = userSession.getLoginId(); XXPortalUser gjUser = daoManager.getXXPortalUser().findByLoginId(currentLoginId); userSession.setXXPortalUser(gjUser); setUserRoles(userSession); } private void setUserRoles(UserSessionBase userSession) { List<String> strRoleList = new ArrayList<String>(); List<XXPortalUserRole> roleList = daoManager.getXXPortalUserRole().findByUserId( userSession.getUserId()); for (XXPortalUserRole gjUserRole : roleList) { String userRole = gjUserRole.getUserRole(); strRoleList.add(userRole); } if (strRoleList.contains(RangerConstants.ROLE_SYS_ADMIN)) { userSession.setUserAdmin(true); userSession.setKeyAdmin(false); } else if (strRoleList.contains(RangerConstants.ROLE_KEY_ADMIN)) { userSession.setKeyAdmin(true); userSession.setUserAdmin(false); } else if (strRoleList.size() == 1 && RangerConstants.ROLE_USER.equals(strRoleList.get(0))) { userSession.setKeyAdmin(false); userSession.setUserAdmin(false); } userSession.setUserRoleList(strRoleList); } public XXAuthSession processFailureLogin(int authStatus, int authType, String loginId, String remoteAddr, String sessionId) { XXAuthSession gjAuthSession = new XXAuthSession(); gjAuthSession.setLoginId(loginId); gjAuthSession.setUserId(null); gjAuthSession.setAuthTime(DateUtil.getUTCDate()); gjAuthSession.setAuthStatus(authStatus); gjAuthSession.setAuthType(authType); gjAuthSession.setDeviceType(RangerCommonEnums.DEVICE_UNKNOWN); gjAuthSession.setExtSessionId(sessionId); gjAuthSession.setRequestIP(remoteAddr); gjAuthSession.setRequestUserAgent(null); gjAuthSession = storeAuthSession(gjAuthSession); return gjAuthSession; } protected boolean validateUserSession(UserSessionBase userSession, String currentLoginId) { if (currentLoginId .equalsIgnoreCase(userSession.getXXPortalUser().getLoginId())) { return true; } else { logger.info( "loginId doesn't match loginId from HTTPSession. Will create new session. loginId=" + currentLoginId + ", userSession=" + userSession, new Exception()); return false; } } @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) protected XXAuthSession storeAuthSession(XXAuthSession gjAuthSession) { // daoManager.getEntityManager().getTransaction().begin(); XXAuthSession dbMAuthSession = daoManager.getXXAuthSession().create( gjAuthSession); // daoManager.getEntityManager().getTransaction().commit(); return dbMAuthSession; } // non-WEB processing public UserSessionBase processStandaloneSuccessLogin(int authType, String ipAddress) { Authentication authentication = SecurityContextHolder.getContext() .getAuthentication(); String currentLoginId = authentication.getName(); // Need to build the UserSession XXPortalUser gjUser = daoManager.getXXPortalUser().findByLoginId(currentLoginId); if (gjUser == null) { logger.error("Error getting user for loginId=" + currentLoginId, new Exception()); return null; } XXAuthSession gjAuthSession = new XXAuthSession(); gjAuthSession.setLoginId(currentLoginId); gjAuthSession.setUserId(gjUser.getId()); gjAuthSession.setAuthTime(DateUtil.getUTCDate()); gjAuthSession.setAuthStatus(XXAuthSession.AUTH_STATUS_SUCCESS); gjAuthSession.setAuthType(authType); gjAuthSession.setDeviceType(RangerCommonEnums.DEVICE_UNKNOWN); gjAuthSession.setExtSessionId(null); gjAuthSession.setRequestIP(ipAddress); gjAuthSession.setRequestUserAgent(null); gjAuthSession = storeAuthSession(gjAuthSession); UserSessionBase userSession = new UserSessionBase(); userSession.setXXPortalUser(gjUser); userSession.setXXAuthSession(gjAuthSession); // create context with user-session and set in thread-local RangerSecurityContext context = new RangerSecurityContext(); context.setUserSession(userSession); RangerContextHolder.setSecurityContext(context); resetUserSessionForProfiles(userSession); resetUserModulePermission(userSession); return userSession; } /** * @param searchCriteria * @return */ public VXAuthSessionList searchAuthSessions(SearchCriteria searchCriteria) { if (searchCriteria == null) { searchCriteria = new SearchCriteria(); } if (searchCriteria.getParamList() != null && !searchCriteria.getParamList().isEmpty()) { int clientTimeOffsetInMinute=RestUtil.getClientTimeOffset(); java.util.Date temp = null; DateUtil dateUtil = new DateUtil(); if (searchCriteria.getParamList().containsKey("startDate")) { temp = (java.util.Date) searchCriteria.getParamList().get( "startDate"); temp = dateUtil.getDateFromGivenDate(temp, 0, 0, 0, 0); temp = dateUtil.addTimeOffset(temp, clientTimeOffsetInMinute); searchCriteria.getParamList().put("startDate", temp); } if (searchCriteria.getParamList().containsKey("endDate")) { temp = (java.util.Date) searchCriteria.getParamList().get( "endDate"); temp = dateUtil.getDateFromGivenDate(temp, 0, 23, 59, 59); temp = dateUtil.addTimeOffset(temp, clientTimeOffsetInMinute); searchCriteria.getParamList().put("endDate", temp); } } return authSessionService.search(searchCriteria); } public VXLong countAuthSessions(SearchCriteria searchCriteria) { return authSessionService.getSearchCount(searchCriteria, AuthSessionService.AUTH_SESSION_SEARCH_FLDS); } public VXAuthSession getAuthSession(Long id) { return authSessionService.readResource(id); } public VXAuthSession getAuthSessionBySessionId(String authSessionId) { if(stringUtil.isEmpty(authSessionId)){ throw restErrorUtil.createRESTException("Please provide the auth session id.", MessageEnums.INVALID_INPUT_DATA); } XXAuthSession xXAuthSession = daoManager.getXXAuthSession() .getAuthSessionBySessionId(authSessionId); if(xXAuthSession==null){ throw restErrorUtil.createRESTException("Please provide a valid " + "session id.", MessageEnums.INVALID_INPUT_DATA); } VXAuthSession vXAuthSession = authSessionService.populateViewBean(xXAuthSession); return vXAuthSession; } public boolean isValidXAUser(String loginId) { XXPortalUser pUser = daoManager.getXXPortalUser().findByLoginId(loginId); if (pUser == null) { logger.error("Error getting user for loginId=" + loginId); return false; } else { logger.info(loginId+" is a valid user"); return true; } } public CopyOnWriteArrayList<UserSessionBase> getActiveSessionsOnServer() { CopyOnWriteArrayList<HttpSession> activeHttpUserSessions = RangerHttpSessionListener.getActiveSessionOnServer(); CopyOnWriteArrayList<UserSessionBase> activeRangerUserSessions = new CopyOnWriteArrayList<UserSessionBase>(); if (CollectionUtils.isEmpty(activeHttpUserSessions)) { return activeRangerUserSessions; } for (HttpSession httpSession : activeHttpUserSessions) { if (httpSession.getAttribute(RangerSecurityContextFormationFilter.AKA_SC_SESSION_KEY) == null) { continue; } RangerSecurityContext securityContext = (RangerSecurityContext) httpSession.getAttribute(RangerSecurityContextFormationFilter.AKA_SC_SESSION_KEY); if (securityContext.getUserSession() != null) { activeRangerUserSessions.add(securityContext.getUserSession()); } } return activeRangerUserSessions; } public Set<UserSessionBase> getActiveUserSessionsForPortalUserId(Long portalUserId) { CopyOnWriteArrayList<UserSessionBase> activeSessions = getActiveSessionsOnServer(); if (CollectionUtils.isEmpty(activeSessions)) { return null; } Set<UserSessionBase> activeUserSessions = new HashSet<UserSessionBase>(); for (UserSessionBase session : activeSessions) { if (session.getUserId().equals(portalUserId)) { activeUserSessions.add(session); } } if (logger.isDebugEnabled()) { logger.debug("No Session Found with portalUserId: " + portalUserId); } return activeUserSessions; } public Set<UserSessionBase> getActiveUserSessionsForXUserId(Long xUserId) { XXPortalUser portalUser = daoManager.getXXPortalUser().findByXUserId(xUserId); if (portalUser != null) { return getActiveUserSessionsForPortalUserId(portalUser.getId()); } else { if (logger.isDebugEnabled()) { logger.debug("Could not find corresponding portalUser for xUserId" + xUserId); } return null; } } public synchronized void refreshPermissionsIfNeeded(UserSessionBase userSession) { if (userSession != null) { Long lastUpdatedTime = (userSession.getRangerUserPermission() != null) ? userSession.getRangerUserPermission().getLastUpdatedTime() : null; if (lastUpdatedTime == null || (Calendar.getInstance().getTimeInMillis() - lastUpdatedTime) > SESSION_UPDATE_INTERVAL_IN_MILLIS) { this.resetUserModulePermission(userSession); } } } }