From 067d76bb90405f05073daf71adcc05e7076559b6 Mon Sep 17 00:00:00 2001 From: chrisr3d Date: Wed, 5 Dec 2018 23:18:55 +0100 Subject: [PATCH] chg: Added parameter to accept UUIDs not v4 - This parameter is not used at the creation of STIX objects, only while converting json format into STIX objects.1 --- stix2/core.py | 26 ++++++++++++++------------ stix2/properties.py | 15 +++++++++++++-- stix2/v20/common.py | 1 + stix2/v20/sdo.py | 8 +++++++- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/stix2/core.py b/stix2/core.py index af74a9e..0985193 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -14,8 +14,9 @@ from .utils import _get_dict, get_class_hierarchy_names class STIXObjectProperty(Property): - def __init__(self, allow_custom=False, *args, **kwargs): + def __init__(self, allow_custom=False, interoperability=False, *args, **kwargs): self.allow_custom = allow_custom + self.interoperability = interoperability super(STIXObjectProperty, self).__init__(*args, **kwargs) def clean(self, value): @@ -33,11 +34,7 @@ class STIXObjectProperty(Property): if 'type' in dictified and dictified['type'] == 'bundle': raise ValueError('This property may not contain a Bundle object') - if self.allow_custom: - parsed_obj = parse(dictified, allow_custom=True) - else: - parsed_obj = parse(dictified) - return parsed_obj + return parse(dictified, self.allow_custom, self.interoperability) class Bundle(_STIXBase): @@ -62,8 +59,13 @@ class Bundle(_STIXBase): else: kwargs['objects'] = list(args) + kwargs.get('objects', []) - self.__allow_custom = kwargs.get('allow_custom', False) - self._properties['objects'].contained.allow_custom = kwargs.get('allow_custom', False) + allow_custom = kwargs.get('allow_custom', False) + self.__allow_custom = allow_custom + self._properties['objects'].contained.allow_custom = allow_custom + interoperability = kwargs.get('interoperability', False) + self.__interoperability = interoperability + self._properties['id'].interoperability = interoperability + self._properties['objects'].contained.interoperability = interoperability super(Bundle, self).__init__(**kwargs) @@ -71,7 +73,7 @@ class Bundle(_STIXBase): STIX2_OBJ_MAPS = {} -def parse(data, allow_custom=False, version=None): +def parse(data, allow_custom=False, interoperability=False, version=None): """Convert a string, dict or file-like object into a STIX object. Args: @@ -97,12 +99,12 @@ def parse(data, allow_custom=False, version=None): obj = _get_dict(data) # convert dict to full python-stix2 obj - obj = dict_to_stix2(obj, allow_custom, version) + obj = dict_to_stix2(obj, allow_custom, interoperability, version) return obj -def dict_to_stix2(stix_dict, allow_custom=False, version=None): +def dict_to_stix2(stix_dict, allow_custom=False, interoperability=False, version=None): """convert dictionary to full python-stix2 object Args: @@ -144,7 +146,7 @@ def dict_to_stix2(stix_dict, allow_custom=False, version=None): return stix_dict raise exceptions.ParseError("Can't parse unknown object type '%s'! For custom types, use the CustomObject decorator." % stix_dict['type']) - return obj_class(allow_custom=allow_custom, **stix_dict) + return obj_class(allow_custom=allow_custom, interoperability=interoperability, **stix_dict) def _register_type(new_type, version=None): diff --git a/stix2/properties.py b/stix2/properties.py index b52c026..baf9cf3 100644 --- a/stix2/properties.py +++ b/stix2/properties.py @@ -25,6 +25,13 @@ ID_REGEX = re.compile("^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type "[89abAB][0-9a-fA-F]{3}-" "[0-9a-fA-F]{12}$") +ID_REGEX_interoperability = re.compile("^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type + "[0-9a-fA-F]{8}-" + "[0-9a-fA-F]{4}-" + "[0-9a-fA-F]{4}-" + "[0-9a-fA-F]{4}-" + "[0-9a-fA-F]{12}$") + ERROR_INVALID_ID = ( "not a valid STIX identifier, must match --" ) @@ -185,8 +192,12 @@ class IDProperty(Property): def clean(self, value): if not value.startswith(self.required_prefix): raise ValueError("must start with '{0}'.".format(self.required_prefix)) - if not ID_REGEX.match(value): - raise ValueError(ERROR_INVALID_ID) + if hasattr(self, 'interoperability') and self.interoperability: + if not ID_REGEX_interoperability.match(value): + raise ValueError(ERROR_INVALID_ID) + else: + if not ID_REGEX.match(value): + raise ValueError(ERROR_INVALID_ID) return value def default(self): diff --git a/stix2/v20/common.py b/stix2/v20/common.py index d574c92..612ec46 100644 --- a/stix2/v20/common.py +++ b/stix2/v20/common.py @@ -135,6 +135,7 @@ class MarkingDefinition(_STIXBase, _MarkingsMixin): if not isinstance(kwargs['definition'], marking_type): defn = _get_dict(kwargs['definition']) kwargs['definition'] = marking_type(**defn) + self._properties['id'].interoperability = kwargs.get('interoperability', False) super(MarkingDefinition, self).__init__(**kwargs) diff --git a/stix2/v20/sdo.py b/stix2/v20/sdo.py index 1a688d1..b6fe37c 100644 --- a/stix2/v20/sdo.py +++ b/stix2/v20/sdo.py @@ -17,7 +17,13 @@ from .observables import ObservableProperty class STIXDomainObject(_STIXBase, _MarkingsMixin): - pass + def __init__(self, *args, **kwargs): + interoperability = kwargs.get('interoperability', False) + self.__interoperability = interoperability + self._properties['id'].interoperability = interoperability + self._properties['created_by_ref'].interoperability = interoperability + + super(STIXDomainObject, self).__init__(*args, **kwargs) class AttackPattern(STIXDomainObject):