You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by pr...@apache.org on 2020/11/13 06:52:10 UTC

[zeppelin] branch master updated: [ZEPPELIN-5116] Accessing zeppelin via knox after knox logout should be redirected to knox login page

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 <pr...@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 <pr...@gmail.com>
    Author: Prarthi <pr...@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.com@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.com@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.com@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 {