Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Black and White listings for the Extension Manager #7989

Merged
merged 59 commits into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
d47c1f4
initial experiment for the blacklist feature
echarles Mar 2, 2020
8b183c3
add listings example
echarles Mar 2, 2020
f71aaf6
Colorize the listed extensions
echarles Mar 4, 2020
f9fc91b
Colorize the listed extensions
echarles Mar 4, 2020
556d145
Add settings to listings example
echarles Mar 5, 2020
7497d0f
Add listings definitions in the packages
echarles Mar 6, 2020
c8eda5c
Depend on jupyterlab-server bw-list branch
echarles Mar 6, 2020
0897ca4
add listings_dir in config
echarles Mar 6, 2020
fb08151
Listings URI configured on server
echarles Mar 6, 2020
c7bfec9
Fetch the listings uri from the listings handler
echarles Mar 7, 2020
2828666
Use listings.json in check_assets
echarles Mar 7, 2020
e7ef828
Package extension-manager depends on coreutils
echarles Mar 7, 2020
c914598
Use signal to communication uris availabilty
echarles Mar 7, 2020
07cb9a5
Change uris
echarles Mar 7, 2020
913985a
Implement disclaimed setting
echarles Mar 8, 2020
56f6fd3
Implement disclaimed setting
echarles Mar 8, 2020
e865b6e
Collapsible disclaimer
echarles Mar 8, 2020
037e2e6
Disclamed should be false by default
echarles Mar 8, 2020
458a83c
Manage listing entries with attributes
echarles Mar 11, 2020
af33ac5
Define refresh time in Makefile
echarles Mar 11, 2020
15ab095
Add docs for listings
echarles Mar 11, 2020
cc6f700
Use correct traits in the doc
echarles Mar 12, 2020
4b309df
Merge branch 'master' into bw-list
echarles Mar 12, 2020
5f58dc5
merge with master
echarles Mar 12, 2020
4670176
Move listings example under exteensionmanager-extension package
echarles Mar 13, 2020
9600ada
Move listings example under exteensionmanager-extension package
echarles Mar 13, 2020
b8f299e
Do not show the blacklisted extensions
echarles Mar 13, 2020
a7e3a75
Better icons
echarles Mar 13, 2020
4969c22
Do not allow to install non-whitelisted in white mode
echarles Mar 13, 2020
82dfd82
Add documentation
echarles Mar 13, 2020
adedbe5
Do not show non whitelisted extensions
echarles Mar 14, 2020
57823d5
Docs for listings configuration
echarles Mar 14, 2020
5e037a0
Disclaimer text on left
echarles Mar 14, 2020
5cc7123
Disclamier css and text
echarles Mar 16, 2020
bc7b5d1
remove listings folder
echarles Mar 17, 2020
34f5cb3
Update docs/source/user/extensions.rst
echarles Mar 18, 2020
d39a131
Update docs/source/user/extensions.rst
echarles Mar 18, 2020
c25624e
ListEntry has only name mandatory
echarles Mar 18, 2020
b5d55a6
Update jupyterlab/labapp.py
echarles Mar 18, 2020
1193c32
Merge branch 'bw-list' of https://github.com/datalayer-contrib/jupyte…
echarles Mar 18, 2020
2ce2c58
Use type union for ListResult
echarles Mar 18, 2020
76c7993
Docs on requestAPI
echarles Mar 18, 2020
3586354
Respect lint rule for jupyterOrg var
echarles Mar 18, 2020
4efdd97
Use Array instead of Map
echarles Mar 18, 2020
ce54ab0
Exit in case of simultaneous black/white list uris
echarles Mar 18, 2020
1459d43
Fix typo in docs
echarles Mar 18, 2020
ea5dd9e
Better reason example
echarles Mar 18, 2020
2f9d0d4
Merge branch 'master' into bw-list
echarles Mar 19, 2020
dc6fae6
Header of collapsible section is Warning
echarles Mar 20, 2020
f112e7b
Header of collapsible section is Warning
echarles Mar 20, 2020
e6dc0c8
Remove commmented code
echarles Mar 20, 2020
37e8a80
listings_refresh should be in seconds
echarles Mar 27, 2020
b64335a
Listing Makefile to print seconds
echarles Mar 27, 2020
69a7aa1
Listings example: refresh every 2 minutes
echarles Mar 27, 2020
6b2e936
Use button to confirm warning
echarles Mar 27, 2020
ed32796
Merge branch 'master' into bw-list
echarles Mar 27, 2020
66e4921
Support default mode
echarles Mar 27, 2020
de5de53
Populate extension discover on load
echarles Mar 28, 2020
b2ec97a
Add key at top level to avoid React console warnings.
echarles Mar 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ examples/chrome-example-test.js
jupyterlab/chrome-test.js
jupyterlab/geckodriver
jupyterlab/schemas
packages/extensionmanager-extension/examples/listings
jupyterlab/staging/index.js
jupyterlab/staging/yarn.js
jupyterlab/themes
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jupyterlab/themes
jupyterlab/geckodriver

