예제 #1
0
  def testEvaluatesNegativeIfNestedRuleEvaluatesNegative(self):
    r = foreman_rules.ForemanClientRule(
        rule_type=foreman_rules.ForemanClientRule.Type.OS,
        os=foreman_rules.ForemanOsClientRule(
            os_windows=False, os_linux=True, os_darwin=False))

    client_id_win = self.SetupClient(0, system="Windows")
    # The Windows client doesn't match rule r
    self.assertFalse(
        r.Evaluate(aff4.FACTORY.Open(client_id_win, token=self.token)))
예제 #2
0
  def testEvaluatesNegativeIfNestedRuleEvaluatesNegative(self):
    r = foreman_rules.ForemanClientRule(
        rule_type=foreman_rules.ForemanClientRule.Type.OS,
        os=foreman_rules.ForemanOsClientRule(
            os_windows=False, os_linux=True, os_darwin=False))

    client_id_win = self.SetupClient(0, system="Windows").Basename()
    # The Windows client doesn't match rule r
    self.assertFalse(
        r.Evaluate(data_store.REL_DB.ReadClientFullInfo(client_id_win)))
예제 #3
0
  def testOperatingSystemSelection(self):
    """Tests that we can distinguish based on operating system."""
    self.SetupClient(1, system="Windows XP")
    self.SetupClient(2, system="Linux")
    self.SetupClient(3, system="Windows 7")

    with utils.Stubber(flow, "StartAFF4Flow", self.StartFlow):
      # Now setup the filters
      now = rdfvalue.RDFDatetime.Now()
      expires = now + rdfvalue.Duration("1h")
      foreman_obj = foreman.GetForeman(token=self.token)

      # Make a new rule
      rule = foreman_rules.ForemanRule(
          created=now, expires=expires, description="Test rule")

      # Matches Windows boxes
      rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
          foreman_rules.ForemanClientRule(
              rule_type=foreman_rules.ForemanClientRule.Type.OS,
              os=foreman_rules.ForemanOsClientRule(os_windows=True))
      ])

      # Will run Test Flow
      rule.actions.Append(
          flow_name="Test Flow", argv=rdf_protodict.Dict(foo="bar"))

      # Clear the rule set and add the new rule to it.
      rule_set = foreman_obj.Schema.RULES()
      rule_set.Append(rule)

      # Assign it to the foreman
      foreman_obj.Set(foreman_obj.Schema.RULES, rule_set)
      foreman_obj.Close()

      self.clients_launched = []
      foreman_obj.AssignTasksToClient(u"C.1000000000000001")
      foreman_obj.AssignTasksToClient(u"C.1000000000000002")
      foreman_obj.AssignTasksToClient(u"C.1000000000000003")

      # Make sure that only the windows machines ran
      self.assertLen(self.clients_launched, 2)
      self.assertEqual(self.clients_launched[0][0],
                       rdf_client.ClientURN(u"C.1000000000000001"))
      self.assertEqual(self.clients_launched[1][0],
                       rdf_client.ClientURN(u"C.1000000000000003"))

      self.clients_launched = []

      # Run again - This should not fire since it did already
      foreman_obj.AssignTasksToClient(u"C.1000000000000001")
      foreman_obj.AssignTasksToClient(u"C.1000000000000002")
      foreman_obj.AssignTasksToClient(u"C.1000000000000003")

      self.assertEmpty(self.clients_launched)
예제 #4
0
  def testEvaluatesPositiveInMatchAllModeIfAllRuleMatch(self):
    # Instantiate a rule set that matches if all of its two
    # operating system rules match
    rs = foreman_rules.ForemanClientRuleSet(
        match_mode=foreman_rules.ForemanClientRuleSet.MatchMode.MATCH_ALL,
        rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=False)),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=True))
        ])

    client_id_lin = self.SetupClient(0, system="Linux")
    # All of the set's rules have os_linux=False, so the whole set matches
    self.assertTrue(
        rs.Evaluate(data_store.REL_DB.ReadClientFullInfo(client_id_lin)))
예제 #5
0
  def testEvaluatesNegativeInMatchAllModeIfOnlyOneRuleMatches(self):
    # Instantiate a rule set that matches if all of its two
    # operating system rules match
    rs = foreman_rules.ForemanClientRuleSet(
        match_mode=foreman_rules.ForemanClientRuleSet.MatchMode.MATCH_ALL,
        rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=False)),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=True))
        ])

    client_id_dar = self.SetupClient(0, system="Darwin")
    # One of the set's rules has os_darwin=False, so the whole set doesn't
    # match with the match all match mode
    self.assertFalse(
        rs.Evaluate(data_store.REL_DB.ReadClientFullInfo(client_id_dar)))
