Exemple #1
0
    def testUserChangesToCopiedFlowAreRespected(self):
        args = flows_processes.ListProcessesArgs(filename_regex="test[a-z]*",
                                                 fetch_binaries=True)
        flow.StartAFF4Flow(flow_name=flows_processes.ListProcesses.__name__,
                           args=args,
                           client_id=self.client_id,
                           output_plugins=[self.email_descriptor],
                           token=self.token)

        # Navigate to client and select newly created flow.
        self.Open("/#/clients/C.0000000000000001/flows")
        self.Click("css=td:contains('ListProcesses')")

        # Open wizard and change the arguments.
        self.Click("css=button[name=copy_flow]")

        self.Type("css=label:contains('Filename Regex') ~ * input",
                  "somethingElse*")

        self.Click(
            "css=label:contains('Fetch Binaries') ~ * input[type=checkbox]")

        # Change output plugin and add another one.
        self.Click("css=label:contains('Output Plugins') ~ * button")
        self.Select(
            "css=grr-output-plugin-descriptor-form "
            "label:contains('Plugin') ~ * select:eq(0)", "DummyOutputPlugin")
        self.Type(
            "css=grr-output-plugin-descriptor-form "
            "label:contains('Filename Regex'):eq(0) ~ * input:text", "foobar!")

        self.Click("css=button:contains('Launch')")

        # Check that flows list got updated and that the new flow is selected.
        self.WaitUntil(
            self.IsElementPresent,
            "css=grr-client-flows-list tr:contains('ListProcesses'):nth(1)")
        self.WaitUntil(
            self.IsElementPresent, "css=grr-client-flows-list "
            "tr:contains('ListProcesses'):nth(0).row-selected")

        # Now open the last flow and check that it has the changes we made.
        fd = aff4.FACTORY.Open(self.client_id.Add("flows"), token=self.token)
        flows = sorted(fd.ListChildren(), key=lambda x: x.age)
        fobj = aff4.FACTORY.Open(flows[-1], token=self.token)

        self.assertEqual(
            fobj.args,
            flows_processes.ListProcessesArgs(
                filename_regex="somethingElse*", ))
        self.assertListEqual(list(fobj.runner_args.output_plugins), [
            rdf_output_plugin.OutputPluginDescriptor(
                plugin_name=gui_test_lib.DummyOutputPlugin.__name__,
                plugin_args=flows_processes.ListProcessesArgs(
                    filename_regex="foobar!")), self.email_descriptor
        ])
Exemple #2
0
    def testCopyingFlowUpdatesFlowListAndSelectsNewFlow(self):
        args = flows_processes.ListProcessesArgs(filename_regex="test[a-z]*",
                                                 fetch_binaries=True)
        flow.StartAFF4Flow(flow_name=flows_processes.ListProcesses.__name__,
                           args=args,
                           client_id=self.client_id,
                           token=self.token)

        # Navigate to client and select newly created flow.
        self.Open("/#/clients/C.0000000000000001/flows")
        self.Click("css=td:contains('ListProcesses')")

        # Check that there's only one ListProcesses flow.
        self.WaitUntilNot(
            self.IsElementPresent,
            "css=grr-client-flows-list tr:contains('ListProcesses'):nth(1)")

        # Open wizard and check if flow arguments are copied.
        self.Click("css=button[name=copy_flow]")
        self.Click("css=button:contains('Launch'):not([disabled])")

        # Check that flows list got updated and that the new flow is selected.
        self.WaitUntil(
            self.IsElementPresent,
            "css=grr-client-flows-list tr:contains('ListProcesses'):nth(1)")
        self.WaitUntil(
            self.IsElementPresent, "css=grr-client-flows-list "
            "tr:contains('ListProcesses'):nth(0).row-selected")
