示例#1
0
    def testReceiveMessageListFleetspeak(self):
        fsd = fs_frontend_tool.GRRFSServer()

        grr_client_nr = 0xab
        grr_client_id_urn = self.SetupClient(grr_client_nr)

        flow_obj = self.FlowSetup(flow_test_lib.FlowOrderTest.__name__,
                                  grr_client_id_urn)

        num_msgs = 9

        session_id = flow_obj.session_id
        messages = [
            rdf_flows.GrrMessage(request_id=1,
                                 response_id=i,
                                 session_id=session_id,
                                 payload=rdfvalue.RDFInteger(i))
            for i in range(1, num_msgs + 1)
        ]

        fs_client_id = b"\x10\x00\x00\x00\x00\x00\x00\xab"
        # fs_client_id should be equivalent to grr_client_id_urn
        self.assertEqual(
            fs_client_id,
            fleetspeak_utils.GRRIDToFleetspeakID(grr_client_id_urn.Basename()))

        message_list = rdf_flows.PackedMessageList()
        communicator.Communicator.EncodeMessageList(
            rdf_flows.MessageList(job=messages), message_list)

        fs_message = fs_common_pb2.Message(message_type="MessageList",
                                           source=fs_common_pb2.Address(
                                               client_id=fs_client_id,
                                               service_name=FS_SERVICE_NAME))
        fs_message.data.Pack(message_list.AsPrimitiveProto())
        fsd.Process(fs_message, None)

        # Make sure the task is still on the client queue
        manager = queue_manager.QueueManager(token=self.token)
        tasks_on_client_queue = manager.Query(grr_client_id_urn, 100)
        self.assertEqual(len(tasks_on_client_queue), 1)

        want_messages = [message.Copy() for message in messages]
        for want_message in want_messages:
            # This is filled in by the frontend as soon as it gets the message.
            want_message.auth_state = (
                rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED)
            want_message.source = grr_client_id_urn

        stored_messages = data_store.DB.ReadResponsesForRequestId(
            session_id, 1)

        self.assertEqual(len(stored_messages), len(want_messages))

        stored_messages.sort(key=lambda m: m.response_id)
        # Check that messages were stored correctly
        for stored_message, want_message in itertools.izip(
                stored_messages, want_messages):
            stored_message.timestamp = None
            self.assertRDFValuesEqual(stored_message, want_message)
  def _SendMessages(self, grr_msgs, background=False):
    """Sends a block of messages through Fleetspeak."""
    message_list = rdf_flows.PackedMessageList()
    communicator.Communicator.EncodeMessageList(
        rdf_flows.MessageList(job=grr_msgs), message_list)
    fs_msg = fs_common_pb2.Message(
        message_type="MessageList",
        destination=fs_common_pb2.Address(service_name="GRR"),
        background=background)
    fs_msg.data.Pack(message_list.AsPrimitiveProto())

    for grr_msg in grr_msgs:
      if (grr_msg.session_id is None or grr_msg.request_id is None or
          grr_msg.response_id is None):
        continue
      # Place all ids in a single annotation, instead of having separate
      # annotations for the flow-id, request-id and response-id. This reduces
      # overall size of the annotations by half (~60 bytes to ~30 bytes).
      annotation = fs_msg.annotations.entries.add()
      annotation.key = _DATA_IDS_ANNOTATION_KEY
      annotation.value = "%s:%d:%d" % (grr_msg.session_id.Basename(),
                                       grr_msg.request_id, grr_msg.response_id)
      if fs_msg.annotations.ByteSize() >= _MAX_ANNOTATIONS_BYTES:
        break

    try:
      sent_bytes = self._fs.Send(fs_msg)
    except (IOError, struct.error):
      logging.critical("Broken local Fleetspeak connection (write end).")
      raise

    communicator.GRR_CLIENT_SENT_BYTES.Increment(sent_bytes)