dev_mode/schemas
dev_mode/listings
dev_mode/static
dev_mode/themes
dev_mode/workspaces
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jupyterlab/geckodriver
jupyterlab/staging/yarn.js
jupyterlab/staging/index.js
packages/ui-components/src/icon/iconimports.ts
packages/extensionmanager/examples/listings

# jetbrains IDE stuff
.idea/
Expand Down
9 changes: 9 additions & 0 deletions docs/source/developer/extension_dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -725,3 +725,12 @@ release process, but this could also be done manually.
Technically, a package that contains only a JupyterLab extension could be created
and published on ``conda-forge``, but it would not be discoverable by the JupyterLab
extension manager.


Listings
^^^^^^^^

You can develop on the extension manager package and :ref:`listings` with the
example shipped in the ``packages/extensionmanager-extension/examples/listings`` folder.

Follow the ``README.md`` instructions in that folder.
1 change: 0 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ JupyterLab is the next-generation web-based user interface for Project Jupyter.
user/jupyterhub
user/export


.. toctree::
:maxdepth: 1
:caption: Developer Guide
Expand Down
195 changes: 193 additions & 2 deletions docs/source/user/extensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ extensions to use and can depend on other extensions. In fact, the whole of
JupyterLab itself is simply a collection of extensions that are no more powerful
or privileged than any custom extension.

.. contents:: Table of contents
:local:
:depth: 1

JupyterLab extensions are `npm <https://www.npmjs.com/>`__ packages (the
standard package format in Javascript development). You can search for the
keyword `jupyterlab-extension
Expand Down Expand Up @@ -74,12 +78,61 @@ Once enabled, you should see a new tab appear in the :ref:`left sidebar <left-si

.. figure:: images/extension_manager_default.png
:align: center
:class: jp-screenshot
:class: jp-screenshotls

**Figure:** The default view has three components: a search bar, an "Installed"
section, and a "Discover" section.


Disclaimer
^^^^^^^^^^

.. danger::

Installing an extension allows it to execute arbitrary code on the
server, kernel, and in the client's browser. Therefor we ask you
to explictitly acknowledge this.


By default, the disclaimer is not checked.

.. figure:: images/listings/disclaimer_unchecked.png
:align: center
:class: jp-screenshot

**Figure:** User has not checked the disclaimer


As the disclaimer is not checked, you can search for an extension,
but can not install it (no Install button is available).

.. figure:: images/listings/disclaimer_unchecked_noinstall.png
:align: center
:class: jp-screenshot

**Figure:** With Disclaimer unchecked, you can not install an extension


To install an extensino, you first have to explicitly check the disclaimer.
Once done, this will remain across sessions and the user does not have to
check it again.

.. figure:: images/listings/disclaimer_checked.png
:align: center
:class: jp-screenshot

**Figure:** Disclaimer checked

For ease of use, you can hide the disclaimer so it takes less space on
your screen.

