Reuse reference regex to match IDs as well.
Note that this means that UUIDs will no longer be converted, even when there's an unambiguous mapping.stix2.0
parent
e749218f9b
commit
d2f703b9d0
|
@ -14,6 +14,17 @@ from .base import _STIXBase
|
||||||
from .exceptions import DictionaryKeyError
|
from .exceptions import DictionaryKeyError
|
||||||
from .utils import _get_dict, parse_into_datetime
|
from .utils import _get_dict, parse_into_datetime
|
||||||
|
|
||||||
|
# This uses the regular expression for a RFC 4122, Version 4 UUID. In the
|
||||||
|
# 8-4-4-4-12 hexadecimal representation, the first hex digit of the third
|
||||||
|
# component must be a 4, and the first hex digit of the fourth component must be
|
||||||
|
# 8, 9, a, or b (10xx bit pattern).
|
||||||
|
ID_REGEX = re.compile("^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type
|
||||||
|
"[0-9a-fA-F]{8}-"
|
||||||
|
"[0-9a-fA-F]{4}-"
|
||||||
|
"4[0-9a-fA-F]{3}-"
|
||||||
|
"[89abAB][0-9a-fA-F]{3}-"
|
||||||
|
"[0-9a-fA-F]{12}$")
|
||||||
|
|
||||||
|
|
||||||
class Property(object):
|
class Property(object):
|
||||||
"""Represent a property of STIX data type.
|
"""Represent a property of STIX data type.
|
||||||
|
@ -171,14 +182,9 @@ class IDProperty(Property):
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
if not value.startswith(self.required_prefix):
|
if not value.startswith(self.required_prefix):
|
||||||
raise ValueError("must start with '{0}'.".format(self.required_prefix))
|
raise ValueError("must start with '{0}'.".format(self.required_prefix))
|
||||||
try:
|
if not ID_REGEX.match(value):
|
||||||
type, orig_id = value.split('--', maxsplit=1)
|
|
||||||
new_uuid = uuid.UUID(orig_id)
|
|
||||||
if new_uuid.variant != uuid.RFC_4122 or new_uuid.version != 4:
|
|
||||||
raise ValueError()
|
|
||||||
except ValueError:
|
|
||||||
raise ValueError("must have a valid UUID after the prefix.")
|
raise ValueError("must have a valid UUID after the prefix.")
|
||||||
return "--".join([type, str(new_uuid)])
|
return value
|
||||||
|
|
||||||
def default(self):
|
def default(self):
|
||||||
return self.required_prefix + str(uuid.uuid4())
|
return self.required_prefix + str(uuid.uuid4())
|
||||||
|
@ -308,10 +314,6 @@ class HexProperty(Property):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
REF_REGEX = re.compile("^[a-z][a-z-]+[a-z]--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}"
|
|
||||||
"-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$")
|
|
||||||
|
|
||||||
|
|
||||||
class ReferenceProperty(Property):
|
class ReferenceProperty(Property):
|
||||||
|
|
||||||
def __init__(self, required=False, type=None):
|
def __init__(self, required=False, type=None):
|
||||||
|
@ -328,7 +330,7 @@ class ReferenceProperty(Property):
|
||||||
if self.type:
|
if self.type:
|
||||||
if not value.startswith(self.type):
|
if not value.startswith(self.type):
|
||||||
raise ValueError("must start with '{0}'.".format(self.type))
|
raise ValueError("must start with '{0}'.".format(self.type))
|
||||||
if not REF_REGEX.match(value):
|
if not ID_REGEX.match(value):
|
||||||
raise ValueError("must match <object-type>--<guid>.")
|
raise ValueError("must match <object-type>--<guid>.")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -123,23 +123,6 @@ def test_id_property_valid_for_type(value):
|
||||||
assert IDProperty(type=type).clean(value) == value
|
assert IDProperty(type=type).clean(value) == value
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("value", [
|
|
||||||
# These are all acceptable input formats that will get translated to the
|
|
||||||
# same ID shown above
|
|
||||||
MY_ID,
|
|
||||||
# These formats are all used in the uuid.UUID() documentation as valid ways
|
|
||||||
# to initialize a UUID. We are ok with accepting them, as they will
|
|
||||||
# get coerced to the right format for an ID.
|
|
||||||
'my-type--{232c9d3f-49fc-4440-bb01-607f638778e7}',
|
|
||||||
'my-type--232c9d3f49fc4440bb01607f638778e7',
|
|
||||||
'my-type--urn:uuid:232c9d3f-49fc-4440-bb01-607f638778e7',
|
|
||||||
# The extra "--" are ignored by split() and accepted by uuid.UUID()
|
|
||||||
'my-type--232c9d3f--49fc--4440--bb01--607f638778e7',
|
|
||||||
])
|
|
||||||
def test_id_property_transform(value):
|
|
||||||
assert ID_PROP.clean(value) == MY_ID
|
|
||||||
|
|
||||||
|
|
||||||
def test_id_property_wrong_type():
|
def test_id_property_wrong_type():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError) as excinfo:
|
||||||
ID_PROP.clean('not-my-type--232c9d3f-49fc-4440-bb01-607f638778e7')
|
ID_PROP.clean('not-my-type--232c9d3f-49fc-4440-bb01-607f638778e7')
|
||||||
|
|
Loading…
Reference in New Issue