Beispiel #1
0
    def _CreateHuntFromHunt(self):
        flow_args = rdf_file_finder.FileFinderArgs(
            paths=["a/*", "b/*"],
            action=rdf_file_finder.FileFinderAction(action_type="STAT"))
        flow_runner_args = rdf_flow_runner.FlowRunnerArgs(
            flow_name=file_finder.FileFinder.__name__)
        client_rule_set = self._CreateForemanClientRuleSet()
        source_h = self.CreateHunt(flow_args=flow_args,
                                   flow_runner_args=flow_runner_args,
                                   description="foo-description",
                                   client_rule_set=client_rule_set)

        ref = rdf_hunts.FlowLikeObjectReference.FromHuntId(
            source_h.urn.Basename())

        # Modify flow_args so that there are differences.
        flow_args.paths = ["b/*", "c/*"]
        client_rule_set.rules[0].regex.field = "FQDN"
        output_plugins = [
            output_plugin.OutputPluginDescriptor(
                plugin_name="TestOutputPlugin")
        ]
        new_h = self.CreateHunt(flow_args=flow_args,
                                flow_runner_args=flow_runner_args,
                                description="bar-description",
                                client_rule_set=client_rule_set,
                                output_plugins=output_plugins,
                                original_object=ref)

        return new_h, source_h
Beispiel #2
0
    def _CreateHuntFromFlow(self):
        self.client_id = self.SetupClient(0)

        flow_args = rdf_file_finder.FileFinderArgs(
            paths=["a/*", "b/*"],
            action=rdf_file_finder.FileFinderAction(action_type="STAT"))
        flow_runner_args = rdf_flow_runner.FlowRunnerArgs(
            flow_name=file_finder.FileFinder.__name__)
        flow_urn = flow.GRRFlow.StartFlow(client_id=self.client_id,
                                          args=flow_args,
                                          runner_args=flow_runner_args,
                                          token=self.token)

        ref = rdf_hunts.FlowLikeObjectReference.FromFlowIdAndClientId(
            flow_urn.Basename(), self.client_id.Basename())
        # Modify flow_args so that there are differences.
        flow_args.paths = ["b/*", "c/*"]
        flow_args.action.action_type = "DOWNLOAD"
        flow_args.conditions = [
            rdf_file_finder.FileFinderCondition(
                condition_type="SIZE",
                size=rdf_file_finder.FileFinderSizeCondition(min_file_size=42))
        ]
        return self.CreateHunt(flow_args=flow_args,
                               flow_runner_args=flow_runner_args,
                               original_object=ref), flow_urn
Beispiel #3
0
    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 = implementation.GRRHunt.StartHunt(
            hunt_name=standard.GenericHunt.__name__,
            flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                flow_name=file_finder.FileFinder.__name__),
            flow_args=rdf_file_finder.FileFinderArgs(
                paths=[self.file_path],
                action=rdf_file_finder.FileFinderAction(
                    action_type="DOWNLOAD"),
            ),
            client_rate=0,
            token=self.token)
        self.hunt.Run()

        self.aff4_file_path = "fs/os/%s" % self.file_path

        self.client_id = self.SetupClient(0)
        self.AssignTasksToClients(client_ids=[self.client_id])
        action_mock = action_mocks.FileFinderClientMock()
        hunt_test_lib.TestHuntHelper(action_mock, [self.client_id],
                                     token=self.token)