Exemple #3
0
    def testOriginalFlowArgsAreShownInCopyForm(self):
        args = flows_processes.ListProcessesArgs(filename_regex="test[a-z]*",
                                                 fetch_binaries=True)
        flow.StartAFF4Flow(flow_name=flows_processes.ListProcesses.__name__,
                           args=args,
                           client_id=self.client_id,
                           output_plugins=[self.email_descriptor],
                           token=self.token)

        # Navigate to client and select newly created flow.
        self.Open("/#/clients/C.0000000000000001/flows")
        self.Click("css=td:contains('ListProcesses')")

        # Open wizard and check if flow arguments are copied.
        self.Click("css=button[name=copy_flow]")

        self.WaitUntil(self.IsTextPresent, "Copy ListProcesses flow")

        self.WaitUntilEqual("test[a-z]*", self.GetValue,
                            "css=label:contains('Filename Regex') ~ * input")

        self.WaitUntil(
            self.IsChecked, "css=label:contains('Fetch Binaries') "
            "~ * input[type=checkbox]")

        # Check that output plugin info is also copied.
        self.WaitUntilEqual("string:EmailOutputPlugin", self.GetValue,
                            "css=label:contains('Plugin') ~ * select")
        self.WaitUntilEqual("test@localhost", self.GetValue,
                            "css=label:contains('Email address') ~ * input")
        self.WaitUntilEqual("42", self.GetValue,
                            "css=label:contains('Emails limit') ~ * input")
Exemple #4
0
    def testCreateFlowFromClientRef(self):
        client_urn = self.SetupClient(0)
        args = processes.ListProcessesArgs(filename_regex="blah",
                                           fetch_binaries=True)

        if data_store.RelationalDBFlowsEnabled():
            flows = data_store.REL_DB.ReadAllFlowObjects(client_urn.Basename())
            self.assertEmpty(flows)
        else:
            children = aff4.FACTORY.Open(client_urn,
                                         token=self.token).ListChildren()
            self.assertEmpty(list(children))

        client_ref = self.api.Client(client_id=client_urn.Basename())
        result_flow = client_ref.CreateFlow(
            name=processes.ListProcesses.__name__,
            args=args.AsPrimitiveProto())

        if data_store.RelationalDBFlowsEnabled():
            flows = data_store.REL_DB.ReadAllFlowObjects(client_urn.Basename())
            self.assertLen(flows, 1)
            self.assertEqual(flows[0].args, args)
        else:
            children = aff4.FACTORY.Open(client_urn,
                                         token=self.token).ListChildren()
            self.assertLen(list(children), 1)
            result_flow_obj = aff4.FACTORY.Open(result_flow.data.urn,
                                                token=self.token)
            self.assertEqual(result_flow_obj.args, args)
Exemple #5
0
    def Run(self):
        client_urn = self.SetupClient(0)
        client_id = client_urn.Basename()

        def ReplaceFlowId():
            if data_store.RelationalDBFlowsEnabled():
                flows = data_store.REL_DB.ReadAllFlowObjects(
                    client_id=client_id)
                self.assertNotEmpty(flows)
                flow_id = flows[0].flow_id
            else:
                flows_dir_fd = aff4.FACTORY.Open(client_urn.Add("flows"),
                                                 token=self.token)
                flow_id = list(flows_dir_fd.ListChildren())[0].Basename()

            return api_regression_test_lib.GetFlowTestReplaceDict(
                client_id, flow_id)

        with test_lib.FakeTime(42):
            self.Check("CreateFlow",
                       args=flow_plugin.ApiCreateFlowArgs(
                           client_id=client_id,
                           flow=flow_plugin.ApiFlow(
                               name=processes.ListProcesses.__name__,
                               args=processes.ListProcessesArgs(
                                   filename_regex=".", fetch_binaries=True),
                               runner_args=rdf_flow_runner.FlowRunnerArgs(
                                   output_plugins=[], notify_to_user=True))),
                       replace=ReplaceFlowId)
