예제 #1
0
  def FetchAndRemoveRequestsAndResponses(self, session_id):
    """Removes WellKnownFlow messages from the queue and returns them."""
    messages = []
    with queue_manager.WellKnownQueueManager(token=self.token) as manager:
      for _, responses in manager.FetchRequestsAndResponses(session_id):
        messages.extend(responses)
        manager.DeleteWellKnownFlowResponses(session_id, responses)

    return messages
예제 #2
0
    def testWellKnownFlowsNotifications(self):
        test_lib.WellKnownSessionTest.messages = []
        test_lib.WellKnownSessionTest2.messages = []
        session_id1 = test_lib.WellKnownSessionTest.well_known_session_id
        session_id2 = test_lib.WellKnownSessionTest2.well_known_session_id

        messages = []
        for i in range(1, 5):
            messages.append(
                rdf_flows.GrrMessage(request_id=0,
                                     response_id=0,
                                     session_id=session_id1,
                                     payload=rdfvalue.RDFInteger(i)))
            messages.append(
                rdf_flows.GrrMessage(request_id=0,
                                     response_id=0,
                                     session_id=session_id2,
                                     payload=rdfvalue.RDFInteger(i)))

        # This test whitelists only one flow.
        self.assertIn(session_id1.FlowName(), self.server.well_known_flows)
        self.assertNotIn(session_id2.FlowName(), self.server.well_known_flows)

        self.server.ReceiveMessages(self.client_id, messages)

        # Wait for async actions to complete
        self.server.thread_pool.Join()

        # Flow 1 should have been processed right away.
        test_lib.WellKnownSessionTest.messages.sort()
        self.assertEqual(test_lib.WellKnownSessionTest.messages,
                         list(range(1, 5)))

        # But not Flow 2.
        self.assertEqual(test_lib.WellKnownSessionTest2.messages, [])

        manager = queue_manager.WellKnownQueueManager(token=self.token)

        notifications = manager.GetNotificationsForAllShards(
            session_id1.Queue())

        # Flow 1 was proecessed on the frontend, no queued responses available.
        responses = list(manager.FetchRequestsAndResponses(session_id1))
        self.assertEqual(responses, [])
        # And also no notifications.
        self.assertNotIn(
            session_id1,
            [notification.session_id for notification in notifications])

        # But for Flow 2 there should be some responses + a notification.
        responses = list(manager.FetchRequestsAndResponses(session_id2))
        self.assertEqual(len(responses), 4)
        self.assertIn(
            session_id2,
            [notification.session_id for notification in notifications])
예제 #3
0
    def PublishMultipleEvents(cls, events, delay=None, token=None):
        """Publish the message into all listeners of the event.

    If event_name is a string, we send the message to all event handlers which
    contain this string in their EVENT static member. This allows the event to
    be sent to multiple interested listeners. Alternatively, the event_name can
    specify a single URN of an event listener to receive the message.

    Args:

      events: A dict with keys being event names and values being lists of
        messages.
      delay: An rdfvalue.Duration object. If given, the event will be published
             after the indicated time.
      token: ACL token.

    Raises:
      ValueError: If the message is invalid. The message must be a Semantic
        Value (instance of RDFValue) or a full GrrMessage.
    """
        with queue_manager.WellKnownQueueManager(token=token) as manager:
            event_name_map = registry.EventRegistry.EVENT_NAME_MAP
            for event_name, messages in events.iteritems():
                handler_urns = []
                if isinstance(event_name, basestring):
                    for event_cls in event_name_map.get(event_name, []):
                        if event_cls.well_known_session_id is None:
                            logging.error(
                                "Well known flow %s has no session_id.",
                                event_cls.__name__)
                        else:
                            handler_urns.append(
                                event_cls.well_known_session_id)

                else:
                    handler_urns.append(event_name)

                for msg in messages:
                    # Allow the event name to be either a string or a URN of an event
                    # listener.
                    if not isinstance(msg, rdfvalue.RDFValue):
                        raise ValueError(
                            "Can only publish RDFValue instances.")

                    # Wrap the message in a GrrMessage if needed.
                    if not isinstance(msg, rdf_flows.GrrMessage):
                        msg = rdf_flows.GrrMessage(payload=msg)

                    # Randomize the response id or events will get overwritten.
                    msg.response_id = msg.task_id = msg.GenerateTaskID()
                    # Well known flows always listen for request id 0.
                    msg.request_id = 0

                    timestamp = None
                    if delay:
                        timestamp = (rdfvalue.RDFDatetime.Now() +
                                     delay).AsMicroSecondsFromEpoch()

                    # Forward the message to the well known flow's queue.
                    for event_urn in handler_urns:
                        manager.QueueResponse(event_urn, msg)
                        manager.QueueNotification(
                            rdf_flows.GrrNotification(session_id=event_urn,
                                                      priority=msg.priority,
                                                      timestamp=timestamp))