From 2179be684324483f0739d3424a5aad8f1bcf8726 Mon Sep 17 00:00:00 2001 From: Carol Willing Date: Wed, 16 Sep 2015 11:57:35 -0700 Subject: [PATCH 1/5] Edit public server security doc --- docs/source/public_server.rst | 69 ++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/docs/source/public_server.rst b/docs/source/public_server.rst index 687323031..4bf846a45 100644 --- a/docs/source/public_server.rst +++ b/docs/source/public_server.rst @@ -4,13 +4,19 @@ Running a notebook server ========================= -The :doc:`Jupyter notebook ` web-application is based on a -server-client structure. This server uses a :ref:`two-process kernel -architecture ` based on ZeroMQ_, as well as Tornado_ for serving -HTTP requests. By default, a notebook server runs on http://127.0.0.1:8888/ -and is accessible only from `localhost`. This document describes how you can -:ref:`secure a notebook server ` and how to :ref:`run it on -a public interface `. +The :doc:`Jupyter notebook ` web application is based on a +server-client structure. The notebook server uses a :ref:`two-process kernel +architecture ` based on ZeroMQ_, as well as Tornado_ for +serving HTTP requests. + +.. note:: + By default, a notebook server runs locally at 127.0.0.1:8888 + and is accessible only from `localhost`. You may access the + notebook server from the browser using `http://127.0.0.1:8888`. + +This document describes how you can +:ref:`secure a notebook server ` and how to +:ref:`run it on a public interface `. .. _ZeroMQ: http://zeromq.org @@ -23,41 +29,60 @@ Securing a notebook server -------------------------- You can protect your notebook server with a simple single password by -setting the :attr:`NotebookApp.password` configurable. You can prepare a -hashed password using the function :func:`notebook.auth.security.passwd`: +configuring the :attr:`NotebookApp.password` setting in +:file:`jupyter_notebook_config.py`. + +Preparing a hashed password +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can prepare a hashed password using the function +:func:`notebook.auth.security.passwd`: .. sourcecode:: ipython In [1]: from notebook.auth import passwd In [2]: passwd() - Enter password: - Verify password: + Enter password: + Verify password: Out[2]: 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed' - -.. note:: + +.. caution:: :func:`~notebook.auth.security.passwd` can also take the password as a string argument. **Do not** pass it as an argument inside an IPython session, as it will be saved in your input history. -You can then add this to your :file:`jupyter_notebook_config.py`, e.g.:: +Adding hashed password to your notebook configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can then add the hashed password to your :file:`jupyter_notebook_config.py`, +e.g.:: # Password to use for web authentication c = get_config() - c.NotebookApp.password = + c.NotebookApp.password = u'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed' -When using a password, it is a good idea to also use SSL, so that your -password is not sent unencrypted by your browser. You can start the notebook -to communicate via a secure protocol mode using a self-signed certificate with +Using SSL for encrypted communication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When using a password, it is a good idea to also use SSL with a web certificate, +so that your hashed password is not sent unencrypted by your browser. + +.. important:: + Web security is rapidly changing and evolving. We provide this document + as a convenience to the user, and recommend that the user keep current on + changes that may impact security, such as new releases of OpenSSL. + The Open Web Application Security Project (`OWASP`_) website is a good resource + on general security issues and web practices. + +You can start the notebook to communicate via a secure protocol mode by setting +``certfile`` option to your self-signed certificate, i.e. ``mycert.pem``, with the command:: - $ ipython notebook --certfile=mycert.pem + $ jupyter notebook --certfile=mycert.pem .. note:: - A self-signed certificate can be generated with ``openssl``. For example, - the following command will create a certificate valid for 365 days with + A self-signed certificate can be generated with ``openssl``. For example, + the following command will create a certificate valid for 365 days with both the key and certificate data written to the same file:: $ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem @@ -74,6 +99,8 @@ notebook server over ``https://``, not over plain ``http://``. The startup message from the server prints this, but it is easy to overlook and think the server is for some reason non-responsive. +.. _OWASP: https://www.owasp.org + .. _notebook_public_server: From de9781dcbab0181852b15dd2a1726223272ba56b Mon Sep 17 00:00:00 2001 From: Carol Willing Date: Wed, 16 Sep 2015 12:51:17 -0700 Subject: [PATCH 2/5] Update doc on securing a notebook server --- docs/source/public_server.rst | 40 +++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/docs/source/public_server.rst b/docs/source/public_server.rst index 4bf846a45..df51307bb 100644 --- a/docs/source/public_server.rst +++ b/docs/source/public_server.rst @@ -47,16 +47,21 @@ You can prepare a hashed password using the function .. caution:: - :func:`~notebook.auth.security.passwd` can also take the password as a string - argument. **Do not** pass it as an argument inside an IPython session, as it + :func:`~notebook.auth.security.passwd` when called with no arguments + will prompt you to enter and verify your password such as + in the above code snippet. Although the function can also + be passed a string as an argument such as ``passwd('mypassword')``, please + **do not** pass a string as an argument inside an IPython session, as it will be saved in your input history. Adding hashed password to your notebook configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can then add the hashed password to your :file:`jupyter_notebook_config.py`, +You can then add the hashed password to your :file:`jupyter_notebook_config.py`. +The default location for this file ``jupyter_notebook_config.py`` in your Jupyter +folder in your home directory, ``~/.jupyter``. e.g.:: - # Password to use for web authentication + # Get notebook configuration and add hashed password c = get_config() c.NotebookApp.password = u'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed' @@ -74,12 +79,12 @@ so that your hashed password is not sent unencrypted by your browser. on general security issues and web practices. You can start the notebook to communicate via a secure protocol mode by setting -``certfile`` option to your self-signed certificate, i.e. ``mycert.pem``, with -the command:: +the ``certfile`` option to your self-signed certificate, i.e. ``mycert.pem``, +with the command:: $ jupyter notebook --certfile=mycert.pem -.. note:: +.. tip:: A self-signed certificate can be generated with ``openssl``. For example, the following command will create a certificate valid for 365 days with @@ -87,17 +92,20 @@ the command:: $ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem -Your browser will warn you of a dangerous certificate because it is -self-signed. If you want to have a fully compliant certificate that will not -raise warnings, it is possible (but rather involved) to obtain one, -as explained in detail in `this tutorial`__. +When starting the notebook server, your browser may warn that your self-signed +certificate is insecure or unrecognized. If you wish to have a fully +compliant self-signed certificate that will not raise warnings, it is possible +(but rather involved) to create one, as explained in detail in `this tutorial`__. .. __: http://arstechnica.com/security/news/2009/12/how-to-get-set-with-a-secure-sertificate-for-free.ars - + +.. TODO: Find an additional resource that walks the user through this two-process step by step. + Keep in mind that when you enable SSL support, you will need to access the notebook server over ``https://``, not over plain ``http://``. The startup -message from the server prints this, but it is easy to overlook and think the -server is for some reason non-responsive. +message from the server prints a reminder in the console, but it is easy to +overlook this detail and think the server is for some reason non-responsive. +**When using SSL, always access the notebook server with ``https://``.** .. _OWASP: https://www.owasp.org @@ -108,7 +116,7 @@ Running a public notebook server -------------------------------- If you want to access your notebook server remotely via a web browser, -you can do the following. +you can do the following. Start by creating a certificate file and a hashed password, as explained above. Then, if you don't already have one, create a config file for the @@ -135,7 +143,7 @@ to ``https://your.host.com:9999`` with ``jupyter notebook``. Firewall Setup -`````````````` +~~~~~~~~~~~~~~ To function correctly, the firewall on the computer running the ipython server must be configured to allow connections from client machines on the ``c.NotebookApp.port`` From ce6ecb730bcd5b22157d896adb17cedf17ac4327 Mon Sep 17 00:00:00 2001 From: Carol Willing Date: Wed, 16 Sep 2015 15:14:35 -0700 Subject: [PATCH 3/5] Edit content on running a public notebook server --- docs/source/public_server.rst | 88 +++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/docs/source/public_server.rst b/docs/source/public_server.rst index df51307bb..d79a3cd4d 100644 --- a/docs/source/public_server.rst +++ b/docs/source/public_server.rst @@ -32,6 +32,18 @@ You can protect your notebook server with a simple single password by configuring the :attr:`NotebookApp.password` setting in :file:`jupyter_notebook_config.py`. +Prerequisite: A notebook configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Check to see if you have a notebook configuration file, +:file:`jupyter_notebook_config.py`. The default location for this file +is your Jupyter folder in your home directory, ``~/.jupyter``. + +If you don't already have one, create a config file for the notebook +using the following command:: + + $ jupyter notebook --generate-config + + Preparing a hashed password ~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can prepare a hashed password using the function @@ -57,9 +69,8 @@ You can prepare a hashed password using the function Adding hashed password to your notebook configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can then add the hashed password to your :file:`jupyter_notebook_config.py`. -The default location for this file ``jupyter_notebook_config.py`` in your Jupyter -folder in your home directory, ``~/.jupyter``. -e.g.:: +The default location for this file :file:`jupyter_notebook_config.py` is in +your Jupyter folder in your home directory, ``~/.jupyter``, e.g.:: # Get notebook configuration and add hashed password c = get_config() @@ -116,53 +127,68 @@ Running a public notebook server -------------------------------- If you want to access your notebook server remotely via a web browser, -you can do the following. +you can do so by running a public notebook server. For optimal security +when running a public notebook server, you should first secure the +server with a password and SSL/HTTPS as described in +:ref:`notebook_server_security`. + +Start by creating a certificate file and a hashed password, as explained in +:ref:`notebook_server_security`. -Start by creating a certificate file and a hashed password, as explained -above. Then, if you don't already have one, create a config file for the -notebook using the following command line:: +If you don't already have one, create a +config file for the notebook using the following command line:: $ jupyter notebook --generate-config -In the ``~/.jupyter`` directory, edit the notebook config file, -``jupyter_notebook_config.py``. By default, the file has all fields -commented; the minimum set you need to uncomment and edit is the following:: +In the ``~/.jupyter`` directory, edit the notebook config file, +``jupyter_notebook_config.py``. By default, the notebook config file has +all fields commented out. The minimum set of configuration options that +you should to uncomment and edit in :file:``jupyter_notebook_config.py`` is the +following:: + # Notebook configuration for public notebook server c = get_config() - # Notebook config + # Set options for certfile, ip, password, and toggle off browser auto-opening c.NotebookApp.certfile = u'/absolute/path/to/your/certificate/mycert.pem' - c.NotebookApp.ip = '*' + c.NotebookApp.ip = u'*' # where * is the desired ip address + c.NotebookApp.password = u'sha1:bcd259ccf...' c.NotebookApp.open_browser = False - c.NotebookApp.password = u'sha1:bcd259ccf...[your hashed password here]' - # It is a good idea to put it on a known, fixed port + + # It is a good idea to set a known, fixed port for server access c.NotebookApp.port = 9999 -You can then start the notebook and access it later by pointing your browser -to ``https://your.host.com:9999`` with ``jupyter notebook``. +You can then start the notebook and access it later by pointing your browser +to ``https://your.host.com:9999`` after starting the ``jupyter notebook`` +client. Firewall Setup ~~~~~~~~~~~~~~ -To function correctly, the firewall on the computer running the ipython server must be -configured to allow connections from client machines on the ``c.NotebookApp.port`` -port to allow connections to the web interface. The firewall must also allow -connections from 127.0.0.1 (localhost) on ports from 49152 to 65535. -These ports are used by the server to communicate with the notebook kernels. -The kernel communication ports are chosen randomly by ZeroMQ, and may require +To function correctly, the firewall on the computer running the jupyter +notebook server must be configured to allow connections from client +machines on the access port ``c.NotebookApp.port`` set in +:file:``jupyter_notebook_config.py`` port to allow connections to the +web interface. The firewall must also allow connections from +127.0.0.1 (localhost) on ports from 49152 to 65535. +These ports are used by the server to communicate with the notebook kernels. +The kernel communication ports are chosen randomly by ZeroMQ, and may require multiple connections per kernel, so a large range of ports must be accessible. -Running with a different URL prefix ------------------------------------ +Running the notebook with a customized URL prefix +------------------------------------------------- + +The notebook dashboard, which is the landing page with an overview +of the notebooks in your working directory, is typically found and accessed +at the default URL ``http://localhost:8888/``. -The notebook dashboard (the landing page with an overview -of the notebooks in your working directory) typically lives at the URL -``http://localhost:8888/``. If you prefer that it lives, together with the -rest of the notebook, under a sub-directory, -e.g. ``http://localhost:8888/ipython/``, you can do so with -configuration options like the following (see above for instructions about -modifying ``jupyter_notebook_config.py``):: +If you prefer to customize the URL prefix for the notebook dashboard, you can +do so through modifying ``jupyter_notebook_config.py``. For example, if you +prefer that the notebook dashboard be located with a sub-directory that +contains other ipython files, e.g. ``http://localhost:8888/ipython/``, +you can do so with configuration options like the following (see above for +instructions about modifying ``jupyter_notebook_config.py``):: c.NotebookApp.base_url = '/ipython/' c.NotebookApp.webapp_settings = {'static_url_prefix':'/ipython/static/'} From 64ae0314882d2af4155336f10317050cefd7462d Mon Sep 17 00:00:00 2001 From: Carol Willing Date: Wed, 16 Sep 2015 15:34:22 -0700 Subject: [PATCH 4/5] Add note and link to RTD in old ipynb doc --- .../Notebook/Configuring the Notebook and Server.ipynb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb b/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb index e63c97a41..75780f741 100644 --- a/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb +++ b/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb @@ -7,6 +7,13 @@ "# Configuring the Notebook and Server" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note: The most current documentation on these topics may be found at the Jupyter notebook documentation on Read the Docs https://jupyter-notebook.readthedocs.org/en/latest/public_server.html.**" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -247,7 +254,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.0" + "version": "3.5.0" } }, "nbformat": 4, From 88554a003e71467ea257f96e6d628b6670d81452 Mon Sep 17 00:00:00 2001 From: Carol Willing Date: Wed, 16 Sep 2015 15:40:27 -0700 Subject: [PATCH 5/5] Fix formatting on ipynb note --- .../Configuring the Notebook and Server.ipynb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb b/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb index 75780f741..7c7cd58e5 100644 --- a/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb +++ b/docs/source/examples/Notebook/Configuring the Notebook and Server.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Note: The most current documentation on these topics may be found at the Jupyter notebook documentation on Read the Docs https://jupyter-notebook.readthedocs.org/en/latest/public_server.html.**" + "**Note:** The most current documentation on these topics may be found in the [Jupyter notebook documentation on Read the Docs](https://jupyter-notebook.readthedocs.org/en/latest/public_server.html)." ] }, { @@ -240,21 +240,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 2", "language": "python", - "name": "python3" + "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.0" + "pygments_lexer": "ipython2", + "version": "2.7.10" } }, "nbformat": 4,