.. figure:: images/listings/disclaimer_hidden.png
:align: center
:class: jp-screenshot

**Figure:** Disclaimer is hidden


Finding Extensions
^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -108,6 +161,8 @@ performs a free-text search of JupyterLab extensions on the NPM registry.
:alt: Screenshot showing an example search result


.. _listings:

Installing an Extension
^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -196,6 +251,143 @@ will be up to you to take these into account or not.



Listings
~~~~~~~~

When searching extensions, JupyterLab displays the complete search result and
the user is free to install any extension. This is the :ref:`default_mode`.

To bring more security, you or your administrator can enable ``blacklists`` or ``whitelists``
mode. JupyterLab will check the extensions against the defined listings.

Only one mode at a time is allowed.

The following details the behavior for the :ref:`blacklist_mode` and the :ref:`whitelist_mode`.
The details to enable configure the listings can be read :ref:`listings_conf`.

.. _default_mode:

Default mode
^^^^^^^^^^^^

In the ``default`` mode, no listing is enabled and the search behavior is unchanged and
is the one described previously.
echarles marked this conversation as resolved.
Show resolved Hide resolved

.. _blacklist_mode:

Blacklist mode
^^^^^^^^^^^^^^

Extensions can be freely downloaded without going through a vetting process.
However, users can add malicious extensions to a blacklist. The extension manager
will show all extensions except for those that have
been explicitly added to the blacklist. Therfore, the extension manager
does not allow you to install blacklisted extensions.

If you, or your administrator, has enabled the blacklist mode,
JupyterLab will use the blacklist and remove all blacklisted
extensions from your search result.

If you have installed an extension before it has been blacklisted,
the extension entry in the installed list will be highlighted
in red. It is recommended that you uninstall it. You can move
your mouse on the question mark icon to read the instructions.

.. figure:: images/listings/installed_blacklisted.png
:align: center
:class: jp-screenshot

**Figure:** Blacklisted installed extension which should be removed


.. _whitelist_mode:

Whitelist mode
^^^^^^^^^^^^^^

A whitelist maintains a set of approved extensions that users can freely
search and install. Extensions need to go through some sort of vetting process
before they are added to the whitelist. When using a whitelist, the extension manager
will only show extensions that have been explicitly added to the whitelist.

If you, or your administrator, has enabled the whitelist mode
JupyterLab will use the whitelist and only show extensions present
in the withelist. The other extensions will not be show in the search result.
echarles marked this conversation as resolved.
Show resolved Hide resolved

If you have installed an whitelisted extension and at some point
in time that extension is removed from the whitelist, the extension entry
in the installed list will be highlighted in red. It is recommended that
you uninstall it. You can move your mouse on the question mark icon to
read the instructions.

.. figure:: images/listings/installed_whitelisted.png
:align: center
:class: jp-screenshot

**Figure:** Whitelisted installed extension which should be removed

.. _listings_conf:

Listing Configuration
^^^^^^^^^^^^^^^^^^^^^

You or your administrator can use the following traits to define the listings loading.

- ``blacklist_uris``: A list of comma-separated URIs to get the blacklist
- ``whitelist_uris``: A list of comma-separated URIs to get the whitelist
- ``listings_refresh_seconds``: The interval delay in seconds to refresh the lists
- ``listings_request_options``: The optional kwargs to use for the listings HTTP requests

For example, to enable blacklist, launch the server with ``--LabServerApp.blacklist_uris``.

The details for the listings_request_options are listed
on the `this page <https://2.python-requests.org/en/v2.7.0/api/#requests.request>`__
(for example, you could pass ``{'timeout': 10}`` to change the HTTP request timeout value).

The listings are json files hosted on the URIs you have given.

For each entry, you have to define the `name` of the extension as published in the NPM registry.
The ``name`` attribute support regular expressions.

Optionally, you can also add some more fields for your records (``type``, ``reason``, ``creation_date``,
``last_update_date``). These optional fields are not used in the user interface.

This is an example of a blacklist file.

.. code:: json

