Ejemplo n.º 1
0
    async def receive(self):
        multipart = await self.socket.recv_multipart()
        parsed_message = parse_multipart_message(multipart)

        if not parsed_message:
            log.error('Received junk off the wire')
            raise MercuryClientException('Message is malformed')

        try:
            message = msgpack.unpackb(parsed_message['message'],
                                      encoding='utf-8')
        except TypeError as type_error:
            log.error('Received unpacked, non-string type: %s : %s' %
                      (type(parsed_message), type_error))
            await self.send_error(parsed_message['address'],
                                  'Client error, message is not packed')
            raise MercuryClientException('Message is malformed')

        except (msgpack.UnpackException,
                msgpack.ExtraData) as msgpack_exception:
            log.error('Received invalid request: %s' % str(msgpack_exception))

            await self.send_error(parsed_message['address'],
                                  'Client error, message is malformed')
            raise MercuryClientException('Message is malformed')

        return parsed_message['address'], message
Ejemplo n.º 2
0
    async def register(self, device_info, agent_info):
        """
        Registration endpoint for all clients. Everything starts here. This method
        will update the device_info payload to include information about itself as the origin.
        The origin is the associated frontend controller's address and port.

        Note, because we are using ZeroMQ as the transport, we don't have TCP envelope
        information, which means we always need to provide host information above the transport
        layer. This leads to a spoofing vector, as such, the inventory controller will soon
        require that Backends be registered, encrypt their messages, and provide an authentication
        token.

        :param device_info: Device information gathered by agent inspectors
        :param agent_info: Agent transport information
        :return: InventoryController response
        """
        if not self.validate_agent_info(agent_info):
            log.debug('Agent payload: {}'.format(agent_info))
            raise MercuryClientException('Received invalid data from agent')

        agent_info['active_since'] = time.time()
        device_info.update({'active': agent_info, 'origin': self.service_info})

        response = await self.inventory_client.insert_one(device_info)
        log.debug('Created/Updated inventory record: %s' %
                  response['message']['object_id'])

        add_active_record(device_info)

        return response
Ejemplo n.º 3
0
    def validate_required(required, data):
        missing = []
        for key in required:
            if key not in data:
                missing.append(key)

        if missing:
            raise MercuryClientException('Message is missing required data: {}'.format(missing))
Ejemplo n.º 4
0
    def raise_reply_error(self, reply):
        """Raise a MercuryCritical exception.

        Called when the client cannot talk to the inventory service.
        :raises: MercuryClientException.
        """
        raise MercuryClientException(
            'Problem talking to {} service: message = {}, tb = {}'.format(
                self._service_name, reply.get('message'),
                '\n'.join(reply.get('tb', []))))
Ejemplo n.º 5
0
    def process(self, message):
        if not self.validate_message(message):
            raise MercuryClientException('Invalid message')

        message.update({'time_created': time.time()})

        self.set_job_info_from_thread(message)

        self.log_collection.insert(message)

        return {'message': 'ok', 'error': False}
Ejemplo n.º 6
0
    def process(self, message):
        """

        :param message:
        :return:
        """
        if message['endpoint'] != 'enqueue_task':
            raise MercuryClientException('Unsupported endpoint')

        self.enqueue_task(message['args'][0])

        return dict(error=False, message='Done')
Ejemplo n.º 7
0
    def get_key(key, data):
        """Gets an item from a dictionary.

        :param key: The key.
        :param data: A dictionary to search for the key.
        :returns: The value associated with the key, if it exists.
        :raises: MercuryClientException if the key is not present.
        """
        try:
            return data[key]
        except KeyError:
            raise MercuryClientException(
                '{} is missing from request'.format(key))
Ejemplo n.º 8
0
    async def insert_one(self, device_info):
        """Insert a new device in inventory.

        :param device_info: A dict containing the new device info.
        :returns: The 'response' field of the transceiver's reply.
        :raises: MercuryClientException if 'mercury_id' is missing.
        """
        mercury_id = device_info.get('mercury_id')
        if not mercury_id:
            raise MercuryClientException('device_info is missing mercury_id')

        payload = {'endpoint': 'insert_one', 'args': [device_info]}
        return await self.transceiver(payload)
Ejemplo n.º 9
0
    def validate_required(required, data):
        """Validates that a message contains the required data.

        :param required: A list of required keys.
        :param data: A dict representing the message.
        :raises: MercuryClientException if the message is missing
            required data.
        """
        missing = []
        for key in required:
            if key not in data:
                missing.append(key)

        if missing:
            raise MercuryClientException(
                'Message is missing required data: {}'.format(missing))
Ejemplo n.º 10
0
    async def update(self, mercury_id, update_data):
        """
        The agents do not have direct access to the Inventory system, as such, we must
        proxy requests for the agent when necessary.

        If the device does not exist in the active_state singleton, an error will be raised

        :param mercury_id:
        :param update_data:
        :return: InventoryController response
        """

        if mercury_id not in active_state:
            raise MercuryClientException(
                'Received update for inactive device: {}'.format(mercury_id))

        log.debug(
            'Received inventory update request for {}'.format(mercury_id))

        return await self.inventory_client.update_one(mercury_id, update_data)
Ejemplo n.º 11
0
 def get_key(key, data):
     try:
         return data[key]
     except KeyError:
         raise MercuryClientException(
             '{} is missing from request'.format(key))