예제 #6
0
  def testEvaluatesNegativeInMatchAnyModeIfNoRuleMatches(self):
    # Instantiate a rule set that matches if any of its two
    # operating system rules matches
    rs = foreman_rules.ForemanClientRuleSet(
        match_mode=foreman_rules.ForemanClientRuleSet.MatchMode.MATCH_ANY,
        rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=False)),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=True))
        ])

    client_id_win = self.SetupClient(0, system="Windows")
    # None of the set's rules has os_windows=True, so the whole set doesn't
    # match
    self.assertFalse(
        rs.Evaluate(data_store.REL_DB.ReadClientFullInfo(client_id_win)))
예제 #7
0
파일: hunt_test.py 프로젝트: cdstelly/grr
    def testHuntWithInvalidForemanRulesDoesNotStart(self):
        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="UNSET", attribute_regex="HUNT"))
        ])

        hunt_obj = rdf_hunt_objects.Hunt(client_rule_set=client_rule_set)
        data_store.REL_DB.WriteHuntObject(hunt_obj)
        with self.assertRaises(ValueError):
            hunt.StartHunt(hunt_obj.hunt_id)
예제 #8
0
  def testEvaluatesPositiveInMatchAnyModeIfOneRuleMatches(self):
    # Instantiate a rule set that matches if any of its two
    # operating system rules matches
    rs = foreman_rules.ForemanClientRuleSet(
        match_mode=foreman_rules.ForemanClientRuleSet.MatchMode.MATCH_ANY,
        rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=False)),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.OS,
                os=foreman_rules.ForemanOsClientRule(
                    os_windows=False, os_linux=True, os_darwin=True))
        ])

    client_id_dar = self.SetupClient(0, system="Darwin")
    # One of the set's rules has os_darwin=True, so the whole set matches
    # with the match any match mode
    self.assertTrue(
        rs.Evaluate(aff4.FACTORY.Open(client_id_dar, token=self.token)))
예제 #9
0
  def testRuleExpiration(self):
    with test_lib.FakeTime(1000):
      foreman_obj = foreman.GetForeman()

      rules = []
      rules.append(
          foreman_rules.ForemanCondition(
              creation_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1000),
              expiration_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1500),
              description="Test rule1",
              hunt_id="H:111111"))
      rules.append(
          foreman_rules.ForemanCondition(
              creation_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1000),
              expiration_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1200),
              description="Test rule2",
              hunt_id="H:222222"))
      rules.append(
          foreman_rules.ForemanCondition(
              creation_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1000),
              expiration_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1500),
              description="Test rule3",
              hunt_id="H:333333"))
      rules.append(
          foreman_rules.ForemanCondition(
              creation_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1000),
              expiration_time=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1300),
              description="Test rule4",
              hunt_id="H:444444"))

      client_id = self.SetupTestClientObject(0x21).client_id

      # Clear the rule set and add the new rules to it.
      for rule in rules:
        # Add some regex that does not match the client.
        rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="SYSTEM", attribute_regex="XXX"))
        ])
        data_store.REL_DB.WriteForemanRule(rule)

    for now, num_rules in [(1000, 4), (1250, 3), (1350, 2), (1600, 0)]:
      with test_lib.FakeTime(now):
        data_store.REL_DB.WriteClientMetadata(
            client_id,
            last_foreman=rdfvalue.RDFDatetime.FromSecondsSinceEpoch(100))
        foreman_obj.AssignTasksToClient(client_id)
        rules = data_store.REL_DB.ReadAllForemanRules()
        self.assertLen(rules, num_rules)
예제 #10
0
  def testFromDictOs(self):
    dct = {
        "rule_type": "OS",
        "os": {
            "os_windows": False,
            "os_linux": True,
        },
    }

    rdf = foreman_rules.ForemanClientRule()
    rdf.FromDict(dct)

    self.assertEqual(rdf.rule_type, foreman_rules.ForemanClientRule.Type.OS)
    self.assertFalse(rdf.os.os_windows)
    self.assertTrue(rdf.os.os_linux)