Beispiel #4
0
    def testAlertEmailIsSentWhenClientKilledDuringHunt(self):
        """Test that client killed messages are handled correctly for hunts."""
        client_id = test_lib.TEST_CLIENT_ID
        self.email_messages = []

        def SendEmail(address, sender, title, message, **_):
            self.email_messages.append(
                dict(address=address,
                     sender=sender,
                     title=title,
                     message=message))

        with hunts_implementation.GRRHunt.StartHunt(
                hunt_name=hunts_standard.GenericHunt.__name__,
                flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                    flow_name=flow_test_lib.FlowWithOneClientRequest.__name__),
                client_rate=0,
                crash_alert_email="*****@*****.**",
                token=self.token) as hunt:
            hunt.Run()
            hunt.StartClients(hunt.session_id, client_id)

        with utils.Stubber(email_alerts.EMAIL_ALERTER, "SendEmail", SendEmail):
            client = flow_test_lib.CrashClientMock(client_id, self.token)
            hunt_test_lib.TestHuntHelper(client, [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.CONFIG["Monitoring.alert_email"]])
Beispiel #5
0
  def Run(self):
    runner_args = rdf_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 = hunt_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)

      flow_test_lib.TestFlowHelper(
          flow_urn,
          client_mock=client_mock,
          client_id=self.client_id,
          token=self.token)

    self.Check(
        "ListFlowResults",
        args=flow_plugin.ApiListFlowResultsArgs(
            client_id=self.client_id.Basename(), flow_id=flow_urn.Basename()),
        replace={flow_urn.Basename(): "W:ABCDEF"})
Beispiel #6
0
    def testOverviewIsShownForNestedHuntFlows(self):
        with implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                    flow_name=gui_test_lib.RecursiveTestFlow.__name__),
                client_rate=0,
                token=self.token) as hunt:
            hunt.Run()

        self.AssignTasksToClients(client_ids=[self.client_id])
        self.RunHunt(client_ids=[self.client_id])

        self.Open("/#/clients/%s" % self.client_id)
        self.Click("css=a[grrtarget='client.flows']")

        # There should be a RecursiveTestFlow in the list. Expand nested flows.
        self.Click("css=tr:contains('RecursiveTestFlow') span.tree_branch")
        # Click on a nested flow.
        self.Click("css=tr:contains('RecursiveTestFlow'):nth(2)")

        # Nested flow should have Depth argument set to 1.
        self.WaitUntil(self.IsElementPresent,
                       "css=td:contains('Depth') ~ td:nth(0):contains('1')")

        # Check that flow id of this flow has forward slash - i.e. consists of
        # 2 components.
        self.WaitUntil(self.IsTextPresent, "Flow ID")
        flow_id = self.GetText("css=dt:contains('Flow ID') ~ dd:nth(0)")
        self.assertTrue("/" in flow_id)
Beispiel #7
0
 def testBaseSessionIdFlowRunnerArgumentIsNotRespected(self):
     args = cron_plugin.ApiCronJob(
         flow_name=standard.CreateAndRunGenericHuntFlow.__name__,
         flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
             base_session_id="aff4:/foo"))
     result = self.handler.Handle(args, token=self.token)
     self.assertFalse(result.flow_runner_args.HasField("base_session_id"))
