def testClientStartupInfo(self): """StartupInfo is written to a separate table, make sure the merge works.""" d = self.db client_id = "C.fc413187fefa1dcf" self._InitializeClient(client_id) client = objects.Client(client_id=client_id, kernel="12.3") client.startup_info = rdf_client.StartupInfo(boot_time=123) client.knowledge_base.fqdn = "test1234.examples.com" d.WriteClient(client) client = d.ReadClient(client_id) self.assertEqual(client.startup_info.boot_time, 123) client.kernel = "12.4" client.startup_info = rdf_client.StartupInfo(boot_time=124) d.WriteClient(client) client.kernel = "12.5" client.startup_info = rdf_client.StartupInfo(boot_time=125) d.WriteClient(client) hist = d.ReadClientHistory(client_id) self.assertEqual(len(hist), 3) startup_infos = [cl.startup_info for cl in hist] self.assertEqual([si.boot_time for si in startup_infos], [125, 124, 123]) # StartupInfos written using WriteClient show up in the StartupInfoHistory. history = d.ReadClientStartupInfoHistory(client_id) self.assertEqual(len(history), 3) self.assertEqual(startup_infos, history)
def testStartupHistory(self): d = self.db client_id = "C.0000000050000001" si = rdf_client.StartupInfo(boot_time=1) with self.assertRaises(db.UnknownClientError): d.WriteClientStartupInfo(client_id, si) self._InitializeClient(client_id) d.WriteClientStartupInfo(client_id, si) si.boot_time = 2 d.WriteClientStartupInfo(client_id, si) si.boot_time = 3 d.WriteClientStartupInfo(client_id, si) last_is = d.ReadClientStartupInfo(client_id) self.assertIsInstance(last_is, rdf_client.StartupInfo) self.assertEqual(last_is.boot_time, 3) self.assertIsInstance(last_is.timestamp, rdfvalue.RDFDatetime) hist = d.ReadClientStartupInfoHistory(client_id) self.assertEqual(len(hist), 3) self.assertEqual([si.boot_time for si in hist], [3, 2, 1]) self.assertIsInstance(hist[0].timestamp, rdfvalue.RDFDatetime) self.assertGreater(hist[0].timestamp, hist[1].timestamp) self.assertGreater(hist[1].timestamp, hist[2].timestamp) md = self.db.ReadClientMetadata(client_id) self.assertEqual(md.startup_info_timestamp, hist[0].timestamp) self.assertIsNone(d.ReadClientStartupInfo("C.0000000000000000")) self.assertEqual(d.ReadClientStartupInfoHistory("C.0000000000000000"), [])
def testWriteClientSnapshotHistoryUpdatesOnlyLastClientTimestamp(self): client_id = self.InitializeClient() client_old = objects.ClientSnapshot(client_id=client_id) client_old.kernel = "1.0.0" client_old.startup_info.client_info.client_name = "foo" self.db.WriteClientSnapshot(client_old) old_timestamp = self.db.ReadClientSnapshot(client_id).timestamp startup_info = rdf_client.StartupInfo() startup_info.client_info.client_name = "bar" self.db.WriteClientStartupInfo(client_id, startup_info) startup_timestamp = self.db.ReadClientStartupInfo(client_id).timestamp client_new = objects.ClientSnapshot(client_id=client_id) client_new.kernel = "2.0.0" client_new.startup_info.client_info.client_name = "baz" client_new.timestamp = rdfvalue.RDFDatetime.Lerp( 0.5, start_time=old_timestamp, end_time=startup_timestamp) self.db.WriteClientSnapshotHistory([client_new]) info = self.db.ReadClientFullInfo(client_id) last_snapshot = info.last_snapshot last_startup_info = info.last_startup_info self.assertEqual(last_snapshot.kernel, "2.0.0") self.assertEqual(last_snapshot.startup_info.client_info.client_name, "baz") self.assertEqual(last_snapshot.timestamp, client_new.timestamp) self.assertEqual(last_startup_info.client_info.client_name, "bar") self.assertEqual(last_startup_info.timestamp, startup_timestamp)
def testReadAllClientsFullInfoReadsMultipleClientsWithMultipleLabels(self): d = self.db for i in range(10): client_id = "C.000000005000000%d" % i self._InitializeClient(client_id) cl = objects.ClientSnapshot( client_id=client_id, knowledge_base=rdf_client.KnowledgeBase( fqdn="test%d.examples.com" % i), kernel="12.3.%d" % i) d.WriteClientSnapshot(cl) d.WriteClientMetadata(client_id, certificate=CERT) si = rdf_client.StartupInfo(boot_time=i) d.WriteClientStartupInfo(client_id, si) d.AddClientLabels( client_id, "test_owner", ["test_label-a-%d" % i, "test_label-b-%d" % i]) c_infos = sorted( d.ReadAllClientsFullInfo(), key=lambda c: c.last_snapshot.client_id) for i, full_info in enumerate(c_infos): self.assertEqual(full_info.last_snapshot.client_id, "C.000000005000000%d" % i) self.assertEqual(full_info.metadata.certificate, CERT) self.assertEqual(full_info.last_startup_info.boot_time, i) self.assertEqual( sorted(full_info.labels, key=lambda l: l.name), [ objects.ClientLabel( owner="test_owner", name="test_label-a-%d" % i), objects.ClientLabel( owner="test_owner", name="test_label-b-%d" % i) ])
def testReadClientStartupInfo(self): d = self.db client_id = self.InitializeClient() d.WriteClientStartupInfo(client_id, rdf_client.StartupInfo(boot_time=1337)) d.WriteClientStartupInfo(client_id, rdf_client.StartupInfo(boot_time=2000)) last_is = d.ReadClientStartupInfo(client_id) self.assertIsInstance(last_is, rdf_client.StartupInfo) self.assertEqual(last_is.boot_time, 2000) self.assertIsInstance(last_is.timestamp, rdfvalue.RDFDatetime) md = self.db.ReadClientMetadata(client_id) self.assertEqual(md.startup_info_timestamp, last_is.timestamp)
def _SetUpReadClientStartupInfoHistoryTest(self): d = self.db self.client_id = self.InitializeClient() timestamps = [rdfvalue.RDFDatetime.Now()] si = rdf_client.StartupInfo(boot_time=1) d.WriteClientStartupInfo(self.client_id, si) timestamps.append(d.ReadClientStartupInfo(self.client_id).timestamp) timestamps.append(rdfvalue.RDFDatetime.Now()) si = rdf_client.StartupInfo(boot_time=2) d.WriteClientStartupInfo(self.client_id, si) timestamps.append(d.ReadClientStartupInfo(self.client_id).timestamp) timestamps.append(rdfvalue.RDFDatetime.Now()) return timestamps
def testReadClientStartupInfoHistory(self): d = self.db client_id = self.InitializeClient() d.WriteClientStartupInfo(client_id, rdf_client.StartupInfo(boot_time=1)) d.WriteClientStartupInfo(client_id, rdf_client.StartupInfo(boot_time=2)) d.WriteClientStartupInfo(client_id, rdf_client.StartupInfo(boot_time=3)) hist = d.ReadClientStartupInfoHistory(client_id) self.assertEqual(len(hist), 3) self.assertEqual([si.boot_time for si in hist], [3, 2, 1]) self.assertIsInstance(hist[0].timestamp, rdfvalue.RDFDatetime) self.assertGreater(hist[0].timestamp, hist[1].timestamp) self.assertGreater(hist[1].timestamp, hist[2].timestamp) md = self.db.ReadClientMetadata(client_id) self.assertEqual(md.startup_info_timestamp, hist[0].timestamp)
def Run(self, unused_arg, ttl=None): """Returns the startup information.""" logging.debug("Sending startup information.") boot_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(psutil.boot_time()) response = rdf_client.StartupInfo( boot_time=boot_time, client_info=GetClientInformation()) self.grr_worker.SendReply( response, session_id=self.well_known_session_id, response_id=0, request_id=0, priority=rdf_flows.GrrMessage.Priority.LOW_PRIORITY, message_type=rdf_flows.GrrMessage.Type.MESSAGE, require_fastpoll=False, ttl=ttl)
def _SetupFullInfoClients(self): for i in range(10): client_id = self.InitializeClient("C.000000005000000%d" % i) cl = objects.ClientSnapshot( client_id=client_id, knowledge_base=rdf_client.KnowledgeBase( fqdn="test%d.examples.com" % i), kernel="12.3.%d" % i) self.db.WriteClientSnapshot(cl) self.db.WriteClientMetadata(client_id, certificate=CERT) si = rdf_client.StartupInfo(boot_time=i) self.db.WriteClientStartupInfo(client_id, si) self.db.AddClientLabels( client_id, "test_owner", ["test_label-a-%d" % i, "test_label-b-%d" % i])
def ProcessMessage(self, message=None, event=None): client_id = message.source # Older client versions do not sent the RDFValue type name explicitly. if event is None: event = rdf_client.StartupInfo(message.args) client_info = event.client_info if client_info.client_version < 2910: python_hack_root_urn = config_lib.CONFIG.Get("Config.python_hack_root") hack_urn = python_hack_root_urn.Add("find_fix.py") fd = aff4.FACTORY.Open(hack_urn, token=self.token) python_blob = fd.Get(fd.Schema.BINARY) if python_blob is None: raise flow.FlowError("Python hack %s not found." % hack_urn) self.CallClient( client_id, standard_actions.ExecutePython, python_code=python_blob)
def ProcessMessage(self, message=None, event=None): """Handle a startup event.""" _ = event # We accept unauthenticated messages so there are no errors but we don't # store the results. if (message.auth_state != rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED): return client_id = message.source client = aff4.FACTORY.Create(client_id, aff4_grr.VFSGRRClient, mode="rw", token=self.token) old_info = client.Get(client.Schema.CLIENT_INFO) old_boot = client.Get(client.Schema.LAST_BOOT_TIME, 0) startup_info = rdf_client.StartupInfo(message.payload) info = startup_info.client_info # Only write to the datastore if we have new information. new_data = (info.client_name, info.client_version, info.revision, info.build_time, info.client_description) old_data = (old_info.client_name, old_info.client_version, old_info.revision, old_info.build_time, old_info.client_description) if new_data != old_data: client.Set(client.Schema.CLIENT_INFO(info)) client.AddLabels(*info.labels, owner="GRR") # Allow for some drift in the boot times (5 minutes). if abs(int(old_boot) - int(startup_info.boot_time)) > 300 * 1e6: client.Set(client.Schema.LAST_BOOT_TIME(startup_info.boot_time)) client.Close() events.Events.PublishEventInline("ClientStartup", message, token=self.token)
def testReadClientFullInfoReturnsCorrectResult(self): d = self.db client_id = self.InitializeClient() cl = objects.ClientSnapshot(client_id=client_id, knowledge_base=rdf_client.KnowledgeBase( fqdn="test1234.examples.com"), kernel="12.3") d.WriteClientSnapshot(cl) d.WriteClientMetadata(client_id, certificate=CERT) si = rdf_client.StartupInfo(boot_time=1) d.WriteClientStartupInfo(client_id, si) d.AddClientLabels(client_id, "test_owner", ["test_label"]) full_info = d.ReadClientFullInfo(client_id) self.assertEqual(full_info.last_snapshot, cl) self.assertEqual(full_info.metadata.certificate, CERT) self.assertEqual(full_info.last_startup_info, si) self.assertEqual( full_info.labels, [objects.ClientLabel(owner="test_owner", name="test_label")])
def testFullInfo(self): d = self.db client_id = "C.0000000050000001" self._InitializeClient(client_id) cl = objects.Client(client_id=client_id, knowledge_base=rdf_client.KnowledgeBase( fqdn="test1234.examples.com"), kernel="12.3") d.WriteClient(cl) d.WriteClientMetadata(client_id, certificate=CERT) si = rdf_client.StartupInfo(boot_time=1) d.WriteClientStartupInfo(client_id, si) d.AddClientLabels(client_id, "test_owner", ["test_label"]) full_info = d.ReadFullInfoClient(client_id) self.assertEqual(full_info["client"], cl) self.assertEqual(full_info["metadata"].certificate, CERT) self.assertEqual(full_info["last_startup_info"], si) self.assertEqual( full_info["labels"], [objects.ClientLabel(owner="test_owner", name="test_label")])