Пример #1
0
    def testOverridesFlowArgsThroughIfOverridesSpecified(self):
        override_flow_args = rdf_file_finder.FileFinderArgs(paths=["bar"])
        h = rr.ApiRobotCreateFlowHandler(robot_id="foo",
                                         override_flow_args=override_flow_args)

        args = api_flow.ApiCreateFlowArgs(client_id=self.client_id.Basename())
        args.flow.name = file_finder.FileFinder.__name__
        args.flow.args = rdf_file_finder.FileFinderArgs(paths=["foo"])

        f = h.Handle(args=args, token=self.token)
        self.assertEqual(f.args.paths, ["bar"])
Пример #2
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
Пример #3
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.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
Пример #4
0
 def Check(path):
     router.CreateFlow(api_flow.ApiCreateFlowArgs(
         flow=api_flow.ApiFlow(
             name=file_finder.FileFinder.__name__,
             args=rdf_file_finder.FileFinderArgs(paths=[path])),
         client_id=self.client_id),
                       token=self.token)
Пример #5
0
    def testFileFinderThrottlingByFlowCountWorks(self):
        self.InitRouterConfig(
            self.__class__.FILE_FINDER_THROTTLED_ROUTER_CONFIG %
            self.token.username)

        args = []
        for p in ["tests.plist", "numbers.txt", "numbers.txt.ver2"]:
            args.append(
                rdf_file_finder.FileFinderArgs(
                    action=rdf_file_finder.FileFinderAction(
                        action_type="STAT"),
                    paths=[p]).AsPrimitiveProto())

        client_ref = self.api.Client(client_id=self.client_id.Basename())

        flow_obj = client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                         args=args[0])
        self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

        flow_obj = client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                         args=args[1])
        self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

        with self.assertRaisesRegexp(RuntimeError, "2 flows run since"):
            client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                  args=args[2])
