def setUp(self): super(ApiGetHuntFileHandlerTest, self).setUp() self.handler = hunt_plugin.ApiGetHuntFileHandler() self.file_path = os.path.join(self.base_path, "test.plist") self.hunt = hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name=file_finder.FileFinder.__name__), flow_args=file_finder.FileFinderArgs( paths=[self.file_path], action=file_finder.FileFinderAction(action_type="DOWNLOAD"), ), client_rate=0, token=self.token) self.hunt.Run() self.results_urn = self.hunt.state.context.results_collection_urn self.aff4_file_path = rdfvalue.RDFURN("os").Add(self.file_path) self.client_id = self.SetupClients(1)[0] self.AssignTasksToClients(client_ids=[self.client_id]) action_mock = action_mocks.ActionMock("TransferBuffer", "StatFile", "HashFile", "HashBuffer") test_lib.TestHuntHelper(action_mock, [self.client_id], token=self.token)
def testCopyHuntPreservesRuleType(self): with self.ACLChecksDisabled(): hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", description="model hunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.TSK, )), client_rule_set=rdf_foreman.ForemanClientRuleSet(rules=[ rdf_foreman.ForemanClientRule( rule_type=rdf_foreman.ForemanClientRule.Type.OS, os=rdf_foreman.ForemanOsClientRule(os_darwin=True)) ]), token=self.token) self.Open("/#main=ManageHunts") self.Click("css=tr:contains('model hunt')") self.Click("css=button[name=CopyHunt]:not([disabled])") # Wait until dialog appears. self.WaitUntil(self.IsTextPresent, "What to run?") # Click on "Next" button. self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Output Processing") # Click on "Next" button self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Where to run?") self.WaitUntil( self.IsElementPresent, "css=grr-new-hunt-wizard-form " "label:contains('Os darwin') ~ * input:checked")
def CreateSampleHunt(self, path=None, stopped=False, output_plugins=None, client_limit=0, client_count=10, token=None): token = token or self.token self.client_ids = self.SetupClients(client_count) with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs( pathspec=rdf_paths.PathSpec( path=path or "/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS, ) ), regex_rules=[rdf_foreman.ForemanAttributeRegex( attribute_name="GRR client", attribute_regex="GRR")], output_plugins=output_plugins or [], client_rate=0, client_limit=client_limit, token=token) as hunt: if not stopped: hunt.Run() with aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=token) as foreman: for client_id in self.client_ids: foreman.AssignTasksToClient(client_id) self.hunt_urn = hunt.urn return aff4.FACTORY.Open(hunt.urn, mode="rw", token=token, age=aff4.ALL_TIMES)
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 testStoppingHuntMarksAllStartedFlowsAsPendingForTermination(self): with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="InfiniteFlow"), regex_rules=[ rdf_foreman.ForemanAttributeRegex(attribute_name="GRR client", attribute_regex="GRR"), ], client_rate=0, token=self.token) as hunt: hunt.Run() self.AssignTasksToClients() # Run long enough for InfiniteFlows to start. self.RunHunt(iteration_limit=len(self.client_ids) * 2) self.StopHunt(hunt.urn) # All flows should be marked for termination now. RunHunt should raise. # If something is wrong with GRRFlow.MarkForTermination mechanism, then # this will run forever. self.RunHunt() for client_id in self.client_ids: flows_root = aff4.FACTORY.Open(client_id.Add("flows"), token=self.token) flows_list = list(flows_root.ListChildren()) # Only one flow (issued by the hunt) is expected. self.assertEqual(len(flows_list), 1) flow_obj = aff4.FACTORY.Open(flows_list[0], aff4_type="InfiniteFlow", token=self.token) self.assertEqual(flow_obj.state.context.state, "ERROR") self.assertEqual(flow_obj.state.context.backtrace, "Parent hunt stopped.")
def RunFlow(self, flow_name=None, plugins=None, flow_args=None, client_mock=None): runner_args = flow_runner.FlowRunnerArgs(flow_name=flow_name or "GetFile", output_plugins=plugins) if flow_args is None: flow_args = transfer.GetFileArgs( pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS)) if client_mock is None: client_mock = test_lib.SampleHuntMock() flow_urn = flow.GRRFlow.StartFlow(client_id=self.client_id, args=flow_args, runner_args=runner_args, token=self.token) for _ in test_lib.TestFlowHelper(flow_urn, client_mock=client_mock, client_id=self.client_id, token=self.token): pass return flow_urn
def _AppendFlowRequest(self, flows, client_id, file_id): flows.Append( client_ids=["C.1%015d" % client_id], runner_args=flow_runner.FlowRunnerArgs(flow_name="GetFile"), args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil%s.txt" % file_id, pathtype=rdf_paths.PathSpec.PathType.OS), ))
def testCreatorPropagation(self): self.CreateAdminUser("adminuser") admin_token = access_control.ACLToken(username="******", reason="testing") # Start a flow that requires admin privileges in the hunt. The # parameters are not valid so the flow will error out but it's # enough to check if the flow was actually run (i.e., it passed # the label test). with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="UpdateClient"), flow_args=administrative.UpdateClientArgs(), regex_rules=[ rdf_foreman.ForemanAttributeRegex(attribute_name="GRR client", attribute_regex="GRR"), ], client_rate=0, token=admin_token) as hunt: hunt.Run() self.CreateUser("nonadmin") nonadmin_token = access_control.ACLToken(username="******", reason="testing") self.AssignTasksToClients() client_mock = test_lib.SampleHuntMock() test_lib.TestHuntHelper(client_mock, self.client_ids, False, nonadmin_token) errors = list(hunt.GetClientsErrors()) # Make sure there are errors... self.assertTrue(errors) # but they are not UnauthorizedAccess. for e in errors: self.assertTrue("UnauthorizedAccess" not in e.backtrace)
def Run(self): runner_args = flow_runner.FlowRunnerArgs( flow_name=transfer.GetFile.__name__) flow_args = transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS)) client_mock = test_lib.SampleHuntMock() with test_lib.FakeTime(42): flow_urn = flow.GRRFlow.StartFlow(client_id=self.client_id, args=flow_args, runner_args=runner_args, token=self.token) for _ in test_lib.TestFlowHelper(flow_urn, client_mock=client_mock, client_id=self.client_id, token=self.token): pass self.Check("GET", "/api/clients/%s/flows/%s/results" % (self.client_id.Basename(), flow_urn.Basename()), replace={flow_urn.Basename(): "W:ABCDEF"})
def testCopyHuntPreservesRuleType(self): with self.ACLChecksDisabled(): hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", description="model hunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.TSK, )), regex_rules=[ rdf_foreman.ForemanAttributeRegex(attribute_name="System", attribute_regex="Darwin") ], token=self.token) self.Open("/#main=ManageHunts") self.Click("css=tr:contains('model hunt')") self.Click("css=button[name=CopyHunt]:not([disabled])") # Wait until dialog appears. self.WaitUntil(self.IsTextPresent, "What to run?") # Click on "Next" button. self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Output Processing") # Click on "Next" button self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Where to run?") self.WaitUntil(self.IsTextPresent, "This rule will match all OS X systems.")
def Handle(self, args, token=None): client_urn = self.GetClientTarget(args, token=token) size_condition = file_finder.FileFinderCondition( condition_type=file_finder.FileFinderCondition.Type.SIZE, size=file_finder.FileFinderSizeCondition( max_file_size=args.max_file_size)) file_finder_args = file_finder.FileFinderArgs( paths=args.paths, action=file_finder.FileFinderAction(action_type=args.action), conditions=[size_condition]) # Check our flow throttling limits, will raise if there are problems. throttler = throttle.FlowThrottler() throttler.EnforceLimits(client_urn, token.username, file_finder.FileFinder.__name__, file_finder_args, token=token) # Limit the whole flow to 200MB so if a glob matches lots of small files we # still don't have too much impact. runner_args = flow_runner.FlowRunnerArgs( client_id=client_urn, flow_name=file_finder.FileFinder.__name__, network_bytes_limit=200 * 1000 * 1000) flow_id = flow.GRRFlow.StartFlow(runner_args=runner_args, token=token, args=file_finder_args) return ApiStartRobotGetFilesOperationResult( operation_id=utils.SmartUnicode(flow_id))
def Start(self): self.state.Register("hunt_id", None) self.state.Register("client_ids", set()) self.state.Register("client_ids_failures", set()) self.state.Register("client_ids_result_reported", set()) self.state.client_ids = base.GetClientTestTargets(token=self.token) if not self.state.client_ids: self.Log("No clients to test on, define them in " "Test.end_to_end_client_ids") return # SetUID is required to run a hunt on the configured end-to-end client # targets without an approval. token = access_control.ACLToken( username="******", reason="Running endtoend tests.").SetUID() runner_args = flow_runner.FlowRunnerArgs(flow_name="EndToEndTestFlow") flow_request = hunts_standard.FlowRequest( client_ids=self.state.client_ids, args=flows_endtoend.EndToEndTestFlowArgs(), runner_args=runner_args) bogus_rule = rdf_foreman.ForemanRegexClientRule( attribute_name="System", attribute_regex="Does not match anything") client_rule_set = rdf_foreman.ForemanClientRuleSet(rules=[ rdf_foreman.ForemanClientRule( rule_type=rdf_foreman.ForemanClientRule.Type.REGEX, regex=bogus_rule) ]) hunt_args = hunts_standard.VariableGenericHuntArgs( flows=[flow_request]) hunt_args.output_plugins = self.GetOutputPlugins() with hunts.GRRHunt.StartHunt(hunt_name="VariableGenericHunt", args=hunt_args, client_rule_set=client_rule_set, client_rate=0, expiry_time="1d", token=token) as hunt: self.state.hunt_id = hunt.session_id hunt.SetDescription("EndToEnd tests run by cron") hunt.Run() hunt.ManuallyScheduleClients(token=token) # Set a callback to check the results after 50 minutes. This should be # plenty of time for the clients to receive the hunt and run the tests, but # not so long that the flow lease will expire. wait_duration = rdfvalue.Duration( config_lib.CONFIG.Get("Test.end_to_end_result_check_wait")) completed_time = rdfvalue.RDFDatetime().Now() + wait_duration self.CallState(next_state="CheckResults", start_time=completed_time)
def testHuntExpiration(self): """This tests that hunts with a client limit terminate correctly.""" with test_lib.FakeTime(1000): with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS)), regex_rules=[ rdf_foreman.ForemanAttributeRegex( attribute_name="GRR client", attribute_regex="GRR") ], client_limit=5, expiry_time=rdfvalue.Duration("1000s"), token=self.token) as hunt: hunt.Run() # Pretend to be the foreman now and dish out hunting jobs to all the # clients (Note we have 10 clients here). foreman = aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) for client_id in self.client_ids: foreman.AssignTasksToClient(client_id) hunt_obj = aff4.FACTORY.Open(hunt.session_id, age=aff4.ALL_TIMES, token=self.token) self.assertEqual(hunt_obj.Get(hunt_obj.Schema.STATE), "STARTED") # Now advance the time such that the hunt expires. time.time = lambda: 5000 # Run the hunt. client_mock = test_lib.SampleHuntMock() test_lib.TestHuntHelper(client_mock, self.client_ids, check_flow_errors=False, token=self.token) # No client should be processed since the hunt is expired. started, finished, errors = hunt_obj.GetClientsCounts() self.assertEqual(started, 0) self.assertEqual(finished, 0) self.assertEqual(errors, 0) hunt_obj = aff4.FACTORY.Open(hunt.session_id, age=aff4.ALL_TIMES, token=self.token) # Hunts are automatically stopped when they expire. self.assertEqual(hunt_obj.Get(hunt_obj.Schema.STATE), "COMPLETED")
def _CreateHunt(self, token): return hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS)), regex_rules=[ rdf_foreman.ForemanAttributeRegex(attribute_name="GRR client", attribute_regex="GRR"), ], client_rate=0, token=token)
def CreateSampleHunt(description, token=None): return hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", description=description, flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS, )), client_rate=0, token=token)
def _CreateHunt(self, description): output_plugins = [ output_plugin.OutputPluginDescriptor( plugin_name="TestOutputPlugin") ] with hunts.GRRHunt.StartHunt( hunt_name=standard.GenericHunt.__name__, flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), output_plugins=output_plugins, description=description, client_rate=0, token=self.token) as hunt: return hunt
def Start(self): with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="Interrogate"), flow_args=flows_discovery.InterrogateArgs(lightweight=False), regex_rules=[], output_plugins=self.GetOutputPlugins(), token=self.token) as hunt: runner = hunt.GetRunner() runner.args.client_rate = 50 runner.args.expiry_time = "1w" runner.args.description = ("Interrogate run by cron to keep host" "info fresh.") runner.Start()
class TestFileFinderOSHomedir(TestFileFinderOSLinux): """List files in homedir with FileFinder. Exercise globbing and interpolation. """ platforms = ["Linux", "Darwin", "Windows"] test_output_path = "/analysis/test/homedirs" action = file_finder.FileFinderAction( action_type=file_finder.FileFinderAction.Action.STAT) args = {"paths": ["%%users.homedir%%/*"], "action": action, "runner_args": flow_runner.FlowRunnerArgs(output=test_output_path)} def CheckFlow(self): results = aff4.FACTORY.Open( self.client_id.Add(self.test_output_path), token=self.token) self.assertEqual(type(results), aff4.RDFValueCollection) self.assertTrue(len(results) > 1)
def Layout(self, request, response): """Render the form for creating the flow args.""" self.flow_name = self._GetFlowName(request) self.flow_cls = flow.GRRFlow.classes.get(self.flow_name) if aff4.issubclass(self.flow_cls, flow.GRRFlow): self.flow_found = True self.form = forms.SemanticProtoFormRenderer( self.flow_cls.GetDefaultArgs(token=request.token), prefix="args").RawHTML(request) self.runner_form = forms.SemanticProtoFormRenderer( flow_runner.FlowRunnerArgs(flow_name=self.flow_name), prefix="runner").RawHTML(request) response = super(SemanticProtoFlowForm, self).Layout(request, response) return self.CallJavascript(response, "SemanticProtoFlowForm.Layout", renderer=self.__class__.__name__)
def RenderAjax(self, request, response): """Parse the flow args from the form and launch the flow.""" self.flow_name = self._GetFlowName(request) self.client_id = request.REQ.get("client_id", None) self.dom_node = request.REQ.get("dom_node") flow_cls = flow.GRRFlow.classes.get(self.flow_name) if flow_cls is not None: self.args = forms.SemanticProtoFormRenderer( flow_cls.args_type(), prefix="args").ParseArgs(request) try: self.args.Validate() except ValueError as e: return self.CallJavascript( response, "SemanticProtoFlowForm.RenderAjaxError", error=str(e)) self.runner_args = forms.SemanticProtoFormRenderer( flow_runner.FlowRunnerArgs(), prefix="runner_").ParseArgs(request) self.runner_args.Validate() self.flow_id = flow.GRRFlow.StartFlow(client_id=self.client_id, flow_name=self.flow_name, token=request.token, args=self.args, runner_args=self.runner_args) self.args_html = semantic.FindRendererForObject( self.args).RawHTML(request) self.runner_args_html = semantic.FindRendererForObject( self.runner_args).RawHTML(request) response = renderers.TemplateRenderer.Layout( self, request, response, apply_template=self.ajax_template) return self.CallJavascript(response, "SemanticProtoFlowForm.RenderAjax", renderer=self.__class__.__name__, dom_node=self.dom_node)
def testHuntCollectionLogging(self): """This tests running the hunt on some clients.""" with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="DummyLogFlow"), client_rate=0, token=self.token) as hunt: hunt.Run() hunt.Log("Log from the hunt itself") hunt_urn = hunt.urn self.AssignTasksToClients() self.RunHunt() # Check logs were written to the hunt collection with aff4.FACTORY.Open(hunt_urn.Add("Logs"), token=self.token, age=aff4.ALL_TIMES) as hunt_logs: # Can't use len with PackedVersionCollection count = 0 for log in hunt_logs: if log.client_id: self.assertTrue(log.client_id in self.client_ids) self.assertTrue(log.log_message in [ "First", "Second", "Third", "Fourth", "Uno", "Dos", "Tres", "Cuatro" ]) self.assertTrue( log.flow_name in ["DummyLogFlow", "DummyLogFlowChild"]) self.assertTrue(str(hunt_urn) in str(log.urn)) else: self.assertEqual(log.log_message, "Log from the hunt itself") self.assertEqual(log.flow_name, "GenericHunt") self.assertEqual(log.urn, hunt_urn) count += 1 # 4 logs for each flow, 2 flow run. One hunt-level log. self.assertEqual(count, 8 * len(self.client_ids) + 1)
def Render(self, args, token=None): client_urn = self.GetClientTarget(args, token=token) size_condition = file_finder.FileFinderCondition( condition_type=file_finder.FileFinderCondition.Type.SIZE, size=file_finder.FileFinderSizeCondition( max_file_size=args.max_file_size)) file_finder_args = file_finder.FileFinderArgs( paths=args.paths, action=file_finder.FileFinderAction(action_type=args.action), conditions=[size_condition]) # Check our flow throttling limits, will raise if there are problems. throttler = throttle.FlowThrottler() throttler.EnforceLimits(client_urn, token.username, "FileFinder", file_finder_args, token=token) # Limit the whole flow to 200MB so if a glob matches lots of small files we # still don't have too much impact. runner_args = flow_runner.FlowRunnerArgs(client_id=client_urn, flow_name="FileFinder", network_bytes_limit=200 * 1000 * 1000) flow_id = flow.GRRFlow.StartFlow(runner_args=runner_args, token=token, args=file_finder_args) # Provide a url where the caller can check on the flow status. status_url = urlparse.urljoin( config_lib.CONFIG["AdminUI.url"], "/api/flows/%s/%s/status" % (client_urn.Basename(), flow_id.Basename())) return dict( flow_id=api_value_renderers.RenderValue(flow_id), flow_args=api_value_renderers.RenderValue(file_finder_args), runner_args=api_value_renderers.RenderValue(runner_args), status_url=status_url)
def ParseFlowArgs(self): """Parse the flow and flow_runner args.""" if self.flow_runner_args is not None: return self.flow_runner_args, self.flow_args flow_path = self.request.REQ.get("flow_path", "") flow_name = os.path.basename(flow_path) if not flow_name: raise ValueError("No flow specified. Please select a flow.") flow_cls = flow.GRRFlow.GetPlugin(flow_name) self.flow_args = forms.SemanticProtoFormRenderer( flow_cls.args_type(), prefix="args").ParseArgs(self.request) self.flow_runner_args = forms.SemanticProtoFormRenderer( flow_runner.FlowRunnerArgs(), prefix="runner").ParseArgs(self.request) self.flow_runner_args.flow_name = flow_name return self.flow_runner_args, self.flow_args
def CreateSampleHunt(description, token=None): hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", description=description, flow_runner_args=flow_runner.FlowRunnerArgs(flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.TSK, )), regex_rules=[ rdf_foreman.ForemanAttributeRegex(attribute_name="GRR client", attribute_regex="GRR") ], output_plugins=[ output_plugin.OutputPluginDescriptor( plugin_name="DummyOutputPlugin", plugin_args=DummyOutputPlugin.args_type( filename_regex="blah!", fetch_binaries=True)) ], client_rate=60, token=token)
def setUp(self): super(ApiGetHuntFilesArchiveHandlerTest, self).setUp() self.handler = hunt_plugin.ApiGetHuntFilesArchiveHandler() self.hunt = hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name=file_finder.FileFinder.__name__), flow_args=file_finder.FileFinderArgs( paths=[os.path.join(self.base_path, "test.plist")], action=file_finder.FileFinderAction(action_type="DOWNLOAD"), ), client_rate=0, token=self.token) self.hunt.Run() client_ids = self.SetupClients(10) self.AssignTasksToClients(client_ids=client_ids) action_mock = action_mocks.ActionMock("TransferBuffer", "StatFile", "HashFile", "HashBuffer") test_lib.TestHuntHelper(action_mock, client_ids, token=self.token)
def testResourceUsageStats(self): client_ids = self.SetupClients(10) with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS, )), regex_rules=[ rdf_foreman.ForemanAttributeRegex( attribute_name="GRR client", attribute_regex="GRR") ], output_plugins=[], client_rate=0, token=self.token) as hunt: hunt.Run() with aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) as foreman: for client_id in client_ids: foreman.AssignTasksToClient(client_id) client_mock = test_lib.SampleHuntMock() test_lib.TestHuntHelper(client_mock, client_ids, False, self.token) hunt = aff4.FACTORY.Open(hunt.urn, aff4_type="GenericHunt", token=self.token) # This is called once for each state method. Each flow above runs the # Start and the StoreResults methods. usage_stats = hunt.state.context.usage_stats self.assertEqual(usage_stats.user_cpu_stats.num, 10) self.assertTrue( math.fabs(usage_stats.user_cpu_stats.mean - 5.5) < 1e-7) self.assertTrue( math.fabs(usage_stats.user_cpu_stats.std - 2.8722813) < 1e-7) self.assertEqual(usage_stats.system_cpu_stats.num, 10) self.assertTrue( math.fabs(usage_stats.system_cpu_stats.mean - 11) < 1e-7) self.assertTrue( math.fabs(usage_stats.system_cpu_stats.std - 5.7445626) < 1e-7) self.assertEqual(usage_stats.network_bytes_sent_stats.num, 10) self.assertTrue( math.fabs(usage_stats.network_bytes_sent_stats.mean - 16.5) < 1e-7) self.assertTrue( math.fabs(usage_stats.network_bytes_sent_stats.std - 8.61684396) < 1e-7) # NOTE: Not checking histograms here. RunningStatsTest tests that mean, # standard deviation and histograms are calculated correctly. Therefore # if mean/stdev values are correct histograms should be ok as well. self.assertEqual(len(usage_stats.worst_performers), 10) prev = usage_stats.worst_performers[0] for p in usage_stats.worst_performers[1:]: self.assertTrue( prev.cpu_usage.user_cpu_time + prev.cpu_usage.system_cpu_time > p.cpu_usage.user_cpu_time + p.cpu_usage.system_cpu_time) prev = p
def testHuntModificationWorksCorrectly(self): """This tests running the hunt on some clients.""" with hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name="GetFile"), flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec( path="/tmp/evil.txt", pathtype=rdf_paths.PathSpec.PathType.OS), ), regex_rules=[ rdf_foreman.ForemanAttributeRegex( attribute_name="GRR client", attribute_regex="GRR") ], client_limit=1, client_rate=0, token=self.token) as hunt: hunt.Run() # Forget about hunt object, we'll use AFF4 for everything. hunt_session_id = hunt.session_id hunt = None # Pretend to be the foreman now and dish out hunting jobs to all the # client.. with aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) as foreman: for client_id in self.client_ids: foreman.AssignTasksToClient(client_id) # Run the hunt. client_mock = test_lib.SampleHuntMock() test_lib.TestHuntHelper(client_mock, self.client_ids, False, self.token) # Re-open the hunt to get fresh data. hunt_obj = aff4.FACTORY.Open(hunt_session_id, age=aff4.ALL_TIMES, ignore_cache=True, token=self.token) # There should be only one client, due to the limit started, _, _ = hunt_obj.GetClientsCounts() self.assertEqual(started, 1) # Check the hunt is paused. self.assertEqual(hunt_obj.Get(hunt_obj.Schema.STATE), "PAUSED") with aff4.FACTORY.Open(hunt_session_id, mode="rw", token=self.token) as hunt_obj: runner = hunt_obj.GetRunner() runner.args.client_limit = 10 runner.Start() # Pretend to be the foreman now and dish out hunting jobs to all the # clients. with aff4.FACTORY.Open("aff4:/foreman", mode="rw", token=self.token) as foreman: for client_id in self.client_ids: foreman.AssignTasksToClient(client_id) test_lib.TestHuntHelper(client_mock, self.client_ids, False, self.token) hunt_obj = aff4.FACTORY.Open(hunt_session_id, age=aff4.ALL_TIMES, token=self.token) # There should be only one client, due to the limit started, _, _ = hunt_obj.GetClientsCounts() self.assertEqual(started, 10)
def testCopyHuntHandlesLiteralExpressionCorrectly(self): """Literals are raw bytes. Testing that raw bytes are processed right.""" literal_match = file_finder.FileFinderContentsLiteralMatchCondition( literal="foo\x0d\xc8bar") with self.ACLChecksDisabled(): hunts.GRRHunt.StartHunt( hunt_name="GenericHunt", description="model hunt", flow_runner_args=flow_runner.FlowRunnerArgs( flow_name=file_finder.FileFinder.__name__), flow_args=file_finder.FileFinderArgs(conditions=[ file_finder.FileFinderCondition( condition_type="CONTENTS_LITERAL_MATCH", contents_literal_match=literal_match) ], paths=["/tmp/evil.txt"]), token=self.token) self.Open("/#main=ManageHunts") self.Click("css=tr:contains('model hunt')") self.Click("css=button[name=CopyHunt]:not([disabled])") # Wait until dialog appears. self.WaitUntil(self.IsTextPresent, "What to run?") # Check that non-default values of sample hunt are prefilled. self.WaitUntilEqual( "foo\\x0d\\xc8bar", self.GetValue, "css=grr-new-hunt-wizard-form " "label:contains('Literal') ~ * input:text") # Click on "Next" button. self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Output Processing") # Click on "Next" button self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Where to run?") # Click on "Next" button self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Review") # Check that the arguments summary is present. self.WaitUntil(self.IsTextPresent, file_finder.FileFinder.__name__) self.WaitUntil(self.IsTextPresent, "foo\\x0d\\xc8bar") # Click on "Run" button self.Click("css=grr-new-hunt-wizard-form button.Next") self.WaitUntil(self.IsTextPresent, "Created Hunt") # Close the window and check that the hunt was created. self.Click("css=button.Next") hunts_root = aff4.FACTORY.Open("aff4:/hunts", token=self.token) hunts_list = sorted(list(hunts_root.ListChildren()), key=lambda x: x.age) self.assertEqual(len(hunts_list), 2) last_hunt = aff4.FACTORY.Open(hunts_list[-1], token=self.token) # Check that the hunt was created with a correct literal value. self.assertEqual(last_hunt.state.args.flow_runner_args.flow_name, file_finder.FileFinder.__name__) self.assertEqual( last_hunt.state.args.flow_args.conditions[0]. contents_literal_match.literal, "foo\x0d\xc8bar")