예제 #11
0
    def testForemanRulesAreCorrectlyPropagatedWhenHuntStarts(self):
        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="HUNT")),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
                integer=foreman_rules.ForemanIntegerClientRule(
                    field="CLIENT_CLOCK",
                    operator=foreman_rules.ForemanIntegerClientRule.Operator.
                    GREATER_THAN,
                    value=1336650631137737))
        ])

        self.assertEmpty(data_store.REL_DB.ReadAllForemanRules())

        hunt_obj = rdf_hunt_objects.Hunt(client_rule_set=client_rule_set)
        hunt_obj.args.hunt_type = hunt_obj.args.HuntType.STANDARD
        data_store.REL_DB.WriteHuntObject(hunt_obj)

        hunt_obj = hunt.StartHunt(hunt_obj.hunt_id)

        rules = data_store.REL_DB.ReadAllForemanRules()
        self.assertLen(rules, 1)
        rule = rules[0]
        self.assertEqual(rule.client_rule_set, client_rule_set)
        self.assertEqual(rule.hunt_id, hunt_obj.hunt_id)
        self.assertEqual(rule.expiration_time,
                         hunt_obj.init_start_time + hunt_obj.duration)

        # Running a second time should not change the rules any more.
        with self.assertRaises(hunt.OnlyPausedHuntCanBeStartedError):
            hunt.StartHunt(hunt_obj.hunt_id)
        rules = data_store.REL_DB.ReadAllForemanRules()
        self.assertLen(rules, 1)
예제 #12
0
    def testOperatingSystemSelection(self):
        """Tests that we can distinguish based on operating system."""
        self.SetupTestClientObject(1, system="Windows XP")
        self.SetupTestClientObject(2, system="Linux")
        self.SetupTestClientObject(3, system="Windows 7")

        with utils.Stubber(implementation.GRRHunt, "StartClients",
                           self.StartClients):
            # Now setup the filters
            now = rdfvalue.RDFDatetime.Now()
            expiration_time = now + rdfvalue.Duration("1h")

            # Make a new rule
            rule = foreman_rules.ForemanCondition(
                creation_time=now,
                expiration_time=expiration_time,
                description="Test rule",
                hunt_name=standard.GenericHunt.__name__,
                hunt_id="H:111111")

            # Matches Windows boxes
            rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
                foreman_rules.ForemanClientRule(
                    rule_type=foreman_rules.ForemanClientRule.Type.OS,
                    os=foreman_rules.ForemanOsClientRule(os_windows=True))
            ])

            data_store.REL_DB.WriteForemanRule(rule)

            self.clients_started = []
            foreman_obj = foreman.GetForeman()
            foreman_obj.AssignTasksToClient(u"C.1000000000000001")
            foreman_obj.AssignTasksToClient(u"C.1000000000000002")
            foreman_obj.AssignTasksToClient(u"C.1000000000000003")

            # Make sure that only the windows machines ran
            self.assertEqual(len(self.clients_started), 2)
            self.assertEqual(self.clients_started[0][1], u"C.1000000000000001")
            self.assertEqual(self.clients_started[1][1], u"C.1000000000000003")

            self.clients_started = []

            # Run again - This should not fire since it did already
            foreman_obj.AssignTasksToClient(u"C.1000000000000001")
            foreman_obj.AssignTasksToClient(u"C.1000000000000002")
            foreman_obj.AssignTasksToClient(u"C.1000000000000003")

            self.assertEqual(len(self.clients_started), 0)
예제 #13
0
  def testFromDictLabel(self):
    dct = {
        "rule_type": "LABEL",
        "label": {
            "label_names": ["quux", "norf", "thud"],
            "match_mode": "MATCH_ANY",
        },
    }

    rdf = foreman_rules.ForemanClientRule()
    rdf.FromDict(dct)

    self.assertEqual(rdf.rule_type, foreman_rules.ForemanClientRule.Type.LABEL)
    self.assertEqual(rdf.label.label_names, ["quux", "norf", "thud"])
    self.assertEqual(rdf.label.match_mode,
                     foreman_rules.ForemanLabelClientRule.MatchMode.MATCH_ANY)