Пример #6
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.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)
Пример #7
0
  def testCopyingFlowWithRawBytesWithNonAsciiCharsInArgumentsWorks(self):
    # Literal is defined simply as "bytes" in its proto definition. We make sure
    # to assign ascii-incompatible value to it here.
    condition = rdf_file_finder.FileFinderCondition.ContentsLiteralMatch(
        literal="zażółć gęślą jaźń")
    action = rdf_file_finder.FileFinderAction.Download()
    args = rdf_file_finder.FileFinderArgs(
        action=action, conditions=[condition], paths=["a/b/*"])

    flow.GRRFlow.StartFlow(
        flow_name=flows_file_finder.FileFinder.__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('FileFinder')")

    # Open wizard and launch the copy flow.
    self.Click("css=button[name=copy_flow]")
    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('FileFinder'):nth(1)")
    self.WaitUntil(
        self.IsElementPresent, "css=grr-client-flows-list "
        "tr:contains('FileFinder'):nth(0).row-selected")
Пример #8
0
  def testCopyACLErrorIsCorrectlyDisplayed(self):
    args = rdf_file_finder.FileFinderArgs(paths=["a/b/*"])
    flow.GRRFlow.StartFlow(
        flow_name=flows_file_finder.FileFinder.__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('FileFinder')")

    # Stub out the API handler to guarantee failure.
    with mock.patch.object(
        api_call_router_with_approval_checks.ApiCallRouterWithApprovalChecks,
        "CreateFlow") as create_flow_mock:
      # The error has to be an ACL error, since ACL errors are not handled
      # by the global errors handler and are not automatically displayed.
      create_flow_mock.side_effect = [
          access_control.UnauthorizedAccess("oh no!")
      ]

      # Open wizard and launch the copy flow.
      self.Click("css=button[name=copy_flow]")
      self.Click("css=button:contains('Launch')")

    self.WaitUntil(self.IsElementPresent,
                   "css=.modal-dialog .text-danger:contains('oh no!')")

    # Check that closing the dialog doesn't change flow selection.
    self.Click("css=button[name=Close]")
    self.WaitUntil(self.IsElementPresent,
                   "css=grr-client-flows-view tr.row-selected")
Пример #9
0
 def Check(path):
     with self.assertRaises(access_control.UnauthorizedAccess):
         router.CreateFlow(api_flow.ApiCreateFlowArgs(
             flow=api_flow.ApiFlow(
                 name=file_finder.FileFinder.__name__,
                 args=rdf_file_finder.FileFinderArgs(paths=[path])),
             client_id=self.client_id),
                           token=self.token)
Пример #10
0
 def _RunFileFinder(self,
                    paths,
                    action,
                    conditions=None,
                    follow_links=True,
                    **kw):
     return self.RunAction(client_file_finder.FileFinderOS,
                           arg=rdf_file_finder.FileFinderArgs(
                               paths=paths,
                               action=action,
                               conditions=conditions,
                               process_non_regular_files=True,
                               follow_links=follow_links,
                               **kw))
Пример #11
0
    def testNoThrottlingDoneByDefault(self):
        self.InitRouterConfig(self.__class__.FILE_FINDER_ROUTER_CONFIG %
                              self.token.username)

        args = rdf_file_finder.FileFinderArgs(
            action=rdf_file_finder.FileFinderAction(action_type="STAT"),
            paths=["tests.plist"]).AsPrimitiveProto()

        client_ref = self.api.Client(client_id=self.client_id.Basename())

        # Create 60 flows in a row to check that no throttling is applied.
        for _ in range(20):
            flow_obj = client_ref.CreateFlow(
                name=file_finder.FileFinder.__name__, args=args)
            self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)
Пример #12
0
    def testDownloadActionSkip(self):
        action = rdf_file_finder.FileFinderAction.Download(
            max_size=0, oversized_file_policy="SKIP")
        args = rdf_file_finder.FileFinderArgs(
            action=action,
            paths=[os.path.join(self.base_path, "hello.exe")],
            process_non_regular_files=True)

        transfer_store = MockTransferStore()
        executor = ClientActionExecutor()
        executor.RegisterWellKnownFlow(transfer_store)
        results = executor.Execute(client_file_finder.FileFinderOS, args)

        self.assertEqual(len(transfer_store.blobs), 0)
        self.assertEqual(len(results), 1)
        self.assertFalse(results[0].HasField("transferred_file"))
        self.assertTrue(results[0].HasField("stat_entry"))
Пример #13
0
    def testDownloadActionDefault(self):
        action = rdf_file_finder.FileFinderAction.Download()
        args = rdf_file_finder.FileFinderArgs(
            action=action,
            paths=[os.path.join(self.base_path, "hello.exe")],
            process_non_regular_files=True)

        transfer_store = MockTransferStore()
        executor = ClientActionExecutor()
        executor.RegisterWellKnownFlow(transfer_store)
        results = executor.Execute(client_file_finder.FileFinderOS, args)

        self.assertEqual(len(results), 1)
        with open(os.path.join(self.base_path, "hello.exe"), "rb") as filedesc:
            actual = transfer_store.Retrieve(results[0].transferred_file)
            expected = filedesc.read()
            self.assertEqual(actual, expected)
Пример #14
0
    def testFileFinderMaxFileSizeOverrideWorks(self):
        self.InitRouterConfig(
            self.__class__.FILE_FINDER_MAX_SIZE_OVERRIDE_CONFIG %
            self.token.username)

        args = rdf_file_finder.FileFinderArgs(
            action=rdf_file_finder.FileFinderAction(action_type="DOWNLOAD"),
            paths=["tests.plist"]).AsPrimitiveProto()

        client_ref = self.api.Client(client_id=self.client_id.Basename())

        flow_obj = client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                         args=args)
        flow_args = self.api.types.UnpackAny(flow_obj.data.args)
        self.assertEqual(flow_args.action.download.max_size, 5000000)
        self.assertEqual(flow_args.action.download.oversized_file_policy,
                         flow_args.action.download.SKIP)
Пример #15
0
    def testFileFinderThrottlingByDuplicateIntervalWorks(self):
        self.InitRouterConfig(
            self.__class__.FILE_FINDER_THROTTLED_ROUTER_CONFIG %
            self.token.username)

        args = rdf_file_finder.FileFinderArgs(
            action=rdf_file_finder.FileFinderAction(action_type="STAT"),
            paths=["tests.plist"]).AsPrimitiveProto()

        client_ref = self.api.Client(client_id=self.client_id.Basename())

        flow_obj = client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                         args=args)
        self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

        flow_obj_2 = client_ref.CreateFlow(
            name=file_finder.FileFinder.__name__, args=args)
        self.assertEqual(flow_obj.flow_id, flow_obj_2.flow_id)
