From 35377399e87f3aadda0a288a29b7527365bacc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Fri, 21 Feb 2020 14:12:36 +0100 Subject: [PATCH] new: Add uuid by default in MISPEvent, add F/L seen in feed output. --- pymisp/abstract.py | 4 ++-- pymisp/mispevent.py | 5 +++-- tests/test_mispevent.py | 10 ++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pymisp/abstract.py b/pymisp/abstract.py index 750842f..8663c2c 100644 --- a/pymisp/abstract.py +++ b/pymisp/abstract.py @@ -220,8 +220,8 @@ class AbstractMISP(MutableMapping, MISPFileCache, metaclass=ABCMeta): else: to_return[field] = getattr(self, field) else: - if field == 'data': - # data in attribute is special + if field in ['data', 'first_seen', 'last_seen']: + # special fields continue raise PyMISPError('The field {} is required in {} when generating a feed.'.format(field, self.__class__.__name__)) to_return = _int_to_str(to_return) diff --git a/pymisp/mispevent.py b/pymisp/mispevent.py index ef8a831..931d8a3 100644 --- a/pymisp/mispevent.py +++ b/pymisp/mispevent.py @@ -167,7 +167,7 @@ class MISPSighting(AbstractMISP): class MISPAttribute(AbstractMISP): _fields_for_feed: set = {'uuid', 'value', 'category', 'type', 'comment', 'data', - 'timestamp', 'to_ids', 'disable_correlation'} + 'timestamp', 'to_ids', 'disable_correlation', 'first_seen', 'last_seen'} def __init__(self, describe_types: Optional[dict]=None, strict: bool=False): """Represents an Attribute @@ -588,7 +588,7 @@ class MISPObject(AbstractMISP): _fields_for_feed: set = {'name', 'meta-category', 'description', 'template_uuid', 'template_version', 'uuid', 'timestamp', 'distribution', - 'sharing_group_id', 'comment'} + 'sharing_group_id', 'comment', 'first_seen', 'last_seen'} def __init__(self, name: str, strict: bool=False, standalone: bool=False, default_attributes_parameters: dict={}, **kwargs): ''' Master class representing a generic MISP object @@ -920,6 +920,7 @@ class MISPEvent(AbstractMISP): # This variable is used in add_attribute in order to avoid duplicating the structure self.describe_types = describe_types + self.uuid: str = str(uuid.uuid4()) self.date: date self.Attribute: List[MISPAttribute] = [] self.Object: List[MISPObject] = [] diff --git a/tests/test_mispevent.py b/tests/test_mispevent.py index 6e0c907..47ba56d 100644 --- a/tests/test_mispevent.py +++ b/tests/test_mispevent.py @@ -29,6 +29,7 @@ class TestMISPEvent(unittest.TestCase): def test_simple(self): with open('tests/mispevent_testfiles/simple.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_event(self): @@ -36,12 +37,14 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.publish() with open('tests/mispevent_testfiles/event.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_loadfile(self): self.mispevent.load_file('tests/mispevent_testfiles/event.json') with open('tests/mispevent_testfiles/event.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_event_tag(self): @@ -53,6 +56,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.add_tag(new_tag) with open('tests/mispevent_testfiles/event_tags.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_attribute(self): @@ -65,6 +69,7 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(attr_tags[0].name, 'osint') with open('tests/mispevent_testfiles/attribute.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) # Fake setting an attribute ID for testing self.mispevent.attributes[0].id = 42 @@ -94,6 +99,7 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(self.mispevent.objects[0].references[0].relationship_type, 'baz') with open('tests/mispevent_testfiles/event_obj_attr_tag.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) @unittest.skip("Not supported on MISP: https://github.com/MISP/MISP/issues/2638 - https://github.com/MISP/PyMISP/issues/168") @@ -116,6 +122,7 @@ class TestMISPEvent(unittest.TestCase): self.assertEqual(attribute.malware_binary, pseudofile) with open('tests/mispevent_testfiles/malware.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_existing_malware(self): @@ -173,6 +180,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[1].uuid = 'b' with open('tests/mispevent_testfiles/event_obj_def_param.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_obj_default_values(self): @@ -189,6 +197,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[0].uuid = 'a' with open('tests/mispevent_testfiles/def_param.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_event_not_edited(self): @@ -293,6 +302,7 @@ class TestMISPEvent(unittest.TestCase): self.mispevent.objects[0].uuid = 'a' with open('tests/mispevent_testfiles/misp_custom_obj.json', 'r') as f: ref_json = json.load(f) + del self.mispevent.uuid self.assertEqual(self.mispevent.to_json(sort_keys=True, indent=2), json.dumps(ref_json, sort_keys=True, indent=2)) def test_first_last_seen(self):