Exemple #6
0
  def testPidFiltering(self):
    client_id = self.SetupClient(0)

    proc_foo = rdf_client.Process()
    proc_foo.pid = 42
    proc_foo.exe = "/usr/bin/foo"

    proc_bar = rdf_client.Process()
    proc_bar.pid = 108
    proc_bar.exe = "/usr/bin/bar"

    proc_baz = rdf_client.Process()
    proc_baz.pid = 1337
    proc_baz.exe = "/usr/bin/baz"

    args = flow_processes.ListProcessesArgs()
    args.pids = [42, 1337]

    client_mock = action_mocks.ListProcessesMock([proc_foo, proc_bar, proc_baz])
    flow_id = flow_test_lib.StartAndRunFlow(
        flow_processes.ListProcesses,
        client_mock=client_mock,
        client_id=client_id,
        flow_args=args,
    )

    results = flow_test_lib.GetFlowResults(client_id=client_id, flow_id=flow_id)
    self.assertLen(results, 2)

    result_exes = {result.exe for result in results}
    self.assertIn("/usr/bin/foo", result_exes)
    self.assertIn("/usr/bin/baz", result_exes)
    self.assertNotIn("/usr/bin/bar", result_exes)
Exemple #7
0
  def testPostMethodWorks(self):
    client_id = self.SetupClient(0)
    args = processes.ListProcessesArgs(
        filename_regex="blah", fetch_binaries=True)

    client_ref = self.api.Client(client_id=client_id)
    result_flow = client_ref.CreateFlow(
        name=processes.ListProcesses.__name__, args=args.AsPrimitiveProto())
    self.assertTrue(result_flow.client_id)
  def testHuntIsStoppedIfAveragePerClientResultsCountTooHigh(self):
    with utils.Stubber(implementation.GRRHunt,
                       "MIN_CLIENTS_FOR_AVERAGE_THRESHOLDS", 4):

      flow_args = processes.ListProcessesArgs()
      flow_runner_args = rdf_flow_runner.FlowRunnerArgs(
          flow_name=processes.ListProcesses.__name__)

      hunt_urn = self.StartHunt(
          flow_args=flow_args,
          flow_runner_args=flow_runner_args,
          avg_results_per_client_limit=1,
          token=self.token)

      def RunOnClients(client_ids, num_processes):
        client_mock = action_mocks.ListProcessesMock(
            [rdf_client.Process(pid=1, exe="a.exe")] * num_processes)
        self.AssignTasksToClients(client_ids)
        hunt_test_lib.TestHuntHelper(
            client_mock, client_ids, check_flow_errors=False, token=self.token)

      def CheckState(expected_state, expected_results_count):
        hunt_obj = aff4.FACTORY.Open(hunt_urn, token=self.token)
        self.assertEqual(hunt_obj.Get(hunt_obj.Schema.STATE), expected_state)
        self.assertEqual(hunt_obj.context.results_count, expected_results_count)

      RunOnClients(self.client_ids[:2], 1)
      # Hunt should still be running: we got 1 response from 2 clients. We need
      # at least 3 clients to start calculating the average.
      CheckState("STARTED", 2)

      RunOnClients([self.client_ids[2]], 2)
      # Hunt should still be running: we got 1 response for first 2 clients and
      # 2 responses for the third. This is over the limit but we need at least 4
      # clients to start applying thresholds.
      CheckState("STARTED", 4)

      RunOnClients([self.client_ids[3]], 0)
      # Hunt should still be running: we got 1 response for first 2 clients,
      # 2 responses for the third and zero for the 4th. This makes it 1 result
      # per client on average. This is within the limit of 1.
      CheckState("STARTED", 4)

      RunOnClients(self.client_ids[4:5], 2)
      # Hunt should be terminated: 5 clients did run and we got 6 results.
      # That's more than the allowed average of 1.
      # Note that this check also implicitly checks that the 6th client didn't
      # run at all (otherwise total number of results would be 8, not 6).
      CheckState("STOPPED", 6)

      self._CheckHuntStoppedNotification(
          "reached the average results per client")
