def _run_command_keys(options, reactor, personality): """ Subcommand "crossbar keys". """ log = make_logger() from crossbar.common.key import _read_node_key from crossbar.common.key import _read_release_key if options.generate: # Generate a new node key pair (2 files), load and check _maybe_generate_key(options.cbdir) else: # Print keys # Release (public) key release_pubkey = _read_release_key() # Node key node_key = _read_node_key(options.cbdir, private=options.private) if options.private: key_title = 'Crossbar.io Node PRIVATE Key' else: key_title = 'Crossbar.io Node PUBLIC Key' log.info('') log.info('{key_title}', key_title=hl('Crossbar Software Release Key', color='yellow', bold=True)) log.info('base64: {release_pubkey}', release_pubkey=release_pubkey[u'base64']) log.info(release_pubkey[u'qrcode'].strip()) log.info('') log.info('{key_title}', key_title=hl(key_title, color='yellow', bold=True)) log.info('hex: {node_key}', node_key=node_key[u'hex']) log.info(node_key[u'qrcode'].strip()) log.info('')
def _run_command_keys(options, reactor, personality): """ Subcommand "crossbar keys". """ log = make_logger() # Generate a new node key pair (2 files), load and check _maybe_generate_key(options.cbdir) # Print keys # Release (public) key release_pubkey = _read_release_key() # Node key node_key = _read_node_key(options.cbdir, private=options.private) if options.private: key_title = 'Crossbar.io Node PRIVATE Key' else: key_title = 'Crossbar.io Node PUBLIC Key' log.info('') log.info('{key_title}', key_title=hl('Crossbar Software Release Key', color='yellow', bold=True)) log.info('base64: {release_pubkey}', release_pubkey=release_pubkey['base64']) log.info(release_pubkey['qrcode'].strip()) log.info('') log.info('{key_title}', key_title=hl(key_title, color='yellow', bold=True)) log.info('hex: {node_key}', node_key=node_key['hex']) log.info(node_key['qrcode'].strip()) log.info('')
def __init__(self, config=None, reactor=None, personality=None): # base ctor NativeProcess.__init__(self, config=config, reactor=reactor, personality=personality) # Release (public) key self._release_pubkey = _read_release_key() # Node (private) key (as a string, in hex) node_key_hex = _read_node_key(self.config.extra.cbdir, private=True)['hex'] privkey = nacl.signing.SigningKey(node_key_hex, encoder=nacl.encoding.HexEncoder) # WAMP-cryptosign signing key self._node_key = cryptosign.SigningKey(privkey)
import uuid import pytest_twisted from copy import deepcopy from pprint import pformat import txaio txaio.use_twisted() from autobahn.wamp.types import SubscribeOptions, PublishOptions from crossbar.common.key import _read_node_key from twisted.internet.defer import DeferredList, ensureDeferred # do not directly import fixtures, or session-scoped ones will get run twice. from ..helpers import * node1_pubkey = _read_node_key('./test/cf1/.crossbar/', private=False)['hex'] node2_pubkey = _read_node_key('./test/cf2/.crossbar/', private=False)['hex'] node3_pubkey = _read_node_key('./test/cf3/.crossbar/', private=False)['hex'] node_rlink_ports = { "node1": 8090, "node2": 8091, "node3": 8092, } node_websocket_ports = { "node1": 9080, "node2": 9081, "node3": 9082, }
# do not directly import fixtures, or session-scoped ones will get run twice. from ..helpers import * if False: node1_cbdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../cf1/.crossbar/') node2_cbdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../cf2/.crossbar/') node3_cbdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../cf3/.crossbar/') else: node1_cbdir = './test/cf1/.crossbar/' node2_cbdir = './test/cf2/.crossbar/' node3_cbdir = './test/cf3/.crossbar/' node1_pubkey = _read_node_key(node1_cbdir, private=False)['hex'] node2_pubkey = _read_node_key(node2_cbdir, private=False)['hex'] node3_pubkey = _read_node_key(node3_cbdir, private=False)['hex'] node_rlink_ports = { "node1": 8090, "node2": 8091, "node3": 8092, } node_websocket_ports = { "node1": 9080, "node2": 9081, "node3": 9082, }
def make_backend_connection(backend_config, frontend_session, cbdir): """ Connects to a 'backend' session with the given config; returns a transport that is definitely connected (e.g. you can send a Hello right away). :param backend_config: Backend connection configuration, for example: .. code-block:: json { 'auth': { 'cryptosign-proxy': { 'type': 'static' } }, 'transport': { 'type': 'rawsocket', 'endpoint': { 'type': 'tcp', 'host': '127.0.0.1', 'port': 8442 }, 'serializer': 'cbor', 'url': 'rs://localhost' } } :param frontend_session: The frontend proxy session for which to create a mapped backend connection. :param cbdir: The node directory. """ from twisted.internet import reactor connected_d = Deferred() backend = _create_transport(0, backend_config['transport']) key = _read_node_key(cbdir, private=True) def create_session(): session = ProxyBackendSession() # we will do cryptosign authentication to any backend if 'auth' in backend_config and 'cryptosign-proxy' in backend_config['auth']: session.add_authenticator(create_authenticator("cryptosign", privkey=key['hex'])) # we allow anonymous authentication to just unix-sockets # currently. I don't think it's a good idea to allow any # anonymous auth to "real" backends over TCP due to # cross-protocol hijinks (and if a Web browser is running on # that machine, any website can try to access the "real" # backend) if 'auth' not in backend_config or 'anonymous-proxy' in backend_config['auth']: if backend_config['transport']['endpoint']['type'] == 'unix': session.add_authenticator(create_authenticator("anonymous")) else: raise RuntimeError('anonymous-proxy authenticator only allowed on Unix domain socket based transports, not type "{}"'.format(backend_config['transport']['endpoint']['type'])) def connected(session, transport): connected_d.callback(session) session.on('connect', connected) return session # client-factory factory = _create_transport_factory(reactor, backend, create_session) endpoint = _create_transport_endpoint(reactor, backend_config['transport']['endpoint']) transport_d = endpoint.connect(factory) def _connected(proto): proto._proxy_other_side = frontend_session return proto def _error(f): if not connected_d.called: connected_d.errback(f) transport_d.addErrback(_error) transport_d.addCallback(_connected) return connected_d
def _backend_connected(backend_session): try: # wait for the WAMP-level transport to connect yield backend_session._on_connect # node private key key = _read_node_key(self._controller._cbdir, private=False) # FIXME authmethods = [ '{}-proxy'.format(x) for x in backend_session._authenticators.keys() ] # authmethods = ['cryptosign-proxy'] self.log.info('Proxy backend session authenticating using authmethods={authmethods} ..', authmethods=authmethods) backend_session.join( accept.realm, authmethods=authmethods, authid=None, authrole=None, authextra={ # for WAMP-cryptosign authentication of the proxy frontend # to the backend router "pubkey": key['hex'], # forward authentication credentials of the connecting client # # the following are the effective (realm, authid, authrole) under # which the client (proxy frontend connection) was successfully # authenticated (using the authmethod+authprovider) "proxy_realm": accept.realm, "proxy_authid": accept.authid, "proxy_authrole": accept.authrole, "proxy_authmethod": accept.authmethod, "proxy_authprovider": accept.authprovider, # this is the authextra returned from the frontend authenticator, which # would normally be returned to the client "proxy_authextra": accept.authextra, } ) def _on_backend_joined(session, details): self.log.info('Proxy backend session JOINED: session_id={backend_session_id} session={backend_session}, details={details}', backend_session_id=hlid(details.session), backend_session=session, pending_session_id=self._pending_session_id, details=details) # we're ready now! store and return the backend session self._backend_session = session # we set the frontend session ID to that of the backend session mapped for our frontend session .. self._session_id = details.session # .. NOT our (fake) pending session ID (generated in the proxy worker) # self._session_id = self._pending_session_id # credentials of the backend session mapped for our frontend session self._realm = details.realm self._authid = details.authid self._authrole = details.authrole # this is the authextra returned for the backend session mapped for our frontend session self._authextra = details.authextra # authentication method & provider are the requested (and succeeding) ones self._authmethod = accept.authmethod self._authprovider = accept.authprovider result.callback(session) backend_session.on('join', _on_backend_joined) return backend_session except Exception as e: self.log.failure() result.errback(e)