Beispiel #8
0
    def RunFlow(self,
                flow_name=None,
                plugins=None,
                flow_args=None,
                client_mock=None):
        runner_args = rdf_flow_runner.FlowRunnerArgs(
            flow_name=flow_name or transfer.GetFile.__name__,
            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 = hunt_test_lib.SampleHuntMock()

        flow_urn = flow.GRRFlow.StartFlow(client_id=self.client_id,
                                          args=flow_args,
                                          runner_args=runner_args,
                                          token=self.token)

        flow_test_lib.TestFlowHelper(flow_urn,
                                     client_mock=client_mock,
                                     client_id=self.client_id,
                                     token=self.token)

        return flow_urn
Beispiel #9
0
  def CreateHunt(self,
                 flow_runner_args=None,
                 flow_args=None,
                 client_rule_set=None,
                 original_object=None,
                 token=None,
                 **kwargs):
    # Only initialize default flow_args value if default flow_runner_args value
    # is to be used.
    if not flow_runner_args:
      flow_args = (
          flow_args or transfer.GetFileArgs(
              pathspec=rdf_paths.PathSpec(
                  path="/tmp/evil.txt",
                  pathtype=rdf_paths.PathSpec.PathType.OS)))

    flow_runner_args = (
        flow_runner_args or
        rdf_flow_runner.FlowRunnerArgs(flow_name=transfer.GetFile.__name__))

    client_rule_set = (client_rule_set or self._CreateForemanClientRuleSet())
    return implementation.GRRHunt.StartHunt(
        hunt_name=standard.GenericHunt.__name__,
        flow_runner_args=flow_runner_args,
        flow_args=flow_args,
        client_rule_set=client_rule_set,
        client_rate=0,
        original_object=original_object,
        token=token or self.token,
        **kwargs)
Beispiel #10
0
    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 implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                    flow_name=transfer.GetFile.__name__),
                flow_args=transfer.GetFileArgs(pathspec=rdf_paths.PathSpec(
                    path=path or "/tmp/evil.txt",
                    pathtype=rdf_paths.PathSpec.PathType.OS,
                )),
                client_rule_set=self._CreateForemanClientRuleSet(),
                output_plugins=output_plugins or [],
                client_rate=0,
                client_limit=client_limit,
                token=token) as hunt:
            if not stopped:
                hunt.Run()

        foreman_obj = foreman.GetForeman(token=token)
        for client_id in self.client_ids:
            foreman_obj.AssignTasksToClient(client_id.Basename())

        self.hunt_urn = hunt.urn
        return aff4.FACTORY.Open(hunt.urn,
                                 mode="rw",
                                 token=token,
                                 age=aff4.ALL_TIMES)
Beispiel #11
0
    def testRunnerArgsBaseSessionIdDoesNotAffectCreatedFlow(self):
        """When multiple clients match, check we run on the latest one."""
        flow_runner_args = rdf_flow_runner.FlowRunnerArgs(
            base_session_id="aff4:/foo")
        args = flow_plugin.ApiCreateFlowArgs(
            client_id=self.client_id.Basename(),
            flow=flow_plugin.ApiFlow(name=processes.ListProcesses.__name__,
                                     runner_args=flow_runner_args))

        result = self.handler.Handle(args, token=self.token)
        self.assertFalse(utils.SmartStr(result.urn).startswith("aff4:/foo"))
Beispiel #12
0
    def _StartHunt(self):
        with implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                    flow_name=flow_test_lib.FlowWithOneNestedFlow.__name__),
                client_rate=0,
                token=self.token) as hunt:
            hunt.Run()

        self.AssignTasksToClients(client_ids=[self.client_urn])
        self.RunHunt(client_ids=[self.client_urn])
Beispiel #13
0
 def _CreateHunt(self, description):
     output_plugins = [
         output_plugin.OutputPluginDescriptor(
             plugin_name="TestOutputPlugin")
     ]
     with implementation.GRRHunt.StartHunt(
             hunt_name=standard.GenericHunt.__name__,
             flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                 flow_name=transfer.GetFile.__name__),
             output_plugins=output_plugins,
             description=description,
             client_rate=0,
             token=self.token) as hunt:
         return hunt
