This is an automated email from the ASF dual-hosted git repository. prabhjyotsingh pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push: new 71da027 [ZEPPELIN-5116] Accessing zeppelin via knox after knox logout should be redirected to knox login page 71da027 is described below commit 71da0272a2f6dfb166231e5dd424abbbaaeaf36b Author: prjain <prarujai...@gmail.com> AuthorDate: Mon Nov 2 15:12:18 2020 +0530 [ZEPPELIN-5116] Accessing zeppelin via knox after knox logout should be redirected to knox login page ### What is this PR for? When zeppelin is running under kerberosRealm the logout doesn't work, it should be redirected to knox login page. With this PR, a fix for this is provided. ### What type of PR is it? Bug Fix ### What is the Jira issue? https://issues.apache.org/jira/projects/ZEPPELIN/issues/ZEPPELIN-5116 ### How should this be tested? 1. Created a cluster 2. Deploy the changes to the cluster 3. Added respective entries in shiro.ini 4. Performed logout and tested Author: prjain <prarujai...@gmail.com> Author: Prarthi <prarujai...@gmail.com> Closes #3961 from PrarthiJain/ZEPPELIN-5116 and squashes the following commits: 614029bbd [prjain] finally block to always execute baseURL 94adcd5bc [prjain] implemented LogoutAPI in KerberosRealm 5e16658b1 [Prarthi] ZEPPELIN-5116: Accessing zeppelin via knox after logout should be redirected to knox login page Change-Id: I4caae974f600dbce59ed20dcbc88a6fa6842b384 --- conf/shiro.ini.template | 15 ++++++ .../zeppelin/realm/kerberos/KerberosRealm.java | 60 +++++++++++++++++++--- .../org/apache/zeppelin/rest/LoginRestApi.java | 37 ++++++++++--- .../src/components/navbar/navbar.controller.js | 3 +- 4 files changed, 99 insertions(+), 16 deletions(-) diff --git a/conf/shiro.ini.template b/conf/shiro.ini.template index 1196ba4..f853346 100644 --- a/conf/shiro.ini.template +++ b/conf/shiro.ini.template @@ -70,6 +70,21 @@ user3 = password4, role2 #knoxJwtRealm.principalMapping = principal.mapping #authc = org.apache.zeppelin.realm.jwt.KnoxAuthenticationFilter +### A sample for configuring Kerberos Realm +# krbRealm = org.apache.zeppelin.realm.kerberos.KerberosRealm +# krbRealm.principal = HTTP/zeppelin.fqdn.domain....@example.com +# krbRealm.keytab = /etc/security/keytabs/spnego.service.keytab +# krbRealm.nameRules = DEFAULT +# krbRealm.signatureSecretFile = /etc/security/http_secret +# krbRealm.tokenValidity = 36000 +# krbRealm.cookieDomain = domain.com +# krbRealm.cookiePath = / +# krbRealm.logout = /logout +# krbRealm.logoutAPI = true +# krbRealm.providerUrl = https://domain.example.com/ +# krbRealm.redirectParam = originalUrl +# authc = org.apache.zeppelin.realm.kerberos.KerberosAuthenticationFilter + sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager ### If caching of user is required then uncomment below lines diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/kerberos/KerberosRealm.java b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/kerberos/KerberosRealm.java index c2a88f7..b7b8791 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/kerberos/KerberosRealm.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/kerberos/KerberosRealm.java @@ -67,13 +67,17 @@ import java.util.regex.Pattern; * The Shiro configuration section should be configured as: * [main] * krbRealm = org.apache.zeppelin.realm.kerberos.KerberosRealm - * krbRealm.principal=HTTP/zeppelin.fqdn.domain....@example.com - * krbRealm.keytab=/etc/security/keytabs/spnego.service.keytab - * krbRealm.nameRules=DEFAULT - * krbRealm.signatureSecretFile=/etc/security/http_secret - * krbRealm.tokenValidity=36000 - * krbRealm.cookieDomain=domain.com - * krbRealm.cookiePath=/ + * krbRealm.principal = HTTP/zeppelin.fqdn.domain....@example.com + * krbRealm.keytab = /etc/security/keytabs/spnego.service.keytab + * krbRealm.nameRules = DEFAULT + * krbRealm.signatureSecretFile = /etc/security/http_secret + * krbRealm.tokenValidity = 36000 + * krbRealm.cookieDomain = domain.com + * krbRealm.cookiePath = / + * krbRealm.logout = logout + * krbRealm.logoutAPI = true + * krbRealm.providerUrl = https://domain.example.com/ + * krbRealm.redirectParam = originalUrl * authc = org.apache.zeppelin.realm.kerberos.KerberosAuthenticationFilter * */ @@ -91,6 +95,10 @@ public class KerberosRealm extends AuthorizingRealm { private boolean isCookiePersistent = false; private String signatureSecretFile = null; private String signatureSecretProvider = "file"; + private String logout = "logout"; + private Boolean logoutAPI = true; + private String providerUrl = "https://domain.example.com/"; + private String redirectParam = "originalUrl"; /** * Constant for the property that specifies the authentication handler to use. @@ -167,6 +175,11 @@ public class KerberosRealm extends AuthorizingRealm { * implementation will be used. */ private static final String SIGNER_SECRET_PROVIDER = "signer.secret.provider"; + /** + * Constant for the configuration property that indicates the path to use to logout + */ + private static final String LOGOUT = "logout"; + private static Signer signer = null; private SignerSecretProvider secretProvider = null; @@ -878,6 +891,7 @@ public class KerberosRealm extends AuthorizingRealm { props.put(PRINCIPAL, principal); props.put(KEYTAB, keytab); props.put(NAME_RULES, nameRules); + props.put(LOGOUT, logout); return props; } @@ -982,6 +996,38 @@ public class KerberosRealm extends AuthorizingRealm { this.signatureSecretProvider = signatureSecretProvider; } + public String getLogout() { + return logout; + } + + public void setLogout(String logout) { + this.logout = logout; + } + + public Boolean getLogoutAPI() { + return logoutAPI; + } + + public void setLogoutAPI(Boolean logoutAPI) { + this.logoutAPI = logoutAPI; + } + + public String getProviderUrl() { + return providerUrl; + } + + public void setProviderUrl(String providerUrl) { + this.providerUrl = providerUrl; + } + + public String getRedirectParam() { + return redirectParam; + } + + public void setRedirectParam(String redirectParam) { + this.redirectParam = redirectParam; + } + /** * Releases any resources initialized by the authentication handler. * <p> diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/LoginRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/LoginRestApi.java index ef222a1..e17eb5e 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/LoginRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/LoginRestApi.java @@ -99,8 +99,10 @@ public class LoginRestApi { } if (response == null) { Map<String, String> data = new HashMap<>(); - data.put("redirectURL", constructKnoxUrl(knoxJwtRealm, knoxJwtRealm.getLogin())); - response = new JsonResponse<>(Status.OK, "", data); + data.put("redirectURL", + constructUrl(knoxJwtRealm.getProviderUrl(), knoxJwtRealm.getRedirectParam(), + knoxJwtRealm.getLogin())); + response = new JsonResponse(Status.OK, "", data); } return response.build(); } @@ -169,6 +171,18 @@ public class LoginRestApi { return false; } + private boolean isKerberosRealmEnabled() { + Collection<Realm> realmsList = authenticationService.getRealmsList(); + if (realmsList != null) { + for (Realm realm : realmsList) { + if (realm instanceof KerberosRealm) { + return true; + } + } + } + return false; + } + private JsonResponse<Map<String, String>> proceedToLogin(Subject currentUser, AuthenticationToken token) { JsonResponse<Map<String, String>> response = null; try { @@ -251,19 +265,28 @@ public class LoginRestApi { } if (isKnoxSSOEnabled()) { KnoxJwtRealm knoxJwtRealm = getJTWRealm(); - data.put("redirectURL", constructKnoxUrl(knoxJwtRealm, knoxJwtRealm.getLogout())); + data.put("redirectURL", + constructUrl(knoxJwtRealm.getProviderUrl(), knoxJwtRealm.getRedirectParam(), + knoxJwtRealm.getLogout())); data.put("isLogoutAPI", knoxJwtRealm.getLogoutAPI().toString()); + } else if (isKerberosRealmEnabled()) { + KerberosRealm kerberosRealm = getKerberosRealm(); + data.put("redirectURL", + constructUrl(kerberosRealm.getProviderUrl(), kerberosRealm.getRedirectParam(), + kerberosRealm.getLogout())); + data.put("isLogoutAPI", kerberosRealm.getLogoutAPI().toString()); } JsonResponse<Map<String, String>> response = new JsonResponse<>(status, "", data); LOG.info(response.toString()); return response.build(); } - private String constructKnoxUrl(KnoxJwtRealm knoxJwtRealm, String path) { - StringBuilder redirectURL = new StringBuilder(knoxJwtRealm.getProviderUrl()); + private String constructUrl(String providerURL, String redirectParam, + String path) { + StringBuilder redirectURL = new StringBuilder(providerURL); redirectURL.append(path); - if (knoxJwtRealm.getRedirectParam() != null) { - redirectURL.append("?").append(knoxJwtRealm.getRedirectParam()).append("="); + if (redirectParam != null) { + redirectURL.append("?").append(redirectParam).append("="); } return redirectURL.toString(); } diff --git a/zeppelin-web/src/components/navbar/navbar.controller.js b/zeppelin-web/src/components/navbar/navbar.controller.js index d6b66fa..9713e50 100644 --- a/zeppelin-web/src/components/navbar/navbar.controller.js +++ b/zeppelin-web/src/components/navbar/navbar.controller.js @@ -107,8 +107,7 @@ function NavCtrl($scope, $rootScope, $http, $routeParams, $location, let res = angular.fromJson(response.data).body; if (res['redirectURL']) { if (res['isLogoutAPI'] === 'true') { - $http.get(res['redirectURL']).then(function() { - }, function() { + $http.get(res['redirectURL']).finally(function() { window.location = baseUrlSrv.getBase(); }); } else {