Пример #1
0
    def __init__(self, config=None):
        ApplicationSession.__init__(self, config)

        # FIXME
        self._default_gas = 100000
        self._chain_id = 4

        profile = config.extra['profile']

        if 'ethkey' in config.extra and config.extra['ethkey']:
            self._ethkey_raw = config.extra['ethkey']
        else:
            self._ethkey_raw = profile.ethkey

        self._ethkey = eth_keys.keys.PrivateKey(self._ethkey_raw)
        self._ethadr = web3.Web3.toChecksumAddress(self._ethkey.public_key.to_canonical_address())
        self._ethadr_raw = binascii.a2b_hex(self._ethadr[2:])

        self.log.info('Client Ethereum key loaded, public address is {adr}',
                      func=hltype(self.__init__), adr=hlid(self._ethadr))

        if 'cskey' in config.extra and config.extra['cskey']:
            cskey = config.extra['cskey']
        else:
            cskey = profile.cskey
        self._key = cryptosign.SigningKey.from_key_bytes(cskey)
        self.log.info('Client WAMP authentication key loaded, public key is {pubkey}',
                      func=hltype(self.__init__), pubkey=hlid('0x' + self._key.public_key()))

        self._running = True
Пример #2
0
    async def authenticate(realm, authid, details):
        """
        this is our dynamic authenticator procedure that will be called by Crossbar.io
        when a session is authenticating
        """
        log.info(
            'authenticate(realm="{realm}", authid="{authid}", details={details}) {func}',
            realm=hl(realm),
            authid=hl(authid),
            details=details,
            func=hltype(create_rlink_authenticator),
        )

        assert ('authmethod' in details)
        assert (details['authmethod'] == 'cryptosign')
        assert ('authextra' in details)
        assert ('pubkey' in details['authextra'])

        pubkey = details['authextra']['pubkey']
        log.info(
            'authenticating session using realm="{realm}", pubkey={pubkey} .. {func}',
            realm=hl(realm),
            pubkey=hl(pubkey),
            func=hltype(create_rlink_authenticator),
        )

        if pubkey in pubkey_to_principals:
            principal = pubkey_to_principals[pubkey]
            auth = {
                'pubkey': pubkey,
                'realm': principal['realm'],
                'authid': principal['authid'],
                'role': principal['role'],
                'extra': principal['extra'],
                'cache': True
            }

            # Note: with WAMP-cryptosign, even though a client may or may not request a `realm`, but in any case, the
            # effective realm the client is authenticated will be returned in the principal `auth['role']` (!)
            effective_realm = auth['realm']

            log.info(
                'found valid principal authid="{authid}", authrole="{authrole}", realm="{realm}" matching given client public key {func}',
                func=hltype(create_rlink_authenticator),
                authid=hl(auth['authid']),
                authrole=hl(auth['role']),
                realm=hl(effective_realm),
            )

            # only now that we know the effective realm a client is to be joined to (see above), maybe active (start)
            # the desired application realm to let the client join to subsequently
            # await _maybe_activate_realm(controller, effective_realm)

            return auth
        else:
            msg = 'no principal with matching public key 0x{}'.format(pubkey)
            log.warn(msg)
            raise ApplicationError('com.example.no_such_user', msg)
