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)))
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)))
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)
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)))
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)))
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)))
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)
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)))
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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
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)
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)
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")
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])
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)
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])
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())
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)) ]))
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))