def FlushQueuedMessages(self): # TODO(amoser): This could be done in a single db call, might be worth # optimizing. if self.flow_requests: data_store.REL_DB.WriteFlowRequests(self.flow_requests) self.flow_requests = [] if self.flow_responses: data_store.REL_DB.WriteFlowResponses(self.flow_responses) self.flow_responses = [] if self.client_messages: client_id = self.rdf_flow.client_id if fleetspeak_utils.IsFleetspeakEnabledClient(client_id): for task in self.client_messages: fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, task) else: data_store.REL_DB.WriteClientMessages(self.client_messages) self.client_messages = [] if self.completed_requests: data_store.REL_DB.DeleteFlowRequests(self.completed_requests) self.completed_requests = [] if self.replies_to_write: data_store.REL_DB.WriteFlowResults( self.rdf_flow.client_id, self.rdf_flow.flow_id, self.replies_to_write) self.replies_to_write = []
def FlushQueuedMessages(self): # TODO(amoser): This could be done in a single db call, might be worth # optimizing. if self.flow_requests: data_store.REL_DB.WriteFlowRequests(self.flow_requests) self.flow_requests = [] if self.flow_responses: data_store.REL_DB.WriteFlowResponses(self.flow_responses) self.flow_responses = [] if self.client_messages: client_id = self.rdf_flow.client_id if fleetspeak_utils.IsFleetspeakEnabledClient(client_id): for task in self.client_messages: fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, task) else: data_store.REL_DB.WriteClientMessages(self.client_messages) self.client_messages = [] if self.completed_requests: data_store.REL_DB.DeleteFlowRequests(self.completed_requests) self.completed_requests = [] if self.replies_to_write: # For top-level hunt-induced flows, write results to the hunt collection. if self.rdf_flow.parent_hunt_id and not self.rdf_flow.parent_flow_id: db_compat.WriteHuntResults(self.rdf_flow.client_id, self.rdf_flow.parent_hunt_id, self.replies_to_write) else: data_store.REL_DB.WriteFlowResults(self.replies_to_write) self.replies_to_write = []
def testSendGrrMessage_negativeAttempts(self): client_id = "C.0123456789abcdef" grr_message = rdf_flows.GrrMessage() with test_lib.ConfigOverrider({ "Server.fleetspeak_send_retry_attempts": -1, }): with self.assertRaises(ValueError): fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, grr_message)
def testSendGrrMessage_allRetriesFailed(self, mock_conn): client_id = "C.0123456789abcdef" grr_message = rdf_flows.GrrMessage() mock_conn.outgoing.InsertMessage.side_effect = grpc.RpcError("Foo") with test_lib.ConfigOverrider({ "Server.fleetspeak_send_retry_attempts": 5, "Server.fleetspeak_send_retry_sleep_time_secs": 0, }): with self.assertRaisesRegex(grpc.RpcError, "Foo"): fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, grr_message) self.assertEqual(mock_conn.outgoing.InsertMessage.call_count, 5)
def testSendGrrMessage_retrySuccess(self, mock_conn, mock_sleep): client_id = "C.0123456789abcdef" grr_message = rdf_flows.GrrMessage() def MockInsertMessage(*args): nonlocal mock_conn mock_conn.outgoing.InsertMessage.side_effect = None raise grpc.RpcError("Foo") mock_conn.outgoing.InsertMessage.side_effect = MockInsertMessage with test_lib.ConfigOverrider({ "Server.fleetspeak_send_retry_attempts": 2, "Server.fleetspeak_send_retry_sleep_time_secs": 3, }): fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, grr_message) self.assertEqual(mock_conn.outgoing.InsertMessage.call_count, 2) self.assertEqual(mock_sleep.call_count, 1) mock_sleep.assert_called_with(3)
def testSendGrrMessage(self, mock_conn): client_id = "C.0123456789abcdef" flow_id = "01234567" grr_message = rdf_flows.GrrMessage( session_id="%s/%s" % (client_id, flow_id), name="TestClientAction", request_id=1) fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, grr_message) mock_conn.outgoing.InsertMessage.assert_called_once() insert_args, _ = mock_conn.outgoing.InsertMessage.call_args fs_message = insert_args[0] expected_annotations = common_pb2.Annotations(entries=[ common_pb2.Annotations.Entry(key="flow_id", value=flow_id), common_pb2.Annotations.Entry(key="request_id", value="1"), ]) unpacked_message = rdf_flows.GrrMessage.protobuf() fs_message.data.Unpack(unpacked_message) self.assertEqual(fs_message.annotations, expected_annotations) self.assertEqual(grr_message.AsPrimitiveProto(), unpacked_message)
def Schedule(self, tasks, mutation_pool, timestamp=None): """Schedule a set of Task() instances.""" non_fleetspeak_tasks = [] for queue, queued_tasks in iteritems( collection.Group(tasks, lambda x: x.queue)): if not queue: continue client_id = _GetClientIdFromQueue(queue) if fleetspeak_utils.IsFleetspeakEnabledClient(client_id, token=self.token): for task in queued_tasks: fleetspeak_utils.SendGrrMessageThroughFleetspeak( client_id, task) continue non_fleetspeak_tasks.extend(queued_tasks) timestamp = timestamp or self.frozen_timestamp mutation_pool.QueueScheduleTasks(non_fleetspeak_tasks, timestamp)
def FlushQueuedMessages(self) -> None: """Flushes queued messages.""" # TODO(amoser): This could be done in a single db call, might be worth # optimizing. if self.flow_requests: data_store.REL_DB.WriteFlowRequests(self.flow_requests) self.flow_requests = [] if self.flow_responses: data_store.REL_DB.WriteFlowResponses(self.flow_responses) self.flow_responses = [] if self.client_action_requests: client_id = self.rdf_flow.client_id if fleetspeak_utils.IsFleetspeakEnabledClient(client_id): for request in self.client_action_requests: msg = rdf_flow_objects.GRRMessageFromClientActionRequest( request) fleetspeak_utils.SendGrrMessageThroughFleetspeak( client_id, msg) else: data_store.REL_DB.WriteClientActionRequests( self.client_action_requests) self.client_action_requests = [] if self.completed_requests: data_store.REL_DB.DeleteFlowRequests(self.completed_requests) self.completed_requests = [] if self.replies_to_write: # For top-level hunt-induced flows, write results to the hunt collection. if self.rdf_flow.parent_hunt_id: data_store.REL_DB.WriteFlowResults(self.replies_to_write) hunt.StopHuntIfCPUOrNetworkLimitsExceeded( self.rdf_flow.parent_hunt_id) else: # Write flow results to REL_DB, even if the flow is a nested flow. data_store.REL_DB.WriteFlowResults(self.replies_to_write) self.replies_to_write = []
def Schedule(self, tasks, mutation_pool, timestamp=None): """Schedule a set of Task() instances.""" non_fleetspeak_tasks = [] for queue, queued_tasks in utils.GroupBy(tasks, lambda x: x.queue).iteritems(): if not queue: continue client_id = _GetClientIdFromQueue(queue) if fleetspeak_utils.IsFleetspeakEnabledClient( client_id, token=self.token): for task in queued_tasks: fleetspeak_utils.SendGrrMessageThroughFleetspeak(client_id, task) continue non_fleetspeak_tasks.extend(queued_tasks) if data_store.RelationalDBReadEnabled(category="client_messages"): data_store.REL_DB.WriteClientMessages(non_fleetspeak_tasks) else: timestamp = timestamp or self.frozen_timestamp mutation_pool.QueueScheduleTasks(non_fleetspeak_tasks, timestamp)