Пример #3
0
    def _send_Allowance(self, from_adr, to_adr, amount):
        # FIXME: estimate gas required for call
        gas = self._default_gas
        gasPrice = self._w3.toWei('10', 'gwei')

        from_adr = self._ethadr

        # each submitted transaction must contain a nonce, which is obtained by the on-chain transaction number
        # for this account, including pending transactions (I think ..;) ..
        nonce = self._w3.eth.getTransactionCount(from_adr, block_identifier='pending')
        self.log.info('{func}::[1/4] - Ethereum transaction nonce: nonce={nonce}',
                      func=hltype(self._send_Allowance),
                      nonce=nonce)

        # serialize transaction raw data from contract call and transaction settings
        raw_transaction = xbr.xbrtoken.functions.approve(to_adr, amount).buildTransaction({
            'from': from_adr,
            'gas': gas,
            'gasPrice': gasPrice,
            'chainId': self._chain_id,  # https://stackoverflow.com/a/57901206/884770
            'nonce': nonce,
        })
        self.log.info(
            '{func}::[2/4] - Ethereum transaction created: raw_transaction=\n{raw_transaction}\n',
            func=hltype(self._send_Allowance),
            raw_transaction=raw_transaction)

        # compute signed transaction from above serialized raw transaction
        signed_txn = self._w3.eth.account.sign_transaction(raw_transaction, private_key=self._ethkey_raw)
        self.log.info(
            '{func}::[3/4] - Ethereum transaction signed: signed_txn=\n{signed_txn}\n',
            func=hltype(self._send_Allowance),
            signed_txn=hlval(binascii.b2a_hex(signed_txn.rawTransaction).decode()))

        # now send the pre-signed transaction to the blockchain via the gateway ..
        # https://web3py.readthedocs.io/en/stable/web3.eth.html  # web3.eth.Eth.sendRawTransaction
        txn_hash = self._w3.eth.sendRawTransaction(signed_txn.rawTransaction)
        txn_hash = bytes(txn_hash)
        self.log.info(
            '{func}::[4/4] - Ethereum transaction submitted: txn_hash=0x{txn_hash}',
            func=hltype(self._send_Allowance),
            txn_hash=hlval(binascii.b2a_hex(txn_hash).decode()))

        return txn_hash
Пример #4
0
    def onJoin(self, details):
        def authenticate(realm, authid, details):
            self.log.info(
                '{func}(realm="{realm}", authid="{authid}", details=details)',
                func=authenticate,
                realm=hlid(realm),
                authid=hlid(authid),
                details=details)
            return 'anonymous'

        yield self.register(authenticate,
                            'crossbarfabriccenter.mrealm.arealm.authenticate')

        self.log.info('{func}() Application realm authenticator ready!',
                      func=hltype(self.onJoin))
Пример #5
0
async def create_authenticator(config, controller):
    """
    Creates and returns a function to do authentication. The actual
    authentication method will be called like:

        authenticate(realm, authid, session_details)

    Note that this function can itself do async work (as can the
    "authenticate" method). For example, we could connect to a
    database here (and then use that connection in the authenticate()
    method)

    'controller' will be None unless `"expose_controller": true` is in
    the config.
    """
    log.info(
        'create_authenticator(config={config}) {func}',
        config=pformat(config),
        func=hltype(create_authenticator),
    )

    def authenticate(realm, authid, details):
        ticket = details['ticket']
        print(
            "WAMP-Ticket dynamic authenticator invoked: realm='{}', authid='{}', ticket='{}'"
            .format(realm, authid, ticket))
        pprint(details)

        if authid in PRINCIPALS_DB:
            if ticket == PRINCIPALS_DB[authid]['ticket']:
                return PRINCIPALS_DB[authid]['role']
            else:
                raise ApplicationError(
                    "com.example.invalid_ticket",
                    "could not authenticate session - invalid ticket '{}' for principal {}"
                    .format(ticket, authid))
        else:
            raise ApplicationError(
                "com.example.no_such_user",
                "could not authenticate session - no such principal {}".format(
                    authid))

    return authenticate
Пример #6
0
    def __init__(self, config_path):
        self._config_path = os.path.abspath(config_path)

        config = configparser.ConfigParser()
        config.read(config_path)

        self.config = config

        profiles = {}
        for profile_name in config.sections():
            profile = Profile.parse(config_path, profile_name,
                                    config.items(profile_name))
            profiles[profile_name] = profile

        self.profiles = profiles

        self.log.debug('profiles loaded: {profiles}',
                       func=hltype(self.__init__),
                       profiles=', '.join(
                           hlval(x) for x in sorted(self.profiles.keys())))
