Show More
@@ -50,7 +50,7 b' from IPython.zmq.ipkernel import (' | |||||
50 | aliases as ipkernel_aliases, |
|
50 | aliases as ipkernel_aliases, | |
51 | IPKernelApp |
|
51 | IPKernelApp | |
52 | ) |
|
52 | ) | |
53 | from IPython.zmq.session import Session |
|
53 | from IPython.zmq.session import Session, default_secure | |
54 | from IPython.zmq.zmqshell import ZMQInteractiveShell |
|
54 | from IPython.zmq.zmqshell import ZMQInteractiveShell | |
55 |
|
55 | |||
56 |
|
56 | |||
@@ -551,6 +551,7 b' class IPythonQtConsoleApp(BaseIPythonApplication):' | |||||
551 | def initialize(self, argv=None): |
|
551 | def initialize(self, argv=None): | |
552 | super(IPythonQtConsoleApp, self).initialize(argv) |
|
552 | super(IPythonQtConsoleApp, self).initialize(argv) | |
553 | self.init_connection_file() |
|
553 | self.init_connection_file() | |
|
554 | default_secure(self.config) | |||
554 | self.init_ssh() |
|
555 | self.init_ssh() | |
555 | self.init_kernel_manager() |
|
556 | self.init_kernel_manager() | |
556 | self.init_qt_elements() |
|
557 | self.init_qt_elements() |
@@ -27,7 +27,6 b' import os' | |||||
27 | import socket |
|
27 | import socket | |
28 | import stat |
|
28 | import stat | |
29 | import sys |
|
29 | import sys | |
30 | import uuid |
|
|||
31 |
|
30 | |||
32 | from multiprocessing import Process |
|
31 | from multiprocessing import Process | |
33 |
|
32 | |||
@@ -36,7 +35,6 b' from zmq.devices import ProcessMonitoredQueue' | |||||
36 | from zmq.log.handlers import PUBHandler |
|
35 | from zmq.log.handlers import PUBHandler | |
37 | from zmq.utils import jsonapi as json |
|
36 | from zmq.utils import jsonapi as json | |
38 |
|
37 | |||
39 | from IPython.config.application import boolean_flag |
|
|||
40 | from IPython.core.profiledir import ProfileDir |
|
38 | from IPython.core.profiledir import ProfileDir | |
41 |
|
39 | |||
42 | from IPython.parallel.apps.baseapp import ( |
|
40 | from IPython.parallel.apps.baseapp import ( | |
@@ -47,8 +45,10 b' from IPython.parallel.apps.baseapp import (' | |||||
47 | from IPython.utils.importstring import import_item |
|
45 | from IPython.utils.importstring import import_item | |
48 | from IPython.utils.traitlets import Instance, Unicode, Bool, List, Dict |
|
46 | from IPython.utils.traitlets import Instance, Unicode, Bool, List, Dict | |
49 |
|
47 | |||
50 | # from IPython.parallel.controller.controller import ControllerFactory |
|
48 | from IPython.zmq.session import ( | |
51 | from IPython.zmq.session import Session |
|
49 | Session, session_aliases, session_flags, default_secure | |
|
50 | ) | |||
|
51 | ||||
52 | from IPython.parallel.controller.heartmonitor import HeartMonitor |
|
52 | from IPython.parallel.controller.heartmonitor import HeartMonitor | |
53 | from IPython.parallel.controller.hub import HubFactory |
|
53 | from IPython.parallel.controller.hub import HubFactory | |
54 | from IPython.parallel.controller.scheduler import TaskScheduler,launch_scheduler |
|
54 | from IPython.parallel.controller.scheduler import TaskScheduler,launch_scheduler | |
@@ -109,20 +109,13 b' flags.update({' | |||||
109 | 'reuse existing json connection files') |
|
109 | 'reuse existing json connection files') | |
110 | }) |
|
110 | }) | |
111 |
|
111 | |||
112 | flags.update(boolean_flag('secure', 'IPControllerApp.secure', |
|
112 | flags.update(session_flags) | |
113 | "Use HMAC digests for authentication of messages.", |
|
113 | ||
114 | "Don't authenticate messages." |
|
|||
115 | )) |
|
|||
116 | aliases = dict( |
|
114 | aliases = dict( | |
117 | secure = 'IPControllerApp.secure', |
|
|||
118 | ssh = 'IPControllerApp.ssh_server', |
|
115 | ssh = 'IPControllerApp.ssh_server', | |
119 | enginessh = 'IPControllerApp.engine_ssh_server', |
|
116 | enginessh = 'IPControllerApp.engine_ssh_server', | |
120 | location = 'IPControllerApp.location', |
|
117 | location = 'IPControllerApp.location', | |
121 |
|
118 | |||
122 | ident = 'Session.session', |
|
|||
123 | user = 'Session.username', |
|
|||
124 | keyfile = 'Session.keyfile', |
|
|||
125 |
|
||||
126 | url = 'HubFactory.url', |
|
119 | url = 'HubFactory.url', | |
127 | ip = 'HubFactory.ip', |
|
120 | ip = 'HubFactory.ip', | |
128 | transport = 'HubFactory.transport', |
|
121 | transport = 'HubFactory.transport', | |
@@ -134,6 +127,7 b' aliases = dict(' | |||||
134 | hwm = 'TaskScheduler.hwm', |
|
127 | hwm = 'TaskScheduler.hwm', | |
135 | ) |
|
128 | ) | |
136 | aliases.update(base_aliases) |
|
129 | aliases.update(base_aliases) | |
|
130 | aliases.update(session_aliases) | |||
137 |
|
131 | |||
138 |
|
132 | |||
139 | class IPControllerApp(BaseParallelApplication): |
|
133 | class IPControllerApp(BaseParallelApplication): | |
@@ -151,9 +145,6 b' class IPControllerApp(BaseParallelApplication):' | |||||
151 | reuse_files = Bool(False, config=True, |
|
145 | reuse_files = Bool(False, config=True, | |
152 | help='Whether to reuse existing json connection files.' |
|
146 | help='Whether to reuse existing json connection files.' | |
153 | ) |
|
147 | ) | |
154 | secure = Bool(True, config=True, |
|
|||
155 | help='Whether to use HMAC digests for extra message authentication.' |
|
|||
156 | ) |
|
|||
157 | ssh_server = Unicode(u'', config=True, |
|
148 | ssh_server = Unicode(u'', config=True, | |
158 | help="""ssh url for clients to use when connecting to the Controller |
|
149 | help="""ssh url for clients to use when connecting to the Controller | |
159 | processes. It should be of the form: [user@]server[:port]. The |
|
150 | processes. It should be of the form: [user@]server[:port]. The | |
@@ -225,6 +216,7 b' class IPControllerApp(BaseParallelApplication):' | |||||
225 | def load_config_from_json(self): |
|
216 | def load_config_from_json(self): | |
226 | """load config from existing json connector files.""" |
|
217 | """load config from existing json connector files.""" | |
227 | c = self.config |
|
218 | c = self.config | |
|
219 | self.log.debug("loading config from JSON") | |||
228 | # load from engine config |
|
220 | # load from engine config | |
229 | with open(os.path.join(self.profile_dir.security_dir, self.engine_json_file)) as f: |
|
221 | with open(os.path.join(self.profile_dir.security_dir, self.engine_json_file)) as f: | |
230 | cfg = json.loads(f.read()) |
|
222 | cfg = json.loads(f.read()) | |
@@ -249,28 +241,23 b' class IPControllerApp(BaseParallelApplication):' | |||||
249 | self.ssh_server = cfg['ssh'] |
|
241 | self.ssh_server = cfg['ssh'] | |
250 | assert int(ports) == c.HubFactory.regport, "regport mismatch" |
|
242 | assert int(ports) == c.HubFactory.regport, "regport mismatch" | |
251 |
|
243 | |||
|
244 | def load_secondary_config(self): | |||
|
245 | """secondary config, loading from JSON and setting defaults""" | |||
|
246 | if self.reuse_files: | |||
|
247 | try: | |||
|
248 | self.load_config_from_json() | |||
|
249 | except (AssertionError,IOError) as e: | |||
|
250 | self.log.error("Could not load config from JSON: %s" % e) | |||
|
251 | self.reuse_files=False | |||
|
252 | # switch Session.key default to secure | |||
|
253 | default_secure(self.config) | |||
|
254 | self.log.debug("Config changed") | |||
|
255 | self.log.debug(repr(self.config)) | |||
|
256 | ||||
252 | def init_hub(self): |
|
257 | def init_hub(self): | |
253 | c = self.config |
|
258 | c = self.config | |
254 |
|
259 | |||
255 | self.do_import_statements() |
|
260 | self.do_import_statements() | |
256 | reusing = self.reuse_files |
|
|||
257 | if reusing: |
|
|||
258 | try: |
|
|||
259 | self.load_config_from_json() |
|
|||
260 | except (AssertionError,IOError): |
|
|||
261 | reusing=False |
|
|||
262 | # check again, because reusing may have failed: |
|
|||
263 | if reusing: |
|
|||
264 | pass |
|
|||
265 | elif self.secure: |
|
|||
266 | key = str(uuid.uuid4()) |
|
|||
267 | # keyfile = os.path.join(self.profile_dir.security_dir, self.exec_key) |
|
|||
268 | # with open(keyfile, 'w') as f: |
|
|||
269 | # f.write(key) |
|
|||
270 | # os.chmod(keyfile, stat.S_IRUSR|stat.S_IWUSR) |
|
|||
271 | c.Session.key = asbytes(key) |
|
|||
272 | else: |
|
|||
273 | key = c.Session.key = b'' |
|
|||
274 |
|
261 | |||
275 | try: |
|
262 | try: | |
276 | self.factory = HubFactory(config=c, log=self.log) |
|
263 | self.factory = HubFactory(config=c, log=self.log) | |
@@ -280,10 +267,10 b' class IPControllerApp(BaseParallelApplication):' | |||||
280 | self.log.error("Couldn't construct the Controller", exc_info=True) |
|
267 | self.log.error("Couldn't construct the Controller", exc_info=True) | |
281 | self.exit(1) |
|
268 | self.exit(1) | |
282 |
|
269 | |||
283 |
if not |
|
270 | if not self.reuse_files: | |
284 | # save to new json config files |
|
271 | # save to new json config files | |
285 | f = self.factory |
|
272 | f = self.factory | |
286 | cdict = {'exec_key' : key, |
|
273 | cdict = {'exec_key' : f.session.key, | |
287 | 'ssh' : self.ssh_server, |
|
274 | 'ssh' : self.ssh_server, | |
288 | 'url' : "%s://%s:%s"%(f.client_transport, f.client_ip, f.regport), |
|
275 | 'url' : "%s://%s:%s"%(f.client_transport, f.client_ip, f.regport), | |
289 | 'location' : self.location |
|
276 | 'location' : self.location | |
@@ -397,11 +384,11 b' class IPControllerApp(BaseParallelApplication):' | |||||
397 | handler.setLevel(self.log_level) |
|
384 | handler.setLevel(self.log_level) | |
398 | self.log.addHandler(handler) |
|
385 | self.log.addHandler(handler) | |
399 | self._log_handler = handler |
|
386 | self._log_handler = handler | |
400 | # # |
|
|||
401 |
|
387 | |||
402 | def initialize(self, argv=None): |
|
388 | def initialize(self, argv=None): | |
403 | super(IPControllerApp, self).initialize(argv) |
|
389 | super(IPControllerApp, self).initialize(argv) | |
404 | self.forward_logging() |
|
390 | self.forward_logging() | |
|
391 | self.load_secondary_config() | |||
405 | self.init_hub() |
|
392 | self.init_hub() | |
406 | self.init_schedulers() |
|
393 | self.init_schedulers() | |
407 |
|
394 |
@@ -36,9 +36,12 b' from IPython.parallel.apps.baseapp import (' | |||||
36 | base_flags, |
|
36 | base_flags, | |
37 | ) |
|
37 | ) | |
38 | from IPython.zmq.log import EnginePUBHandler |
|
38 | from IPython.zmq.log import EnginePUBHandler | |
|
39 | from IPython.zmq.session import ( | |||
|
40 | Session, session_aliases, session_flags | |||
|
41 | ) | |||
39 |
|
42 | |||
40 | from IPython.config.configurable import Configurable |
|
43 | from IPython.config.configurable import Configurable | |
41 | from IPython.zmq.session import Session |
|
44 | ||
42 | from IPython.parallel.engine.engine import EngineFactory |
|
45 | from IPython.parallel.engine.engine import EngineFactory | |
43 | from IPython.parallel.engine.streamkernel import Kernel |
|
46 | from IPython.parallel.engine.streamkernel import Kernel | |
44 | from IPython.parallel.util import disambiguate_url, asbytes |
|
47 | from IPython.parallel.util import disambiguate_url, asbytes | |
@@ -113,10 +116,6 b' aliases = dict(' | |||||
113 | c = 'IPEngineApp.startup_command', |
|
116 | c = 'IPEngineApp.startup_command', | |
114 | s = 'IPEngineApp.startup_script', |
|
117 | s = 'IPEngineApp.startup_script', | |
115 |
|
118 | |||
116 | ident = 'Session.session', |
|
|||
117 | user = 'Session.username', |
|
|||
118 | keyfile = 'Session.keyfile', |
|
|||
119 |
|
||||
120 | url = 'EngineFactory.url', |
|
119 | url = 'EngineFactory.url', | |
121 | ssh = 'EngineFactory.sshserver', |
|
120 | ssh = 'EngineFactory.sshserver', | |
122 | sshkey = 'EngineFactory.sshkey', |
|
121 | sshkey = 'EngineFactory.sshkey', | |
@@ -131,7 +130,10 b' aliases = dict(' | |||||
131 |
|
130 | |||
132 | ) |
|
131 | ) | |
133 | aliases.update(base_aliases) |
|
132 | aliases.update(base_aliases) | |
134 |
|
133 | aliases.update(session_aliases) | ||
|
134 | flags = {} | |||
|
135 | flags.update(base_flags) | |||
|
136 | flags.update(session_flags) | |||
135 |
|
137 | |||
136 | class IPEngineApp(BaseParallelApplication): |
|
138 | class IPEngineApp(BaseParallelApplication): | |
137 |
|
139 | |||
@@ -172,6 +174,7 b' class IPEngineApp(BaseParallelApplication):' | |||||
172 | logging to a central location.""") |
|
174 | logging to a central location.""") | |
173 |
|
175 | |||
174 | aliases = Dict(aliases) |
|
176 | aliases = Dict(aliases) | |
|
177 | flags = Dict(flags) | |||
175 |
|
178 | |||
176 | # def find_key_file(self): |
|
179 | # def find_key_file(self): | |
177 | # """Set the key file. |
|
180 | # """Set the key file. | |
@@ -214,12 +217,9 b' class IPEngineApp(BaseParallelApplication):' | |||||
214 | with open(self.url_file) as f: |
|
217 | with open(self.url_file) as f: | |
215 | d = json.loads(f.read()) |
|
218 | d = json.loads(f.read()) | |
216 |
|
219 | |||
217 | try: |
|
220 | if 'exec_key' in d: | |
218 | config.Session.key |
|
221 | config.Session.key = asbytes(d['exec_key']) | |
219 | except AttributeError: |
|
222 | ||
220 | if d['exec_key']: |
|
|||
221 | config.Session.key = asbytes(d['exec_key']) |
|
|||
222 |
|
||||
223 | try: |
|
223 | try: | |
224 | config.EngineFactory.location |
|
224 | config.EngineFactory.location | |
225 | except AttributeError: |
|
225 | except AttributeError: |
@@ -38,7 +38,9 b' from IPython.utils.importstring import import_item' | |||||
38 | from IPython.zmq.entry_point import write_connection_file |
|
38 | from IPython.zmq.entry_point import write_connection_file | |
39 | from IPython.zmq.heartbeat import Heartbeat |
|
39 | from IPython.zmq.heartbeat import Heartbeat | |
40 | from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows |
|
40 | from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows | |
41 |
from IPython.zmq.session import |
|
41 | from IPython.zmq.session import ( | |
|
42 | Session, session_flags, session_aliases, default_secure, | |||
|
43 | ) | |||
42 |
|
44 | |||
43 |
|
45 | |||
44 | #----------------------------------------------------------------------------- |
|
46 | #----------------------------------------------------------------------------- | |
@@ -68,6 +70,11 b' kernel_flags.update({' | |||||
68 | "redirect stderr to the null device"), |
|
70 | "redirect stderr to the null device"), | |
69 | }) |
|
71 | }) | |
70 |
|
72 | |||
|
73 | # inherit flags&aliases for Sessions | |||
|
74 | kernel_aliases.update(session_aliases) | |||
|
75 | kernel_flags.update(session_flags) | |||
|
76 | ||||
|
77 | ||||
71 |
|
78 | |||
72 | #----------------------------------------------------------------------------- |
|
79 | #----------------------------------------------------------------------------- | |
73 | # Application class for starting a Kernel |
|
80 | # Application class for starting a Kernel | |
@@ -186,7 +193,7 b' class KernelApp(BaseIPythonApplication):' | |||||
186 | self.connection_file = "kernel-%s.json"%os.getpid() |
|
193 | self.connection_file = "kernel-%s.json"%os.getpid() | |
187 |
|
194 | |||
188 | self.load_connection_file() |
|
195 | self.load_connection_file() | |
189 |
|
196 | |||
190 | def init_sockets(self): |
|
197 | def init_sockets(self): | |
191 | # Create a context, a session, and the kernel sockets. |
|
198 | # Create a context, a session, and the kernel sockets. | |
192 | self.log.info("Starting the kernel at pid: %i", os.getpid()) |
|
199 | self.log.info("Starting the kernel at pid: %i", os.getpid()) | |
@@ -228,6 +235,7 b' class KernelApp(BaseIPythonApplication):' | |||||
228 |
|
235 | |||
229 | def init_session(self): |
|
236 | def init_session(self): | |
230 | """create our session object""" |
|
237 | """create our session object""" | |
|
238 | default_secure(self.config) | |||
231 | self.session = Session(config=self.config, username=u'kernel') |
|
239 | self.session = Session(config=self.config, username=u'kernel') | |
232 |
|
240 | |||
233 | def init_blackhole(self): |
|
241 | def init_blackhole(self): |
@@ -43,6 +43,7 b' from zmq.utils import jsonapi' | |||||
43 | from zmq.eventloop.ioloop import IOLoop |
|
43 | from zmq.eventloop.ioloop import IOLoop | |
44 | from zmq.eventloop.zmqstream import ZMQStream |
|
44 | from zmq.eventloop.zmqstream import ZMQStream | |
45 |
|
45 | |||
|
46 | from IPython.config.application import Application, boolean_flag | |||
46 | from IPython.config.configurable import Configurable, LoggingConfigurable |
|
47 | from IPython.config.configurable import Configurable, LoggingConfigurable | |
47 | from IPython.utils.importstring import import_item |
|
48 | from IPython.utils.importstring import import_item | |
48 | from IPython.utils.jsonutil import extract_dates, squash_dates, date_default |
|
49 | from IPython.utils.jsonutil import extract_dates, squash_dates, date_default | |
@@ -71,6 +72,7 b' def squash_unicode(obj):' | |||||
71 | #----------------------------------------------------------------------------- |
|
72 | #----------------------------------------------------------------------------- | |
72 | # globals and defaults |
|
73 | # globals and defaults | |
73 | #----------------------------------------------------------------------------- |
|
74 | #----------------------------------------------------------------------------- | |
|
75 | ||||
74 | key = 'on_unknown' if jsonapi.jsonmod.__name__ == 'jsonlib' else 'default' |
|
76 | key = 'on_unknown' if jsonapi.jsonmod.__name__ == 'jsonlib' else 'default' | |
75 | json_packer = lambda obj: jsonapi.dumps(obj, **{key:date_default}) |
|
77 | json_packer = lambda obj: jsonapi.dumps(obj, **{key:date_default}) | |
76 | json_unpacker = lambda s: extract_dates(jsonapi.loads(s)) |
|
78 | json_unpacker = lambda s: extract_dates(jsonapi.loads(s)) | |
@@ -81,9 +83,43 b' pickle_unpacker = pickle.loads' | |||||
81 | default_packer = json_packer |
|
83 | default_packer = json_packer | |
82 | default_unpacker = json_unpacker |
|
84 | default_unpacker = json_unpacker | |
83 |
|
85 | |||
84 |
|
||||
85 | DELIM=b"<IDS|MSG>" |
|
86 | DELIM=b"<IDS|MSG>" | |
86 |
|
87 | |||
|
88 | ||||
|
89 | #----------------------------------------------------------------------------- | |||
|
90 | # Mixin tools for apps that use Sessions | |||
|
91 | #----------------------------------------------------------------------------- | |||
|
92 | ||||
|
93 | session_aliases = dict( | |||
|
94 | ident = 'Session.session', | |||
|
95 | user = 'Session.username', | |||
|
96 | keyfile = 'Session.keyfile', | |||
|
97 | ) | |||
|
98 | ||||
|
99 | session_flags = { | |||
|
100 | 'secure' : ({'Session' : { 'key' : str_to_bytes(str(uuid.uuid4())), | |||
|
101 | 'keyfile' : '' }}, | |||
|
102 | """Use HMAC digests for authentication of messages. | |||
|
103 | Setting this flag will generate a new UUID to use as the HMAC key. | |||
|
104 | """), | |||
|
105 | 'no-secure' : ({'Session' : { 'key' : b'', 'keyfile' : '' }}, | |||
|
106 | """Don't authenticate messages."""), | |||
|
107 | } | |||
|
108 | ||||
|
109 | def default_secure(cfg): | |||
|
110 | """Set the default behavior for a config environment to be secure. | |||
|
111 | ||||
|
112 | If Session.key/keyfile have not been set, set Session.key to | |||
|
113 | a new random UUID. | |||
|
114 | """ | |||
|
115 | ||||
|
116 | if 'Session' in cfg: | |||
|
117 | if 'key' in cfg.Session or 'keyfile' in cfg.Session: | |||
|
118 | return | |||
|
119 | # key/keyfile not specified, generate new UUID: | |||
|
120 | cfg.Session.key = str_to_bytes(str(uuid.uuid4())) | |||
|
121 | ||||
|
122 | ||||
87 | #----------------------------------------------------------------------------- |
|
123 | #----------------------------------------------------------------------------- | |
88 | # Classes |
|
124 | # Classes | |
89 | #----------------------------------------------------------------------------- |
|
125 | #----------------------------------------------------------------------------- | |
@@ -256,6 +292,7 b' class Session(Configurable):' | |||||
256 | help="""Username for the Session. Default is your system username.""") |
|
292 | help="""Username for the Session. Default is your system username.""") | |
257 |
|
293 | |||
258 | # message signature related traits: |
|
294 | # message signature related traits: | |
|
295 | ||||
259 | key = CBytes(b'', config=True, |
|
296 | key = CBytes(b'', config=True, | |
260 | help="""execution key, for extra authentication.""") |
|
297 | help="""execution key, for extra authentication.""") | |
261 | def _key_changed(self, name, old, new): |
|
298 | def _key_changed(self, name, old, new): | |
@@ -272,6 +309,8 b' class Session(Configurable):' | |||||
272 | with open(new, 'rb') as f: |
|
309 | with open(new, 'rb') as f: | |
273 | self.key = f.read().strip() |
|
310 | self.key = f.read().strip() | |
274 |
|
311 | |||
|
312 | # serialization traits: | |||
|
313 | ||||
275 | pack = Any(default_packer) # the actual packer function |
|
314 | pack = Any(default_packer) # the actual packer function | |
276 | def _pack_changed(self, name, old, new): |
|
315 | def _pack_changed(self, name, old, new): | |
277 | if not callable(new): |
|
316 | if not callable(new): |
General Comments 0
You need to be logged in to leave comments.
Login now