def test_01_list(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB and test if there is one record """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/addressgroup.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) for idea in self.messages_pass: results, actions = self.config.match(idea) if True in results: pass else: print("passing rules") print("Test FAILED!!!") for idea in self.messages_notpass: results, actions = self.config.match(idea) if True not in results: pass else: print("NOT passing rules") print("Test FAILED!!!")
def test_05_malformedyaml(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/malformedyaml.yaml') self.fail("Malformed YAML must raise exception with error.") except Exception: pass
def test_01_receive_message(self): """Perform multiple actions on matched message If an action is matched perform these actions: * Mark * Mongo * File Load multiple_actions.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser( os.path.dirname(__file__) + '/rc_config/multiple_actions.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) # The actions must be checked in reversed order # Check if file created by File Action exists self.assertTrue(os.path.exists("testfile.idea"), True) # Find the event in DB rec = self.collection.find_one() self.assertTrue(rec["ID"], "e214d2d9-359b-443d-993d-3cc5637107a0") # Check if message was marked self.assertEqual(rec['Test'], True)
def test_01_send_email(self): """ Load email.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.config = Config( os.path.dirname(__file__) + '/rc_config/email.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg) # Check if mail arrived in /var/mail/nemea # TODO: parametrize the user m = mailbox.mbox('/var/mail/nemea') for key in m.iterkeys(): # To be sure it is our email we will match TO, FROM and SUBJECT fields if (m[key]['subject'] == 'Attempt.Login (cz.uhk.apate.cowrie): 1.2.3.4 -> 195.113.165.128/25' and m[key]['from'] == '*****@*****.**' and m[key]['to'] == '*****@*****.**'): # Remove given email from mailbox # There is some wierd behaviour regarding un/locking and flushing # Only worked for me when tests were run as root m.lock() m.discard(key) m.unlock() m.flush() m.close() return self.fail("No email was received")
def test_03_oneruledrop(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/minimaldrop.yaml') self.assertNotEqual(self.config, None) results, actions = self.config.match(self.msg) self.assertEqual(results, [True])
def test_01_mark_simple(self): """ Load mark.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser( os.path.dirname(__file__) + '/rc_config/mark.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) of1 = "/tmp/output1.idea" of2 = "/tmp/output2.idea" with open(of1, "r") as f: stored = json.load(f) self.assertEqual(stored['Test'], True) with open(of2, "r") as f: stored = json.load(f) self.assertEqual(stored["_CESNET"]["Status"]["Processed"], True) try: os.unlink(of1) except Exception: pass try: os.unlink(of2) except Exception: pass
def test_01_load_basic_config(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/incompleterules.yaml') self.fail("Rules must contain at least one rule.") except Exception as e: self.assertEqual( str(e), "YAML file should contain at least one `rule` in `rules`.")
def test_00_load_basic_config(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/empty.yaml') self.fail( "Empty configuration file shouldn't be loaded! It must contain rules." ) except Exception as e: self.assertEqual(str(e), "YAML file must contain `rules`.")
def test_02_basic_match(self): self.parser = Parser(os.path.dirname(__file__) + '/rc_config/basic.yaml'); self.config = Config(self.parser); try: results, actions = self.config.match(self.msg) except Exception: pass self.assertEqual(results[0], True)
def test_01_drop(self): """ Load drop.yaml configuration file, parse it and analyze it """ self.config = Config( os.path.dirname(__file__) + '/rc_config/drop.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg)
class RCAddressGroupTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open("/tmp/testwhitelist", 'w') as f: f.write("192.168.0.0/24\n10.0.1.1\n") with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) self.parser = Parser(os.path.dirname(__file__) + '/rc_config/mongo.yaml') self.config = Config(self.parser); # format from IDEA message: "Source": [{"IP4": ["1.2.3.4"]}] self.messages_pass = [] for ip in ["10.0.0.9", "10.0.0.10", "192.168.0.254", "10.0.1.1"]: m = copy.deepcopy(self.msg) m["Source"][0]["IP4"][0] = ip self.messages_pass.append(m) self.messages_notpass = [] for ip in ["1.2.3.5", "10.10.0.1", "192.168.1.1"]: m = copy.deepcopy(self.msg) m["Source"][0]["IP4"][0] = ip self.messages_notpass.append(m) def test_01_list(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB and test if there is one record """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/addressgroup.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) for idea in self.messages_pass: results, actions = self.config.match(idea) if True in results: pass else: print("passing rules") print("Test FAILED!!!") for idea in self.messages_notpass: results, actions = self.config.match(idea) if True not in results: pass else: print("NOT passing rules") print("Test FAILED!!!")
class RCMultipleActionsTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) self.client = pymongo.MongoClient("localhost", 27017) self.collection = self.client["rc_test"]["alerts"] # Remove the collection (just for assurance) self.collection.drop() def tearDown(self): # Remove created file os.remove("testfile.idea") @unittest.skipIf(pymongo_missing, "missing pymongo, skipping mongodb test with elseactions") def test_01_receive_message(self): """Perform multiple elseactions on matched message If an action is matched perform these actions: * Mark * Mongo * File Load multiple_elseactions.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions, if action is performed, which it shouldn't, it raises the DropMsg exception (uncaught here) """ self.parser = Parser( os.path.dirname(__file__) + '/rc_config/multiple_elseactions.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) # The actions must be checked in reversed order # Check if file created by File Action exists self.assertTrue(os.path.exists("testfile.idea"), True) # Find the event in DB rec = self.collection.find_one() self.assertTrue(rec["ID"], "e214d2d9-359b-443d-993d-3cc5637107a0") # Check if message was marked self.assertEqual(rec['Test'], True)
def test_02_check_record(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB, find it, and check contents """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/mongo.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) self.config.match(self.msg)
def test_01_store_record(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB and test if there is one record """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/mongo.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) self.config.match(self.msg)
class RCFileTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_01_file_created(self): """ Load email.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser( os.path.dirname(__file__) + '/rc_config/file.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) self.assertTrue( os.path.exists( self.config.conf["custom_actions"][0]["file"]["path"]), True) os.remove(self.config.conf["custom_actions"][0]["file"]["path"]) def test_02_file_content(self): self.parser = Parser( os.path.dirname(__file__) + '/rc_config/file.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) filepath = self.config.conf["custom_actions"][0]["file"]["path"] # Delete the Config instance in order to close file pointer del self.config with open(filepath, 'r') as f: self.content = json.load(f) os.remove(filepath) self.assertTrue(self.content["ID"], "e214d2d9-359b-443d-993d-3cc5637107a0")
class RCBaseTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_02_basic_match(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/tautology.yaml') results, actions = self.config.match(self.msg) self.assertEqual(results, 5 * [True] + 3 * [False]) performedActions = [] for al in actions: ruleactions = [] for a in al: ruleactions.append(a.actionId) performedActions.append(ruleactions) expectedActions = 5 * [['basic_mark']] + 3 * [[]] self.assertEqual(performedActions, expectedActions)
def test_02_basic_match(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/tautology.yaml') results, actions = self.config.match(self.msg) self.assertEqual(results, 5 * [True] + 3 * [False]) performedActions = [] for al in actions: ruleactions = [] for a in al: ruleactions.append(a.actionId) performedActions.append(ruleactions) expectedActions = 5 * [['basic_mark']] + 3 * [[]] self.assertEqual(performedActions, expectedActions)
def test_01_file_created(self): """ Load email.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.config = Config( os.path.dirname(__file__) + '/rc_config/file.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg) self.assertTrue( os.path.exists( self.config.conf["custom_actions"][0]["file"]["path"]), True) os.remove(self.config.conf["custom_actions"][0]["file"]["path"])
class RCEMailTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass @unittest.skip("skipping send email test 1") def test_01_send_email(self): """ Load email.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.config = Config( os.path.dirname(__file__) + '/rc_config/email.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg) # Check if mail arrived in /var/mail/nemea # TODO: parametrize the user m = mailbox.mbox('/var/mail/nemea') for key in m.iterkeys(): # To be sure it is our email we will match TO, FROM and SUBJECT fields if (m[key]['subject'] == 'Attempt.Login (cz.uhk.apate.cowrie): 1.2.3.4 -> 195.113.165.128/25' and m[key]['from'] == '*****@*****.**' and m[key]['to'] == '*****@*****.**'): # Remove given email from mailbox # There is some wierd behaviour regarding un/locking and flushing # Only worked for me when tests were run as root m.lock() m.discard(key) m.unlock() m.flush() m.close() return self.fail("No email was received")
def test_02_file_content(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/file.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg) filepath = self.config.conf["custom_actions"][0]["file"]["path"] # Delete the Config instance in order to close file pointer del self.config with open(filepath, 'r') as f: self.content = json.load(f) os.remove(filepath) self.assertTrue(self.content["ID"], "e214d2d9-359b-443d-993d-3cc5637107a0")
def test_01_load_basic_config(self): """ Load basic configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/basic.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) # There should be only one address group self.assertEqual(len(self.config.addrGroups), 1) # There should be only one custom action and DROP action self.assertEqual(len(self.config.actions), 2) # There should be only one rule self.assertEqual(len(self.config.rules), 1)
class RCMarkTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_01_mark_simple(self): """ Load mark.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser( os.path.dirname(__file__) + '/rc_config/mark.yaml') self.config = Config(self.parser) self.assertNotEqual(self.config, None) self.config.match(self.msg) of1 = "/tmp/output1.idea" of2 = "/tmp/output2.idea" with open(of1, "r") as f: stored = json.load(f) self.assertEqual(stored['Test'], True) with open(of2, "r") as f: stored = json.load(f) self.assertEqual(stored["_CESNET"]["Status"]["Processed"], True) try: os.unlink(of1) except Exception: pass try: os.unlink(of2) except Exception: pass
def test_04_secondruleterminated(self): of = "/tmp/output1.idea" if os.path.isfile(of): os.unlink(of) self.config = Config( os.path.dirname(__file__) + '/rc_config/minimalfirstdrop.yaml') self.assertNotEqual(self.config, None) results, actions = self.config.match(self.msg) # only one rule should have been processed since drop was in the first rule self.assertEqual(results, [True]) if os.path.isfile(of) and os.stat(of).st_size: os.unlink(of) self.fail( "Drop action was the first one, file should not be existing.") else: try: os.unlink(of) except Exception: pass
def setUp(self): """ Example message created by a conv function in a reporter """ with open("/tmp/testwhitelist", 'w') as f: f.write("192.168.0.0/24\n10.0.1.1\n") with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) self.config = Config(os.path.dirname(__file__) + '/rc_config/mongo.yaml'); # format from IDEA message: "Source": [{"IP4": ["1.2.3.4"]}] self.messages_pass = [] for ip in ["10.0.0.9", "10.0.0.10", "192.168.0.254", "10.0.1.1"]: m = copy.deepcopy(self.msg) m["Source"][0]["IP4"][0] = ip self.messages_pass.append(m) self.messages_notpass = [] for ip in ["1.2.3.5", "10.10.0.1", "192.168.1.1"]: m = copy.deepcopy(self.msg) m["Source"][0]["IP4"][0] = ip self.messages_notpass.append(m)
class RCDropTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_01_drop(self): """ Load drop.yaml configuration file, parse it and analyze it """ self.config = Config( os.path.dirname(__file__) + '/rc_config/drop.yaml') self.assertNotEqual(self.config, None) self.config.match(self.msg)
class RCMongoTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def test_01_store_record(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB and test if there is one record """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/mongo.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) self.config.match(self.msg) #self.assertEqual(self.collection.find().count(), 1) def test_02_check_record(self): """ Load mongo.yaml configuration file, parse it and analyze it This shouldn't rise any exceptions Should store message in DB, find it, and check contents """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/mongo.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) self.config.match(self.msg)
class RCBaseTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_01_load_basic_config(self): """ Load basic configuration file, parse it and analyze it This shouldn't rise any exceptions """ self.parser = Parser(os.path.dirname(__file__) + '/rc_config/basic.yaml'); self.config = Config(self.parser); self.assertNotEqual(self.config, None) # There should be only one address group self.assertEqual(len(self.config.addrGroups), 1) # There should be only one custom action and DROP action self.assertEqual(len(self.config.actions), 2) # There should be only one rule self.assertEqual(len(self.config.rules), 1) def test_02_basic_match(self): self.parser = Parser(os.path.dirname(__file__) + '/rc_config/basic.yaml'); self.config = Config(self.parser); try: results, actions = self.config.match(self.msg) except Exception: pass self.assertEqual(results[0], True)
def test_01_init(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/all_actions.yaml')
class RCEmptyFileTest(unittest.TestCase): def setUp(self): """ Example message created by a conv function in a reporter """ with open(os.path.dirname(__file__) + '/rc_msg.json', 'r') as f: self.msg = json.load(f) def tearDown(self): pass def test_00_load_basic_config(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/empty.yaml') self.fail( "Empty configuration file shouldn't be loaded! It must contain rules." ) except Exception as e: self.assertEqual(str(e), "YAML file must contain `rules`.") def test_01_load_basic_config(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/incompleterules.yaml') self.fail("Rules must contain at least one rule.") except Exception as e: self.assertEqual( str(e), "YAML file should contain at least one `rule` in `rules`.") def test_02_onerule(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/minimal.yaml') self.assertNotEqual(self.config, None) def test_03_oneruledrop(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/minimaldrop.yaml') self.assertNotEqual(self.config, None) results, actions = self.config.match(self.msg) self.assertEqual(results, [True]) def test_04_secondruleterminated(self): of = "/tmp/output1.idea" if os.path.isfile(of): os.unlink(of) self.config = Config( os.path.dirname(__file__) + '/rc_config/minimalfirstdrop.yaml') self.assertNotEqual(self.config, None) results, actions = self.config.match(self.msg) # only one rule should have been processed since drop was in the first rule self.assertEqual(results, [True]) if os.path.isfile(of) and os.stat(of).st_size: os.unlink(of) self.fail( "Drop action was the first one, file should not be existing.") else: try: os.unlink(of) except Exception: pass def test_05_malformedyaml(self): try: self.config = Config( os.path.dirname(__file__) + '/rc_config/malformedyaml.yaml') self.fail("Malformed YAML must raise exception with error.") except Exception: pass
def test_02_onerule(self): self.config = Config( os.path.dirname(__file__) + '/rc_config/minimal.yaml') self.assertNotEqual(self.config, None)