##// END OF EJS Templates
sign notebooks
MinRK -
Show More
@@ -26,7 +26,7 b' import shutil'
26 26 from tornado import web
27 27
28 28 from .nbmanager import NotebookManager
29 from IPython.nbformat import current
29 from IPython.nbformat import current, sign
30 30 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
31 31 from IPython.utils import tz
32 32
@@ -207,13 +207,14 b' class FileNotebookManager(NotebookManager):'
207 207 model['path'] = path
208 208 model['last_modified'] = last_modified
209 209 model['created'] = created
210 if content is True:
210 if content:
211 211 with io.open(os_path, 'r', encoding='utf-8') as f:
212 212 try:
213 213 nb = current.read(f, u'json')
214 214 except Exception as e:
215 215 raise web.HTTPError(400, u"Unreadable Notebook: %s %s" % (os_path, e))
216 216 model['content'] = nb
217 sign.mark_trusted_cells(nb, self.secret)
217 218 return model
218 219
219 220 def save_notebook_model(self, model, name='', path=''):
@@ -236,6 +237,10 b' class FileNotebookManager(NotebookManager):'
236 237 # Save the notebook file
237 238 os_path = self.get_os_path(new_name, new_path)
238 239 nb = current.to_notebook_json(model['content'])
240
241 if sign.check_trusted_cells(nb):
242 sign.trust_notebook(nb, self.secret, self.signature_scheme)
243
239 244 if 'name' in nb['metadata']:
240 245 nb['metadata']['name'] = u''
241 246 try:
@@ -17,12 +17,16 b' Authors:'
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 import base64
21 import hashlib
22 import io
20 23 import os
21 24
22 25 from IPython.config.configurable import LoggingConfigurable
26 from IPython.core.application import BaseIPythonApplication
23 27 from IPython.nbformat import current
24 28 from IPython.utils import py3compat
25 from IPython.utils.traitlets import Unicode, TraitError
29 from IPython.utils.traitlets import Unicode, TraitError, Enum, Bytes
26 30
27 31 #-----------------------------------------------------------------------------
28 32 # Classes
@@ -42,6 +46,35 b' class NotebookManager(LoggingConfigurable):'
42 46
43 47 filename_ext = Unicode(u'.ipynb')
44 48
49 signature_scheme = Enum(hashlib.algorithms, default_value='sha256', config=True,
50 help="""The signature scheme used to sign notebooks."""
51 )
52
53 secret = Bytes(config=True,
54 help="""The secret key with which notebooks are signed."""
55 )
56 def _secret_default(self):
57 # note : this assumes an Application is running
58 profile_dir = BaseIPythonApplication.instance().profile_dir
59 secret_file = os.path.join(profile_dir.security_dir, 'notebook_secret')
60 if os.path.exists(secret_file):
61 with io.open(secret_file, 'rb') as f:
62 return f.read()
63 else:
64 secret = base64.encodestring(os.urandom(1024))
65 self.log.info("Writing output secret to %s", secret_file)
66 with io.open(secret_file, 'wb') as f:
67 f.write(secret)
68 try:
69 os.chmod(secret_file, 0o600)
70 except OSError:
71 self.log.warn(
72 "Could not set permissions on %s",
73 secret_file
74 )
75 return secret
76
77
45 78 def path_exists(self, path):
46 79 """Does the API-style path (directory) actually exist?
47 80
@@ -530,6 +530,7 b' var IPython = (function (IPython) {'
530 530 } else {
531 531 this.set_input_prompt();
532 532 }
533 this.output_area.trusted = data.trusted || false;
533 534 this.output_area.fromJSON(data.outputs);
534 535 if (data.collapsed !== undefined) {
535 536 if (data.collapsed) {
@@ -552,6 +553,7 b' var IPython = (function (IPython) {'
552 553 var outputs = this.output_area.toJSON();
553 554 data.outputs = outputs;
554 555 data.language = 'python';
556 data.trusted = this.output_area.trusted;
555 557 data.collapsed = this.collapsed;
556 558 return data;
557 559 };
@@ -31,6 +31,7 b' var IPython = (function (IPython) {'
31 31 this.outputs = [];
32 32 this.collapsed = false;
33 33 this.scrolled = false;
34 this.trusted = true;
34 35 this.clear_queued = null;
35 36 if (prompt_area === undefined) {
36 37 this.prompt_area = true;
@@ -309,7 +310,7 b' var IPython = (function (IPython) {'
309 310 });
310 311 return json;
311 312 };
312
313
313 314 OutputArea.prototype.append_output = function (json) {
314 315 this.expand();
315 316 // Clear the output if clear is queued.
@@ -331,6 +332,7 b' var IPython = (function (IPython) {'
331 332 } else if (json.output_type === 'stream') {
332 333 this.append_stream(json);
333 334 }
335
334 336 this.outputs.push(json);
335 337
336 338 // Only reset the height to automatic if the height is currently
@@ -526,12 +528,26 b' var IPython = (function (IPython) {'
526 528 'text/plain'
527 529 ];
528 530
531 OutputArea.safe_outputs = {
532 'text/plain' : true,
533 'image/png' : true,
534 'image/jpeg' : true
535 };
536
529 537 OutputArea.prototype.append_mime_type = function (json, element) {
530
531 538 for (var type_i in OutputArea.display_order) {
532 539 var type = OutputArea.display_order[type_i];
533 540 var append = OutputArea.append_map[type];
534 541 if ((json[type] !== undefined) && append) {
542 if (!this.trusted && !OutputArea.safe_outputs[type]) {
543 // not trusted show warning and do not display
544 var content = {
545 text : "Untrusted " + type + " output ignored.",
546 stream : "stderr"
547 }
548 this.append_stream(content);
549 continue;
550 }
535 551 var md = json.metadata || {};
536 552 append.apply(this, [json[type], md, element]);
537 553 return true;
@@ -757,6 +773,7 b' var IPython = (function (IPython) {'
757 773 // clear all, no need for logic
758 774 this.element.html("");
759 775 this.outputs = [];
776 this.trusted = true;
760 777 this.unscroll_area();
761 778 return;
762 779 };
@@ -769,13 +786,6 b' var IPython = (function (IPython) {'
769 786 var len = outputs.length;
770 787 var data;
771 788
772 // We don't want to display javascript on load, so remove it from the
773 // display order for the duration of this function call, but be sure to
774 // put it back in there so incoming messages that contain javascript
775 // representations get displayed
776 var js_index = OutputArea.display_order.indexOf('application/javascript');
777 OutputArea.display_order.splice(js_index, 1);
778
779 789 for (var i=0; i<len; i++) {
780 790 data = outputs[i];
781 791 var msg_type = data.output_type;
@@ -788,9 +798,6 b' var IPython = (function (IPython) {'
788 798
789 799 this.append_output(data);
790 800 }
791
792 // reinsert javascript into display order, see note above
793 OutputArea.display_order.splice(js_index, 0, 'application/javascript');
794 801 };
795 802
796 803
General Comments 0
You need to be logged in to leave comments. Login now