예제 #14
0
    def testPausingAndRestartingDoesNotStartHuntTwiceOnTheSameClient(self):
        """This tests if the hunt completes when some clients hang or raise."""
        client_ids = self.SetupClients(10)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:

            hunt.GetRunner().Start()

            hunt_id = hunt.urn

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            num_tasks = foreman.AssignTasksToClient(client_id.Basename())
            self.assertEqual(num_tasks, 1)

        client_mock = hunt_test_lib.SampleHuntMock(failrate=2)
        hunt_test_lib.TestHuntHelper(client_mock, client_ids, False,
                                     self.token)

        # Pausing and running hunt: this leads to the fresh rules being written
        # to Foreman.RULES.
        with aff4.FACTORY.Open(hunt_id, mode="rw", token=self.token) as hunt:
            runner = hunt.GetRunner()
            runner.Pause()
            runner.Start()

        # Recreating the foreman so that it updates list of rules.
        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            num_tasks = foreman.AssignTasksToClient(client_id.Basename())
            # No tasks should be assigned as this hunt ran on all the clients
            # before.
            self.assertEqual(num_tasks, 0)
예제 #15
0
    def testInvalidRules(self):
        """Tests the behavior when the field is left UNSET in a rule."""

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="UNSET", attribute_regex="HUNT"))
        ])

        with implementation.StartHunt(hunt_name=BrokenSampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:

            runner = hunt.GetRunner()
            self.assertRaises(ValueError, runner.Start)
예제 #16
0
  def testFromDictRegex(self):
    dct = {
        "rule_type": "REGEX",
        "regex": {
            "attribute_regex": "[a-z]+[0-9]",
            "field": "FQDN",
        },
    }

    rdf = foreman_rules.ForemanClientRule()
    rdf.FromDict(dct)

    self.assertEqual(rdf.rule_type, foreman_rules.ForemanClientRule.Type.REGEX)
    self.assertEqual(rdf.regex.attribute_regex, "[a-z]+[0-9]")
    self.assertEqual(
        rdf.regex.field,
        foreman_rules.ForemanRegexClientRule.ForemanStringField.FQDN)
예제 #17
0
 def _GetTestRule(self, hunt_id="H:123456", expires=None):
     now = rdfvalue.RDFDatetime.Now()
     expiration_time = expires or now + rdfvalue.Duration("2w")
     rule = foreman_rules.ForemanCondition(creation_time=now,
                                           expiration_time=expiration_time,
                                           description="Test rule",
                                           hunt_id=hunt_id)
     rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
         foreman_rules.ForemanClientRule(
             rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
             integer=foreman_rules.ForemanIntegerClientRule(
                 field="INSTALL_TIME",
                 operator=foreman_rules.ForemanIntegerClientRule.Operator.
                 LESS_THAN,
                 value=now))
     ])
     return rule
예제 #18
0
    def testBrokenHunt(self):
        """This tests the behavior when a hunt raises an exception."""

        # Set up 10 clients.
        client_ids = self.SetupClients(10)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=BrokenSampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:

            hunt.GetRunner().Start()

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            foreman.AssignTasksToClient(client_id.Basename())

        # Run the hunt.
        client_mock = hunt_test_lib.SampleHuntMock(failrate=2)
        hunt_test_lib.TestHuntHelper(client_mock, client_ids, False,
                                     self.token)

        hunt_obj = aff4.FACTORY.Open(hunt.session_id,
                                     mode="rw",
                                     age=aff4.ALL_TIMES,
                                     token=self.token)
        started, finished, errors = hunt_obj.GetClientsCounts()

        self.assertEqual(started, 10)
        # There should be errors for the five clients where the hunt raised.
        self.assertEqual(errors, 5)
        # All of the clients that have the file should still finish eventually.
        self.assertEqual(finished, 5)
예제 #19
0
  def testFromDictInteger(self):
    dct = {
        "rule_type": "INTEGER",
        "integer": {
            "operator": "EQUAL",
            "value": 42,
            "field": "CLIENT_VERSION",
        },
    }

    rdf = foreman_rules.ForemanClientRule()
    rdf.FromDict(dct)

    self.assertEqual(rdf.rule_type,
                     foreman_rules.ForemanClientRule.Type.INTEGER)
    self.assertEqual(rdf.integer.operator,
                     foreman_rules.ForemanIntegerClientRule.Operator.EQUAL)
    self.assertEqual(rdf.integer.value, 42)
    self.assertEqual(
        rdf.integer.field, foreman_rules.ForemanIntegerClientRule
        .ForemanIntegerField.CLIENT_VERSION)
