From 3a0f19f1a4c633cc2723ae33c100cda8549e30e5 Mon Sep 17 00:00:00 2001 From: MinRK Date: Sun, 21 Sep 2014 16:19:30 -0700 Subject: [PATCH] cookie_secret is no longer bytes add utils.random_hex for generating a unicode object with random hex bytes --- jupyterhub/app.py | 12 ++++++++---- jupyterhub/orm.py | 2 +- jupyterhub/spawner.py | 2 +- jupyterhub/tests/test_orm.py | 2 +- jupyterhub/utils.py | 11 ++++++++++- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 870e805f..a58e4dd7 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -25,7 +25,7 @@ from tornado.log import LogFormatter from tornado import gen, web from IPython.utils.traitlets import ( - Unicode, Integer, Dict, TraitError, List, Bool, Bytes, Any, + Unicode, Integer, Dict, TraitError, List, Bool, Any, DottedObjectName, Set, ) from IPython.config import Application, catch_config_error @@ -37,7 +37,7 @@ from . import handlers, apihandlers from . import orm from ._data import DATA_FILES_PATH -from .utils import url_path_join +from .utils import url_path_join, random_hex, TimeoutError # classes for config from .auth import Authenticator, PAMAuthenticator @@ -190,9 +190,13 @@ class JupyterHubApp(Application): if newnew != new: self.hub_prefix = newnew - cookie_secret = Bytes(config=True) + cookie_secret = Unicode(config=True, + help="""The cookie secret to use to encrypt cookies. + Loaded from the JPY_COOKIE_SECRET env variable by default. + """ + ) def _cookie_secret_default(self): - return b'secret!' + return os.environ.get('JPY_COOKIE_SECRET', random_hex(64)) authenticator = DottedObjectName("jupyterhub.auth.PAMAuthenticator", config=True, help="""Class for authenticating users. diff --git a/jupyterhub/orm.py b/jupyterhub/orm.py index 34399a1b..665388b5 100644 --- a/jupyterhub/orm.py +++ b/jupyterhub/orm.py @@ -71,7 +71,7 @@ class Server(Base): ip = Column(Unicode, default=u'localhost') port = Column(Integer, default=random_port) base_url = Column(Unicode, default=u'/') - cookie_secret = Column(Binary, default=b'secret') + cookie_secret = Column(Unicode, default=u'') cookie_name = Column(Unicode, default=u'cookie') def __repr__(self): diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py index b7cf08d4..75ec4274 100644 --- a/jupyterhub/spawner.py +++ b/jupyterhub/spawner.py @@ -60,7 +60,7 @@ class Spawner(LoggingConfigurable): env = os.environ.copy() for key in ['HOME', 'USER', 'USERNAME', 'LOGNAME', 'LNAME']: env.pop(key, None) - self._env_key(env, 'COOKIE_SECRET', self.user.server.cookie_secret.decode('ascii')) + self._env_key(env, 'COOKIE_SECRET', self.user.server.cookie_secret) self._env_key(env, 'API_TOKEN', self.api_token) return env diff --git a/jupyterhub/tests/test_orm.py b/jupyterhub/tests/test_orm.py index bd651942..c2c29113 100644 --- a/jupyterhub/tests/test_orm.py +++ b/jupyterhub/tests/test_orm.py @@ -21,7 +21,7 @@ def test_server(db): assert server.proto == 'http' assert isinstance(server.port, int) assert isinstance(server.cookie_name, unicode) - assert isinstance(server.cookie_secret, bytes) + assert isinstance(server.cookie_secret, unicode) assert server.url == 'http://localhost:%i/' % server.port diff --git a/jupyterhub/utils.py b/jupyterhub/utils.py index fd6da426..236b30bf 100644 --- a/jupyterhub/utils.py +++ b/jupyterhub/utils.py @@ -3,7 +3,9 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. +import binascii import errno +import os import socket from tornado import web, gen, ioloop from tornado.log import app_log @@ -11,7 +13,8 @@ from tornado.log import app_log from IPython.html.utils import url_path_join try: - TimeoutError + # make TimeoutError importable on Python >= 3.3 + TimeoutError = TimeoutError except NameError: # python < 3.3 class TimeoutError(Exception): @@ -25,6 +28,12 @@ def random_port(): sock.close() return port +def random_hex(nbytes): + """Return nbytes random bytes as a unicode hex string + + It will have length nbytes * 2 + """ + return binascii.hexlify(os.urandom(nbytes)).decode('ascii') @gen.coroutine def wait_for_server(ip, port, timeout=10):