Пример #16
0
    def testFileFinderHashMaxFileSizeCanBeOverriden(self):
        router = self._CreateRouter(
            file_finder_flow=rr.RobotRouterFileFinderFlowParams(
                enabled=True, max_file_size=42))

        ha = rdf_file_finder.FileFinderHashActionOptions()
        ha.max_size = 80
        ha.oversized_file_policy = ha.OversizedFilePolicy.HASH_TRUNCATED

        path = "/foo/bar"
        handler = router.CreateFlow(api_flow.ApiCreateFlowArgs(
            flow=api_flow.ApiFlow(name=file_finder.FileFinder.__name__,
                                  args=rdf_file_finder.FileFinderArgs(
                                      paths=[path],
                                      action=rdf_file_finder.FileFinderAction(
                                          action_type="HASH", hash=ha))),
            client_id=self.client_id),
                                    token=self.token)

        ha = handler.override_flow_args.action.hash
        self.assertEqual(ha.oversized_file_policy, ha.OversizedFilePolicy.SKIP)
        self.assertEqual(ha.max_size, 42)
Пример #17
0
    def testFileFinderDownloadMaxFileSizeCanBeOverriden(self):
        router = self._CreateRouter(
            file_finder_flow=rr.RobotRouterFileFinderFlowParams(
                enabled=True, max_file_size=42))

        da = rdf_file_finder.FileFinderDownloadActionOptions()
        da.max_size = 80
        da.oversized_file_policy = da.OversizedFilePolicy.DOWNLOAD_TRUNCATED

        path = "/foo/bar"
        handler = router.CreateFlow(api_flow.ApiCreateFlowArgs(
            flow=api_flow.ApiFlow(name=file_finder.FileFinder.__name__,
                                  args=rdf_file_finder.FileFinderArgs(
                                      paths=[path],
                                      action=rdf_file_finder.FileFinderAction(
                                          action_type="DOWNLOAD",
                                          download=da))),
            client_id=self.client_id),
                                    token=self.token)

        da = handler.override_flow_args.action.download
        self.assertEqual(da.oversized_file_policy, da.OversizedFilePolicy.SKIP)
        self.assertEqual(da.max_size, 42)
Пример #18
0
    def Run(self):
        def ReplaceCronJobUrn():
            jobs = list(cronjobs.GetCronManager().ListJobs(token=self.token))
            return {jobs[0]: "CreateAndRunGeneicHuntFlow_1234"}

        flow_args = standard.CreateGenericHuntFlowArgs()
        flow_args.hunt_args.flow_args = rdf_file_finder.FileFinderArgs(
            paths=["c:\\windows\\system32\\notepad.*"])
        flow_args.hunt_args.flow_runner_args.flow_name = (
            file_finder.FileFinder.__name__)
        flow_args.hunt_runner_args.client_rule_set.rules = [
            foreman_rules.ForemanClientRule(
                os=foreman_rules.ForemanOsClientRule(os_windows=True))
        ]
        flow_args.hunt_runner_args.description = "Foobar! (cron)"

        self.Check("CreateCronJob",
                   args=cron_plugin.ApiCronJob(
                       description="Foobar!",
                       flow_name=standard.CreateAndRunGenericHuntFlow.__name__,
                       periodicity=604800,
                       lifetime=3600,
                       flow_args=flow_args),
                   replace=ReplaceCronJobUrn)