예제 #20
0
    def testClientLimit(self):
        """This tests that we can limit hunts to a number of clients."""

        # Set up 10 clients.
        client_ids = self.SetupClients(10)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                      client_limit=5,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:
            hunt.Run()

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            foreman.AssignTasksToClient(client_id.Basename())

        # Run the hunt.
        client_mock = hunt_test_lib.SampleHuntMock(failrate=2)
        hunt_test_lib.TestHuntHelper(client_mock, client_ids, False,
                                     self.token)

        hunt_obj = aff4.FACTORY.Open(hunt.urn,
                                     mode="rw",
                                     age=aff4.ALL_TIMES,
                                     token=self.token)

        started, finished, _ = hunt_obj.GetClientsCounts()
        # We limited here to 5 clients.
        self.assertEqual(started, 5)
        self.assertEqual(finished, 5)
예제 #21
0
    def _RunRateLimitedHunt(self, client_ids, start_time):
        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=DummyHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=1,
                                      token=self.token) as hunt:
            hunt.Run()

        # Pretend to be the foreman now and dish out hunting jobs to all the
        # clients..
        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            foreman.AssignTasksToClient(client_id.Basename())

        self.assertEmpty(DummyHunt.client_ids)

        # Run the hunt.
        worker_mock = worker_test_lib.MockWorker(check_flow_errors=True,
                                                 queues=[queues.HUNTS],
                                                 token=self.token)

        # One client is scheduled in the first minute.
        with test_lib.FakeTime(start_time + 2):
            worker_mock.Simulate()
        self.assertLen(DummyHunt.client_ids, 1)

        # No further clients will be scheduled until the end of the first minute.
        with test_lib.FakeTime(start_time + 59):
            worker_mock.Simulate()
        self.assertLen(DummyHunt.client_ids, 1)

        return worker_mock, hunt.urn
예제 #22
0
    def testProcessing(self):
        """This tests running the hunt on some clients."""

        # Set up 10 clients.
        client_ids = self.SetupClients(10)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:

            hunt.GetRunner().Start()

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            foreman.AssignTasksToClient(client_id.Basename())

        # Run the hunt.
        client_mock = hunt_test_lib.SampleHuntMock(failrate=2)
        hunt_test_lib.TestHuntHelper(client_mock, client_ids, False,
                                     self.token)

        hunt_obj = aff4.FACTORY.Open(hunt.session_id,
                                     mode="r",
                                     age=aff4.ALL_TIMES,
                                     aff4_type=standard.SampleHunt,
                                     token=self.token)

        started, finished, _ = hunt_obj.GetClientsCounts()
        self.assertEqual(started, 10)
        self.assertEqual(finished, 10)
예제 #23
0
    def testHangingClients(self):
        """This tests if the hunt completes when some clients hang or raise."""
        # Set up 10 clients.
        client_ids = self.SetupClients(10)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_rate=0,
                                      token=self.token) as hunt:

            hunt.GetRunner().Start()

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        for client_id in client_ids:
            foreman.AssignTasksToClient(client_id.Basename())

        client_mock = hunt_test_lib.SampleHuntMock(failrate=2)
        # Just pass 8 clients to run, the other two went offline.
        hunt_test_lib.TestHuntHelper(client_mock, client_ids[1:9], False,
                                     self.token)

        hunt_obj = aff4.FACTORY.Open(hunt.session_id,
                                     mode="rw",
                                     age=aff4.ALL_TIMES,
                                     token=self.token)

        started, finished, _ = hunt_obj.GetClientsCounts()
        # We started the hunt on 10 clients.
        self.assertEqual(started, 10)
        # But only 8 should have finished.
        self.assertEqual(finished, 8)
예제 #24
0
    def testCopyHuntPreservesRuleType(self):
        implementation.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")
예제 #25
0
    def testCallback(self, client_limit=None):
        """Checks that the foreman uses the callback specified in the action."""
        client_urn = self.SetupClient(0)
        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="GRR"))
        ])

        with implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                      client_rule_set=client_rule_set,
                                      client_limit=client_limit,
                                      client_rate=0,
                                      token=self.token) as hunt:

            hunt.GetRunner().Start()

        # Create a client that matches our regex.
        with aff4.FACTORY.Open(client_urn, mode="rw",
                               token=self.token) as client:
            info = client.Schema.CLIENT_INFO()
            info.client_name = "GRR Monitor"
            client.Set(client.Schema.CLIENT_INFO, info)

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        with utils.Stubber(standard.SampleHunt, "StartClients", self.Callback):
            self.called = []

            client_id = client_urn.Basename()
            foreman.AssignTasksToClient(client_id)

            self.assertLen(self.called, 1)
            self.assertEqual(self.called[0][1], [client_id])