Exemple #9
0
  def testCreateFlowWithUnicodeArguments(self):
    unicode_str = "🐊 🐢 🦎 🐍"

    client_id = self.SetupClient(0)
    args = processes.ListProcessesArgs(
        filename_regex=unicode_str, fetch_binaries=True)

    client_ref = self.api.Client(client_id=client_id)
    result_flow = client_ref.CreateFlow(
        name=processes.ListProcesses.__name__, args=args.AsPrimitiveProto())

    got_flow = client_ref.Flow(flow_id=result_flow.flow_id).Get()
    self.assertEqual(got_flow.args.filename_regex, unicode_str)
Exemple #10
0
  def testApprovalIndicatesThatHuntWasCopiedFromFlow(self):
    email_descriptor = rdf_output_plugin.OutputPluginDescriptor(
        plugin_name=compatibility.GetName(email_plugin.EmailOutputPlugin),
        plugin_args=email_plugin.EmailOutputPluginArgs(
            email_address="test@localhost", emails_limit=42))

    args = flows_processes.ListProcessesArgs(
        filename_regex="test[a-z]*", fetch_binaries=True)

    flow_test_lib.StartFlow(
        flows_processes.ListProcesses,
        flow_args=args,
        client_id=self.client_id,
        output_plugins=[email_descriptor])

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

    # Open the wizard.
    self.Click("css=button[name=create_hunt]")

    # Go to the hunt parameters page.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    # Go to the output plugins page.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    # Go to the rules page.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    # Go to the review page.
    self.Click("css=grr-new-hunt-wizard-form button.Next")

    # Create the hunt.
    self.Click("css=button:contains('Create Hunt')")
    self.Click("css=button:contains('Done')")

    # Request an approval.
    hunts = data_store.REL_DB.ListHuntObjects(offset=0, count=1)
    h = hunts[0]
    approval_id = self.RequestHuntApproval(
        h.hunt_id,
        requestor=self.token.username,
        reason="reason",
        approver=self.token.username)

    # Open the approval page.
    self.Open("/#/users/%s/approvals/hunt/%s/%s" %
              (self.token.username, h.hunt_id, approval_id))
    self.WaitUntil(self.IsElementPresent,
                   "css=div.panel-body:contains('This hunt was created from')")
Exemple #11
0
  def testCreateFlowFromClientRef(self):
    client_id = self.SetupClient(0)
    args = processes.ListProcessesArgs(
        filename_regex="blah", fetch_binaries=True)

    flows = data_store.REL_DB.ReadAllFlowObjects(client_id)
    self.assertEmpty(flows)

    client_ref = self.api.Client(client_id=client_id)
    client_ref.CreateFlow(
        name=processes.ListProcesses.__name__, args=args.AsPrimitiveProto())

    flows = data_store.REL_DB.ReadAllFlowObjects(client_id)
    self.assertLen(flows, 1)
    self.assertEqual(flows[0].args, args)
Exemple #12
0
  def testCreateFlowFromClientObject(self):
    client_urn = self.SetupClient(0)
    args = processes.ListProcessesArgs(
        filename_regex="blah", fetch_binaries=True)

    children = aff4.FACTORY.Open(client_urn, token=self.token).ListChildren()
    self.assertEmpty(list(children))

    client = self.api.Client(client_id=client_urn.Basename()).Get()
    result_flow = client.CreateFlow(
        name=processes.ListProcesses.__name__, args=args.AsPrimitiveProto())

    children = aff4.FACTORY.Open(client_urn, token=self.token).ListChildren()
    self.assertLen(list(children), 1)
    result_flow_obj = aff4.FACTORY.Open(result_flow.data.urn, token=self.token)
    self.assertEqual(result_flow_obj.args, args)