{
"blacklist": [
{
"name": "@jupyterlab-examples/launcher",
"type": "jupyterlab",
"reason": "@jupyterlab-examples/launcher is blacklisted for test purpose - Do NOT take this for granted!!!",
"creation_date": "2020-03-11T03:28:56.782Z",
saulshanabrook marked this conversation as resolved.
Show resolved Hide resolved
"last_update_date": "2020-03-11T03:28:56.782Z"
}
]
}


In the following whitelist example a ``@jupyterlab/*`` will whitelist
all jupyterlab organization extensions.

.. code:: json

{
"whitelist": [
{
"name": "@jupyterlab/*",
"type": "jupyterlab",
"reason": "All @jupyterlab org extensions are whitelisted, of course...",
"creation_date": "2020-03-11T03:28:56.782Z",
"last_update_date": "2020-03-11T03:28:56.782Z"
}
]
}



Using the Terminal
~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -532,4 +724,3 @@ By default, the location is ``~/.jupyter/lab/workspaces/``, where ``~`` is the u
because these files are typically shared across Python environments.
The location can be modified using the ``JUPYTERLAB_WORKSPACES_DIR`` environment variable. These files can be imported and exported to create default "profiles",
using the :ref:`workspace command line tool <url-workspaces-cli>`.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion jupyterlab/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def load_config(nbapp):
config.app_version = info['version']
config.cache_files = True
config.schemas_dir = pjoin(app_dir, 'schemas')
config.listings_dir = pjoin(app_dir, 'listings')
config.templates_dir = pjoin(app_dir, 'static')
config.themes_dir = pjoin(app_dir, 'themes')
config.user_settings_dir = user_settings_dir
Expand Down Expand Up @@ -96,7 +97,7 @@ def load_jupyter_server_extension(nbapp):
web_app = nbapp.web_app
logger = nbapp.log
base_url = nbapp.base_url

# Handle the app_dir
app_dir = getattr(nbapp, 'app_dir', get_app_dir())

Expand Down
31 changes: 31 additions & 0 deletions packages/extensionmanager-extension/examples/listings/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export BLACK_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/blacklist_simple.json"
# export BLACK_LIST_URIS=""
# export WHITE_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/whitelist_only_jlab.json"
export WHITE_LIST_URIS=""
export LISTINGS_REFRESH_SECONDS=120
export LISTINGS_REQUEST_OPTS="{'timeout': 10}"

listings-uris:
@exec echo Using blacklist URIs: ${BLACK_LIST_URIS}
@exec echo Using whitelist URIs: ${WHITE_LIST_URIS}
@exec echo Refreshing lists every ${LISTINGS_REFRESH_SECONDS} seconds
@exec echo Using ${LISTINGS_REQUEST_OPTS} for the HTTP requests

dev: listings-uris
@exec python main.py \
--dev \
--no-browser \
--LabServerApp.blacklist_uris=${BLACK_LIST_URIS} \
--LabServerApp.whitelist_uris=${WHITE_LIST_URIS} \
--LabServerApp.listings_refresh_seconds=${LISTINGS_REFRESH_SECONDS} \
--LabServerApp.listings_request_options=${LISTINGS_REQUEST_OPTS}

watch: listings-uris
@exec python main.py \
--dev \
--no-browser \
--watch \
--LabServerApp.blacklist_uris=${BLACK_LIST_URIS} \
--LabServerApp.whitelist_uris=${WHITE_LIST_URIS} \
--LabServerApp.listings_refresh_seconds=${LISTINGS_REFRESH_SECONDS} \
--LabServerApp.listings_request_options=${LISTINGS_REQUEST_OPTS}
21 changes: 21 additions & 0 deletions packages/extensionmanager-extension/examples/listings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# JupyterLab Listings Example

This example allows you to develop the black/white listings features

First build JupyterLab in dev mode.

```bash
jupyter lab build --dev-mode
```

For iterative development, launch in `watch` mode.

```bash
make watch
```

Otherwise, launch in `dev` mode.

```bash
make dev
```
Loading