Beispiel #14
0
    def InitializeContext(self, args):
        """Initializes the context of this flow."""
        if args is None:
            args = rdf_flow_runner.FlowRunnerArgs()

        output_plugins_states = []
        for plugin_descriptor in args.output_plugins:
            if not args.client_id:
                self.Log(
                    "Not initializing output plugin %s as flow does not run on "
                    "the client.", plugin_descriptor.plugin_name)
                continue

            output_base_urn = self.session_id.Add(OUTPUT_PLUGIN_BASE_SUFFIX)
            plugin_class = plugin_descriptor.GetPluginClass()
            plugin = plugin_class(self.flow_obj.output_urn,
                                  args=plugin_descriptor.plugin_args,
                                  output_base_urn=output_base_urn,
                                  token=self.token)
            try:
                plugin.InitializeState()
                # TODO(amoser): Those do not need to be inside the state, they
                # could be part of the plugin descriptor.
                plugin.state["logs"] = []
                plugin.state["errors"] = []

                output_plugins_states.append(
                    rdf_flow_runner.OutputPluginState(
                        plugin_state=plugin.state,
                        plugin_descriptor=plugin_descriptor))
            except Exception as e:  # pylint: disable=broad-except
                logging.info(
                    "Plugin %s failed to initialize (%s), ignoring it.",
                    plugin, e)

        parent_creator = None
        if self.parent_runner:
            parent_creator = self.parent_runner.context.creator

        context = rdf_flow_runner.FlowContext(
            create_time=rdfvalue.RDFDatetime.Now(),
            creator=parent_creator or self.token.username,
            current_state="Start",
            output_plugins_states=output_plugins_states,
            state=rdf_flow_runner.FlowContext.State.RUNNING,
        )

        return context
Beispiel #15
0
  def Start(self):
    with hunts_implementation.GRRHunt.StartHunt(
        hunt_name=hunts_standard.GenericHunt.__name__,
        client_limit=0,
        flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
            flow_name=flows_discovery.Interrogate.__name__),
        flow_args=flows_discovery.InterrogateArgs(lightweight=False),
        output_plugins=self.GetOutputPlugins(),
        token=self.token) as hunt:

      runner = hunt.GetRunner()
      runner.runner_args.crash_limit = 500
      runner.runner_args.client_rate = 50
      runner.runner_args.expiry_time = "1w"
      runner.runner_args.description = ("Interrogate run by cron to keep host"
                                        "info fresh.")
      runner.Start()
Beispiel #16
0
 def CreateSampleHunt(self, description, token=None):
     implementation.GRRHunt.StartHunt(
         hunt_name=standard.GenericHunt.__name__,
         description=description,
         flow_runner_args=rdf_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.TSK,
         )),
         client_rule_set=self._CreateForemanClientRuleSet(),
         output_plugins=[
             output_plugin.OutputPluginDescriptor(
                 plugin_name="DummyOutputPlugin",
                 plugin_args=gui_test_lib.DummyOutputPlugin.args_type(
                     filename_regex="blah!", fetch_binaries=True))
         ],
         client_rate=60,
         token=token)
Beispiel #17
0
    def setUp(self):
        super(ApiGetExportedHuntResultsHandlerTest, self).setUp()

        self.handler = hunt_plugin.ApiGetExportedHuntResultsHandler()

        self.hunt = implementation.GRRHunt.StartHunt(
            hunt_name=standard.GenericHunt.__name__,
            flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
                flow_name=flow_test_lib.DummyFlowWithSingleReply.__name__),
            client_rate=0,
            token=self.token)
        self.hunt.Run()

        self.client_ids = self.SetupClients(5)
        # Ensure that clients are processed sequentially - this way the test won't
        # depend on the order of results in the collection (which is normally
        # random).
        for cid in self.client_ids:
            self.AssignTasksToClients(client_ids=[cid])
            client_mock = hunt_test_lib.SampleHuntMock()
            hunt_test_lib.TestHuntHelper(client_mock, [cid], token=self.token)
Beispiel #18
0
  def testCopyHuntPreservesRuleType(self):
    implementation.GRRHunt.StartHunt(
        hunt_name=standard.GenericHunt.__name__,
        description="model hunt",
        flow_runner_args=rdf_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.TSK,
            )),
        client_rule_set=foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.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.IsElementPresent,
                   "css=grr-wizard-form:contains('What to run?')")
    # Click on "Next" button
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Hunt parameters')")
    # Click on "Next" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('How to process results')")
    # Click on "Next" button
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Where to run?')")
    self.WaitUntil(
        self.IsElementPresent, "css=grr-new-hunt-wizard-form "
        "label:contains('Os darwin') ~ * input:checked")
Beispiel #19
0
  def Run(self):

    def ReplaceFlowId():
      flows_dir_fd = aff4.FACTORY.Open(
          self.client_id.Add("flows"), token=self.token)
      flow_urn = list(flows_dir_fd.ListChildren())[0]
      return {flow_urn.Basename(): "W:ABCDEF"}

    with test_lib.FakeTime(42):
      self.Check(
          "CreateFlow",
          args=flow_plugin.ApiCreateFlowArgs(
              client_id=self.client_id.Basename(),
              flow=flow_plugin.ApiFlow(
                  name=processes.ListProcesses.__name__,
                  args=processes.ListProcessesArgs(
                      filename_regex=".", fetch_binaries=True),
                  runner_args=rdf_flow_runner.FlowRunnerArgs(
                      output_plugins=[],
                      priority="HIGH_PRIORITY",
                      notify_to_user=False))),
          replace=ReplaceFlowId)
Beispiel #20
0
    def testGetPluginArgsHandlesMissingPluginsCorrectly(self):
        descriptor = output_plugin.OutputPluginDescriptor(
            plugin_name="TestOutputPluginWithArgs",
            plugin_args=rdf_flow_runner.FlowRunnerArgs(
                flow_name=transfer.GetFile.__name__))
        serialized = descriptor.SerializeToString()

        deserialized = output_plugin.OutputPluginDescriptor()
        deserialized.ParseFromString(serialized)
        self.assertEqual(deserialized, descriptor)
        self.assertEqual(deserialized.GetPluginClass(),
                         TestOutputPluginWithArgs)

        with utils.Stubber(output_plugin.OutputPlugin, "classes", {}):
            deserialized = output_plugin.OutputPluginDescriptor()
            deserialized.ParseFromString(serialized)

            self.assertTrue(deserialized.GetPluginClass(),
                            output_plugin.UnknownOutputPlugin)
            # UnknownOutputPlugin should just return serialized arguments as bytes.
            self.assertEqual(deserialized.plugin_args,
                             descriptor.plugin_args.SerializeToString())
