def run_command_start(options, reactor=None): """ Subcommand "crossbar start". """ assert reactor # do not allow to run more than one Crossbar.io instance # from the same Crossbar.io node directory # pid_data = check_is_running(options.cbdir) if pid_data: print("Crossbar.io is already running from node directory {} (PID {}).".format(options.cbdir, pid_data['pid'])) sys.exit(1) else: fp = os.path.join(options.cbdir, _PID_FILENAME) with open(fp, 'wb') as fd: argv = options.argv options_dump = vars(options) pid_data = { 'pid': os.getpid(), 'argv': argv, 'options': {x: y for x, y in options_dump.items() if x not in ["func", "argv"]} } fd.write("{}\n".format( json.dumps( pid_data, sort_keys=False, indent=4, separators=(', ', ': '), ensure_ascii=False ) ).encode('utf8')) # remove node PID file when reactor exits # def remove_pid_file(): fp = os.path.join(options.cbdir, _PID_FILENAME) if os.path.isfile(fp): os.remove(fp) reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file) log = make_logger() # represents the running Crossbar.io node # node = Node(options.cbdir, reactor=reactor) # possibly generate new node key # pubkey = node.maybe_generate_key(options.cbdir) # check and load the node configuration # try: node.load(options.config) except InvalidConfigException as e: log.error("Invalid node configuration") log.error("{e!s}", e=e) sys.exit(1) except: raise # Print the banner. # for line in BANNER.splitlines(): log.info(click.style(("{:>40}").format(line), fg='yellow', bold=True)) # bannerFormat = "{:<18} {:<24}" bannerFormat = " {} {}" log.info(bannerFormat.format("Crossbar.io Version:", click.style(crossbar.__version__, fg='yellow', bold=True))) if pubkey: log.info(bannerFormat.format("Node Public Key:", click.style(pubkey, fg='yellow', bold=True))) log.info() log.info("Running from node directory '{cbdir}'", cbdir=options.cbdir) log.info("Controller process starting ({python}-{reactor}) ..", python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1]) # now actually start the node .. # def start_crossbar(): d = node.start(cdc_mode=options.cdc) def on_error(err): log.error("{e!s}", e=err.value) log.error("Could not start node: {err}", err=err) if reactor.running: reactor.stop() d.addErrback(on_error) reactor.callWhenRunning(start_crossbar) # enter event loop # try: reactor.run() except Exception: log.failure("Could not start reactor - {log_failure.value}")
class CrossbarRouter(object): serializers = [u'msgpack'] def __init__(self, host='localhost', port=61000, realm=u'golem', datadir=None, crossbar_dir='crossbar', crossbar_log_level='trace'): if datadir: self.working_dir = os.path.join(datadir, crossbar_dir) else: self.working_dir = crossbar_dir if not os.path.exists(self.working_dir): os.makedirs(self.working_dir) if not os.path.isdir(self.working_dir): raise IOError("'{}' is not a directory".format(self.working_dir)) self.address = WebSocketAddress(host, port, realm) self.log_level = crossbar_log_level self.node = None self.pubkey = None self.options = self._build_options() self.config = self._build_config(self.address, self.serializers) logger.debug('xbar init with cfg: %s', self.config) def start(self, reactor, callback, errback): reactor.callWhenRunning(self._start, self.options, reactor, callback, errback) @inlineCallbacks def stop(self): yield self.node._controller.shutdown() def _start(self, options, reactor, callback, errback): self._start_node(options, reactor).addCallbacks(callback, errback) def _start_node(self, options, reactor): self.node = Node(options.cbdir, reactor=reactor) self.node.log = LoggerBridge() self.pubkey = self.node.maybe_generate_key(options.cbdir) checkconfig.check_config(self.config) self.node._config = self.config return self.node.start() def _build_options(self, argv=None, config=None): return CrossbarRouterOptions( cbdir=self.working_dir, logdir=None, loglevel=self.log_level, argv=argv, config=config ) @staticmethod def _build_config(address, serializers, allowed_origins=u'*', realm=u'golem', enable_webstatus=False): return { 'version': 2, 'workers': [{ 'type': u'router', 'options': { 'title': u'Golem' }, 'transports': [ { 'type': u'websocket', 'serializers': serializers, 'endpoint': { 'type': u'tcp', 'interface': unicode(address.host), 'port': address.port }, 'url': unicode(address), 'options': { 'allowed_origins': allowed_origins, 'enable_webstatus': enable_webstatus, } } ], 'components': [], "realms": [{ "name": realm, "roles": [{ "name": u'anonymous', "permissions": [{ "uri": u'*', "allow": { "call": True, "register": True, "publish": True, "subscribe": True } }] }] }], }] }
def run_command_start(options, reactor=None): """ Subcommand "crossbar start". """ assert reactor # do not allow to run more than one Crossbar.io instance # from the same Crossbar.io node directory # pid_data = check_is_running(options.cbdir) if pid_data: print( "Crossbar.io is already running from node directory {} (PID {}).". format(options.cbdir, pid_data['pid'])) sys.exit(1) else: fp = os.path.join(options.cbdir, _PID_FILENAME) with open(fp, 'wb') as fd: argv = options.argv options_dump = vars(options) pid_data = { 'pid': os.getpid(), 'argv': argv, 'options': { x: y for x, y in options_dump.items() if x not in ["func", "argv"] } } fd.write("{}\n".format( json.dumps(pid_data, sort_keys=False, indent=4, separators=(', ', ': '), ensure_ascii=False)).encode('utf8')) # remove node PID file when reactor exits # def remove_pid_file(): fp = os.path.join(options.cbdir, _PID_FILENAME) if os.path.isfile(fp): os.remove(fp) reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file) log = make_logger() # represents the running Crossbar.io node # node = Node(options.cbdir, reactor=reactor) # possibly generate new node key # pubkey = node.maybe_generate_key(options.cbdir) # check and load the node configuration # try: node.load(options.config) except InvalidConfigException as e: log.error("Invalid node configuration") log.error("{e!s}", e=e) sys.exit(1) except: raise # Print the banner. # for line in BANNER.splitlines(): log.info(click.style(("{:>40}").format(line), fg='yellow', bold=True)) # bannerFormat = "{:<18} {:<24}" bannerFormat = " {} {}" log.info( bannerFormat.format( "Crossbar.io Version:", click.style(crossbar.__version__, fg='yellow', bold=True))) if pubkey: log.info( bannerFormat.format("Node Public Key:", click.style(pubkey, fg='yellow', bold=True))) log.info() log.info("Running from node directory '{cbdir}'", cbdir=options.cbdir) log.info("Controller process starting ({python}-{reactor}) ..", python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1]) # now actually start the node .. # def start_crossbar(): d = node.start(cdc_mode=options.cdc) def on_error(err): log.error("{e!s}", e=err.value) log.error("Could not start node: {err}", err=err) if reactor.running: reactor.stop() d.addErrback(on_error) reactor.callWhenRunning(start_crossbar) # enter event loop # try: reactor.run() except Exception: log.failure("Could not start reactor - {log_failure.value}")
class CrossbarRouter(object): serializers = ['msgpack'] @enum.unique class CrossbarRoles(enum.Enum): admin = enum.auto() docker = enum.auto() # pylint: disable=too-many-arguments def __init__(self, datadir: str, host: str = CROSSBAR_HOST, port: int = CROSSBAR_PORT, realm: str = CROSSBAR_REALM, crossbar_log_level: str = 'info', ssl: bool = True, generate_secrets: bool = False) -> None: self.working_dir = os.path.join(datadir, CROSSBAR_DIR) os.makedirs(self.working_dir, exist_ok=True) if not os.path.isdir(self.working_dir): raise IOError("'{}' is not a directory".format(self.working_dir)) self.cert_manager = cert.CertificateManager(self.working_dir) if generate_secrets: self.cert_manager.generate_secrets() self.address = WebSocketAddress(host, port, realm, ssl) self.log_level = crossbar_log_level self.node = None self.pubkey = None self.options = self._build_options() self.config = self._build_config(self.address, self.serializers, self.cert_manager) logger.debug('xbar init with cfg: %s', json.dumps(self.config)) def start(self, reactor, options=None): # imports reactor from crossbar.controller.node import Node, default_native_workers options = options or self.options if self.address.ssl: self.cert_manager.generate_if_needed() self.node = Node(options.cbdir, reactor=reactor) self.pubkey = self.node.maybe_generate_key(options.cbdir) workers = default_native_workers() checkconfig.check_config(self.config, workers) self.node._config = self.config return self.node.start() @inlineCallbacks def stop(self): yield self.node._controller.shutdown() # noqa # pylint: disable=protected-access def _build_options(self, argv=None, config=None): return CrossbarRouterOptions( cbdir=self.working_dir, logdir=None, loglevel=self.log_level, argv=argv, config=config ) @staticmethod def _users_config(cert_manager: cert.CertificateManager): # configuration for crsb_users with admin priviliges admin_role: str = CrossbarRouter.CrossbarRoles.admin.name docker_role: str = CrossbarRouter.CrossbarRoles.docker.name user_roles = { cert_manager.CrossbarUsers.golemapp: admin_role, cert_manager.CrossbarUsers.golemcli: admin_role, cert_manager.CrossbarUsers.electron: admin_role, cert_manager.CrossbarUsers.docker: docker_role, } crsb_users = {} for user, role in user_roles.items(): entry = {} entry['secret'] = cert_manager.get_secret(user) entry['role'] = role crsb_users[user.name] = entry return crsb_users @staticmethod def _build_config(address: WebSocketAddress, serializers: Iterable[str], cert_manager: cert.CertificateManager, realm: str = CROSSBAR_REALM, enable_webstatus: bool = False): allowed_origins = [ 'http://' + address.host + ':*', 'https://' + address.host + ':*' ] ws_endpoint = { 'type': 'tcp', 'interface': address.host, 'port': address.port, } if address.ssl: ws_endpoint["tls"] = { "key": cert_manager.key_path, "certificate": cert_manager.cert_path, "dhparam": cert_manager.dh_path, } return { 'version': 2, 'controller': { 'options': { 'shutdown': ['shutdown_on_shutdown_requested'] } }, 'workers': [{ 'type': 'router', 'options': { 'title': 'Golem' }, 'transports': [{ 'type': 'websocket', 'serializers': serializers, 'endpoint': ws_endpoint, 'url': str(address), 'options': { 'allowed_origins': allowed_origins, 'enable_webstatus': enable_webstatus, }, "auth": { "wampcra": { "type": "static", "users": CrossbarRouter._users_config(cert_manager) } } }], 'components': [], "realms": [{ "name": realm, "roles": [ { "name": CrossbarRouter.CrossbarRoles.admin.name, "permissions": [{ "uri": '*', "allow": { "call": True, "register": True, "publish": True, "subscribe": True } }] }, { "name": CrossbarRouter.CrossbarRoles.docker.name, "permissions": [ { "uri": '*', "allow": { "call": False, "register": False, "publish": False, "subscribe": False } }, { # more specific config takes precedence "uri": f'{DOCKER_URI}.*', "allow": { "call": True, "register": False, "publish": False, "subscribe": False } }, { "uri": 'sys.exposed_procedures', "allow": { "call": True, "register": False, "publish": False, "subscribe": False }, }, ] }] }], }] }