RANGER-685 : Make Ranger Admin participate in Knox SSO Signed-off-by: sneethiraj <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/d5c707ff Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/d5c707ff Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/d5c707ff Branch: refs/heads/tag-policy Commit: d5c707ffc5517722d6a5514ded2ed31a0d4ae6e4 Parents: e267c09 Author: Gautam Borad <[email protected]> Authored: Thu Nov 19 21:43:42 2015 +0530 Committer: sneethiraj <[email protected]> Committed: Thu Nov 19 11:53:08 2015 -0500 ---------------------------------------------------------------------- security-admin/pom.xml | 18 + security-admin/scripts/install.properties | 12 + security-admin/scripts/setup.sh | 26 ++ .../org/apache/ranger/biz/RangerBizUtil.java | 11 + .../apache/ranger/common/UserSessionBase.java | 10 +- .../org/apache/ranger/rest/ServiceREST.java | 9 + .../handler/RangerAuthenticationProvider.java | 29 ++ .../RangerAuthenticationEntryPoint.java | 6 +- .../filter/RangerSSOAuthenticationFilter.java | 424 +++++++++++++++++++ .../RangerSecurityContextFormationFilter.java | 13 +- .../security/web/filter/SSOAuthentication.java | 55 +++ .../web/filter/SSOAuthenticationProperties.java | 62 +++ .../resources/conf.dist/ranger-admin-site.xml | 26 ++ .../conf.dist/security-applicationContext.xml | 95 +---- .../src/main/webapp/scripts/utils/XAUtils.js | 7 +- .../webapp/scripts/views/common/ErrorView.js | 9 +- .../webapp/scripts/views/common/ProfileBar.js | 30 +- 17 files changed, 749 insertions(+), 93 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/pom.xml ---------------------------------------------------------------------- diff --git a/security-admin/pom.xml b/security-admin/pom.xml index 3c26837..1fedbd0 100644 --- a/security-admin/pom.xml +++ b/security-admin/pom.xml @@ -407,6 +407,24 @@ <artifactId>spring-test</artifactId> <version>${springframework.test.version}</version> </dependency> + + <dependency> + <groupId>com.nimbusds</groupId> + <artifactId>nimbus-jose-jwt</artifactId> + <version>3.9</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + <version>3.0</version> + </dependency> </dependencies> <build> <pluginManagement> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/scripts/install.properties ---------------------------------------------------------------------- diff --git a/security-admin/scripts/install.properties b/security-admin/scripts/install.properties index f3af716..2d52890 100644 --- a/security-admin/scripts/install.properties +++ b/security-admin/scripts/install.properties @@ -109,6 +109,18 @@ unix_group=ranger # # +#-------- SSO CONFIG - Start ------------------ +# +sso_enabled=false +sso_providerurl=https://localhost:8443/gateway/knoxsso/api/v1/websso +sso_publickey= +sso_cookiename=hadoop-jwt +sso_query_param_originalurl=originalUrl +# +#-------- SSO CONFIG - Start ------------------ +# + +# # UNIX authentication service for Policy Manager # # PolicyManager can authenticate using UNIX username/password http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/scripts/setup.sh ---------------------------------------------------------------------- diff --git a/security-admin/scripts/setup.sh b/security-admin/scripts/setup.sh index 36696a0..8b67f98 100755 --- a/security-admin/scripts/setup.sh +++ b/security-admin/scripts/setup.sh @@ -110,6 +110,11 @@ sqlserver_audit_file=$(get_prop 'sqlserver_audit_file' $PROPFILE) sqlanywhere_core_file=$(get_prop 'sqlanywhere_core_file' $PROPFILE) sqlanywhere_audit_file=$(get_prop 'sqlanywhere_audit_file' $PROPFILE) cred_keystore_filename=$(eval echo "$(get_prop 'cred_keystore_filename' $PROPFILE)") +sso_enabled=$(get_prop 'sso_enabled' $PROPFILE) +sso_providerurl=$(get_prop 'sso_providerurl' $PROPFILE) +sso_publickey=$(get_prop 'sso_publickey' $PROPFILE) +sso_cookiename=$(get_prop 'sso_cookiename' $PROPFILE) +sso_query_param_originalurl=$(get_prop 'sso_query_param_originalurl' $PROPFILE) DB_HOST="${db_host}" @@ -339,6 +344,27 @@ update_properties() { log "[E] $to_file_default does not exists" ; exit 1; fi + propertyName=ranger.sso.enabled + newPropertyValue="${sso_enabled}" + updatePropertyToFilePy $propertyName $newPropertyValue $to_file_ranger + + propertyName=ranger.sso.providerurl + newPropertyValue="${sso_providerurl}" + updatePropertyToFilePy $propertyName $newPropertyValue $to_file_ranger + + propertyName=ranger.sso.publicKey + newPropertyValue="${sso_publickey}" + updatePropertyToFilePy $propertyName $newPropertyValue $to_file_ranger + + propertyName=ranger.sso.cookiename + newPropertyValue="${sso_cookiename}" + updatePropertyToFilePy $propertyName $newPropertyValue $to_file_ranger + + propertyName=ranger.sso.query.param.originalurl + newPropertyValue="${sso_query_param_originalurl}" + updatePropertyToFilePy $propertyName $newPropertyValue $to_file_ranger + + if [ "${DB_FLAVOR}" == "MYSQL" ] then propertyName=ranger.jpa.jdbc.url http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/biz/RangerBizUtil.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerBizUtil.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerBizUtil.java index 689e165..e00db2c 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/RangerBizUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerBizUtil.java @@ -1520,5 +1520,16 @@ public class RangerBizUtil { return true; } + + public boolean isSSOEnabled() { + UserSessionBase session = ContextUtil.getCurrentUserSession(); + if (session != null) { + return session.isSSOEnabled() == null ? PropertiesUtil.getBooleanProperty("ranger.sso.enabled", false) : session.isSSOEnabled(); + } else { + throw restErrorUtil.createRESTException( + "User session is not created", + MessageEnums.OPER_NOT_ALLOWED_FOR_STATE); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/common/UserSessionBase.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/common/UserSessionBase.java b/security-admin/src/main/java/org/apache/ranger/common/UserSessionBase.java index 175459c..4473d74 100644 --- a/security-admin/src/main/java/org/apache/ranger/common/UserSessionBase.java +++ b/security-admin/src/main/java/org/apache/ranger/common/UserSessionBase.java @@ -39,7 +39,7 @@ public class UserSessionBase implements Serializable { private List<String> userRoleList = new ArrayList<String>(); private RangerUserPermission rangerUserPermission; int clientTimeOffsetInMinute = 0; - + private Boolean isSSOEnabled; public Long getUserId() { if (xXPortalUser != null) { return xXPortalUser.getId(); @@ -128,6 +128,14 @@ public class UserSessionBase implements Serializable { + public Boolean isSSOEnabled() { + return isSSOEnabled; + } + + public void setSSOEnabled(Boolean isSSOEnabled) { + this.isSSOEnabled = isSSOEnabled; + } + public static class RangerUserPermission implements Serializable { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java index 9173d6e..d92fd41 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java @@ -37,6 +37,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; @@ -1929,4 +1930,12 @@ public class ServiceREST { return ret; } + + @GET + @Path("/checksso") + @Produces(MediaType.TEXT_PLAIN) + public String checkSSO() { + return String.valueOf(bizUtil.isSSOEnabled()); + } + } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/handler/RangerAuthenticationProvider.java ---------------------------------------------------------------------- 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 40b08c4..3920ab3 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 @@ -75,6 +75,8 @@ public class RangerAuthenticationProvider implements AuthenticationProvider { private LdapAuthenticator authenticator; + private boolean ssoEnabled = false; + public RangerAuthenticationProvider() { } @@ -82,6 +84,14 @@ public class RangerAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { + if(isSsoEnabled()){ + if (authentication != null){ + authentication = getSSOAuthentication(authentication); + if(authentication!=null && authentication.isAuthenticated()){ + return authentication; + } + } + }else{ String sha256PasswordUpdateDisable=PropertiesUtil.getProperty("ranger.sha256Password.update.disable", "false"); if(rangerAuthenticationMethod==null){ rangerAuthenticationMethod="NONE"; @@ -155,6 +165,7 @@ public class RangerAuthenticationProvider implements AuthenticationProvider { } return authentication; } + } return authentication; } @@ -521,4 +532,22 @@ public class RangerAuthenticationProvider implements AuthenticationProvider { } return authentication; } + + private Authentication getSSOAuthentication(Authentication authentication) throws AuthenticationException{ + return authentication; + } + + /** + * @return the ssoEnabled + */ + public boolean isSsoEnabled() { + return ssoEnabled; + } + + /** + * @param ssoEnabled the ssoEnabled to set + */ + public void setSsoEnabled(boolean ssoEnabled) { + this.ssoEnabled = ssoEnabled; + } } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/web/authentication/RangerAuthenticationEntryPoint.java ---------------------------------------------------------------------- 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 52228dd..0b61498 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 @@ -35,6 +35,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.view.VXResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.AuthenticationException; @@ -129,9 +130,12 @@ public class RangerAuthenticationEntryPoint extends } response.sendError(ajaxReturnCode, ""); } else if (!(requestURL.startsWith(reqServletPath))) { + if(requestURL.contains(RangerSSOAuthenticationFilter.LOCAL_LOGIN_URL)){ + if (request.getSession() != null) + request.getSession().setAttribute("locallogin","true"); + } super.commence(request, response, authException); } - } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..960a25f --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSSOAuthenticationFilter.java @@ -0,0 +1,424 @@ +package org.apache.ranger.security.web.filter; + +import com.google.inject.Inject; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jose.JWSVerifier; +import com.nimbusds.jose.crypto.RSASSAVerifier; +import com.nimbusds.jwt.SignedJWT; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetails; + +import javax.servlet.*; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.interfaces.RSAPublicKey; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.ranger.common.PropertiesUtil; +import org.apache.ranger.common.UserSessionBase; +import org.apache.ranger.security.context.RangerContextHolder; +import org.apache.ranger.security.context.RangerSecurityContext; +import org.apache.ranger.security.handler.RangerAuthenticationProvider; + +import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +public class RangerSSOAuthenticationFilter implements Filter { + Logger LOG = LoggerFactory.getLogger(RangerSSOAuthenticationFilter.class); + + public static final String BROWSER_USERAGENT = "ranger.sso.browser.useragent"; + public static final String JWT_AUTH_PROVIDER_URL = "ranger.sso.providerurl"; + public static final String JWT_PUBLIC_KEY = "ranger.sso.publicKey"; + public static final String JWT_COOKIE_NAME = "ranger.sso.cookiename"; + public static final String JWT_ORIGINAL_URL_QUERY_PARAM = "ranger.sso.query.param.originalurl"; + public static final String JWT_COOKIE_NAME_DEFAULT = "hadoop-jwt"; + public static final String JWT_ORIGINAL_URL_QUERY_PARAM_DEFAULT = "originalUrl"; + public static final String LOCAL_LOGIN_URL = "locallogin"; + + private SSOAuthenticationProperties jwtProperties; + + private String originalUrlQueryParam = "originalUrl"; + private String authenticationProviderUrl = null; + private RSAPublicKey publicKey = null; + private String cookieName = "hadoop-jwt"; + private boolean ssoEnabled = false; + + @Inject + public RangerSSOAuthenticationFilter(){ + jwtProperties = getJwtProperties(); + loadJwtProperties(); + } + + public RangerSSOAuthenticationFilter( + SSOAuthenticationProperties jwtProperties){ + this.jwtProperties = jwtProperties; + loadJwtProperties(); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + /* + * doFilter of RangerSSOAuthenticationFilter is the first in the filter list so in this it check for the request + * if the request is from browser, doesn't contain local login and sso is enabled then it process the request against knox sso + * else if it's ssoenable and the request is with local login string then it show's the appropriate msg + * else if ssoenable is false then it contiunes with further filters as it was before sso + */ + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException { + + RangerSecurityContext context = RangerContextHolder.getSecurityContext(); + UserSessionBase session = context != null ? context.getUserSession() : null; + ssoEnabled = session != null ? session.isSSOEnabled() : PropertiesUtil.getBooleanProperty("ranger.sso.enabled", false); + + String userAgent = ((HttpServletRequest)servletRequest).getHeader("User-Agent"); + if(((HttpServletRequest) servletRequest).getSession() != null){ + if(((HttpServletRequest) servletRequest).getSession().getAttribute("locallogin") != null){ + ssoEnabled = false; + servletRequest.setAttribute("ssoEnabled", false); + filterChain.doFilter(servletRequest, servletResponse); + return; + } + } + //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 && !((HttpServletRequest) servletRequest).getRequestURI().contains(LOCAL_LOGIN_URL) && isWebUserAgent(userAgent)) { + //if jwt properties are loaded and is current not authenticated then it will go for sso authentication + if (jwtProperties != null && !isAuthenticated()) { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; + String serializedJWT = getJWTFromCookie(httpServletRequest); + // if we get the hadoop-jwt token from the cookies then will process it further + if (serializedJWT != null) { + SignedJWT jwtToken = null; + try { + jwtToken = SignedJWT.parse(serializedJWT); + boolean valid = validateToken(jwtToken); + //if the public key provide is correct and also token is not expired the process token + if (valid) { + String userName = jwtToken.getJWTClaimsSet().getSubject(); + LOG.info("SSO login user : "+userName); + + String rangerLdapDefaultRole = PropertiesUtil.getProperty("ranger.ldap.default.role", "ROLE_USER"); + //if we get the userName from the token then log into ranger using the same user + if (userName != null && !userName.trim().isEmpty()) { + final List<GrantedAuthority> grantedAuths = new ArrayList<>(); + grantedAuths.add(new SimpleGrantedAuthority(rangerLdapDefaultRole)); + final UserDetails principal = new User(userName, "",grantedAuths); + final Authentication finalAuthentication = new UsernamePasswordAuthenticationToken(principal, "", grantedAuths); + WebAuthenticationDetails webDetails = new WebAuthenticationDetails(httpServletRequest); + ((AbstractAuthenticationToken) finalAuthentication).setDetails(webDetails); + RangerAuthenticationProvider authenticationProvider = new RangerAuthenticationProvider(); + authenticationProvider.setSsoEnabled(ssoEnabled); + final Authentication authentication = authenticationProvider.authenticate(finalAuthentication); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + + filterChain.doFilter(servletRequest,httpServletResponse); + } + // if the token is not valid then redirect to knox sso + else { + String ssourl = constructLoginURL(httpServletRequest); + if(LOG.isDebugEnabled()) + LOG.debug("SSO URL = " + ssourl); + httpServletResponse.sendRedirect(ssourl); + } + } catch (ParseException e) { + LOG.warn("Unable to parse the JWT token", e); + } + } + // if the jwt token is not available then redirect it to knox sso + else { + String ssourl = constructLoginURL(httpServletRequest); + if(LOG.isDebugEnabled()) + LOG.debug("SSO URL = " + ssourl); + httpServletResponse.sendRedirect(ssourl); + } + } + //if property is not loaded or is already authenticated then proceed further with next filter + else { + filterChain.doFilter(servletRequest, servletResponse); + } + } else if(ssoEnabled && ((HttpServletRequest) servletRequest).getRequestURI().contains(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, ""); + 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); + } + //if sso is not enable or the request is not from browser then proceed further with next filter + else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + private boolean isWebUserAgent(String userAgent) { + boolean isWeb = false; + if (jwtProperties != null) { + String userAgentList[] = jwtProperties.getUserAgentList(); + if(userAgentList != null && userAgentList.length > 0){ + for(String ua : userAgentList){ + if(userAgent.toLowerCase().startsWith(ua.toLowerCase())){ + isWeb = true; + break; + } + } + } + } + return isWeb; + } + + /** + * @return the ssoEnabled + */ + public boolean isSsoEnabled() { + return ssoEnabled; + } + + /** + * @param ssoEnabled the ssoEnabled to set + */ + public void setSsoEnabled(boolean ssoEnabled) { + this.ssoEnabled = ssoEnabled; + } + + private void loadJwtProperties() { + if (jwtProperties != null) { + authenticationProviderUrl = jwtProperties.getAuthenticationProviderUrl(); + publicKey = jwtProperties.getPublicKey(); + cookieName = jwtProperties.getCookieName(); + originalUrlQueryParam = jwtProperties.getOriginalUrlQueryParam(); + } + } + + /** + * Do not try to validate JWT if user already authenticated via other + * provider + * + * @return true, if JWT validation required + */ + private boolean isAuthenticated() { + Authentication existingAuth = SecurityContextHolder.getContext().getAuthentication(); + return !(!(existingAuth != null && existingAuth.isAuthenticated()) || existingAuth instanceof SSOAuthentication); + } + + /** + * Encapsulate the acquisition of the JWT token from HTTP cookies within the + * request. + * + * @param req + * servlet request to get the JWT token from + * @return serialized JWT token + */ + protected String getJWTFromCookie(HttpServletRequest req) { + String serializedJWT = null; + Cookie[] cookies = req.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookieName != null && cookieName.equals(cookie.getName())) { + if(LOG.isDebugEnabled()) + LOG.debug(cookieName + " cookie has been found and is being processed"); + serializedJWT = cookie.getValue(); + break; + } + } + } + return serializedJWT; + } + + /** + * 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 delimiter = "?"; + if (authenticationProviderUrl.contains("?")) { + delimiter = "&"; + } + String loginURL = authenticationProviderUrl + delimiter + originalUrlQueryParam + "=" + request.getRequestURL().toString(); + return loginURL; + } + + /** + * 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 + * the override of the entire token validation algorithm. + * + * @param jwtToken + * the token to validate + * @return true if valid + */ + protected boolean validateToken(SignedJWT jwtToken) { + boolean sigValid = validateSignature(jwtToken); + if (!sigValid) { + LOG.warn("Signature of JWT token could not be verified. Please check the public key"); + } + boolean expValid = validateExpiration(jwtToken); + if (!expValid) { + LOG.warn("Expiration time validation of JWT token failed."); + } + return sigValid && expValid; + } + + /** + * Verify the signature of the JWT token in this method. This method depends + * on the public key that was established during init based upon the + * provisioned public key. Override this method in subclasses in order to + * customize the signature verification behavior. + * + * @param jwtToken + * the token that contains the signature to be validated + * @return valid true if signature verifies successfully; false otherwise + */ + protected boolean validateSignature(SignedJWT jwtToken) { + boolean valid = false; + if (JWSObject.State.SIGNED == jwtToken.getState()) { + if(LOG.isDebugEnabled()) + LOG.debug("SSO token is in a SIGNED state"); + if (jwtToken.getSignature() != null) { + if(LOG.isDebugEnabled()) + LOG.debug("SSO token signature is not null"); + try { + JWSVerifier verifier = new RSASSAVerifier(publicKey); + if (jwtToken.verify(verifier)) { + valid = true; + if(LOG.isDebugEnabled()) + LOG.debug("SSO token has been successfully verified"); + } else { + LOG.warn("SSO signature verification failed.Please check the public key"); + } + } catch (JOSEException je) { + LOG.warn("Error while validating signature", je); + } + } + } + return valid; + } + + /** + * Validate that the expiration time of the JWT token has not been violated. + * If it has then throw an AuthenticationException. Override this method in + * subclasses in order to customize the expiration validation behavior. + * + * @param jwtToken + * the token that contains the expiration date to validate + * @return valid true if the token has not expired; false otherwise + */ + protected boolean validateExpiration(SignedJWT jwtToken) { + boolean valid = false; + try { + Date expires = jwtToken.getJWTClaimsSet().getExpirationTime(); + if (expires != null && new Date().before(expires)) { + if(LOG.isDebugEnabled()) + LOG.debug("SSO token expiration date has been " + "successfully validated"); + valid = true; + } else { + LOG.warn("SSO expiration date validation failed."); + } + } catch (ParseException pe) { + LOG.warn("SSO expiration date validation failed.", pe); + } + return valid; + } + + @Override + public void destroy() { + } + + public SSOAuthenticationProperties getJwtProperties() { + String providerUrl = PropertiesUtil.getProperty(JWT_AUTH_PROVIDER_URL); + if (providerUrl != null) { + String publicKeyPath = PropertiesUtil.getProperty(JWT_PUBLIC_KEY); + if (publicKeyPath == null) { + LOG.error("Public key pem not specified for SSO auth provider {}. SSO auth will be disabled.",providerUrl); + return null; + } + try { + RSAPublicKey publicKey = parseRSAPublicKey(publicKeyPath); + SSOAuthenticationProperties jwtProperties = new SSOAuthenticationProperties(); + jwtProperties.setAuthenticationProviderUrl(providerUrl); + jwtProperties.setPublicKey(publicKey); + + jwtProperties.setCookieName(PropertiesUtil.getProperty(JWT_COOKIE_NAME, JWT_COOKIE_NAME_DEFAULT)); + jwtProperties.setOriginalUrlQueryParam(PropertiesUtil.getProperty(JWT_ORIGINAL_URL_QUERY_PARAM, JWT_ORIGINAL_URL_QUERY_PARAM_DEFAULT)); + String userAgent = PropertiesUtil.getProperty(BROWSER_USERAGENT); + if(userAgent != null && !userAgent.isEmpty()){ + jwtProperties.setUserAgentList(userAgent.split(",")); + } + return jwtProperties; + + } catch (IOException e) { + LOG.error("Unable to read public certificate file. JWT auth will be disabled.",e); + return null; + } catch (CertificateException e) { + LOG.error("Unable to parse public certificate file. JWT auth will be disabled.",e); + return null; + } catch (ServletException e) { + LOG.error("ServletException while processing the properties",e); + } + } else { + return null; + } + return jwtProperties; + } + + /* + * public static RSAPublicKey getPublicKeyFromFile(String filePath) throws + * IOException, CertificateException { + * FileUtils.readFileToString(new File(filePath)); + * getPublicKeyFromString(pemString); } + */ + + public static RSAPublicKey parseRSAPublicKey(String pem) + throws CertificateException, UnsupportedEncodingException, + ServletException { + String PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"; + String PEM_FOOTER = "\n-----END CERTIFICATE-----"; + String fullPem = PEM_HEADER + pem + PEM_FOOTER; + PublicKey key = null; + try { + CertificateFactory fact = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = new ByteArrayInputStream(fullPem.getBytes("UTF8")); + X509Certificate cer = (X509Certificate) fact.generateCertificate(is); + key = cer.getPublicKey(); + } catch (CertificateException ce) { + String message = null; + if (pem.startsWith(PEM_HEADER)) { + message = "CertificateException - be sure not to include PEM header " + "and footer in the PEM configuration element."; + } else { + message = "CertificateException - PEM may be corrupt"; + } + throw new ServletException(message, ce); + } catch (UnsupportedEncodingException uee) { + throw new ServletException(uee); + } + return (RSAPublicKey) key; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSecurityContextFormationFilter.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSecurityContextFormationFilter.java b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSecurityContextFormationFilter.java index d92fcbb..df529b6 100644 --- a/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSecurityContextFormationFilter.java +++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/RangerSecurityContextFormationFilter.java @@ -128,13 +128,18 @@ public class RangerSecurityContextFormationFilter extends GenericFilterBean { UserSessionBase userSession = sessionMgr.processSuccessLogin( XXAuthSession.AUTH_TYPE_PASSWORD, userAgent); - if(userSession!=null && userSession.getClientTimeOffsetInMinute()==0){ - userSession.setClientTimeOffsetInMinute(clientTimeOffset); + if (userSession != null) { + + Object ssoEnabledObj = request.getAttribute("ssoEnabled"); + Boolean ssoEnabled = ssoEnabledObj != null ? new Boolean(String.valueOf(ssoEnabledObj)) : PropertiesUtil.getBooleanProperty("ranger.sso.enabled", false); + userSession.setSSOEnabled(ssoEnabled); + + if (userSession.getClientTimeOffsetInMinute() == 0) { + userSession.setClientTimeOffsetInMinute(clientTimeOffset); + } } context.setUserSession(userSession); - -// xUserMgr.checkPermissionRoleByGivenUrls(httpRequest.getRequestURL().toString(),httpMethod); } HttpServletResponse res = (HttpServletResponse)response; res.setHeader("X-Frame-Options", "DENY" ); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthentication.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthentication.java b/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthentication.java new file mode 100644 index 0000000..b6c39e6 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthentication.java @@ -0,0 +1,55 @@ +package org.apache.ranger.security.web.filter; + +import com.nimbusds.jwt.SignedJWT; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * Internal token which describes JWT authentication + */ +public class SSOAuthentication implements Authentication { + + private SignedJWT token; + private boolean authenticated = false; + + public SSOAuthentication(SignedJWT token) { + this.token = token; + } + + @Override + public SignedJWT getCredentials() { + return token; + } + + @Override + public Object getDetails() { + return null; + } + + @Override + public boolean isAuthenticated() { + return authenticated; + } + + @Override + public void setAuthenticated(boolean authenticated) throws IllegalArgumentException { + this.authenticated = authenticated; + } + + @Override + public String getName() { + return null; + } + + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return null; + } + + @Override + public Object getPrincipal() { + return null; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthenticationProperties.java ---------------------------------------------------------------------- diff --git a/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthenticationProperties.java b/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthenticationProperties.java new file mode 100644 index 0000000..aa29de0 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/security/web/filter/SSOAuthenticationProperties.java @@ -0,0 +1,62 @@ +package org.apache.ranger.security.web.filter; + +import java.security.interfaces.RSAPublicKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class SSOAuthenticationProperties { + + private String authenticationProviderUrl = null; + private RSAPublicKey publicKey = null; + private String cookieName = "hadoop-jwt"; + private String originalUrlQueryParam = null; + private String[] userAgentList = null; + + public String getAuthenticationProviderUrl() { + return authenticationProviderUrl; + } + + public void setAuthenticationProviderUrl(String authenticationProviderUrl) { + this.authenticationProviderUrl = authenticationProviderUrl; + } + + public RSAPublicKey getPublicKey() { + return publicKey; + } + + public void setPublicKey(RSAPublicKey publicKey) { + this.publicKey = publicKey; + } + + public String getCookieName() { + return cookieName; + } + + public void setCookieName(String cookieName) { + this.cookieName = cookieName; + } + + public String getOriginalUrlQueryParam() { + return originalUrlQueryParam; + } + + public void setOriginalUrlQueryParam(String originalUrlQueryParam) { + this.originalUrlQueryParam = originalUrlQueryParam; + } + + /** + * @return the userAgentList + */ + public String[] getUserAgentList() { + return userAgentList; + } + + /** + * @param userAgentList the userAgentList to set + */ + public void setUserAgentList(String[] userAgentList) { + this.userAgentList = userAgentList; + } +} + http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml ---------------------------------------------------------------------- diff --git a/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml b/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml index fe7320c..6ee48f4 100644 --- a/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml +++ b/security-admin/src/main/resources/conf.dist/ranger-admin-site.xml @@ -228,4 +228,30 @@ <value>(sAMAccountName={0})</value> <description></description> </property> + <!-- SSO Properties Starts--> + <property> + <name>ranger.sso.providerurl</name> + <value>https://127.0.0.1:8443/gateway/knoxsso/api/v1/websso</value> + </property> + <property> + <name>ranger.sso.publicKey</name> + <value>MIICVjCCAb+gAwIBAgIJAPPvOtuTxFeiMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRUZXN0MQ0wCwYDVQQHEwRUZXN0MQ8wDQYDVQQKEwZIYWRvb3AxDTALBgNVBAsTBFRlc3QxIDAeBgNVBAMTF2M2NDAxLmFtYmFyaS5hcGFjaGUub3JnMB4XDTE1MDcxNjE4NDcyM1oXDTE2MDcxNTE4NDcyM1owbTELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFRlc3QxDTALBgNVBAcTBFRlc3QxDzANBgNVBAoTBkhhZG9vcDENMAsGA1UECxMEVGVzdDEgMB4GA1UEAxMXYzY0MDEuYW1iYXJpLmFwYWNoZS5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFs/rymbiNvg8lDhsdAqvh5uHP6iMtfv9IYpDleShjkS1C+IqId6bwGIEO8yhIS5BnfUR/fcnHi2ZNrXX7xQUtQe7M9tDIKu48w//InnZ6VpAqjGShWxcSzR6UB/YoGe5ytHS6MrXaormfBg3VWtDoy2MS83W8pweS6p5JnK7S5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEANyVg6EzE2q84gq7wQfLt9t047nYFkxcRfzhNVL3LB8p6IkM4RUrzWq4kLA+z+bpY2OdpkTOewUpEdVKzOQd4V7vRxpdANxtbG/XXrJAAcY/S+eMy1eDK73cmaVPnxPUGWmMnQXUiTLab+w8tBQhNbq6BOQ42aOrLxA8k/M4cV1A=</value> + </property> + <property> + <name>ranger.sso.cookiename</name> + <value>hadoop-jwt</value> + </property> + <property> + <name>ranger.sso.enabled</name> + <value>false</value> + </property> + <property> + <name>ranger.sso.query.param.originalurl</name> + <value>originalUrl</value> + </property> + <property> + <name>ranger.sso.browser.useragent</name> + <value>Mozilla,chrome</value> + </property> + <!-- SSO Properties Ends--> </configuration> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/resources/conf.dist/security-applicationContext.xml ---------------------------------------------------------------------- diff --git a/security-admin/src/main/resources/conf.dist/security-applicationContext.xml b/security-admin/src/main/resources/conf.dist/security-applicationContext.xml index 162afc6..329053f 100644 --- a/security-admin/src/main/resources/conf.dist/security-applicationContext.xml +++ b/security-admin/src/main/resources/conf.dist/security-applicationContext.xml @@ -30,31 +30,12 @@ http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd"> - <!-- TEMP ADD START--> - <security:http pattern="/test/social_login.jsp" security="none" /> - <!-- TEMP ADD END --> <security:http pattern="/login.jsp" security="none" /> - <security:http pattern="/ms_version.jsp" security="none" /> - <security:http pattern="/userRegistration.jsp" security="none" /> - <security:http pattern="/forgotPassword.jsp" security="none" /> - <security:http pattern="public/failedLogin.jsp" security="none" /> <security:http pattern="/styles/**" security="none" /> <security:http pattern="/fonts/**" security="none" /> <security:http pattern="/scripts/**" security="none" /> - <security:http pattern="/bower_components/**" security="none" /> <security:http pattern="/libs/**" security="none" /> <security:http pattern="/images/**" security="none" /> - <security:http pattern="/service/registration" security="none" /> - <security:http pattern="/service/users/firstnames" security="none" /> - <security:http pattern="/components/globalize/**" security="none" /> - <security:http pattern="/resetPassword.jsp" security="none" /> - <security:http pattern="/captcha/**" security="none" /> - <security:http pattern="/service/registration/**" security="none" /> - <security:http pattern="/public/**" security="none" /> - <security:http pattern="/test/**" security="none" /> - <security:http pattern="/test.html" security="none" /> - <security:http pattern="/loadInit.html" security="none" /> - <security:http pattern="/service/documents/result/**" security="none" /> <security:http pattern="/service/assets/policyList/*" security="none"/> <security:http pattern="/service/assets/resources/grant" security="none"/> <security:http pattern="/service/assets/resources/revoke" security="none"/> @@ -63,34 +44,16 @@ http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd"> <security:http pattern="/service/plugins/services/revoke/*" security="none"/> <security:http pattern="/service/tags/download/*" security="none"/> - <!--<security:http pattern="/service/users/default" security="none"/> - <security:http pattern="/service/xusers/groups/**" security="none"/> - <security:http pattern="/service/xusers/users/*" security="none"/> - <security:http pattern="/service/xusers/groupusers/*" security="none"/>--> - - <security:http auto-config="false" create-session="always" entry-point-ref="authenticationProcessingFilterEntryPoint"> + <security:http disable-url-rewriting="true" use-expressions="true" create-session="always" entry-point-ref="authenticationProcessingFilterEntryPoint"> <security:session-management session-fixation-protection="newSession" /> - <!-- security:remember-me user-service-ref="userService" key="REMEMBER_ME_PASSWORD"/ --> - - <!-- Restricted URLs to admin--> - <security:intercept-url pattern="/service/crud/**" access="ROLE_SYS_ADMIN" /> - <security:intercept-url pattern="/service/users/activations/**" access="ROLE_SYS_ADMIN" /> - - <!-- Allow annoymous access --> - <security:intercept-url pattern="/service/general/feedbacks" access="IS_AUTHENTICATED_ANONYMOUSLY" /> - - <!-- give read access to lesson api --> - <security:intercept-url pattern="/service/lesson/**" access="IS_AUTHENTICATED_ANONYMOUSLY" method="GET"/> - - <!-- Restricted URLs to only authenticated users--> - <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED" /> - + <intercept-url pattern="/**" access="isAuthenticated()"/> + <custom-filter ref="ssoAuthenticationFilter" after="BASIC_AUTH_FILTER" /> + <security:custom-filter position="FORM_LOGIN_FILTER" ref="customUsernamePasswordAuthenticationFilter"/> - <!-- security:custom-filter before="ANONYMOUS_FILTER" ref="rememberMeFilter" / --> <security:custom-filter position="LAST" ref="userContextFormationFilter"/> <security:access-denied-handler error-page="/public/failedLogin.jsp?access_denied=1"/> - <security:logout delete-cookies="JSESSIONID, xa_rmc" logout-url="/logout.html" success-handler-ref="customLogoutSuccessHandler" /> + <security:logout delete-cookies="JSESSIONID,hadoop-jwt,xa_rmc" logout-url="/logout.html" success-handler-ref="customLogoutSuccessHandler" /> <http-basic entry-point-ref="authenticationProcessingFilterEntryPoint"/> </security:http> @@ -108,7 +71,6 @@ http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd"> <beans:property name="authenticationManager" ref="authenticationManager"/> <beans:property name="authenticationSuccessHandler" ref="ajaxAuthSuccessHandler"/> <beans:property name="authenticationFailureHandler" ref="ajaxAuthFailureHandler"/> - <!-- beans:property name="rememberMeServices" ref="rememberMeServices"/ --> </beans:bean> <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.apache.ranger.security.web.authentication.RangerAuthenticationEntryPoint"> @@ -127,6 +89,10 @@ http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd"> <beans:bean id="customLogoutSuccessHandler" class="org.apache.ranger.security.web.authentication.CustomLogoutSuccessHandler"> </beans:bean> + <beans:bean id="ssoAuthenticationFilter" class="org.apache.ranger.security.web.filter.RangerSSOAuthenticationFilter"> + <beans:property name="ssoEnabled" value="${ranger.sso.enabled}"/> + </beans:bean> + <beans:bean id="userContextFormationFilter" class="org.apache.ranger.security.web.filter.RangerSecurityContextFormationFilter"/> <security:jdbc-user-service id="userService" data-source-ref="defaultDataSource" @@ -136,50 +102,13 @@ http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd"> WHERE usr.LOGIN_ID=? AND usr_role.USER_ID = usr.ID" /> - <beans:bean id="customAuthenticationProvider" class="org.apache.ranger.security.handler.RangerAuthenticationProvider" > - <beans:property name="rangerAuthenticationMethod" value="${ranger.authentication.method}" /> - </beans:bean> + <beans:bean id="customAuthenticationProvider" class="org.apache.ranger.security.handler.RangerAuthenticationProvider" > + <beans:property name="rangerAuthenticationMethod" value="${ranger.authentication.method}" /> + </beans:bean> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="customAuthenticationProvider"/> - <!-- <security:authentication-manager alias="authenticationManager"> --> - <!-- AD_SEC_SETTINGS_START --> - <!-- AD_SEC_SETTINGS_END--> - <!-- LDAP_SEC_SETTINGS_START --> - <!-- LDAP_SEC_SETTINGS_END --> - <!-- UNIX_SEC_SETTINGS_START --> - <!-- UNIX_SEC_SETTINGS_END --> - <!-- <security:authentication-provider user-service-ref="userService"> - <security:password-encoder hash="md5"> - <security:salt-source user-property="username"/> - </security:password-encoder> - </security:authentication-provider> --> - <!-- security:authentication-provider ref="rememberMeAuthenticationProvider"/ --> </security:authentication-manager> - <security:global-method-security pre-post-annotations="enabled" /> - - <!-- UNIX_BEAN_SETTINGS_START --> - <!-- UNIX_BEAN_SETTINGS_END --> - <!-- AD_BEAN_SETTINGS_START --> - <!-- AD_BEAN_SETTINGS_END --> - <!-- LDAP_BEAN_SETTINGS_START --> - <!-- LDAP_BEAN_SETTINGS_END --> - <!-- beans:bean id="rememberMeFilter" class="org.apache.ranger.security.web.filter.MyRememberMeFilter"> - <beans:property name="rememberMeServices" ref="rememberMeServices"/> - <beans:property name="authenticationManager" ref="authenticationManager" /> - </beans:bean> - <beans:bean id="rememberMeServices" class= - "org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"> - <beans:property name="userDetailsService" ref="userService"/> - <beans:property name="cookieName" value="xa_rmc" /> - <beans:property name="key" value="REMEMBER_ME_PASSWORD"/> - <beans:property name="alwaysRemember" value="true"/> - </beans:bean> - - <beans:bean id="rememberMeAuthenticationProvider" class= - "org.springframework.security.authentication.RememberMeAuthenticationProvider"> - <beans:property name="key" value="REMEMBER_ME_PASSWORD"/> - </beans:bean --> <beans:bean id="securityEventListener" class ="org.apache.ranger.security.listener.SpringEventListener"/> </beans:beans> http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/webapp/scripts/utils/XAUtils.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js b/security-admin/src/main/webapp/scripts/utils/XAUtils.js index 8cb90e3..0f3aa3d 100644 --- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js +++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js @@ -1030,10 +1030,15 @@ define(function(require) { XAUtils.filterAllowedActions = function(controller) { var SessionMgr = require('mgrs/SessionMgr'); var XAGlobals = require('utils/XAGlobals'); + var vError = require('views/common/ErrorView'); + var App = require('App'); var that = this; var vXPortalUser = SessionMgr.getUserProfile(); if(_.isEmpty(vXPortalUser.attributes)){ - return controller; + App.rContent.show(new vError({ + status : 204 + })); + return; } var denyControllerActions = [], denyModulesObj = []; var userModuleNames = _.pluck(vXPortalUser.get('userPermList'),'moduleName'); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/webapp/scripts/views/common/ErrorView.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/common/ErrorView.js b/security-admin/src/main/webapp/scripts/views/common/ErrorView.js index a9d5739..4f8f463 100644 --- a/security-admin/src/main/webapp/scripts/views/common/ErrorView.js +++ b/security-admin/src/main/webapp/scripts/views/common/ErrorView.js @@ -37,7 +37,10 @@ define(function(require){ if(this.status == 401){ msg = 'Access Denied (401)' moreInfo = "Sorry, you don't have enough privileges to view this page."; - }else{ + } else if(this.status == 204){ + msg = 'No Content (204)' + moreInfo = "Sorry, Please sync-up the users with your source directory."; + } else { msg = 'Page not found (404).' moreInfo = "Sorry, this page isn't here or has moved."; } @@ -82,6 +85,10 @@ define(function(require){ onRender: function() { this.initializePlugins(); $('#r_breadcrumbs').hide(); + if(this.status == 204){ + this.ui.goBackBtn.hide(); + this.ui.home.hide(); + } }, goBackClick : function(){ history.back(); http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/d5c707ff/security-admin/src/main/webapp/scripts/views/common/ProfileBar.js ---------------------------------------------------------------------- diff --git a/security-admin/src/main/webapp/scripts/views/common/ProfileBar.js b/security-admin/src/main/webapp/scripts/views/common/ProfileBar.js index 0f87270..0bb9648 100644 --- a/security-admin/src/main/webapp/scripts/views/common/ProfileBar.js +++ b/security-admin/src/main/webapp/scripts/views/common/ProfileBar.js @@ -53,7 +53,8 @@ define(function(require){ return events; }, onLogout : function(){ - var url = 'security-admin-web/logout.html'; + var url = 'security-admin-web/logout.html', + that = this; $.ajax({ url : url, type : 'GET', @@ -61,13 +62,38 @@ define(function(require){ "cache-control" : "no-cache" }, success : function() { - window.location.replace('login.jsp'); + that.checkKnoxSSO() +// window.location.replace('login.jsp'); }, error : function(jqXHR, textStatus, err ) { } }); }, + checkKnoxSSO : function(){ + var url = 'service/plugins/checksso'; + $.ajax({ + url : url, + type : 'GET', + headers : { + "cache-control" : "no-cache" + }, + success : function(resp) { + console.log(resp) + if(!_.isUndefined(resp) && resp){ + window.location.replace(''); + } else { + window.location.replace('login.jsp'); + } + }, + error : function(jqXHR, textStatus, err ) { + if( jqXHR.status == 419 ){ + window.location.replace('login.jsp'); + } + } + + }); + }, /** * intialize a new ProfileBar ItemView * @constructs
