コード例 #1
0
  def QueueNotification(self, notification=None, timestamp=None, **kw):
    """Queues a notification for a flow."""

    if notification is None:
      notification = rdf_flows.GrrNotification(**kw)

    session_id = notification.session_id

    if session_id:
      if timestamp is None:
        timestamp = self.frozen_timestamp

      notification.timestamp = timestamp

      # We must not store more than one notification per session id and
      # timestamp or there will be race conditions. We therefore only keep
      # the one with the highest request number (indicated by last_status).
      # Note that timestamp might be None. In that case we also only want
      # to keep the latest.
      if timestamp is None:
        ts_str = "None"
      else:
        ts_str = int(timestamp)
      key = "%s!%s" % (session_id, ts_str)
      existing = self.notifications.get(key)
      if existing is not None:
        if existing.last_status < notification.last_status:
          self.notifications[key] = notification
      else:
        self.notifications[key] = notification
コード例 #2
0
ファイル: worker_test.py プロジェクト: rainser/grr
    def CheckNotificationsDisappear(self, session_id):
        worker_obj = worker_lib.GRRWorker(token=self.token)
        manager = queue_manager.QueueManager(token=self.token)
        notification = rdf_flows.GrrNotification(session_id=session_id)
        with data_store.DB.GetMutationPool() as pool:
            manager.NotifyQueue(notification, mutation_pool=pool)

        notifications = manager.GetNotificationsByPriority(queues.FLOWS).get(
            notification.priority, [])

        # Check the notification is there. With multiple worker queue shards we can
        # get other notifications such as for audit event listeners, so we need to
        # filter out ours.
        notifications = [
            x for x in notifications if x.session_id == session_id
        ]
        self.assertEqual(len(notifications), 1)

        # Process all messages
        worker_obj.RunOnce()
        worker_obj.thread_pool.Join()

        notifications = manager.GetNotificationsByPriority(queues.FLOWS).get(
            notification.priority, [])
        notifications = [
            x for x in notifications if x.session_id == session_id
        ]

        # Check the notification is now gone.
        self.assertEqual(len(notifications), 0)
コード例 #3
0
ファイル: aff4_grr.py プロジェクト: rainser/grr
  def ExpireRules(self):
    """Removes any rules with an expiration date in the past."""
    rules = self.Get(self.Schema.RULES)
    new_rules = self.Schema.RULES()
    now = time.time() * 1e6
    expired_session_ids = set()

    for rule in rules:
      if rule.expires > now:
        new_rules.Append(rule)
      else:
        for action in rule.actions:
          if action.hunt_id:
            expired_session_ids.add(action.hunt_id)

    if expired_session_ids:
      with data_store.DB.GetMutationPool() as pool:
        # Notify the worker to mark this hunt as terminated.
        manager = queue_manager.QueueManager(token=self.token)
        manager.MultiNotifyQueue(
            [
                rdf_flows.GrrNotification(session_id=session_id)
                for session_id in expired_session_ids
            ],
            mutation_pool=pool)

    if len(new_rules) < len(rules):
      self.Set(self.Schema.RULES, new_rules)
      self.Flush()
コード例 #4
0
ファイル: worker_test.py プロジェクト: rainser/grr
    def testNotificationReschedulingTTL(self):
        """Test that notifications are not rescheduled forever."""

        with test_lib.FakeTime(10000):
            worker_obj = worker_lib.GRRWorker(token=self.token)
            flow_obj = self.FlowSetup("RaisingTestFlow")
            session_id = flow_obj.session_id
            flow_obj.Close()

            with queue_manager.QueueManager(token=self.token) as manager:
                notification = rdf_flows.GrrNotification(session_id=session_id,
                                                         timestamp=time.time(),
                                                         last_status=1)
                with data_store.DB.GetMutationPool() as pool:
                    manager.NotifyQueue(notification, mutation_pool=pool)

                notifications = manager.GetNotifications(queues.FLOWS)
                # Check the notification is there.
                notifications = [
                    n for n in notifications if n.session_id == session_id
                ]
                self.assertEqual(len(notifications), 1)

        delay = flow_runner.FlowRunner.notification_retry_interval

        ttl = notification.ttl
        for i in xrange(ttl - 1):
            with test_lib.FakeTime(10000 + 100 + delay * (i + 1)):
                # Process all messages.
                worker_obj.RunOnce()
                worker_obj.thread_pool.Join()

                notifications = manager.GetNotifications(queues.FLOWS)
                # Check the notification is for the correct session_id.
                notifications = [
                    n for n in notifications if n.session_id == session_id
                ]
                self.assertEqual(len(notifications), 1)

        with test_lib.FakeTime(10000 + 100 + delay * ttl):
            # Process all messages.
            worker_obj.RunOnce()
            worker_obj.thread_pool.Join()

            notifications = manager.GetNotifications(queues.FLOWS)
            self.assertEqual(len(notifications), 0)