Пример #7
0
async def create_authenticator(config, controller):
    """
    Creates and returns a function to do authentication. The actual
    authentication method will be called like:

        authenticate(realm, authid, session_details)

    Note that this function can itself do async work (as can the
    "authenticate" method). For example, we could connect to a
    database here (and then use that connection in the authenticate()
    method)

    'controller' will be None unless `"expose_controller": true` is in
    the config.
    """
    log.info(
        'create_authenticator(config={config}) {func}',
        config=pformat(config),
        func=hltype(create_authenticator),
    )

    def authenticate(realm, authid, details):
        print(
            "WAMP-CRA dynamic authenticator invoked: realm='{}', authid='{}'".
            format(realm, authid))
        pprint(details)

        if authid in USERDB:
            # return a dictionary with authentication information ...
            return USERDB[authid]
        else:
            raise ApplicationError(
                'com.example.no_such_user',
                'could not authenticate session - no such user {}'.format(
                    authid))

    return authenticate
Пример #8
0
 def run_on_button1(widget):
     self.log.info('{func}({widget})',
                   func=hltype(run_on_button1),
                   widget=widget)
     reactor.callLater(0, on_button1, widget)
Пример #9
0
async def create_rlink_authenticator(config, controller):
    """
    Create an authenticator function for the listening transport of router workers
    in a worker group of a router cluster to authenticate rlink connections incoming
    from other workers in this worker group.

    The actual authentication method will be called like:

        authenticate(realm, authid, session_details)

    Note that this function can itself do async work (as can the
    "authenticate" method). For example, we could connect to a
    database here (and then use that connection in the authenticate()
    method)

    'controller' will be None unless `"expose_controller": true` is in
    the config.
    """
    log.info(
        '{func}(config={config}, controller={controller})',
        config=pformat(config),
        func=hltype(create_rlink_authenticator),
        controller=hltype(controller),
    )

    pubkey_to_principals = {}
    for p in PRINCIPALS:
        for k in p['authorized_keys']:
            if k in pubkey_to_principals:
                raise Exception("ambiguous key {}".format(k))
            else:
                pubkey_to_principals[k] = p

    async def authenticate(realm, authid, details):
        """
        this is our dynamic authenticator procedure that will be called by Crossbar.io
        when a session is authenticating
        """
        log.info(
            'authenticate(realm="{realm}", authid="{authid}", details={details}) {func}',
            realm=hl(realm),
            authid=hl(authid),
            details=details,
            func=hltype(create_rlink_authenticator),
        )

        assert ('authmethod' in details)
        assert (details['authmethod'] == 'cryptosign')
        assert ('authextra' in details)
        assert ('pubkey' in details['authextra'])

        pubkey = details['authextra']['pubkey']
        log.info(
            'authenticating session using realm="{realm}", pubkey={pubkey} .. {func}',
            realm=hl(realm),
            pubkey=hl(pubkey),
            func=hltype(create_rlink_authenticator),
        )

        if pubkey in pubkey_to_principals:
            principal = pubkey_to_principals[pubkey]
            auth = {
                'pubkey': pubkey,
                'realm': principal['realm'],
                'authid': principal['authid'],
                'role': principal['role'],
                'extra': principal['extra'],
                'cache': True
            }

            # Note: with WAMP-cryptosign, even though a client may or may not request a `realm`, but in any case, the
            # effective realm the client is authenticated will be returned in the principal `auth['role']` (!)
            effective_realm = auth['realm']

            log.info(
                'found valid principal authid="{authid}", authrole="{authrole}", realm="{realm}" matching given client public key {func}',
                func=hltype(create_rlink_authenticator),
                authid=hl(auth['authid']),
                authrole=hl(auth['role']),
                realm=hl(effective_realm),
            )

            # only now that we know the effective realm a client is to be joined to (see above), maybe active (start)
            # the desired application realm to let the client join to subsequently
            # await _maybe_activate_realm(controller, effective_realm)

            return auth
        else:
            msg = 'no principal with matching public key 0x{}'.format(pubkey)
            log.warn(msg)
            raise ApplicationError('com.example.no_such_user', msg)

    return authenticate