예제 #26
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)
예제 #27
0
    def testIntegerComparisons(self):
        """Tests that we can use integer matching rules on the foreman."""

        base_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(
            1336480583.077736)
        boot_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(
            1336300000.000000)

        self.SetupClient(0x11, system="Windows XP", install_time=base_time)
        self.SetupClient(0x12, system="Windows 7", install_time=base_time)
        # This one was installed one week earlier.
        one_week_ago = base_time - rdfvalue.DurationSeconds("1w")
        self.SetupClient(0x13, system="Windows 7", install_time=one_week_ago)
        self.SetupClient(0x14, system="Windows 7", last_boot_time=boot_time)

        with utils.Stubber(hunt, "StartHuntFlowOnClient",
                           self.StartHuntFlowOnClient):
            now = rdfvalue.RDFDatetime.Now()
            expiration_time = now + rdfvalue.DurationSeconds("1h")

            # Make a new rule
            rule = foreman_rules.ForemanCondition(
                creation_time=now,
                expiration_time=expiration_time,
                description="Test rule(old)",
                hunt_id="111111")

            # Matches the old client
            one_hour_ago = base_time - rdfvalue.DurationSeconds("1h")
            rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
                foreman_rules.ForemanClientRule(
                    rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
                    integer=foreman_rules.ForemanIntegerClientRule(
                        field="INSTALL_TIME",
                        operator=foreman_rules.ForemanIntegerClientRule.
                        Operator.LESS_THAN,
                        value=one_hour_ago.AsSecondsSinceEpoch()))
            ])

            data_store.REL_DB.WriteForemanRule(rule)

            # Make a new rule
            rule = foreman_rules.ForemanCondition(
                creation_time=now,
                expiration_time=expiration_time,
                description="Test rule(new)",
                hunt_id="222222")

            # Matches the newer clients
            rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
                foreman_rules.ForemanClientRule(
                    rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
                    integer=foreman_rules.ForemanIntegerClientRule(
                        field="INSTALL_TIME",
                        operator=foreman_rules.ForemanIntegerClientRule.
                        Operator.GREATER_THAN,
                        value=one_hour_ago.AsSecondsSinceEpoch()))
            ])

            data_store.REL_DB.WriteForemanRule(rule)

            # Make a new rule
            rule = foreman_rules.ForemanCondition(
                creation_time=now,
                expiration_time=expiration_time,
                description="Test rule(eq)",
                hunt_id="333333")

            # Note that this also tests the handling of nonexistent attributes.
            rule.client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
                foreman_rules.ForemanClientRule(
                    rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
                    integer=foreman_rules.ForemanIntegerClientRule(
                        field="LAST_BOOT_TIME",
                        operator="EQUAL",
                        value=boot_time.AsSecondsSinceEpoch()))
            ])

            data_store.REL_DB.WriteForemanRule(rule)

            foreman_obj = foreman.Foreman()

            self.clients_started = []
            foreman_obj.AssignTasksToClient(u"C.1000000000000011")
            foreman_obj.AssignTasksToClient(u"C.1000000000000012")
            foreman_obj.AssignTasksToClient(u"C.1000000000000013")
            foreman_obj.AssignTasksToClient(u"C.1000000000000014")

            # Make sure that the clients ran the correct flows.
            self.assertLen(self.clients_started, 4)
            self.assertEqual(self.clients_started[0][1], u"C.1000000000000011")
            self.assertEqual("222222", self.clients_started[0][0])
            self.assertEqual(self.clients_started[1][1], u"C.1000000000000012")
            self.assertEqual("222222", self.clients_started[1][0])
            self.assertEqual(self.clients_started[2][1], u"C.1000000000000013")
            self.assertEqual("111111", self.clients_started[2][0])
            self.assertEqual(self.clients_started[3][1], u"C.1000000000000014")
            self.assertEqual("333333", self.clients_started[3][0])