コード例 #5
0
ファイル: flow_test.py プロジェクト: rainser/grr
    def testReordering(self):
        """Check that out of order client messages are reordered."""
        flow_obj = self.FlowSetup(flow_test_lib.FlowOrderTest.__name__)

        # Simulate processing messages arriving in random order
        message_ids = [2, 1, 4, 3, 5]
        self.SendMessages(message_ids, flow_obj.session_id)

        # Send the status message
        self.SendOKStatus(6, flow_obj.session_id)

        runner = flow_obj.GetRunner()
        notification = rdf_flows.GrrNotification(
            timestamp=rdfvalue.RDFDatetime.Now())
        runner.ProcessCompletedRequests(notification)

        # Check that the messages were processed in order
        self.assertEqual(flow_obj.messages, [1, 2, 3, 4, 5])
コード例 #6
0
ファイル: worker_test.py プロジェクト: rainser/grr
    def testNotificationRacesAreResolved(self):
        # We need a random flow object for this test.
        session_id = flow.StartFlow(client_id=self.client_id,
                                    flow_name="WorkerSendingTestFlow",
                                    token=self.token)
        worker_obj = worker_lib.GRRWorker(token=self.token)
        manager = queue_manager.QueueManager(token=self.token)
        manager.DeleteNotification(session_id)
        manager.Flush()

        # We simulate a race condition here - the notification for request #1 is
        # there but the actual request #1 is not. The worker should pick up the
        # notification, notice that the request #1 is not there yet and reschedule
        # the notification.
        notification = rdf_flows.GrrNotification(session_id=session_id,
                                                 last_status=1)
        with data_store.DB.GetMutationPool() as pool:
            manager.NotifyQueue(notification, mutation_pool=pool)

        notifications = manager.GetNotifications(queues.FLOWS)
        # Check the notification is there.
        notifications = [
            n for n in notifications if n.session_id == session_id
        ]
        self.assertEqual(len(notifications), 1)

        # Process all messages
        worker_obj.RunOnce()
        worker_obj.thread_pool.Join()

        delay = flow_runner.FlowRunner.notification_retry_interval
        with test_lib.FakeTime(time.time() + 10 + delay):
            requeued_notifications = manager.GetNotifications(queues.FLOWS)
            # Check that there is a new notification.
            notifications = [
                n for n in notifications if n.session_id == session_id
            ]
            self.assertEqual(len(requeued_notifications), 1)

            self.assertEqual(requeued_notifications[0].first_queued,
                             notifications[0].first_queued)
            self.assertNotEqual(requeued_notifications[0].timestamp,
                                notifications[0].timestamp)
コード例 #7
0
ファイル: flow_test.py プロジェクト: rainser/grr
    def testAuthentication1(self):
        """Test that flows refuse to processes unauthenticated messages."""
        flow_obj = self.FlowSetup(flow_test_lib.FlowOrderTest.__name__)

        # Simulate processing messages arriving in random order
        message_ids = [2, 1, 4, 3, 5]
        self.SendMessages(message_ids,
                          flow_obj.session_id,
                          authenticated=False)

        # Send the status message
        self.SendOKStatus(6, flow_obj.session_id)

        runner = flow_obj.GetRunner()
        notification = rdf_flows.GrrNotification(
            timestamp=rdfvalue.RDFDatetime.Now())
        runner.ProcessCompletedRequests(notification)

        # Now messages should actually be processed
        self.assertEqual(flow_obj.messages, [])
コード例 #8
0
ファイル: flow_test.py プロジェクト: rainser/grr
    def testAuthentication2(self):
        """Test that flows refuse to processes unauthenticated messages.

    Here we try to simulate an attacker injecting unauthenticated
    messages midstream.

    The current implementation actually fails to process the entire
    flow since the injected messages displace the real ones if they
    arrive earlier. This can be an effective DoS against legitimate
    clients but would require attackers to guess session ids.
    """
        flow_obj = self.FlowSetup(flow_test_lib.FlowOrderTest.__name__)

        # Simulate processing messages arriving in random order
        message_ids = [1, 2]
        self.SendMessages(message_ids, flow_obj.session_id, authenticated=True)

        # Now suppose some of the messages are spoofed
        message_ids = [3, 4, 5]
        self.SendMessages(message_ids,
                          flow_obj.session_id,
                          authenticated=False)

        # And now our real messages arrive
        message_ids = [5, 6]
        self.SendMessages(message_ids, flow_obj.session_id, authenticated=True)

        # Send the status message
        self.SendOKStatus(7, flow_obj.session_id)

        runner = flow_obj.GetRunner()
        notification = rdf_flows.GrrNotification(
            timestamp=rdfvalue.RDFDatetime.Now())
        runner.ProcessCompletedRequests(notification)

        # Some messages should actually be processed
        self.assertEqual(flow_obj.messages, [1, 2, 5, 6])