Esempio n. 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 response in manager.FetchResponses(session_id):
                messages.append(response)
            manager.DeleteWellKnownFlowResponses(session_id, messages)

        return messages
Esempio n. 2
0
  def testWellKnownFlowsNotifications(self):
    flow_test_lib.WellKnownSessionTest.messages = []
    flow_test_lib.WellKnownSessionTest2.messages = []
    session_id1 = flow_test_lib.WellKnownSessionTest.well_known_session_id
    session_id2 = flow_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(test_lib.TEST_CLIENT_ID, messages)

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

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

    # But not Flow 2.
    self.assertEqual(flow_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.FetchResponses(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.FetchResponses(session_id2))
    self.assertEqual(len(responses), 4)
    self.assertIn(session_id2,
                  [notification.session_id for notification in notifications])
Esempio n. 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).AsMicrosecondsSinceEpoch()

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