##// END OF EJS Templates
enable HMAC message signing by default in kernels...
MinRK -
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 reusing:
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 Session
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