Beispiel #21
0
    def StartFlow(cls,
                  args=None,
                  runner_args=None,
                  parent_flow=None,
                  sync=True,
                  token=None,
                  **kwargs):
        """The main factory function for Creating and executing a new flow.

    Args:

      args: An arg protocol buffer which is an instance of the required flow's
        args_type class attribute.

      runner_args: an instance of FlowRunnerArgs() protocol buffer which is used
        to initialize the runner for this flow.

      parent_flow: A parent flow or None if this is a top level flow.

      sync: If True, the Start method of this flow will be called
         inline. Otherwise we schedule the starting of this flow on another
         worker.

      token: Security credentials token identifying the user.

      **kwargs: If args or runner_args are not specified, we construct these
        protobufs from these keywords.

    Returns:
      the session id of the flow.

    Raises:
      RuntimeError: Unknown or invalid parameters were provided.
    """
        # Build the runner args from the keywords.
        if runner_args is None:
            runner_args = rdf_flow_runner.FlowRunnerArgs()

        cls.FilterArgsFromSemanticProtobuf(runner_args, kwargs)

        # When asked to run a flow in the future this implied it will run
        # asynchronously.
        if runner_args.start_time:
            sync = False

        # Is the required flow a known flow?
        try:
            flow_cls = registry.FlowRegistry.FlowClassByName(
                runner_args.flow_name)
        except ValueError:
            stats.STATS.IncrementCounter("grr_flow_invalid_flow_count")
            raise RuntimeError("Unable to locate flow %s" %
                               runner_args.flow_name)

        # If no token is specified, raise.
        if not token:
            raise access_control.UnauthorizedAccess(
                "A token must be specified.")

        # For the flow itself we use a supervisor token.
        token = token.SetUID()

        # Extend the expiry time of this token indefinitely. Python on Windows only
        # supports dates up to the year 3000.
        token.expiry = rdfvalue.RDFDatetime.FromHumanReadable("2997-01-01")

        if flow_cls.category and not runner_args.client_id:
            raise RuntimeError(
                "Flow with category (user-visible flow) has to be "
                "started on a client, but runner_args.client_id "
                "is missing.")

        # We create an anonymous AFF4 object first, The runner will then generate
        # the appropriate URN.
        flow_obj = aff4.FACTORY.Create(None, flow_cls, token=token)

        # Now parse the flow args into the new object from the keywords.
        if args is None:
            args = flow_obj.args_type()

        cls.FilterArgsFromSemanticProtobuf(args, kwargs)

        # Check that the flow args are valid.
        args.Validate()

        # Store the flow args.
        flow_obj.args = args
        flow_obj.runner_args = runner_args

        # At this point we should exhaust all the keyword args. If any are left
        # over, we do not know what to do with them so raise.
        if kwargs:
            raise type_info.UnknownArg("Unknown parameters to StartFlow: %s" %
                                       kwargs)

        # Create a flow runner to run this flow with.
        if parent_flow:
            parent_runner = parent_flow.runner
        else:
            parent_runner = None

        runner = flow_obj.CreateRunner(parent_runner=parent_runner,
                                       runner_args=runner_args)

        logging.info(u"Scheduling %s(%s) on %s", flow_obj.urn,
                     runner_args.flow_name, runner_args.client_id)

        if sync:
            # Just run the first state inline. NOTE: Running synchronously means
            # that this runs on the thread that starts the flow. The advantage is
            # that that Start method can raise any errors immediately.
            flow_obj.Start()
        else:
            # Running Asynchronously: Schedule the start method on another worker.
            runner.CallState(next_state="Start",
                             start_time=runner_args.start_time)

        # The flow does not need to actually remain running.
        if not runner.OutstandingRequests():
            flow_obj.Terminate()

        flow_obj.Close()

        # Publish an audit event, only for top level flows.
        if parent_flow is None:
            events.Events.PublishEvent("Audit",
                                       rdf_events.AuditEvent(
                                           user=token.username,
                                           action="RUN_FLOW",
                                           flow_name=runner_args.flow_name,
                                           urn=flow_obj.urn,
                                           client=runner_args.client_id),
                                       token=token)

        return flow_obj.urn