예제 #28
0
    def testStopping(self):
        """Tests if we can stop a hunt."""

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        rules = foreman.Get(foreman.Schema.RULES)

        # Make sure there are no rules yet.
        self.assertEmpty(rules)
        now = rdfvalue.RDFDatetime.Now()
        expires = rdfvalue.Duration("1h").Expiry()
        # Add some rules.
        rules = [
            foreman_rules.ForemanRule(created=now,
                                      expires=expires,
                                      description="Test rule1"),
            foreman_rules.ForemanRule(created=now,
                                      expires=expires,
                                      description="Test rule2")
        ]
        self.AddForemanRules(rules)

        client_rule_set = foreman_rules.ForemanClientRuleSet(rules=[
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.REGEX,
                regex=foreman_rules.ForemanRegexClientRule(
                    field="CLIENT_NAME", attribute_regex="HUNT")),
            foreman_rules.ForemanClientRule(
                rule_type=foreman_rules.ForemanClientRule.Type.INTEGER,
                integer=foreman_rules.ForemanIntegerClientRule(
                    field="CLIENT_CLOCK",
                    operator=foreman_rules.ForemanIntegerClientRule.Operator.
                    GREATER_THAN,
                    value=1336650631137737))
        ])

        hunt = implementation.StartHunt(hunt_name=standard.SampleHunt.__name__,
                                        client_rule_set=client_rule_set,
                                        client_rate=0,
                                        token=self.token)

        with hunt:
            runner = hunt.GetRunner()
            runner.Start()

            # Add some more rules.
            rules = [
                foreman_rules.ForemanRule(created=now,
                                          expires=expires,
                                          description="Test rule3"),
                foreman_rules.ForemanRule(created=now,
                                          expires=expires,
                                          description="Test rule4")
            ]
            self.AddForemanRules(rules)

            foreman = aff4.FACTORY.Open("aff4:/foreman",
                                        mode="rw",
                                        token=self.token)
            rules = foreman.Get(foreman.Schema.RULES)
            self.assertLen(rules, 5)

            # It should be running.
            self.assertTrue(runner.IsHuntStarted())

            # Now we stop the hunt.
            hunt.Stop()

        foreman = aff4.FACTORY.Open("aff4:/foreman",
                                    mode="rw",
                                    token=self.token)
        rules = foreman.Get(foreman.Schema.RULES)
        # The rule for this hunt should be deleted but the rest should be there.
        self.assertLen(rules, 4)

        # And the hunt should report no outstanding requests any more.
        with hunt:
            self.assertFalse(hunt.GetRunner().IsHuntStarted())
예제 #29
0
  def testCopyHuntRespectsUserChanges(self):
    self.CreateSampleHunt("model hunt", 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 and then click through.
    self.WaitUntil(self.IsTextPresent, "What to run?")

    # Change values in the flow configuration.
    self.Type(
        "css=grr-new-hunt-wizard-form label:contains('Path') "
        "~ * input:text", "/tmp/very-evil.txt")

    self.Select(
        "css=grr-new-hunt-wizard-form label:contains('Pathtype') "
        "~ * select", "OS")

    # 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')")

    self.Type(
        "css=grr-new-hunt-wizard-form label:contains('Description') "
        "~ * input:text", "my personal copy")

    self.Type(
        "css=grr-new-hunt-wizard-form label:contains('Client rate') "
        "~ * input", "42")

    # Click on "Next" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsTextPresent, "How to process results")

    # Change output plugin and add another one.
    self.Click("css=grr-new-hunt-wizard-form button[name=Add]")
    self.Select("css=grr-configure-output-plugins-page select:eq(0)",
                "DummyOutputPlugin")
    self.Type(
        "css=grr-configure-output-plugins-page "
        "label:contains('Filename Regex'):eq(0) ~ * input:text", "foobar!")

    # Click on "Next" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsTextPresent, "Where to run?")

    # Replace a rule with another one.
    self.Click("css=grr-configure-rules-page button[name=Remove]")
    self.Click("css=grr-configure-rules-page button[name=Add]")
    self.Click("css=grr-configure-rules-page label:contains('Os darwin') ~ * "
               "input[type=checkbox]")

    # Click on "Next" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsTextPresent, "Review")

    # Check that expected values are shown in the review.
    self.WaitUntil(self.IsTextPresent, "OS")
    self.WaitUntil(self.IsTextPresent, "/tmp/very-evil.txt")
    self.WaitUntil(self.IsTextPresent, transfer.GetFile.__name__)
    self.WaitUntil(self.IsTextPresent, "DummyOutputPlugin")
    self.WaitUntil(self.IsTextPresent, "foobar!")
    self.WaitUntil(self.IsTextPresent, "blah!")
    self.WaitUntil(self.IsTextPresent, "my personal copy")
    self.WaitUntil(self.IsTextPresent, "Os darwin")
    self.WaitUntil(self.IsTextPresent, "42")

    # Click on "Run" button.
    self.Click("css=grr-new-hunt-wizard-form button.Next")
    self.WaitUntil(self.IsTextPresent, "Created Hunt")

    if data_store.RelationalDBReadEnabled():
      hunts_list = sorted(
          data_store.REL_DB.ReadHuntObjects(offset=0, count=10),
          key=lambda x: x.create_time)

      self.assertLen(hunts_list, 2)

      last_hunt = hunts_list[-1]

      self.assertEqual(last_hunt.args.standard.flow_args.pathspec.path,
                       "/tmp/very-evil.txt")
      self.assertEqual(last_hunt.args.standard.flow_args.pathspec.pathtype,
                       "OS")
      self.assertEqual(last_hunt.args.standard.flow_name,
                       transfer.GetFile.__name__)

      self.assertLen(last_hunt.output_plugins, 2)
      self.assertEqual(last_hunt.output_plugins[0].plugin_name,
                       "DummyOutputPlugin")
      self.assertEqual(last_hunt.output_plugins[0].plugin_args.filename_regex,
                       "foobar!")
      self.assertEqual(last_hunt.output_plugins[0].plugin_args.fetch_binaries,
                       False)
      self.assertEqual(last_hunt.output_plugins[1].plugin_name,
                       "DummyOutputPlugin")
      self.assertEqual(last_hunt.output_plugins[1].plugin_args.filename_regex,
                       "blah!")
      self.assertEqual(last_hunt.output_plugins[1].plugin_args.fetch_binaries,
                       True)

      self.assertAlmostEqual(last_hunt.client_rate, 42)
      self.assertEqual(last_hunt.description, "my personal copy")
      self.assertEqual(
          last_hunt.client_rule_set,
          foreman_rules.ForemanClientRuleSet(rules=[
              foreman_rules.ForemanClientRule(
                  os=foreman_rules.ForemanOsClientRule(os_darwin=True))
          ]))
    else:
      hunts_root = aff4.FACTORY.Open("aff4:/hunts", token=self.token)
      hunts_list = sorted(list(hunts_root.ListChildren()), key=lambda x: x.age)

      self.assertLen(hunts_list, 2)
      last_hunt = aff4.FACTORY.Open(hunts_list[-1], token=self.token)

      self.assertEqual(last_hunt.args.flow_args.pathspec.path,
                       "/tmp/very-evil.txt")
      self.assertEqual(last_hunt.args.flow_args.pathspec.pathtype, "OS")
      self.assertEqual(last_hunt.args.flow_runner_args.flow_name,
                       transfer.GetFile.__name__)

      self.assertLen(last_hunt.runner_args.output_plugins, 2)
      self.assertEqual(last_hunt.runner_args.output_plugins[0].plugin_name,
                       "DummyOutputPlugin")
      self.assertEqual(
          last_hunt.runner_args.output_plugins[0].plugin_args.filename_regex,
          "foobar!")
      self.assertEqual(
          last_hunt.runner_args.output_plugins[0].plugin_args.fetch_binaries,
          False)
      self.assertEqual(last_hunt.runner_args.output_plugins[1].plugin_name,
                       "DummyOutputPlugin")
      self.assertEqual(
          last_hunt.runner_args.output_plugins[1].plugin_args.filename_regex,
          "blah!")
      self.assertEqual(
          last_hunt.runner_args.output_plugins[1].plugin_args.fetch_binaries,
          True)

      runner_args = last_hunt.runner_args
      self.assertAlmostEqual(runner_args.client_rate, 42)
      self.assertEqual(runner_args.description, "my personal copy")
      self.assertEqual(
          runner_args.client_rule_set,
          foreman_rules.ForemanClientRuleSet(rules=[
              foreman_rules.ForemanClientRule(
                  os=foreman_rules.ForemanOsClientRule(os_darwin=True))
          ]))
예제 #30
0
 def GenerateSample(number=0):
   # Wrap the operating system rule sample generator
   return foreman_rules.ForemanClientRule(
       rule_type=foreman_rules.ForemanClientRule.Type.OS,
       os=ForemanOsClientRuleTest.GenerateSample(number))