def SetUpCrashedFlowInHunt(self): client_ids = [ rdf_client.ClientURN("C.%016X" % i) for i in range(0, 10) ] client_mocks = dict([(client_id, test_lib.CrashClientMock(client_id, self.token)) for client_id in client_ids]) client_rule_set = rdf_foreman.ForemanClientRuleSet(rules=[ rdf_foreman.ForemanClientRule( rule_type=rdf_foreman.ForemanClientRule.Type.REGEX, regex=rdf_foreman.ForemanRegexClientRule( attribute_name="GRR client", attribute_regex="")) ]) with hunts.GRRHunt.StartHunt(hunt_name="SampleHunt", client_rule_set=client_rule_set, client_rate=0, token=self.token) as hunt: hunt.Run() foreman = aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) for client_id in client_ids: self.assertTrue(foreman.AssignTasksToClient(client_id)) test_lib.TestHuntHelperWithMultipleMocks(client_mocks, False, self.token) return client_ids
def Run(self): client_ids = self.SetupClients(1) client_mocks = dict([(client_id, test_lib.CrashClientMock(client_id, self.token)) for client_id in client_ids]) with test_lib.FakeTime(42): with self.CreateHunt(description="the hunt") as hunt_obj: hunt_obj.Run() with test_lib.FakeTime(45): self.AssignTasksToClients(client_ids) test_lib.TestHuntHelperWithMultipleMocks(client_mocks, False, self.token) crashes = aff4.FACTORY.Open(hunt_obj.urn.Add("crashes"), mode="r", token=self.token) crash = list(crashes)[0] session_id = crash.session_id.Basename() replace = { hunt_obj.urn.Basename(): "H:123456", session_id: "H:11223344" } self.Check("GET", "/api/hunts/%s/crashes" % hunt_obj.urn.Basename(), replace=replace) self.Check("GET", "/api/hunts/%s/crashes?count=1" % hunt_obj.urn.Basename(), replace=replace) self.Check("GET", ("/api/hunts/%s/crashes?offset=1&count=1" % hunt_obj.urn.Basename()), replace=replace)
def testAlertEmailIsSentWhenClientKilled(self): """Test that client killed messages are handled correctly.""" self.email_messages = [] def SendEmail(address, sender, title, message, **_): self.email_messages.append( dict(address=address, sender=sender, title=title, message=message)) with utils.Stubber(email_alerts.EMAIL_ALERTER, "SendEmail", SendEmail): client = test_lib.CrashClientMock(self.client_id, self.token) for _ in test_lib.TestFlowHelper( "FlowWithOneClientRequest", client, client_id=self.client_id, token=self.token, check_flow_errors=False): pass self.assertEqual(len(self.email_messages), 1) email_message = self.email_messages[0] # We expect the email to be sent. self.assertEqual( email_message.get("address", ""), config_lib.CONFIG["Monitoring.alert_email"]) self.assertTrue(str(self.client_id) in email_message["title"]) # Make sure the flow state is included in the email message. for s in ["flow_name", "FlowWithOneClientRequest", "current_state"]: self.assertTrue(s in email_message["message"]) flow_obj = aff4.FACTORY.Open( client.flow_id, age=aff4.ALL_TIMES, token=self.token) self.assertEqual(flow_obj.context.state, rdf_flows.FlowContext.State.ERROR) # Make sure client object is updated with the last crash. client_obj = aff4.FACTORY.Open(self.client_id, token=self.token) crash = client_obj.Get(client_obj.Schema.LAST_CRASH) self.CheckCrash(crash, flow_obj.session_id) # Make sure crashes collections are created and written # into proper locations. First check the per-client crashes collection. client_crashes = sorted( list( aff4_grr.VFSGRRClient.CrashCollectionForCID( self.client_id, token=self.token)), key=lambda x: x.timestamp) self.assertTrue(len(client_crashes) >= 1) crash = list(client_crashes)[0] self.CheckCrash(crash, flow_obj.session_id) # Check per-flow crash collection. Check that crash written there is # equal to per-client crash. flow_crashes = sorted( list(flow_obj.GetValuesForAttribute(flow_obj.Schema.CLIENT_CRASH)), key=lambda x: x.timestamp) self.assertEqual(len(flow_crashes), len(client_crashes)) for a, b in zip(flow_crashes, client_crashes): self.assertEqual(a, b)
def testAlertEmailIsSentWhenClientKilledDuringHunt(self): """Test that client killed messages are handled correctly for hunts.""" self.email_messages = [] def SendEmail(address, sender, title, message, **_): self.email_messages.append(dict(address=address, sender=sender, title=title, message=message)) with hunts.GRRHunt.StartHunt(hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="FlowWithOneClientRequest"), client_rate=0, crash_alert_email="*****@*****.**", token=self.token) as hunt: hunt.Run() hunt.StartClients(hunt.session_id, self.client_id) with utils.Stubber(email_alerts.EMAIL_ALERTER, "SendEmail", SendEmail): client = test_lib.CrashClientMock(self.client_id, self.token) test_lib.TestHuntHelper(client, [self.client_id], token=self.token, check_flow_errors=False) self.assertEqual(len(self.email_messages), 2) self.assertListEqual( [self.email_messages[0]["address"], self.email_messages[1]["address"]], ["*****@*****.**", config_lib.CONFIG["Monitoring.alert_email"]])
def Run(self): client_ids = self.SetupClients(1) client_mocks = dict([(client_id, test_lib.CrashClientMock( client_id, self.token)) for client_id in client_ids]) with test_lib.FakeTime(42): with self.CreateHunt(description="the hunt") as hunt_obj: hunt_obj.Run() with test_lib.FakeTime(45): self.AssignTasksToClients(client_ids) test_lib.TestHuntHelperWithMultipleMocks(client_mocks, False, self.token) crashes = implementation.GRRHunt.CrashCollectionForHID( hunt_obj.urn, token=self.token) crash = list(crashes)[0] session_id = crash.session_id.Basename() replace = {hunt_obj.urn.Basename(): "H:123456", session_id: "H:11223344"} self.Check( "ListHuntCrashes", args=hunt_plugin.ApiListHuntCrashesArgs( hunt_id=hunt_obj.urn.Basename()), replace=replace) self.Check( "ListHuntCrashes", args=hunt_plugin.ApiListHuntCrashesArgs( hunt_id=hunt_obj.urn.Basename(), count=1), replace=replace) self.Check( "ListHuntCrashes", args=hunt_plugin.ApiListHuntCrashesArgs( hunt_id=hunt_obj.urn.Basename(), offset=1, count=1), replace=replace)
def SetUpCrashedFlowInHunt(self): client_ids = [rdfvalue.ClientURN("C.%016X" % i) for i in range(0, 10)] client_mocks = dict([(client_id, test_lib.CrashClientMock(client_id, self.token)) for client_id in client_ids]) with hunts.GRRHunt.StartHunt(hunt_name="SampleHunt", regex_rules=[ rdfvalue.ForemanAttributeRegex( attribute_name="GRR client", attribute_regex="GRR") ], client_rate=0, token=self.token) as hunt: hunt.Run() foreman = aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) for client_id in client_ids: foreman.AssignTasksToClient(client_id) test_lib.TestHuntHelperWithMultipleMocks(client_mocks, False, self.token) return client_ids
def Run(self): client_ids = self.SetupClients(1) client_id = client_ids[0] client_mock = test_lib.CrashClientMock(client_id, self.token) with test_lib.FakeTime(42): with self.CreateHunt(description="the hunt") as hunt_obj: hunt_obj.Run() with test_lib.FakeTime(45): self.AssignTasksToClients(client_ids) test_lib.TestHuntHelperWithMultipleMocks({client_id: client_mock}, False, self.token) crashes = aff4_grr.VFSGRRClient.CrashCollectionForCID(client_id, token=self.token) crash = list(crashes)[0] session_id = crash.session_id.Basename() replace = { hunt_obj.urn.Basename(): "H:123456", session_id: "H:11223344" } self.Check("ListClientCrashes", args=client_plugin.ApiListClientCrashesArgs( client_id=client_id.Basename()), replace=replace) self.Check("ListClientCrashes", args=client_plugin.ApiListClientCrashesArgs( client_id=client_id.Basename(), count=1), replace=replace) self.Check("ListClientCrashes", args=client_plugin.ApiListClientCrashesArgs( client_id=client_id.Basename(), offset=1, count=1), replace=replace)
def SetUpCrashedFlow(self): client = test_lib.CrashClientMock(self.client_id, self.token) for _ in test_lib.TestFlowHelper("FlowWithOneClientRequest", client, client_id=self.client_id, token=self.token, check_flow_errors=False): pass
def RecordCrash(self, client_id, timestamp): with test_lib.FakeTime(timestamp): client = test_lib.CrashClientMock(client_id, self.token) for _ in test_lib.TestFlowHelper( test_lib.FlowWithOneClientRequest.__name__, client, client_id=client_id, token=self.token, check_flow_errors=False): pass
def RecordCrash(self, client_id, timestamp): with utils.Stubber(time, "time", timestamp.AsSecondsFromEpoch): client = test_lib.CrashClientMock(client_id, self.token) for _ in test_lib.TestFlowHelper("FlowWithOneClientRequest", client, client_id=client_id, token=self.token, check_flow_errors=False): pass
def SetUpCrashedFlow(self): client = test_lib.CrashClientMock(self.client_id, self.token) for _ in test_lib.TestFlowHelper("ListDirectory", client, client_id=self.client_id, pathspec=rdfvalue.PathSpec( path="/", pathtype=1), token=self.token, check_flow_errors=False): pass
def testListCrashes(self): self.hunt_obj.Run() client_ids = self.SetupClients(2) client_mocks = dict([(client_id, test_lib.CrashClientMock( client_id, self.token)) for client_id in client_ids]) self.AssignTasksToClients(client_ids) test_lib.TestHuntHelperWithMultipleMocks(client_mocks, False, self.token) crashes = list(self.api.Hunt(self.hunt_obj.urn.Basename()).ListCrashes()) self.assertEqual(len(crashes), 2) self.assertEqual( set(x.client.client_id for x in crashes), set(x.Basename() for x in client_ids)) for c in crashes: self.assertEqual(c.crash_message, "Client killed during transaction")
def testClientKilled(self): """Test that client killed messages are handled correctly.""" self.email_message = {} def SendEmail(address, sender, title, message, **_): self.email_message.update( dict(address=address, sender=sender, title=title, message=message)) with test_lib.Stubber(email_alerts, "SendEmail", SendEmail): client = test_lib.CrashClientMock(self.client_id, self.token) for _ in test_lib.TestFlowHelper( "ListDirectory", client, client_id=self.client_id, pathspec=rdfvalue.PathSpec(path="/"), token=self.token, check_flow_errors=False): pass # We expect the email to be sent. self.assertEqual(self.email_message.get("address", ""), config_lib.CONFIG["Monitoring.alert_email"]) self.assertTrue(str(self.client_id) in self.email_message["title"]) # Make sure the flow state is included in the email message. for s in ["Flow name", "ListDirectory", "current_state"]: self.assertTrue(s in self.email_message["message"]) flow_obj = aff4.FACTORY.Open(client.flow_id, age=aff4.ALL_TIMES, token=self.token) self.assertEqual(flow_obj.state.context.state, rdfvalue.Flow.State.ERROR) # Make sure crashes RDFValueCollections are created and written # into proper locations. First check the per-client crashes collection. client_crashes = sorted(list( aff4.FACTORY.Open(self.client_id.Add("crashes"), aff4_type="PackedVersionedCollection", token=self.token)), key=lambda x: x.timestamp) self.assertTrue(len(client_crashes) >= 1) crash = list(client_crashes)[0] self.assertEqual(crash.client_id, self.client_id) self.assertEqual(crash.session_id, flow_obj.session_id) self.assertEqual(crash.client_info.client_name, "GRR Monitor") self.assertEqual(crash.crash_type, "aff4:/flows/W:CrashHandler") self.assertEqual(crash.crash_message, "Client killed during transaction") # Check per-flow crash collection. Check that crash written there is # equal to per-client crash. flow_crashes = sorted(list( flow_obj.GetValuesForAttribute(flow_obj.Schema.CLIENT_CRASH)), key=lambda x: x.timestamp) self.assertEqual(len(flow_crashes), len(client_crashes)) for a, b in zip(flow_crashes, client_crashes): self.assertEqual(a, b) # Check global crash collection. Check that crash written there is # equal to per-client crash. global_crashes = sorted(aff4.FACTORY.Open( aff4.ROOT_URN.Add("crashes"), aff4_type="PackedVersionedCollection", token=self.token), key=lambda x: x.timestamp) self.assertEqual(len(global_crashes), len(client_crashes)) for a, b in zip(global_crashes, client_crashes): self.assertEqual(a, b)