diff --git a/IPython/html/services/notebooks/filenbmanager.py b/IPython/html/services/notebooks/filenbmanager.py index 81aeeed..26e2a54 100644 --- a/IPython/html/services/notebooks/filenbmanager.py +++ b/IPython/html/services/notebooks/filenbmanager.py @@ -214,7 +214,7 @@ class FileNotebookManager(NotebookManager): except Exception as e: raise web.HTTPError(400, u"Unreadable Notebook: %s %s" % (os_path, e)) model['content'] = nb - sign.mark_trusted_cells(nb, self.secret) + sign.mark_trusted_cells(nb, self.notary.secret) return model def save_notebook_model(self, model, name='', path=''): @@ -239,7 +239,7 @@ class FileNotebookManager(NotebookManager): nb = current.to_notebook_json(model['content']) if sign.check_trusted_cells(nb): - sign.trust_notebook(nb, self.secret, self.signature_scheme) + sign.trust_notebook(nb, self.notary.secret, self.notary.signature_scheme) if 'name' in nb['metadata']: nb['metadata']['name'] = u'' diff --git a/IPython/html/services/notebooks/nbmanager.py b/IPython/html/services/notebooks/nbmanager.py index a638e8d..43f9b91 100644 --- a/IPython/html/services/notebooks/nbmanager.py +++ b/IPython/html/services/notebooks/nbmanager.py @@ -17,16 +17,12 @@ Authors: # Imports #----------------------------------------------------------------------------- -import base64 -import hashlib -import io import os from IPython.config.configurable import LoggingConfigurable -from IPython.core.application import BaseIPythonApplication -from IPython.nbformat import current +from IPython.nbformat import current, sign from IPython.utils import py3compat -from IPython.utils.traitlets import Unicode, TraitError, Enum, Bytes +from IPython.utils.traitlets import Instance, Unicode, TraitError #----------------------------------------------------------------------------- # Classes @@ -46,34 +42,9 @@ class NotebookManager(LoggingConfigurable): filename_ext = Unicode(u'.ipynb') - signature_scheme = Enum(hashlib.algorithms, default_value='sha256', config=True, - help="""The signature scheme used to sign notebooks.""" - ) - - secret = Bytes(config=True, - help="""The secret key with which notebooks are signed.""" - ) - def _secret_default(self): - # note : this assumes an Application is running - profile_dir = BaseIPythonApplication.instance().profile_dir - secret_file = os.path.join(profile_dir.security_dir, 'notebook_secret') - if os.path.exists(secret_file): - with io.open(secret_file, 'rb') as f: - return f.read() - else: - secret = base64.encodestring(os.urandom(1024)) - self.log.info("Writing output secret to %s", secret_file) - with io.open(secret_file, 'wb') as f: - f.write(secret) - try: - os.chmod(secret_file, 0o600) - except OSError: - self.log.warn( - "Could not set permissions on %s", - secret_file - ) - return secret - + notary = Instance(sign.NotebookNotary) + def _notary_default(self): + return sign.NotebookNotary(parent=self) def path_exists(self, path): """Does the API-style path (directory) actually exist? diff --git a/IPython/nbformat/sign.py b/IPython/nbformat/sign.py index 3e15deb..f518fea 100644 --- a/IPython/nbformat/sign.py +++ b/IPython/nbformat/sign.py @@ -10,11 +10,16 @@ # Imports #----------------------------------------------------------------------------- +import base64 from contextlib import contextmanager import hashlib from hmac import HMAC +import io +import os from IPython.utils.py3compat import string_types, unicode_type, cast_bytes +from IPython.config import LoggingConfigurable +from IPython.utils.traitlets import Instance, Bytes, Enum #----------------------------------------------------------------------------- # Code @@ -138,4 +143,51 @@ def check_trusted_cells(nb): return False return True - \ No newline at end of file + +class NotebookNotary(LoggingConfigurable): + """A class for configuring notebook signatures + + It stores the secret with which to sign notebooks, + and the hashing scheme to use for notebook signatures. + """ + + signature_scheme = Enum(hashlib.algorithms, default_value='sha256', config=True, + help="""The signature scheme used to sign notebooks.""" + ) + + profile_dir = Instance("IPython.core.profiledir.ProfileDir") + def _profile_dir_default(self): + from IPython.core.application import BaseIPythonApplication + if BaseIPythonApplication.initialized(): + app = BaseIPythonApplication.instance() + else: + # create an app, without the global instance + app = BaseIPythonApplication() + app.initialize() + return app.profile_dir + + secret = Bytes(config=True, + help="""The secret key with which notebooks are signed.""" + ) + def _secret_default(self): + # note : this assumes an Application is running + profile_dir = self.profile_dir + secret_file = os.path.join(profile_dir.security_dir, 'notebook_secret') + if os.path.exists(secret_file): + with io.open(secret_file, 'rb') as f: + return f.read() + else: + secret = base64.encodestring(os.urandom(1024)) + self.log.info("Writing output secret to %s", secret_file) + with io.open(secret_file, 'wb') as f: + f.write(secret) + try: + os.chmod(secret_file, 0o600) + except OSError: + self.log.warn( + "Could not set permissions on %s", + secret_file + ) + return secret + + \ No newline at end of file