Пример #19
0
    def testFlowDuplicateLimit(self):
        # Disable the request limit checking by setting it to 0.
        throttler = throttle.FlowThrottler(
            daily_req_limit=0, dup_interval=rdfvalue.Duration("1200s"))

        # Running the same flow immediately should fail
        with test_lib.FakeTime(self.BASE_TIME):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    flow_test_lib.DummyLogFlow.__name__,
                                    None,
                                    token=self.token)

            flow.StartFlow(client_id=self.client_id,
                           flow_name=flow_test_lib.DummyLogFlow.__name__,
                           token=self.token)

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        flow_test_lib.DummyLogFlow.__name__,
                                        None,
                                        token=self.token)

        # Doing the same outside the window should work
        with test_lib.FakeTime(self.BASE_TIME + 1200 + 1):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    flow_test_lib.DummyLogFlow.__name__,
                                    None,
                                    token=self.token)

            flow.StartFlow(client_id=self.client_id,
                           flow_name=flow_test_lib.DummyLogFlow.__name__,
                           token=self.token)

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        flow_test_lib.DummyLogFlow.__name__,
                                        None,
                                        token=self.token)

        # Now try a flow with more complicated args
        args = rdf_file_finder.FileFinderArgs(
            paths=["/tmp/1", "/tmp/2"],
            action=rdf_file_finder.FileFinderAction(action_type="STAT"))

        with test_lib.FakeTime(self.BASE_TIME):
            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    file_finder.FileFinder.__name__,
                                    args,
                                    token=self.token)

            flow.StartFlow(
                client_id=self.client_id,
                flow_name=file_finder.FileFinder.__name__,
                token=self.token,
                paths=["/tmp/1", "/tmp/2"],
                action=rdf_file_finder.FileFinderAction(action_type="STAT"))

            with self.assertRaises(throttle.ErrorFlowDuplicate):
                throttler.EnforceLimits(self.client_id,
                                        self.token.username,
                                        file_finder.FileFinder.__name__,
                                        args,
                                        token=self.token)

            # Different args should succeed.
            args = rdf_file_finder.FileFinderArgs(
                paths=["/tmp/1", "/tmp/3"],
                action=rdf_file_finder.FileFinderAction(action_type="STAT"))

            throttler.EnforceLimits(self.client_id,
                                    self.token.username,
                                    file_finder.FileFinder.__name__,
                                    args,
                                    token=self.token)
Пример #20
0
    def testFileFinderWorkflowWorks(self):
        self.InitRouterConfig(self.__class__.FILE_FINDER_ROUTER_CONFIG %
                              self.token.username)

        client_ref = self.api.Client(client_id=self.client_id.Basename())

        args = rdf_file_finder.FileFinderArgs(
            paths=[
                os.path.join(self.base_path, "test.plist"),
                os.path.join(self.base_path, "numbers.txt"),
                os.path.join(self.base_path, "numbers.txt.ver2")
            ],
            action=rdf_file_finder.FileFinderAction.Download(
            )).AsPrimitiveProto()
        flow_obj = client_ref.CreateFlow(name=file_finder.FileFinder.__name__,
                                         args=args)
        self.assertEqual(flow_obj.data.state, flow_obj.data.RUNNING)

        # Now run the flow we just started.
        client_id = rdf_client.ClientURN(flow_obj.client_id)
        flow_urn = client_id.Add("flows").Add(flow_obj.flow_id)
        flow_test_lib.TestFlowHelper(
            flow_urn,
            client_id=client_id,
            client_mock=action_mocks.FileFinderClientMock(),
            token=self.token)

        # Refresh flow.
        flow_obj = client_ref.Flow(flow_obj.flow_id).Get()
        self.assertEqual(flow_obj.data.state, flow_obj.data.TERMINATED)

        # Check that we got 3 results (we downloaded 3 files).
        results = list(flow_obj.ListResults())
        self.assertEqual(len(results), 3)
        # We expect results to be FileFinderResult.
        self.assertItemsEqual([
            os.path.basename(r.payload.stat_entry.pathspec.path)
            for r in results
        ], ["test.plist", "numbers.txt", "numbers.txt.ver2"])

        # Now downloads the files archive.
        zip_stream = StringIO.StringIO()
        flow_obj.GetFilesArchive().WriteToStream(zip_stream)
        zip_fd = zipfile.ZipFile(zip_stream)

        # Now check that the archive has only "test.plist" file, as it's the
        # only file that matches the whitelist (see FILE_FINDER_ROUTER_CONFIG).
        # There should be 3 items in the archive: the hash of the "test.plist"
        # file, the symlink to this hash and the MANIFEST file.
        namelist = zip_fd.namelist()
        self.assertEqual(len(namelist), 3)

        # First component of every path in the archive is the containing folder,
        # we should strip it.
        namelist = [os.path.join(*n.split(os.sep)[1:]) for n in namelist]
        self.assertEqual(
            sorted([
                # pyformat: disable
                os.path.join(self.client_id.Basename(), "fs", "os",
                             self.base_path.strip("/"), "test.plist"),
                os.path.join(self.client_id.Basename(), "client_info.yaml"),
                "MANIFEST"
                # pyformat: enable
            ]),
            sorted(namelist))
Пример #21
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.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")