Beispiel #22
0
    def testCPULimitForHunts(self):
        worker_obj = worker_lib.GRRWorker(token=self.token)

        client_ids = ["C.%016X" % i for i in xrange(10, 20)]
        result = {}
        client_mocks = []
        for client_id in client_ids:
            client_mock = action_mocks.CPULimitClientMock(result)
            client_mock = flow_test_lib.MockClient(
                rdf_client.ClientURN(client_id), client_mock, token=self.token)

            client_mock.EnableResourceUsage(user_cpu_usage=[10],
                                            system_cpu_usage=[10],
                                            network_usage=[1000])
            client_mocks.append(client_mock)

        flow_runner_args = rdf_flow_runner.FlowRunnerArgs(
            flow_name=flow_test_lib.CPULimitFlow.__name__)
        with implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=flow_runner_args,
                cpu_limit=5000,
                per_client_cpu_limit=10000,
                network_bytes_limit=1000000,
                client_rate=0,
                token=self.token) as hunt:
            hunt.GetRunner().Start()

        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[:1])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[1:2])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[2:3])
        self._Process(client_mocks, worker_obj)

        # The limiting factor here is the overall hunt limit of 5000 cpu
        # seconds. Clients that finish should decrease the remaining quota
        # and the following clients should get the reduced quota.
        self.assertEqual(result["cpulimit"], [
            5000.0, 4980.0, 4960.0, 4940.0, 4920.0, 4900.0, 4880.0, 4860.0,
            4840.0
        ])
        self.assertEqual(result["networklimit"], [
            1000000L, 999000L, 998000L, 997000L, 996000L, 995000L, 994000L,
            993000L, 992000L
        ])

        result.clear()

        with implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=flow_runner_args,
                per_client_cpu_limit=3000,
                per_client_network_limit_bytes=3000000,
                client_rate=0,
                token=self.token) as hunt:
            hunt.GetRunner().Start()

        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[:1])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[1:2])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[2:3])
        self._Process(client_mocks, worker_obj)

        # This time, the per client limit is 3000s / 3000000 bytes. Every
        # client should get the same limit.
        self.assertEqual(result["cpulimit"], [
            3000.0, 2980.0, 2960.0, 3000.0, 2980.0, 2960.0, 3000.0, 2980.0,
            2960.0
        ])
        self.assertEqual(result["networklimit"], [
            3000000, 2999000, 2998000, 3000000, 2999000, 2998000, 3000000,
            2999000, 2998000
        ])
        result.clear()

        for client_mock in client_mocks:
            client_mock.EnableResourceUsage(user_cpu_usage=[500],
                                            system_cpu_usage=[500],
                                            network_usage=[1000000])

        with implementation.GRRHunt.StartHunt(
                hunt_name=standard.GenericHunt.__name__,
                flow_runner_args=flow_runner_args,
                per_client_cpu_limit=3000,
                cpu_limit=5000,
                per_client_network_limit_bytes=3000000,
                network_bytes_limit=5000000,
                client_rate=0,
                token=self.token) as hunt:
            hunt.GetRunner().Start()

        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[:1])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[1:2])
        self._Process(client_mocks, worker_obj)
        implementation.GRRHunt.StartClients(hunt.session_id, client_ids[2:3])
        self._Process(client_mocks, worker_obj)

        # The first client gets the full per client limit of 3000s, and
        # uses all of it. The hunt has a limit of just 5000 total so the
        # second client gets started with a limit of 2000. It can only run
        # two of three states, the last client will not be started at all
        # due to out of quota.
        self.assertEqual(result["cpulimit"],
                         [3000.0, 2000.0, 1000.0, 2000.0, 1000.0])
        self.assertEqual(result["networklimit"],
                         [3000000, 2000000, 1000000, 2000000, 1000000])

        errors = list(hunt.GetClientsErrors())
        self.assertEqual(len(errors), 2)
        # Client side out of cpu.
        self.assertIn("CPU limit exceeded", errors[0].log_message)
        # Server side out of cpu.
        self.assertIn("Out of CPU quota", errors[1].backtrace)
Beispiel #23
0
  def testCopyHuntHandlesLiteralExpressionCorrectly(self):
    """Literals are raw bytes. Testing that raw bytes are processed right."""
    literal_match = rdf_file_finder.FileFinderContentsLiteralMatchCondition(
        literal="foo\x0d\xc8bar")

    implementation.GRRHunt.StartHunt(
        hunt_name=standard.GenericHunt.__name__,
        description="model hunt",
        flow_runner_args=rdf_flow_runner.FlowRunnerArgs(
            flow_name=file_finder.FileFinder.__name__),
        flow_args=rdf_file_finder.FileFinderArgs(
            conditions=[
                rdf_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.IsElementPresent,
                   "css=grr-wizard-form:contains('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.IsElementPresent,
                   "css=grr-wizard-form:contains('Hunt parameters')")
    # Click on "Next" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('How to process results')")
    # Click on "Next" button
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Where to run?')")
    # Click on "Next" button
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Review')")

    # Check that the arguments summary is present.
    self.WaitUntil(
        self.IsElementPresent,
        "css=grr-wizard-form:contains('%s')" % 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.IsElementPresent,
                   "css=grr-wizard-form:contains('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.args.flow_runner_args.flow_name,
                     file_finder.FileFinder.__name__)
    self.assertEqual(
        last_hunt.args.flow_args.conditions[0].contents_literal_match.literal,
        "foo\x0d\xc8bar")