mirror of https://github.com/MISP/PyMISP
parent
bbc68f4f2d
commit
0d86a4339f
|
@ -640,8 +640,15 @@ class MISPObject(AbstractMISP):
|
||||||
self.name: str = name
|
self.name: str = name
|
||||||
self._known_template: bool = False
|
self._known_template: bool = False
|
||||||
self.id: int
|
self.id: int
|
||||||
|
self._definition: Optional[Dict]
|
||||||
|
|
||||||
self._set_template(kwargs.get('misp_objects_path_custom'))
|
misp_objects_template_custom = kwargs.pop('misp_objects_template_custom', None)
|
||||||
|
misp_objects_path_custom = kwargs.pop('misp_objects_path_custom', None)
|
||||||
|
if misp_objects_template_custom:
|
||||||
|
self._set_template(misp_objects_template_custom=misp_objects_template_custom)
|
||||||
|
else:
|
||||||
|
# Fall back to default path if None
|
||||||
|
self._set_template(misp_objects_path_custom=misp_objects_path_custom)
|
||||||
|
|
||||||
self.uuid: str = str(uuid.uuid4())
|
self.uuid: str = str(uuid.uuid4())
|
||||||
self.first_seen: datetime
|
self.first_seen: datetime
|
||||||
|
@ -679,14 +686,19 @@ class MISPObject(AbstractMISP):
|
||||||
self.standalone = standalone
|
self.standalone = standalone
|
||||||
|
|
||||||
def _load_template_path(self, template_path: Union[Path, str]) -> bool:
|
def _load_template_path(self, template_path: Union[Path, str]) -> bool:
|
||||||
self._definition: Optional[Dict] = self._load_json(template_path)
|
template = self._load_json(template_path)
|
||||||
if not self._definition:
|
if not template:
|
||||||
|
self._definition = None
|
||||||
return False
|
return False
|
||||||
|
self._load_template(template)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _load_template(self, template: Dict) -> None:
|
||||||
|
self._definition = template
|
||||||
setattr(self, 'meta-category', self._definition['meta-category'])
|
setattr(self, 'meta-category', self._definition['meta-category'])
|
||||||
self.template_uuid = self._definition['uuid']
|
self.template_uuid = self._definition['uuid']
|
||||||
self.description = self._definition['description']
|
self.description = self._definition['description']
|
||||||
self.template_version = self._definition['version']
|
self.template_version = self._definition['version']
|
||||||
return True
|
|
||||||
|
|
||||||
def _set_default(self):
|
def _set_default(self):
|
||||||
if not hasattr(self, 'comment'):
|
if not hasattr(self, 'comment'):
|
||||||
|
@ -715,16 +727,21 @@ class MISPObject(AbstractMISP):
|
||||||
self.name = object_name
|
self.name = object_name
|
||||||
self._set_template(misp_objects_path_custom)
|
self._set_template(misp_objects_path_custom)
|
||||||
|
|
||||||
def _set_template(self, misp_objects_path_custom: Optional[Union[Path, str]] = None):
|
def _set_template(self, misp_objects_path_custom: Optional[Union[Path, str]] = None, misp_objects_template_custom: Optional[Dict] = None):
|
||||||
if misp_objects_path_custom:
|
if misp_objects_template_custom:
|
||||||
# If misp_objects_path_custom is given, and an object with the given name exists, use that.
|
# A complete template was given to the constructor
|
||||||
if isinstance(misp_objects_path_custom, str):
|
self._load_template(misp_objects_template_custom)
|
||||||
self.misp_objects_path = Path(misp_objects_path_custom)
|
self._known_template = True
|
||||||
else:
|
else:
|
||||||
self.misp_objects_path = misp_objects_path_custom
|
if misp_objects_path_custom:
|
||||||
|
# If misp_objects_path_custom is given, and an object with the given name exists, use that.
|
||||||
|
if isinstance(misp_objects_path_custom, str):
|
||||||
|
self.misp_objects_path = Path(misp_objects_path_custom)
|
||||||
|
else:
|
||||||
|
self.misp_objects_path = misp_objects_path_custom
|
||||||
|
|
||||||
# Try to get the template
|
# Try to get the template
|
||||||
self._known_template = self._load_template_path(self.misp_objects_path / self.name / 'definition.json')
|
self._known_template = self._load_template_path(self.misp_objects_path / self.name / 'definition.json')
|
||||||
|
|
||||||
if not self._known_template and self._strict:
|
if not self._known_template and self._strict:
|
||||||
raise UnknownMISPObjectTemplate('{} is unknown in the MISP object directory.'.format(self.name))
|
raise UnknownMISPObjectTemplate('{} is unknown in the MISP object directory.'.format(self.name))
|
||||||
|
@ -789,6 +806,10 @@ class MISPObject(AbstractMISP):
|
||||||
else:
|
else:
|
||||||
self._known_template = False
|
self._known_template = False
|
||||||
|
|
||||||
|
# depending on how the object is initialized, we may have a few keys to pop
|
||||||
|
kwargs.pop('misp_objects_template_custom', None)
|
||||||
|
kwargs.pop('misp_objects_path_custom', None)
|
||||||
|
|
||||||
if 'distribution' in kwargs and kwargs['distribution'] is not None:
|
if 'distribution' in kwargs and kwargs['distribution'] is not None:
|
||||||
self.distribution = kwargs.pop('distribution')
|
self.distribution = kwargs.pop('distribution')
|
||||||
self.distribution = int(self.distribution)
|
self.distribution = int(self.distribution)
|
||||||
|
@ -903,9 +924,7 @@ class MISPObject(AbstractMISP):
|
||||||
else:
|
else:
|
||||||
attribute = MISPObjectAttribute({})
|
attribute = MISPObjectAttribute({})
|
||||||
# Overwrite the parameters of self._default_attributes_parameters with the ones of value
|
# Overwrite the parameters of self._default_attributes_parameters with the ones of value
|
||||||
attribute.from_dict(object_relation=object_relation, **dict(self._default_attributes_parameters, **value))
|
attribute.from_dict(object_relation=object_relation, **{**self._default_attributes_parameters, **value})
|
||||||
# FIXME New syntax python3 only, keep for later.
|
|
||||||
# attribute.from_dict(object_relation=object_relation, **{**self._default_attributes_parameters, **value})
|
|
||||||
self.__fast_attribute_access[object_relation].append(attribute)
|
self.__fast_attribute_access[object_relation].append(attribute)
|
||||||
self.Attribute.append(attribute)
|
self.Attribute.append(attribute)
|
||||||
self.edited = True
|
self.edited = True
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
"description": "TestTemplate.",
|
"description": "TestTemplate.",
|
||||||
"distribution": "5",
|
"distribution": "5",
|
||||||
"meta-category": "file",
|
"meta-category": "file",
|
||||||
"misp_objects_path_custom": "tests/mispevent_testfiles",
|
|
||||||
"name": "test_object_template",
|
"name": "test_object_template",
|
||||||
"sharing_group_id": "0",
|
"sharing_group_id": "0",
|
||||||
"template_uuid": "4ec55cc6-9e49-4c64-b794-03c25c1a6589",
|
"template_uuid": "4ec55cc6-9e49-4c64-b794-03c25c1a6589",
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import json
|
import json
|
||||||
import sys
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import glob
|
import glob
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -285,17 +284,47 @@ class TestMISPEvent(unittest.TestCase):
|
||||||
misp_obj = self.mispevent.get_object_by_id(1556)
|
misp_obj = self.mispevent.get_object_by_id(1556)
|
||||||
self.assertEqual(misp_obj.uuid, '5a3cd604-e11c-4de5-bbbf-c170950d210f')
|
self.assertEqual(misp_obj.uuid, '5a3cd604-e11c-4de5-bbbf-c170950d210f')
|
||||||
|
|
||||||
def test_userdefined_object(self):
|
def test_userdefined_object_custom_template(self):
|
||||||
|
self.init_event()
|
||||||
|
with open('tests/mispevent_testfiles/test_object_template/definition.json') as f:
|
||||||
|
template = json.load(f)
|
||||||
|
self.mispevent.add_object(name='test_object_template', strict=True,
|
||||||
|
misp_objects_template_custom=template)
|
||||||
|
with self.assertRaises(InvalidMISPObject) as e:
|
||||||
|
# Fail on required
|
||||||
|
self.mispevent.to_json(sort_keys=True, indent=2)
|
||||||
|
self.assertEqual(e.exception.message, '{\'member3\'} are required.')
|
||||||
|
|
||||||
|
a = self.mispevent.objects[0].add_attribute('member3', value='foo')
|
||||||
|
del a.uuid
|
||||||
|
with self.assertRaises(InvalidMISPObject) as e:
|
||||||
|
# Fail on requiredOneOf
|
||||||
|
self.mispevent.to_json(sort_keys=True, indent=2)
|
||||||
|
self.assertEqual(e.exception.message, 'At least one of the following attributes is required: member1, member2')
|
||||||
|
|
||||||
|
a = self.mispevent.objects[0].add_attribute('member1', value='bar')
|
||||||
|
del a.uuid
|
||||||
|
a = self.mispevent.objects[0].add_attribute('member1', value='baz')
|
||||||
|
del a.uuid
|
||||||
|
with self.assertRaises(InvalidMISPObject) as e:
|
||||||
|
# member1 is not a multiple
|
||||||
|
self.mispevent.to_json(sort_keys=True, indent=2)
|
||||||
|
self.assertEqual(e.exception.message, 'Multiple occurrences of member1 is not allowed')
|
||||||
|
|
||||||
|
self.mispevent.objects[0].attributes = self.mispevent.objects[0].attributes[:2]
|
||||||
|
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_userdefined_object_custom_dir(self):
|
||||||
self.init_event()
|
self.init_event()
|
||||||
self.mispevent.add_object(name='test_object_template', strict=True, misp_objects_path_custom='tests/mispevent_testfiles')
|
self.mispevent.add_object(name='test_object_template', strict=True, misp_objects_path_custom='tests/mispevent_testfiles')
|
||||||
with self.assertRaises(InvalidMISPObject) as e:
|
with self.assertRaises(InvalidMISPObject) as e:
|
||||||
# Fail on required
|
# Fail on required
|
||||||
self.mispevent.to_json(sort_keys=True, indent=2)
|
self.mispevent.to_json(sort_keys=True, indent=2)
|
||||||
if sys.version_info >= (3, ):
|
self.assertEqual(e.exception.message, '{\'member3\'} are required.')
|
||||||
self.assertEqual(e.exception.message, '{\'member3\'} are required.')
|
|
||||||
else:
|
|
||||||
# Python2 bullshit
|
|
||||||
self.assertEqual(e.exception.message, 'set([u\'member3\']) are required.')
|
|
||||||
|
|
||||||
a = self.mispevent.objects[0].add_attribute('member3', value='foo')
|
a = self.mispevent.objects[0].add_attribute('member3', value='foo')
|
||||||
del a.uuid
|
del a.uuid
|
||||||
|
|
Loading…
Reference in New Issue