Factored out more of the STIX identifier validity checking,
partly inspired by PR #263. This resulted in some error message format changes (an improvement, I think), which caused some unit test breakage. Removed those asserts from the unit tests, since tests shouldn't be testing human-targeted error messages.master
parent
ed106f23ff
commit
da5978d317
|
@ -41,6 +41,38 @@ def _check_uuid(uuid_str, spec_version):
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_id(id_, spec_version, required_prefix):
|
||||||
|
"""
|
||||||
|
Check the STIX identifier for correctness, raise an exception if there are
|
||||||
|
errors.
|
||||||
|
|
||||||
|
:param id_: The STIX identifier
|
||||||
|
:param spec_version: The STIX specification version to use
|
||||||
|
:param required_prefix: The required prefix on the identifier, if any.
|
||||||
|
This function doesn't add a "--" suffix to the prefix, so callers must
|
||||||
|
add it if it is important. Pass None to skip the prefix check.
|
||||||
|
:raises ValueError: If there are any errors with the identifier
|
||||||
|
"""
|
||||||
|
if required_prefix:
|
||||||
|
if not id_.startswith(required_prefix):
|
||||||
|
raise ValueError("must start with '{}'.".format(required_prefix))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if required_prefix:
|
||||||
|
uuid_part = id_[len(required_prefix):]
|
||||||
|
else:
|
||||||
|
idx = id_.index("--")
|
||||||
|
uuid_part = id_[idx+2:]
|
||||||
|
|
||||||
|
result = _check_uuid(uuid_part, spec_version)
|
||||||
|
except ValueError:
|
||||||
|
# replace their ValueError with ours
|
||||||
|
raise ValueError(ERROR_INVALID_ID.format(id_))
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
raise ValueError(ERROR_INVALID_ID.format(id_))
|
||||||
|
|
||||||
|
|
||||||
class Property(object):
|
class Property(object):
|
||||||
"""Represent a property of STIX data type.
|
"""Represent a property of STIX data type.
|
||||||
|
|
||||||
|
@ -198,19 +230,7 @@ class IDProperty(Property):
|
||||||
super(IDProperty, self).__init__()
|
super(IDProperty, self).__init__()
|
||||||
|
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
if not value.startswith(self.required_prefix):
|
_validate_id(value, self.spec_version, self.required_prefix)
|
||||||
raise ValueError("must start with '{}'.".format(self.required_prefix))
|
|
||||||
|
|
||||||
uuid_part = value[len(self.required_prefix):]
|
|
||||||
try:
|
|
||||||
result = _check_uuid(uuid_part, self.spec_version)
|
|
||||||
except ValueError:
|
|
||||||
# replace their ValueError with ours
|
|
||||||
raise ValueError(ERROR_INVALID_ID.format(value))
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
raise ValueError(ERROR_INVALID_ID.format(value))
|
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def default(self):
|
def default(self):
|
||||||
|
@ -396,26 +416,7 @@ class ReferenceProperty(Property):
|
||||||
value = value.id
|
value = value.id
|
||||||
value = str(value)
|
value = str(value)
|
||||||
|
|
||||||
if self.required_prefix:
|
_validate_id(value, self.spec_version, self.required_prefix)
|
||||||
if not value.startswith(self.required_prefix):
|
|
||||||
raise ValueError(
|
|
||||||
"must start with '{}'.".format(self.required_prefix),
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if self.required_prefix:
|
|
||||||
uuid_part = value[len(self.required_prefix):]
|
|
||||||
else:
|
|
||||||
idx = value.index("--")
|
|
||||||
uuid_part = value[idx+2:]
|
|
||||||
|
|
||||||
result = _check_uuid(uuid_part, self.spec_version)
|
|
||||||
except ValueError:
|
|
||||||
# replace their ValueError with ours
|
|
||||||
raise ValueError(ERROR_INVALID_ID.format(value))
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
raise ValueError(ERROR_INVALID_ID.format(value))
|
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,6 @@ def test_indicator_created_ref_invalid_format():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v20.Indicator
|
assert excinfo.value.cls == stix2.v20.Indicator
|
||||||
assert excinfo.value.prop_name == "created_by_ref"
|
assert excinfo.value.prop_name == "created_by_ref"
|
||||||
assert excinfo.value.reason == "must start with 'identity'."
|
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
|
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_revoked_invalid():
|
def test_indicator_revoked_invalid():
|
||||||
|
|
|
@ -87,8 +87,6 @@ def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v20.Report
|
assert excinfo.value.cls == stix2.v20.Report
|
||||||
assert excinfo.value.prop_name == "object_refs"
|
assert excinfo.value.prop_name == "object_refs"
|
||||||
assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID
|
|
||||||
assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
@ -59,8 +59,6 @@ def test_sighting_bad_where_sighted_refs():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v20.Sighting
|
assert excinfo.value.cls == stix2.v20.Sighting
|
||||||
assert excinfo.value.prop_name == "where_sighted_refs"
|
assert excinfo.value.prop_name == "where_sighted_refs"
|
||||||
assert excinfo.value.reason == "must start with 'identity'."
|
|
||||||
assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
|
|
||||||
|
|
||||||
|
|
||||||
def test_sighting_type_must_be_sightings():
|
def test_sighting_type_must_be_sightings():
|
||||||
|
@ -69,8 +67,6 @@ def test_sighting_type_must_be_sightings():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v20.Sighting
|
assert excinfo.value.cls == stix2.v20.Sighting
|
||||||
assert excinfo.value.prop_name == "type"
|
assert excinfo.value.prop_name == "type"
|
||||||
assert excinfo.value.reason == "must equal 'sighting'."
|
|
||||||
assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'."
|
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_sighting():
|
def test_invalid_kwarg_to_sighting():
|
||||||
|
|
|
@ -116,8 +116,6 @@ def test_indicator_created_ref_invalid_format():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v21.Indicator
|
assert excinfo.value.cls == stix2.v21.Indicator
|
||||||
assert excinfo.value.prop_name == "created_by_ref"
|
assert excinfo.value.prop_name == "created_by_ref"
|
||||||
assert excinfo.value.reason == "must start with 'identity'."
|
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
|
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_revoked_invalid():
|
def test_indicator_revoked_invalid():
|
||||||
|
|
|
@ -88,8 +88,6 @@ def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v21.Report
|
assert excinfo.value.cls == stix2.v21.Report
|
||||||
assert excinfo.value.prop_name == "object_refs"
|
assert excinfo.value.prop_name == "object_refs"
|
||||||
assert excinfo.value.reason == stix2.properties.ERROR_INVALID_ID
|
|
||||||
assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
@ -61,8 +61,6 @@ def test_sighting_bad_where_sighted_refs():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v21.Sighting
|
assert excinfo.value.cls == stix2.v21.Sighting
|
||||||
assert excinfo.value.prop_name == "where_sighted_refs"
|
assert excinfo.value.prop_name == "where_sighted_refs"
|
||||||
assert excinfo.value.reason == "must start with 'identity'."
|
|
||||||
assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
|
|
||||||
|
|
||||||
|
|
||||||
def test_sighting_type_must_be_sightings():
|
def test_sighting_type_must_be_sightings():
|
||||||
|
|
Loading…
Reference in New Issue