示例#3
0
def SendGrrMessageThroughFleetspeak(grr_id: str,
                                    grr_msg: rdf_flows.GrrMessage) -> None:
    """Sends the given GrrMessage through FS with retrying.

  The send operation is retried if a `grpc.RpcError` occurs.

  The maximum number of retries corresponds to the config value
  `Server.fleetspeak_send_retry_attempts`.

  A retry is delayed by the number of seconds specified in the config value
  `Server.fleetspeak_send_retry_sleep_time_secs`.

  Args:
    grr_id: ID of grr client to send message to.
    grr_msg: GRR message to send.
  """
    fs_msg = fs_common_pb2.Message(message_type="GrrMessage",
                                   destination=fs_common_pb2.Address(
                                       client_id=GRRIDToFleetspeakID(grr_id),
                                       service_name="GRR"))
    fs_msg.data.Pack(grr_msg.AsPrimitiveProto())
    if grr_msg.session_id is not None:
        annotation = fs_msg.annotations.entries.add()
        annotation.key, annotation.value = "flow_id", grr_msg.session_id.Basename(
        )
    if grr_msg.request_id is not None:
        annotation = fs_msg.annotations.entries.add()
        annotation.key, annotation.value = "request_id", str(
            grr_msg.request_id)
    fleetspeak_connector.CONN.outgoing.InsertMessage(
        fs_msg,
        single_try_timeout=WRITE_SINGLE_TRY_TIMEOUT,
        timeout=WRITE_TOTAL_TIMEOUT)
示例#4
0
 def testInsertMessage(self):
     t = FakeStub()
     s = client.OutgoingConnection(None, 'test', t)
     s.InsertMessage(common_pb2.Message())
     self.assertTrue(t.insert_done)
     self.assertFalse(t.insert_errors)
     self.assertEqual(t.message.source.service_name, 'test')
示例#5
0
  def _SendMessages(self, grr_msgs, priority=fs_common_pb2.Message.MEDIUM):
    """Sends a block of messages through Fleetspeak."""
    message_list = rdf_flows.PackedMessageList()
    communicator.Communicator.EncodeMessageList(
        rdf_flows.MessageList(job=grr_msgs), message_list)

    fs_msg = fs_common_pb2.Message(
        message_type="MessageList",
        destination=fs_common_pb2.Address(service_name="GRR"),
        priority=priority)
    fs_msg.data.Pack(message_list.AsPrimitiveProto())

    try:
      sent_bytes = self._fs.Send(fs_msg)
    except (IOError, struct.error) as e:
      logging.fatal(
          "Broken local Fleetspeak connection (write end): %r",
          e,
          exc_info=True)
      # The fatal call above doesn't terminate the program. The reasons for
      # this might include Python threads persistency, or Python logging
      # mechanisms' inconsistency.
      os._exit(1)  # pylint: disable=protected-access

    stats.STATS.IncrementCounter("grr_client_sent_bytes", sent_bytes)
示例#6
0
 def _WriteStartupData(self, version):
     startup_msg = common_pb2.Message(
         message_type="StartupData",
         destination=common_pb2.Address(service_name="system"))
     startup_msg.data.Pack(
         channel_pb2.StartupData(pid=os.getpid(), version=version))
     self._SendImpl(startup_msg)
示例#7
0
def SendGrrMessageThroughFleetspeak(grr_id, msg):
    """Sends the given GrrMessage through FS."""
    fs_msg = fs_common_pb2.Message(message_type="GrrMessage",
                                   destination=fs_common_pb2.Address(
                                       client_id=GRRIDToFleetspeakID(grr_id),
                                       service_name="GRR"))
    fs_msg.data.Pack(msg.AsPrimitiveProto())
    fleetspeak_connector.CONN.outgoing.InsertMessage(fs_msg)
示例#8
0
def RestartFleetspeakGrrService(grr_id: Text) -> None:
  """Restarts the GRR service on the given client."""
  restart_req = fs_system_pb2.RestartServiceRequest(name="GRR")
  fs_msg = fs_common_pb2.Message()
  fs_msg.message_type = "RestartService"
  fs_msg.destination.client_id = GRRIDToFleetspeakID(grr_id)
  fs_msg.destination.service_name = "system"
  fs_msg.data.Pack(restart_req)

  fleetspeak_connector.CONN.outgoing.InsertMessage(fs_msg)
示例#9
0
def KillFleetspeak(grr_id: Text, force: bool) -> None:
  """Kills Fleespeak on the given client."""
  die_req = fs_system_pb2.DieRequest(force=force)
  fs_msg = fs_common_pb2.Message()
  fs_msg.message_type = "Die"
  fs_msg.destination.client_id = GRRIDToFleetspeakID(grr_id)
  fs_msg.destination.service_name = "system"
  fs_msg.data.Pack(die_req)

  fleetspeak_connector.CONN.outgoing.InsertMessage(fs_msg)
    def testReceiveMessageList(self):
        fs_server = fleetspeak_frontend_server.GRRFSServer()
        client_id = "C.1234567890123456"
        flow_id = "12345678"
        data_store.REL_DB.WriteClientMetadata(client_id,
                                              fleetspeak_enabled=True)

        rdf_flow = rdf_flow_objects.Flow(
            client_id=client_id,
            flow_id=flow_id,
            create_time=rdfvalue.RDFDatetime.Now())
        data_store.REL_DB.WriteFlowObject(rdf_flow)

        flow_request = rdf_flow_objects.FlowRequest(client_id=client_id,
                                                    flow_id=flow_id,
                                                    request_id=1)

        data_store.REL_DB.WriteFlowRequests([flow_request])
        session_id = "%s/%s" % (client_id, flow_id)
        fs_client_id = fleetspeak_utils.GRRIDToFleetspeakID(client_id)
        grr_messages = []
        for i in range(1, 10):
            grr_message = rdf_flows.GrrMessage(request_id=1,
                                               response_id=i + 1,
                                               session_id=session_id,
                                               payload=rdfvalue.RDFInteger(i))
            grr_messages.append(grr_message)
        packed_messages = rdf_flows.PackedMessageList()
        communicator.Communicator.EncodeMessageList(
            rdf_flows.MessageList(job=grr_messages), packed_messages)
        fs_message = fs_common_pb2.Message(message_type="MessageList",
                                           source=fs_common_pb2.Address(
                                               client_id=fs_client_id,
                                               service_name=FS_SERVICE_NAME))
        fs_message.data.Pack(packed_messages.AsPrimitiveProto())
        fs_message.validation_info.tags["foo"] = "bar"

        with test_lib.FakeTime(
                rdfvalue.RDFDatetime.FromSecondsSinceEpoch(123)):
            fs_server.Process(fs_message, None)

        # Ensure the last-ping timestamp gets updated.
        client_data = data_store.REL_DB.MultiReadClientMetadata([client_id])
        self.assertEqual(client_data[client_id].ping,
                         rdfvalue.RDFDatetime.FromSecondsSinceEpoch(123))
        self.assertEqual(
            client_data[client_id].last_fleetspeak_validation_info.
            ToStringDict(), {"foo": "bar"})

        flow_data = data_store.REL_DB.ReadAllFlowRequestsAndResponses(
            client_id, flow_id)
        self.assertLen(flow_data, 1)
        stored_flow_request, flow_responses = flow_data[0]
        self.assertEqual(stored_flow_request, flow_request)
        self.assertLen(flow_responses, 9)
示例#11
0
    def Heartbeat(self):
        """Sends a heartbeat to the Fleetspeak client.

    If this daemonservice is configured to use heartbeats, clients that don't
    call this method often enough are considered faulty and are restarted by
    Fleetspeak.
    """
        heartbeat_msg = common_pb2.Message(
            message_type="Heartbeat",
            destination=common_pb2.Address(service_name="system"))
        self._SendImpl(heartbeat_msg)
    def testReceiveMessages_Relational(self):
        if not data_store.RelationalDBEnabled():
            self.skipTest("Rel-db-only test.")

        fs_server = fs_frontend_tool.GRRFSServer()
        client_id = "C.1234567890123456"
        flow_id = "12345678"
        data_store.REL_DB.WriteClientMetadata(client_id,
                                              fleetspeak_enabled=True)

        rdf_flow = rdf_flow_objects.Flow(
            client_id=client_id,
            flow_id=flow_id,
            create_time=rdfvalue.RDFDatetime.Now())
        data_store.REL_DB.WriteFlowObject(rdf_flow)

        flow_request = rdf_flow_objects.FlowRequest(client_id=client_id,
                                                    flow_id=flow_id,
                                                    request_id=1)

        data_store.REL_DB.WriteFlowRequests([flow_request])
        session_id = "%s/%s" % (client_id, flow_id)
        fs_client_id = fleetspeak_utils.GRRIDToFleetspeakID(client_id)
        fs_messages = []
        for i in range(1, 10):
            grr_message = rdf_flows.GrrMessage(request_id=1,
                                               response_id=i + 1,
                                               session_id=session_id,
                                               payload=rdfvalue.RDFInteger(i))
            fs_message = fs_common_pb2.Message(
                message_type="GrrMessage",
                source=fs_common_pb2.Address(client_id=fs_client_id,
                                             service_name=FS_SERVICE_NAME))
            fs_message.data.Pack(grr_message.AsPrimitiveProto())
            fs_messages.append(fs_message)

        with test_lib.FakeTime(
                rdfvalue.RDFDatetime.FromSecondsSinceEpoch(123)):
            for fs_message in fs_messages:
                fs_server.Process(fs_message, None)

        # Ensure the last-ping timestamp gets updated.
        client_data = data_store.REL_DB.MultiReadClientMetadata([client_id])
        self.assertEqual(client_data[client_id].ping,
                         rdfvalue.RDFDatetime.FromSecondsSinceEpoch(123))

        flow_data = data_store.REL_DB.ReadAllFlowRequestsAndResponses(
            client_id, flow_id)
        self.assertLen(flow_data, 1)
        stored_flow_request, flow_responses = flow_data[0]
        self.assertEqual(stored_flow_request, flow_request)
        self.assertLen(flow_responses, 9)
示例#13
0
def SendGrrMessageThroughFleetspeak(grr_id, grr_msg):
  """Sends the given GrrMessage through FS."""
  fs_msg = fs_common_pb2.Message(
      message_type="GrrMessage",
      destination=fs_common_pb2.Address(
          client_id=GRRIDToFleetspeakID(grr_id), service_name="GRR"))
  fs_msg.data.Pack(grr_msg.AsPrimitiveProto())
  if grr_msg.session_id is not None:
    annotation = fs_msg.annotations.entries.add()
    annotation.key, annotation.value = "flow_id", grr_msg.session_id.Basename()
  if grr_msg.request_id is not None:
    annotation = fs_msg.annotations.entries.add()
    annotation.key, annotation.value = "request_id", str(grr_msg.request_id)
  fleetspeak_connector.CONN.outgoing.InsertMessage(fs_msg)
示例#14
0
 def testGetFleetspeakPendingMessages(self):
   conn = mock.MagicMock()
   proto_response = admin_pb2.GetPendingMessagesResponse(
       messages=[common_pb2.Message(message_id=b"foo")])
   conn.outgoing.GetPendingMessages.return_value = proto_response
   with mock.patch.object(fleetspeak_connector, "CONN", conn):
     result = fleetspeak_utils.GetFleetspeakPendingMessages(
         "C.1000000000000000", 1, 2, True)
     self.assertEqual(result, proto_response)
     get_args, _ = conn.outgoing.GetPendingMessages.call_args
     get_req = get_args[0]
     self.assertSameElements(get_req.client_ids,
                             [b"\x10\x00\x00\x00\x00\x00\x00\x00"])
     self.assertEqual(get_req.offset, 1)
     self.assertEqual(get_req.limit, 2)
     self.assertEqual(get_req.want_data, True)
示例#15
0
    def testPingIsRecorded(self):
        service_name = "GRR"
        fake_service_client = _FakeGRPCServiceClient(service_name)

        fleetspeak_connector.Reset()
        fleetspeak_connector.Init(service_client=fake_service_client)

        fsd = fs_frontend_tool.GRRFSServer()

        grr_client_nr = 0xab
        grr_client = self.SetupTestClientObject(grr_client_nr)
        self.SetupClient(grr_client_nr)

        messages = [
            rdf_flows.GrrMessage(request_id=1,
                                 response_id=1,
                                 session_id="F:123456",
                                 payload=rdfvalue.RDFInteger(1))
        ]

        fs_client_id = "\x10\x00\x00\x00\x00\x00\x00\xab"
        # fs_client_id should be equivalent to grr_client_id_urn
        self.assertEqual(
            fs_client_id,
            fleetspeak_utils.GRRIDToFleetspeakID(grr_client.client_id))

        message_list = rdf_flows.PackedMessageList()
        communicator.Communicator.EncodeMessageList(
            rdf_flows.MessageList(job=messages), message_list)

        fs_message = fs_common_pb2.Message(message_type="MessageList",
                                           source=fs_common_pb2.Address(
                                               client_id=fs_client_id,
                                               service_name=service_name))
        fs_message.data.Pack(message_list.AsPrimitiveProto())

        fake_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(42)
        with test_lib.FakeTime(fake_time):
            fsd.Process(fs_message, None)

        md = data_store.REL_DB.ReadClientMetadata(grr_client.client_id)
        self.assertEqual(md.ping, fake_time)

        with aff4.FACTORY.Open(grr_client.client_id) as client:
            self.assertEqual(client.Get(client.Schema.PING), fake_time)
示例#16
0
文件: client.py 项目: kant/fleetspeak
  def Recv(self):
    """Accept a message from Fleetspeak.

    Returns:
      A tuple (common_pb2.Message, size of the message in bytes).
    Raises:
      ProtocolError: If we receive unexpected data from Fleetspeak.
    """
    size = struct.unpack(_STRUCT_FMT, self._ReadN(_STRUCT_LEN))[0]
    if size > MAX_SIZE:
      raise ProtocolError("Expected size to be at most %d, got %d" %
                          (MAX_SIZE, size))
    buf = self._ReadN(size)
    self._ReadMagic()
    res = common_pb2.Message()
    res.ParseFromString(buf)

    return res, len(buf)
示例#17
0
    def _SendMessages(self, grr_msgs, background=False):
        """Sends a block of messages through Fleetspeak."""
        message_list = rdf_flows.PackedMessageList()
        communicator.Communicator.EncodeMessageList(
            rdf_flows.MessageList(job=grr_msgs), message_list)
        fs_msg = fs_common_pb2.Message(
            message_type="MessageList",
            destination=fs_common_pb2.Address(service_name="GRR"),
            background=background)
        fs_msg.data.Pack(message_list.AsPrimitiveProto())

        try:
            sent_bytes = self._fs.Send(fs_msg)
        except (IOError, struct.error) as e:
            logging.critical("Broken local Fleetspeak connection (write end).")
            raise e

        stats.STATS.IncrementCounter("grr_client_sent_bytes", sent_bytes)
    def testWriteLastPingForNewClients(self):
        if not data_store.RelationalDBEnabled():
            self.skipTest("Rel-db-only test.")

        fs_server = fs_frontend_tool.GRRFSServer()
        client_id = "C.1234567890123456"
        flow_id = "12345678"
        session_id = "%s/%s" % (client_id, flow_id)
        fs_client_id = fleetspeak_utils.GRRIDToFleetspeakID(client_id)

        grr_message = rdf_flows.GrrMessage(request_id=1,
                                           response_id=1,
                                           session_id=session_id,
                                           payload=rdfvalue.RDFInteger(1))
        fs_message = fs_common_pb2.Message(message_type="GrrMessage",
                                           source=fs_common_pb2.Address(
                                               client_id=fs_client_id,
                                               service_name=FS_SERVICE_NAME))
        fs_message.data.Pack(grr_message.AsPrimitiveProto())
        fake_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(123)

        with mock.patch.object(
                events.Events, "PublishEvent",
                wraps=events.Events.PublishEvent) as publish_event_fn:
            with mock.patch.object(data_store.REL_DB,
                                   "WriteClientMetadata",
                                   wraps=data_store.REL_DB.WriteClientMetadata
                                   ) as write_metadata_fn:
                with test_lib.FakeTime(fake_time):
                    fs_server.Process(fs_message, None)
                self.assertEqual(write_metadata_fn.call_count, 1)
                client_data = data_store.REL_DB.MultiReadClientMetadata(
                    [client_id])
                self.assertEqual(client_data[client_id].ping, fake_time)
                # TODO(user): publish_event_fn.assert_any_call(
                #     "ClientEnrollment", mock.ANY, token=mock.ANY) doesn't work here
                # for some reason.
                triggered_events = []
                for call_args, _ in publish_event_fn.call_args_list:
                    if call_args:
                        triggered_events.append(call_args[0])
                self.assertIn("ClientEnrollment", triggered_events)