Exemple #13
0
  def testAddingOutputPluginToCopiedFlowWorks(self):
    args = flows_processes.ListProcessesArgs(
        filename_regex="test[a-z]*", fetch_binaries=True)
    flow_test_lib.StartFlow(
        flows_processes.ListProcesses, flow_args=args, client_id=self.client_id)

    # Navigate to client and select newly created flow.
    self.Open("/#/clients/C.0000000000000001/flows")
    self.Click("css=td:contains('ListProcesses')")

    # Open wizard and check if flow arguments are copied.
    self.Click("css=button[name=copy_flow]")

    self.Click("css=label:contains('Output Plugins') ~ * button")
    self.WaitUntil(self.IsElementPresent,
                   "css=label:contains('Plugin') ~ * select")
    def Run(self):
        client_id = self.SetupClient(0)

        def ReplaceFlowId():
            flows_dir_fd = aff4.FACTORY.Open(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=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=[], notify_to_user=False))),
                       replace=ReplaceFlowId)
  def Run(self):
    client_id = self.SetupClient(0)

    def ReplaceFlowId():
      flows = data_store.REL_DB.ReadAllFlowObjects(client_id=client_id)
      self.assertNotEmpty(flows)
      flow_id = flows[0].flow_id

      return api_regression_test_lib.GetFlowTestReplaceDict(client_id, flow_id)

    with test_lib.FakeTime(42):
      self.Check(
          "CreateFlow",
          args=flow_plugin.ApiCreateFlowArgs(
              client_id=client_id,
              flow=flow_plugin.ApiFlow(
                  name=processes.ListProcesses.__name__,
                  args=processes.ListProcessesArgs(
                      filename_regex=".", fetch_binaries=True),
                  runner_args=rdf_flow_runner.FlowRunnerArgs(
                      output_plugins=[], notify_to_user=True))),
          replace=ReplaceFlowId)
Exemple #16
0
  def testCreateHuntFromFlow(self):
    email_descriptor = rdf_output_plugin.OutputPluginDescriptor(
        plugin_name=compatibility.GetName(email_plugin.EmailOutputPlugin),
        plugin_args=email_plugin.EmailOutputPluginArgs(
            email_address="test@localhost", emails_limit=42))

    args = flows_processes.ListProcessesArgs(
        filename_regex="test[a-z]*", fetch_binaries=True)

    flow_test_lib.StartFlow(
        flows_processes.ListProcesses,
        flow_args=args,
        client_id=self.client_id,
        output_plugins=[email_descriptor])

    # Navigate to client and select newly created flow.
    self.Open("/#/clients/%s" % self.client_id)
    self.Click("css=a[grrtarget='client.flows']")
    self.Click("css=td:contains('ListProcesses')")

    # Open wizard and check if flow arguments are copied.
    self.Click("css=button[name=create_hunt]")

    self.WaitUntilEqual("test[a-z]*", self.GetValue,
                        "css=label:contains('Filepath Regex') ~ * input")

    self.WaitUntil(
        self.IsChecked, "css=label:contains('Fetch Binaries') "
        "~ * input[type=checkbox]")

    # Go to output plugins page and check that we did not copy the output
    # plugins.
    self.Click("css=button:contains('Next')")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Hunt parameters')")
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('How to process results')")

    self.WaitUntilNot(self.IsElementPresent,
                      "css=grr-output-plugin-descriptor-form")

    # Nothing else to check, so finish the hunt.
    # 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.Click("css=button:contains('Next')")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-wizard-form:contains('Review')")
    self.Click("css=button:contains('Create Hunt')")
    self.Click("css=button:contains('Done')")

    # Check that we get redirected to ManageHunts.
    self.WaitUntilEqual(1, self.GetCssCount,
                        "css=grr-hunts-list table tbody tr")
    self.WaitUntilEqual(1, self.GetCssCount,
                        "css=grr-hunts-list table tbody tr.row-selected")
    self.WaitUntil(self.IsTextPresent, "GenericHunt")
    self.WaitUntil(self.IsTextPresent,
                   compatibility.GetName(flows_processes.ListProcesses))