You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by zj...@apache.org on 2020/10/19 04:55:09 UTC

[zeppelin] branch master updated: [ZEPPELIN-5061] fix note list broadcast

This is an automated email from the ASF dual-hosted git repository.

zjffdu 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 605d704  [ZEPPELIN-5061] fix note list broadcast
605d704 is described below

commit 605d7044d824cb863b5ec1f517781ff81562386f
Author: David Golightly <da...@leapyear.io>
AuthorDate: Mon Sep 28 09:28:46 2020 -0700

    [ZEPPELIN-5061] fix note list broadcast
    
    ### What is this PR for?
    As described in the linked issue, there has been a bug where, when a user creates or updates a note, that user's note list is published to all connected users, instead of their own note lists. This has the security problem that it leaks information about a user's note list to other users who may not have permission to see it. This PR fixes that bug by querying each connected user's note list and publishing that instead.
    
    ### What type of PR is it?
    Bug Fix
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/ZEPPELIN-5061
    
    ### How should this be tested?
    Manual testing:
    * Configure a list of users using a `shiro.ini` file. Example:
    ```
    [users]
    # List of users with their password allowed to access Zeppelin.
    # To use a different strategy (LDAP / Database / ...) check the shiro doc at http://shiro.apache.org/configuration.html#Configuration-INISections
    admin = password1, admin
    user1 = password2, role1
    user2 = password3, role1
    ```
    * Turn off public notebooks in `zeppelin-site.xml` by setting the property `zeppelin.notebook.public` to `false`
    * Boot Zeppelin server on this PR
    * Log in as user1
    * In a separate browser, log in as user2
    * As user1, create a note
    Previous result: user1's note appears on user2's dashboard. Refreshing user2's browser will cause the note to disappear from their dashboard.
    Fixed expectations:
    - user1's note does not appear on user2's dashboard.
    - the display of any notes created by user1 is not affected when user2 creates a note
    - when `zeppelin.notebook.public` is set to `true`, user1's note appears as expected on user1's dashboard
    
    Author: David Golightly <da...@leapyear.io>
    
    Closes #3926 from david-golightly-leapyear/dg/notebook-sharing-fix and squashes the following commits:
    
    175285e9c [David Golightly] address feedback
    4f0023143 [David Golightly] get variable outside of loop
    99306186c [David Golightly] remove unused import
    e9926e6ca [David Golightly] fix note list broadcast
    
    (cherry picked from commit 596c287b744989451e09e7747218f3cd99e6b140)
    Signed-off-by: Jeff Zhang <zj...@apache.org>
---
 .../apache/zeppelin/socket/ConnectionManager.java  | 12 +++++++
 .../org/apache/zeppelin/socket/NotebookServer.java | 39 ++++++++++------------
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/ConnectionManager.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/ConnectionManager.java
index fa99501..e7f99aa 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/ConnectionManager.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/ConnectionManager.java
@@ -360,6 +360,18 @@ public class ConnectionManager {
     }
   }
 
+  public interface UserIterator {
+    public void handleUser(String user, Set<String> userAndRoles);
+  }
+
+  public void forAllUsers(UserIterator iterator) {
+    for (String user : userSocketMap.keySet()) {
+      Set<String> userAndRoles = authorizationService.getRoles(user);
+      userAndRoles.add(user);
+      iterator.handleUser(user, userAndRoles);
+    }
+  }
+
   public void broadcastNoteListExcept(List<NoteInfo> notesInfo,
                                       AuthenticationInfo subject) {
     Set<String> userAndRoles;
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
index 45e1abe..2c7ece1 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
@@ -81,6 +81,7 @@ import org.apache.zeppelin.service.JobManagerService;
 import org.apache.zeppelin.service.NotebookService;
 import org.apache.zeppelin.service.ServiceContext;
 import org.apache.zeppelin.service.SimpleServiceCallback;
+import org.apache.zeppelin.socket.ConnectionManager.UserIterator;
 import org.apache.zeppelin.ticket.TicketContainer;
 import org.apache.zeppelin.types.InterpreterSettingsList;
 import org.apache.zeppelin.user.AuthenticationInfo;
@@ -636,17 +637,22 @@ public class NotebookServer extends WebSocketServlet
   }
 
   public void inlineBroadcastNoteList(AuthenticationInfo subject, Set<String> userAndRoles) {
-    if (subject == null) {
-      subject = new AuthenticationInfo(StringUtils.EMPTY);
-    }
-    //send first to requesting user
+    broadcastNoteListUpdate();
+  }
+
+  public void broadcastNoteListUpdate() {
     AuthorizationService authorizationService = getNotebookAuthorizationService();
-    List<NoteInfo> notesInfo = getNotebook().getNotesInfo(
-        noteId -> authorizationService.isReader(noteId, userAndRoles));
-    Message message = new Message(OP.NOTES_INFO).put("notes", notesInfo);
-    getConnectionManager().multicastToUser(subject.getUser(), message);
-    //to others afterwards
-    getConnectionManager().broadcastNoteListExcept(notesInfo, subject);
+
+    getConnectionManager().forAllUsers(new UserIterator() {
+      @Override
+      public void handleUser(String user, Set<String> userAndRoles) {
+        List<NoteInfo> notesInfo = getNotebook().getNotesInfo(
+            noteId -> authorizationService.isReader(noteId, userAndRoles));
+
+        getConnectionManager().multicastToUser(user,
+          new Message(OP.NOTES_INFO).put("notes", notesInfo));
+      }
+    });
   }
 
   public void broadcastNoteList(AuthenticationInfo subject, Set<String> userAndRoles) {
@@ -772,18 +778,7 @@ public class NotebookServer extends WebSocketServlet
 
   public void broadcastReloadedNoteList(NotebookSocket conn, ServiceContext context)
       throws IOException {
-    getNotebookService().listNotesInfo(true, context,
-        new WebSocketServiceCallback<List<NoteInfo>>(conn) {
-          @Override
-          public void onSuccess(List<NoteInfo> notesInfo,
-                                ServiceContext context) throws IOException {
-            super.onSuccess(notesInfo, context);
-            getConnectionManager().multicastToUser(context.getAutheInfo().getUser(),
-                new Message(OP.NOTES_INFO).put("notes", notesInfo));
-            //to others afterwards
-            getConnectionManager().broadcastNoteListExcept(notesInfo, context.getAutheInfo());
-          }
-        });
+    broadcastNoteListUpdate();
   }
 
   void permissionError(NotebookSocket conn, String op, String userName, Set<String> userAndRoles,