You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by sp...@apache.org on 2021/08/27 14:14:43 UTC
[ranger] branch ranger-2.2 updated: RANGER-3363: Added support in
ranger admin for handling session timeout requests with knox proxy
This is an automated email from the ASF dual-hosted git repository.
spolavarapu pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.2 by this push:
new fd90d0d RANGER-3363: Added support in ranger admin for handling session timeout requests with knox proxy
fd90d0d is described below
commit fd90d0d4d37b2a2ca4c82b641929153a4dfb31dd
Author: Sailaja Polavarapu <sp...@cloudera.com>
AuthorDate: Fri Aug 27 07:12:49 2021 -0700
RANGER-3363: Added support in ranger admin for handling session timeout requests with knox proxy
---
.../main/java/org/apache/ranger/rest/UserREST.java | 7 ++
.../RangerAuthenticationEntryPoint.java | 4 +-
.../web/filter/RangerKRBAuthenticationFilter.java | 44 +++++++++-
.../web/filter/RangerSSOAuthenticationFilter.java | 96 ++--------------------
.../main/java/org/apache/ranger/util/RestUtil.java | 85 +++++++++++++++++++
.../java/org/apache/ranger/view/VXPortalUser.java | 15 ++++
6 files changed, 158 insertions(+), 93 deletions(-)
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/UserREST.java b/security-admin/src/main/java/org/apache/ranger/rest/UserREST.java
index ffdf101..f91d7f4 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/UserREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/UserREST.java
@@ -20,7 +20,9 @@
package org.apache.ranger.rest;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
@@ -37,6 +39,7 @@ import org.apache.log4j.Logger;
import org.apache.ranger.biz.UserMgr;
import org.apache.ranger.biz.XUserMgr;
import org.apache.ranger.common.MessageEnums;
+import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerConfigUtil;
import org.apache.ranger.common.RangerConstants;
@@ -277,7 +280,11 @@ public class UserREST {
try {
logger.debug("getUserProfile(). httpSessionId="
+ request.getSession().getId());
+ Map<String, String> configProperties = new HashMap<>();
+ Long inactivityTimeout = PropertiesUtil.getLongProperty("ranger.service.inactivity.timeout", 15*60);
+ configProperties.put("inactivityTimeout", Long.toString(inactivityTimeout));
VXPortalUser userProfile = userManager.getUserProfileByLoginId();
+ userProfile.setConfigProperties(configProperties);
return userProfile;
} catch (Throwable t) {
logger.error(
diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/authentication/RangerAuthenticationEntryPoint.java b/security-admin/src/main/java/org/apache/ranger/security/web/authentication/RangerAuthenticationEntryPoint.java
index 3e56d9f..c2e4a3e 100644
--- a/security-admin/src/main/java/org/apache/ranger/security/web/authentication/RangerAuthenticationEntryPoint.java
+++ b/security-admin/src/main/java/org/apache/ranger/security/web/authentication/RangerAuthenticationEntryPoint.java
@@ -33,7 +33,7 @@ import org.apache.ranger.biz.SessionMgr;
import org.apache.ranger.common.JSONUtil;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RangerConfigUtil;
-import org.apache.ranger.security.web.filter.RangerSSOAuthenticationFilter;
+import org.apache.ranger.util.RestUtil;
import org.apache.ranger.view.VXResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
@@ -126,7 +126,7 @@ public class RangerAuthenticationEntryPoint extends
}
response.sendError(ajaxReturnCode, "");
} else if (!(requestURL.contains(servletPath))) {
- if(requestURL.contains(RangerSSOAuthenticationFilter.LOCAL_LOGIN_URL)){
+ if(requestURL.contains(RestUtil.LOCAL_LOGIN_URL)){
if (request.getSession() != null){
request.getSession().setAttribute("locallogin","true");
request.getServletContext().setAttribute(request.getSession().getId(), "locallogin");
diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerKRBAuthenticationFilter.java b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerKRBAuthenticationFilter.java
index 9877e14..c0ff06e 100644
--- a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerKRBAuthenticationFilter.java
+++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerKRBAuthenticationFilter.java
@@ -52,6 +52,7 @@ import javax.servlet.descriptor.JspConfigDescriptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.commons.collections.iterators.IteratorEnumeration;
import org.apache.hadoop.conf.Configuration;
@@ -65,6 +66,7 @@ import org.apache.ranger.biz.UserMgr;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.security.handler.RangerAuthenticationProvider;
+import org.apache.ranger.util.RestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -113,6 +115,8 @@ public class RangerKRBAuthenticationFilter extends RangerKrbFilter {
private static final String KERBEROS_TYPE = "kerberos";
private static final String S_USER = "suser";
+ private String originalUrlQueryParam = "originalUrl";
+ public static final String LOGOUT_URL = "/logout";
public RangerKRBAuthenticationFilter() {
try {
@@ -395,11 +399,45 @@ public class RangerKRBAuthenticationFilter extends RangerKrbFilter {
throw restErrorUtil.createRESTException("RangerKRBAuthenticationFilter Failed : "+e.getMessage());
}
}
- }else{
- filterChain.doFilter(request, response);
+ } else {
+ String action = httpRequest.getParameter("action");
+ String doAsUser = request.getParameter("doAs");
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("RangerKRBAuthenticationFilter: request URL = " + httpRequest.getRequestURI());
+ }
+
+ boolean allowTrustedProxy = PropertiesUtil.getBooleanProperty(ALLOW_TRUSTED_PROXY, false);
+
+ if (allowTrustedProxy && StringUtils.isNotEmpty(doAsUser) && existingAuth.isAuthenticated()
+ && StringUtils.equals(action, RestUtil.TIMEOUT_ACTION)) {
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+ String xForwardedURL = RestUtil.constructForwardableURL(httpRequest);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("xForwardedURL = " + xForwardedURL);
+ }
+ String logoutUrl = xForwardedURL;
+ logoutUrl = StringUtils.replace(logoutUrl, httpRequest.getRequestURI(), LOGOUT_URL);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("logoutUrl value is " + logoutUrl);
+ }
+ String redirectUrl = RestUtil.constructRedirectURL(httpRequest, logoutUrl, xForwardedURL, originalUrlQueryParam);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Redirect URL = " + redirectUrl);
+ LOG.debug("session id = " + httpRequest.getRequestedSessionId());
+ }
+
+ HttpSession httpSession = httpRequest.getSession(false);
+ if (httpSession != null) {
+ httpSession.invalidate();
+ }
+ httpResponse.sendRedirect(redirectUrl);
+ } else {
+ filterChain.doFilter(request, response);
+ }
}
}
-
+
private boolean isSpnegoEnable(String authType){
String principal = PropertiesUtil.getProperty(PRINCIPAL);
String keytabPath = PropertiesUtil.getProperty(KEYTAB);
diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java
index 6d35991..abbf2d9 100644
--- a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java
+++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java
@@ -26,6 +26,7 @@ import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jwt.SignedJWT;
+import org.apache.ranger.util.RestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -53,7 +54,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
-import java.util.Enumeration;
import java.util.List;
import org.apache.commons.lang.StringUtils;
@@ -88,9 +88,7 @@ public class RangerSSOAuthenticationFilter implements Filter {
public static final String JWT_EXPECTED_SIGALG = "ranger.sso.expected.sigalg";
public static final String JWT_DEFAULT_SIGALG = "RS256";
- public static final String LOCAL_LOGIN_URL = "locallogin";
public static final String DEFAULT_BROWSER_USERAGENT = "ranger.default.browser-useragents";
- public static final String PROXY_RANGER_URL_PATH = "/ranger";
private SSOAuthenticationProperties jwtProperties;
@@ -130,7 +128,7 @@ public class RangerSSOAuthenticationFilter implements Filter {
HttpServletRequest httpRequest = (HttpServletRequest)servletRequest;
- String xForwardedURL = constructForwardableURL(httpRequest);
+ String xForwardedURL = RestUtil.constructForwardableURL(httpRequest);
if (httpRequest.getRequestedSessionId() != null && !httpRequest.isRequestedSessionIdValid()){
synchronized(httpRequest.getServletContext()){
@@ -154,7 +152,7 @@ public class RangerSSOAuthenticationFilter implements Filter {
}
}
//If sso is enable and request is not for local login and is from browser then it will go inside and try for knox sso authentication
- if (ssoEnabled && !httpRequest.getRequestURI().contains(LOCAL_LOGIN_URL)) {
+ if (ssoEnabled && !httpRequest.getRequestURI().contains(RestUtil.LOCAL_LOGIN_URL)) {
//if jwt properties are loaded and is current not authenticated then it will go for sso authentication
//Note : Need to remove !isAuthenticated() after knoxsso solve the bug from cross-origin script
if (jwtProperties != null && !isAuthenticated()) {
@@ -203,7 +201,7 @@ public class RangerSSOAuthenticationFilter implements Filter {
httpServletResponse.setStatus(RangerConstants.SC_AUTHENTICATION_TIMEOUT);
httpServletResponse.setHeader("X-Rngr-Redirect-Url", ssourl);
} else {
- ssourl = constructLoginURL(httpRequest, xForwardedURL);
+ ssourl = RestUtil.constructRedirectURL(httpRequest, authenticationProviderUrl, xForwardedURL, originalUrlQueryParam);
if (LOG.isDebugEnabled()) {
LOG.debug("SSO URL = " + ssourl);
}
@@ -231,7 +229,7 @@ public class RangerSSOAuthenticationFilter implements Filter {
httpServletResponse.setStatus(RangerConstants.SC_AUTHENTICATION_TIMEOUT);
httpServletResponse.setHeader("X-Rngr-Redirect-Url", ssourl);
} else {
- ssourl = constructLoginURL(httpRequest, xForwardedURL);
+ ssourl = RestUtil.constructRedirectURL(httpRequest, authenticationProviderUrl, xForwardedURL, originalUrlQueryParam);
if (LOG.isDebugEnabled()) {
LOG.debug("SSO URL = " + ssourl);
}
@@ -246,11 +244,11 @@ public class RangerSSOAuthenticationFilter implements Filter {
else {
filterChain.doFilter(servletRequest, servletResponse);
}
- } else if(ssoEnabled && ((HttpServletRequest) servletRequest).getRequestURI().contains(LOCAL_LOGIN_URL) && isWebUserAgent(userAgent) && isAuthenticated()){
+ } else if(ssoEnabled && ((HttpServletRequest) servletRequest).getRequestURI().contains(RestUtil.LOCAL_LOGIN_URL) && isWebUserAgent(userAgent) && isAuthenticated()){
//If already there's an active session with sso and user want's to switch to local login(i.e without sso) then it won't be navigated to local login
// In this scenario the user as to use separate browser
- String url = ((HttpServletRequest) servletRequest).getRequestURI().replace(LOCAL_LOGIN_URL+"/", "");
- url = url.replace(LOCAL_LOGIN_URL, "");
+ String url = ((HttpServletRequest) servletRequest).getRequestURI().replace(RestUtil.LOCAL_LOGIN_URL+"/", "");
+ url = url.replace(RestUtil.LOCAL_LOGIN_URL, "");
LOG.warn("There is an active session and if you want local login to ranger, try this on a separate browser");
((HttpServletResponse)servletResponse).sendRedirect(url);
}
@@ -260,57 +258,6 @@ public class RangerSSOAuthenticationFilter implements Filter {
}
}
- private String constructForwardableURL(HttpServletRequest httpRequest) {
- String xForwardedProto = "";
- String xForwardedHost = "";
- String xForwardedContext = "";
- Enumeration<?> names = httpRequest.getHeaderNames();
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- Enumeration<?> values = httpRequest.getHeaders(name);
- String value = "";
- if (values != null) {
- while (values.hasMoreElements()) {
- value = (String) values.nextElement();
- }
- }
- if (StringUtils.trimToNull(name) != null && StringUtils.trimToNull(value) != null) {
- if (name.equalsIgnoreCase("x-forwarded-proto")) {
- xForwardedProto = value;
- } else if (name.equalsIgnoreCase("x-forwarded-host")) {
- xForwardedHost = value;
- } else if (name.equalsIgnoreCase("x-forwarded-context")) {
- xForwardedContext = value;
- }
- }
- }
- if (xForwardedHost.contains(",")) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("xForwardedHost value is " + xForwardedHost + " it contains multiple hosts, selecting the first host.");
- }
- xForwardedHost = xForwardedHost.split(",")[0].trim();
- }
- String xForwardedURL = "";
- if (StringUtils.trimToNull(xForwardedProto) != null) {
- //if header contains x-forwarded-host and x-forwarded-context
- if (StringUtils.trimToNull(xForwardedHost) != null && StringUtils.trimToNull(xForwardedContext) != null) {
- xForwardedURL = xForwardedProto + "://" + xForwardedHost + xForwardedContext + PROXY_RANGER_URL_PATH + httpRequest.getRequestURI();
- } else if (StringUtils.trimToNull(xForwardedHost) != null) {
- //if header contains x-forwarded-host and does not contains x-forwarded-context
- xForwardedURL = xForwardedProto + "://" + xForwardedHost + httpRequest.getRequestURI();
- } else {
- //if header does not contains x-forwarded-host and x-forwarded-context
- //preserve the x-forwarded-proto value coming from the request.
- String requestURL = httpRequest.getRequestURL().toString();
- if (StringUtils.trimToNull(requestURL) != null && requestURL.startsWith("http:")) {
- requestURL = requestURL.replaceFirst("http", xForwardedProto);
- }
- xForwardedURL = requestURL;
- }
- }
- return xForwardedURL;
- }
-
private Authentication getGrantedAuthority(Authentication authentication) {
UsernamePasswordAuthenticationToken result=null;
if(authentication!=null && authentication.isAuthenticated()){
@@ -394,33 +341,6 @@ public class RangerSSOAuthenticationFilter implements Filter {
}
/**
- * Create the URL to be used for authentication of the user in the absence
- * of a JWT token within the incoming request.
- *
- * @param request
- * for getting the original request URL
- * @return url to use as login url for redirect
- */
- protected String constructLoginURL(HttpServletRequest request, String xForwardedURL) {
- String delimiter = "?";
- if (authenticationProviderUrl.contains("?")) {
- delimiter = "&";
- }
- String loginURL = authenticationProviderUrl + delimiter + originalUrlQueryParam + "=";
- if (StringUtils.trimToNull(xForwardedURL) != null) {
- loginURL += xForwardedURL + getOriginalQueryString(request);
- } else {
- loginURL += request.getRequestURL().append(getOriginalQueryString(request));
- }
- return loginURL;
- }
-
- private String getOriginalQueryString(HttpServletRequest request) {
- String originalQueryString = request.getQueryString();
- return (originalQueryString == null) ? "" : "?" + originalQueryString;
- }
-
- /**
* This method provides a single method for validating the JWT for use in
* request processing. It provides for the override of specific aspects of
* this implementation through submethods used within but also allows for
diff --git a/security-admin/src/main/java/org/apache/ranger/util/RestUtil.java b/security-admin/src/main/java/org/apache/ranger/util/RestUtil.java
index 4d7388f..b66a7ae 100644
--- a/security-admin/src/main/java/org/apache/ranger/util/RestUtil.java
+++ b/security-admin/src/main/java/org/apache/ranger/util/RestUtil.java
@@ -22,13 +22,22 @@
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang.StringUtils;
import org.apache.ranger.security.context.RangerContextHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
+import java.util.Enumeration;
+
@Component
public class RestUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(RestUtil.class);
public static final String timeOffsetCookieName = "clientTimeOffset";
+ public static final String TIMEOUT_ACTION = "timeout";
+ private static final String PROXY_RANGER_URL_PATH = "/ranger";
+ public static final String LOCAL_LOGIN_URL = "locallogin";
public static Integer getTimeOffset(HttpServletRequest request) {
Integer cookieVal = 0;
@@ -74,4 +83,80 @@ public class RestUtil {
return clientTimeOffsetInMinute;
}
+ public static String constructForwardableURL(HttpServletRequest httpRequest) {
+ String xForwardedProto = "";
+ String xForwardedHost = "";
+ String xForwardedContext = "";
+ Enumeration<?> names = httpRequest.getHeaderNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+ Enumeration<?> values = httpRequest.getHeaders(name);
+ String value = "";
+ if (values != null) {
+ while (values.hasMoreElements()) {
+ value = (String) values.nextElement();
+ }
+ }
+ if (StringUtils.trimToNull(name) != null && StringUtils.trimToNull(value) != null) {
+ if (name.equalsIgnoreCase("x-forwarded-proto")) {
+ xForwardedProto = value;
+ } else if (name.equalsIgnoreCase("x-forwarded-host")) {
+ xForwardedHost = value;
+ } else if (name.equalsIgnoreCase("x-forwarded-context")) {
+ xForwardedContext = value;
+ }
+ }
+ }
+ if (xForwardedHost.contains(",")) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("xForwardedHost value is " + xForwardedHost + " it contains multiple hosts, selecting the first host.");
+ }
+ xForwardedHost = xForwardedHost.split(",")[0].trim();
+ }
+ String xForwardedURL = "";
+ if (StringUtils.trimToNull(xForwardedProto) != null) {
+ //if header contains x-forwarded-host and x-forwarded-context
+ if (StringUtils.trimToNull(xForwardedHost) != null && StringUtils.trimToNull(xForwardedContext) != null) {
+ xForwardedURL = xForwardedProto + "://" + xForwardedHost + xForwardedContext + PROXY_RANGER_URL_PATH + httpRequest.getRequestURI();
+ } else if (StringUtils.trimToNull(xForwardedHost) != null) {
+ //if header contains x-forwarded-host and does not contains x-forwarded-context
+ xForwardedURL = xForwardedProto + "://" + xForwardedHost + httpRequest.getRequestURI();
+ } else {
+ //if header does not contains x-forwarded-host and x-forwarded-context
+ //preserve the x-forwarded-proto value coming from the request.
+ String requestURL = httpRequest.getRequestURL().toString();
+ if (StringUtils.trimToNull(requestURL) != null && requestURL.startsWith("http:")) {
+ requestURL = requestURL.replaceFirst("http", xForwardedProto);
+ }
+ xForwardedURL = requestURL;
+ }
+ }
+ return xForwardedURL;
+ }
+
+ public static String constructRedirectURL(HttpServletRequest request, String redirectUrl, String xForwardedURL, String originalUrlQueryParam) {
+ String delimiter = "?";
+ if (redirectUrl.contains("?")) {
+ delimiter = "&";
+ }
+ String loginURL = redirectUrl + delimiter + originalUrlQueryParam + "=";
+ if (StringUtils.trimToNull(xForwardedURL) != null) {
+ loginURL += xForwardedURL + getOriginalQueryString(request);
+ } else {
+ loginURL += request.getRequestURL().append(getOriginalQueryString(request));
+ }
+ return loginURL;
+ }
+
+ private static String getOriginalQueryString(HttpServletRequest request) {
+ String originalQueryString = request.getQueryString();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("originalQueryString = " + originalQueryString);
+ }
+ if (originalQueryString == null || originalQueryString.contains("action")) {
+ return "";
+ } else {
+ return "?" + originalQueryString;
+ }
+ }
}
\ No newline at end of file
diff --git a/security-admin/src/main/java/org/apache/ranger/view/VXPortalUser.java b/security-admin/src/main/java/org/apache/ranger/view/VXPortalUser.java
index 5a1b203..fdb2709 100644
--- a/security-admin/src/main/java/org/apache/ranger/view/VXPortalUser.java
+++ b/security-admin/src/main/java/org/apache/ranger/view/VXPortalUser.java
@@ -21,6 +21,7 @@
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
@@ -98,6 +99,12 @@ public class VXPortalUser extends VXDataObject implements java.io.Serializable {
protected String syncSource;
/**
+ * Configuration properties.
+ *
+ */
+ protected Map<String, String> configProperties;
+
+ /**
* Default constructor. This will set all the attributes to default value.
*/
public VXPortalUser ( ) {
@@ -321,6 +328,14 @@ public class VXPortalUser extends VXDataObject implements java.io.Serializable {
this.otherAttributes = otherAttributes;
}
+ public Map<String, String> getConfigProperties() {
+ return configProperties;
+ }
+
+ public void setConfigProperties(Map<String, String> configProperties) {
+ this.configProperties = configProperties;
+ }
+
/**
* @return {@link String} - sync Source attribute.
*/