Add exception for invalid Property values.
parent
3c17c9259c
commit
2aa1f5cedd
|
@ -9,3 +9,5 @@ from .sdo import AttackPattern, Campaign, CourseOfAction, Identity, Indicator, \
|
||||||
Vulnerability
|
Vulnerability
|
||||||
from .sro import Relationship, Sighting
|
from .sro import Relationship, Sighting
|
||||||
from .markings import MarkingDefinition, GranularMarking, StatementMarking, TLPMarking
|
from .markings import MarkingDefinition, GranularMarking, StatementMarking, TLPMarking
|
||||||
|
|
||||||
|
from . import exceptions
|
||||||
|
|
|
@ -4,6 +4,7 @@ import collections
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from .exceptions import STIXValueError
|
||||||
from .utils import format_datetime, get_timestamp, NOW
|
from .utils import format_datetime, get_timestamp, NOW
|
||||||
|
|
||||||
__all__ = ['STIXJSONEncoder', '_STIXBase']
|
__all__ = ['STIXJSONEncoder', '_STIXBase']
|
||||||
|
@ -41,10 +42,7 @@ class _STIXBase(collections.Mapping):
|
||||||
try:
|
try:
|
||||||
kwargs[prop_name] = prop.validate(kwargs[prop_name])
|
kwargs[prop_name] = prop.validate(kwargs[prop_name])
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
msg = "Invalid value for {0} '{1}': {2}"
|
raise STIXValueError(self.__class__, prop_name, reason=str(exc))
|
||||||
raise ValueError(msg.format(self.__class__.__name__,
|
|
||||||
prop_name,
|
|
||||||
exc))
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
cls = self.__class__
|
cls = self.__class__
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
class STIXError(Exception):
|
||||||
|
"""Base class for errors generated in the stix2 library."""
|
||||||
|
|
||||||
|
|
||||||
|
class STIXValueError(STIXError, ValueError):
|
||||||
|
"""An invalid value was provided to a STIX object's __init__."""
|
||||||
|
|
||||||
|
def __init__(self, cls, prop_name, reason):
|
||||||
|
self.cls = cls
|
||||||
|
self.prop_name = prop_name
|
||||||
|
self.reason = reason
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "Invalid value for {0.cls.__name__} '{0.prop_name}': {0.reason}"
|
||||||
|
return msg.format(self)
|
|
@ -158,5 +158,5 @@ class SelectorProperty(Property):
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
if not SELECTOR_REGEX.match(value):
|
if not SELECTOR_REGEX.match(value):
|
||||||
raise ValueError("values must adhere to selector syntax")
|
raise ValueError("must adhere to selector syntax.")
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -51,23 +51,32 @@ def test_empty_bundle():
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_with_wrong_type():
|
def test_bundle_with_wrong_type():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Bundle(type="not-a-bundle")
|
stix2.Bundle(type="not-a-bundle")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'bundle'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'type': must equal 'bundle'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'type': must equal 'bundle'."
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_id_must_start_with_bundle():
|
def test_bundle_id_must_start_with_bundle():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Bundle(id='my-prefix--')
|
stix2.Bundle(id='my-prefix--')
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'bundle--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'id': must start with 'bundle--'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'id': must start with 'bundle--'."
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_with_wrong_spec_version():
|
def test_bundle_with_wrong_spec_version():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Bundle(spec_version="1.2")
|
stix2.Bundle(spec_version="1.2")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "spec_version"
|
||||||
|
assert excinfo.value.reason == "must equal '2.0'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'spec_version': must equal '2.0'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'spec_version': must equal '2.0'."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,16 +67,22 @@ def test_indicator_autogenerated_fields(indicator):
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_type_must_be_indicator():
|
def test_indicator_type_must_be_indicator():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Indicator(type='xxx', **INDICATOR_KWARGS)
|
stix2.Indicator(type='xxx', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'indicator'."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'type': must equal 'indicator'."
|
assert str(excinfo.value) == "Invalid value for Indicator 'type': must equal 'indicator'."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_id_must_start_with_indicator():
|
def test_indicator_id_must_start_with_indicator():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Indicator(id='my-prefix--', **INDICATOR_KWARGS)
|
stix2.Indicator(id='my-prefix--', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'indicator--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'id': must start with 'indicator--'."
|
assert str(excinfo.value) == "Invalid value for Indicator 'id': must start with 'indicator--'."
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,14 +99,22 @@ def test_indicator_required_field_pattern():
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_created_ref_invalid_format():
|
def test_indicator_created_ref_invalid_format():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Indicator(created_by_ref='myprefix--12345678', **INDICATOR_KWARGS)
|
stix2.Indicator(created_by_ref='myprefix--12345678', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
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'."
|
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():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Indicator(revoked='false', **INDICATOR_KWARGS)
|
stix2.Indicator(revoked='false', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "revoked"
|
||||||
|
assert excinfo.value.reason == "must be a boolean value."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'revoked': must be a boolean value."
|
assert str(excinfo.value) == "Invalid value for Indicator 'revoked': must be a boolean value."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,16 +51,22 @@ def test_malware_autogenerated_fields(malware):
|
||||||
|
|
||||||
|
|
||||||
def test_malware_type_must_be_malware():
|
def test_malware_type_must_be_malware():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Malware(type='xxx', **MALWARE_KWARGS)
|
stix2.Malware(type='xxx', **MALWARE_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'malware'."
|
||||||
assert str(excinfo.value) == "Invalid value for Malware 'type': must equal 'malware'."
|
assert str(excinfo.value) == "Invalid value for Malware 'type': must equal 'malware'."
|
||||||
|
|
||||||
|
|
||||||
def test_malware_id_must_start_with_malware():
|
def test_malware_id_must_start_with_malware():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Malware(id='my-prefix--', **MALWARE_KWARGS)
|
stix2.Malware(id='my-prefix--', **MALWARE_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'malware--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Malware 'id': must start with 'malware--'."
|
assert str(excinfo.value) == "Invalid value for Malware 'id': must start with 'malware--'."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -87,13 +87,16 @@ def test_granular_example():
|
||||||
|
|
||||||
|
|
||||||
def test_granular_example_with_bad_selector():
|
def test_granular_example_with_bad_selector():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.GranularMarking(
|
stix2.GranularMarking(
|
||||||
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
|
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
|
||||||
selectors=["abc[0]"] # missing "."
|
selectors=["abc[0]"] # missing "."
|
||||||
)
|
)
|
||||||
|
|
||||||
assert str(excinfo.value) == "Invalid value for GranularMarking 'selectors': values must adhere to selector syntax"
|
assert excinfo.value.cls == stix2.GranularMarking
|
||||||
|
assert excinfo.value.prop_name == "selectors"
|
||||||
|
assert excinfo.value.reason == "must adhere to selector syntax."
|
||||||
|
assert str(excinfo.value) == "Invalid value for GranularMarking 'selectors': must adhere to selector syntax."
|
||||||
|
|
||||||
|
|
||||||
def test_campaign_with_granular_markings_example():
|
def test_campaign_with_granular_markings_example():
|
||||||
|
|
|
@ -54,16 +54,22 @@ def test_relationship_autogenerated_fields(relationship):
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_type_must_be_relationship():
|
def test_relationship_type_must_be_relationship():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS)
|
stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'relationship'."
|
||||||
assert str(excinfo.value) == "Invalid value for Relationship 'type': must equal 'relationship'."
|
assert str(excinfo.value) == "Invalid value for Relationship 'type': must equal 'relationship'."
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_id_must_start_with_relationship():
|
def test_relationship_id_must_start_with_relationship():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS)
|
stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'relationship--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Relationship 'id': must start with 'relationship--'."
|
assert str(excinfo.value) == "Invalid value for Relationship 'id': must start with 'relationship--'."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ def test_report_example_objects_in_object_refs():
|
||||||
|
|
||||||
|
|
||||||
def test_report_example_objects_in_object_refs_with_bad_id():
|
def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Report(
|
stix2.Report(
|
||||||
id="report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
|
id="report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
|
||||||
created_by_ref="identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
|
created_by_ref="identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
|
||||||
|
@ -80,6 +80,9 @@ def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Report
|
||||||
|
assert excinfo.value.prop_name == "object_refs"
|
||||||
|
assert excinfo.value.reason == "must match <object-type>--<guid>."
|
||||||
assert str(excinfo.value) == "Invalid value for Report 'object_refs': must match <object-type>--<guid>."
|
assert str(excinfo.value) == "Invalid value for Report 'object_refs': must match <object-type>--<guid>."
|
||||||
|
|
||||||
# TODO: Add other examples
|
# TODO: Add other examples
|
||||||
|
|
|
@ -48,7 +48,7 @@ def test_sighting_all_required_fields():
|
||||||
def test_sighting_bad_where_sighted_refs():
|
def test_sighting_bad_where_sighted_refs():
|
||||||
now = dt.datetime(2016, 4, 6, 20, 6, 37, tzinfo=pytz.utc)
|
now = dt.datetime(2016, 4, 6, 20, 6, 37, tzinfo=pytz.utc)
|
||||||
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Sighting(
|
stix2.Sighting(
|
||||||
type='sighting',
|
type='sighting',
|
||||||
id=SIGHTING_ID,
|
id=SIGHTING_ID,
|
||||||
|
@ -58,13 +58,19 @@ def test_sighting_bad_where_sighted_refs():
|
||||||
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
|
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Sighting
|
||||||
|
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'."
|
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():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.STIXValueError) as excinfo:
|
||||||
stix2.Sighting(type='xxx', **SIGHTING_KWARGS)
|
stix2.Sighting(type='xxx', **SIGHTING_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Sighting
|
||||||
|
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'."
|
assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'."
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue