Some more updates, primarily to ReferenceProperty (and related code)

master
Desai, Kartikey H 2019-08-29 17:15:51 -04:00
parent 5825118ad4
commit f69b13a006
9 changed files with 45 additions and 16 deletions

View File

@ -15,7 +15,10 @@ import stix2
from .base import _Observable, _STIXBase from .base import _Observable, _STIXBase
from .core import STIX2_OBJ_MAPS, parse, parse_observable from .core import STIX2_OBJ_MAPS, parse, parse_observable
from .exceptions import CustomContentError, DictionaryKeyError from .exceptions import (
CustomContentError, DictionaryKeyError, MissingPropertiesError,
MutuallyExclusivePropertiesError,
)
from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
ERROR_INVALID_ID = ( ERROR_INVALID_ID = (
@ -417,15 +420,27 @@ class HexProperty(Property):
class ReferenceProperty(Property): class ReferenceProperty(Property):
def __init__(self, valid_types=None, spec_version=stix2.DEFAULT_VERSION, **kwargs): def __init__(self, valid_types=None, invalid_types=None, spec_version=stix2.DEFAULT_VERSION, **kwargs):
""" """
references sometimes must be to a specific object type references sometimes must be to a specific object type
""" """
self.spec_version = spec_version self.spec_version = spec_version
# These checks need to be done prior to the STIX object finishing construction
# and thus we can't use base.py's _check_mutually_exclusive_properties()
# in the typical location of _check_object_constraints() in sdo.py
if valid_types and invalid_types:
raise MutuallyExclusivePropertiesError(self.__class__, ['invalid_types', 'valid_types'])
elif valid_types is None and invalid_types is None:
raise MissingPropertiesError(self.__class__, ['invalid_types', 'valid_types'])
if valid_types and type(valid_types) is not list: if valid_types and type(valid_types) is not list:
valid_types = [valid_types] valid_types = [valid_types]
elif invalid_types and type(invalid_types) is not list:
invalid_types = [invalid_types]
self.valid_types = valid_types self.valid_types = valid_types
self.invalid_types = invalid_types
super(ReferenceProperty, self).__init__(**kwargs) super(ReferenceProperty, self).__init__(**kwargs)
@ -434,8 +449,18 @@ class ReferenceProperty(Property):
value = value.id value = value.id
value = str(value) value = str(value)
if self.valid_types and value[:value.index('--')] in self.valid_types: possible_prefix = value[:value.index('--') + 2]
required_prefix = value[:value.index('--') + 2]
if self.valid_types:
if possible_prefix in self.valid_types:
required_prefix = possible_prefix
else:
raise ValueError("The type-specifying prefix for this identifier is invalid")
elif self.invalid_types:
if possible_prefix not in self.invalid_types:
required_prefix = possible_prefix
else:
raise ValueError("The type-specifying prefix for this identifier is invalid")
_validate_id(value, self.spec_version, required_prefix) _validate_id(value, self.spec_version, required_prefix)

View File

@ -276,7 +276,7 @@ def test_boolean_property_invalid(value):
def test_reference_property(): def test_reference_property():
ref_prop = ReferenceProperty(valid_types=None, spec_version="2.0") ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.0")
assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000") assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000")
with pytest.raises(ValueError): with pytest.raises(ValueError):

View File

@ -271,7 +271,7 @@ def test_boolean_property_invalid(value):
def test_reference_property(): def test_reference_property():
ref_prop = ReferenceProperty(valid_types=None, spec_version="2.1") ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.1")
assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000") assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000")
with pytest.raises(ValueError): with pytest.raises(ValueError):

View File

@ -233,7 +233,7 @@ class Report(STIXDomainObject):
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('published', TimestampProperty(required=True)), ('published', TimestampProperty(required=True)),
('object_refs', ListProperty(ReferenceProperty(valid_types=None, spec_version='2.0'), required=True)), ('object_refs', ListProperty(ReferenceProperty(invalid_types="", spec_version='2.0'), required=True)),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty, required=True)), ('labels', ListProperty(StringProperty, required=True)),
('external_references', ListProperty(ExternalReference)), ('external_references', ListProperty(ExternalReference)),

View File

@ -16,6 +16,8 @@ class Relationship(STIXRelationshipObject):
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714340>`__. `the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714340>`__.
""" """
_invalid_source_target_types = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting']
_type = 'relationship' _type = 'relationship'
_properties = OrderedDict([ _properties = OrderedDict([
('type', TypeProperty(_type)), ('type', TypeProperty(_type)),
@ -25,8 +27,8 @@ class Relationship(STIXRelationshipObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('relationship_type', StringProperty(required=True)), ('relationship_type', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('source_ref', ReferenceProperty(valid_types=None, spec_version='2.0', required=True)), ('source_ref', ReferenceProperty(invalid_types=_invalid_source_target_types, spec_version='2.0', required=True)),
('target_ref', ReferenceProperty(valid_types=None, spec_version='2.0', required=True)), ('target_ref', ReferenceProperty(invalid_types=_invalid_source_target_types, spec_version='2.0', required=True)),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)), ('labels', ListProperty(StringProperty)),
('external_references', ListProperty(ExternalReference)), ('external_references', ListProperty(ExternalReference)),
@ -65,7 +67,7 @@ class Sighting(STIXRelationshipObject):
('first_seen', TimestampProperty()), ('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()), ('last_seen', TimestampProperty()),
('count', IntegerProperty(min=0, max=999999999)), ('count', IntegerProperty(min=0, max=999999999)),
('sighting_of_ref', ReferenceProperty(valid_types=None, spec_version='2.0', required=True)), ('sighting_of_ref', ReferenceProperty(valid_types="Left to user", spec_version='2.0', required=True)),
('observed_data_refs', ListProperty(ReferenceProperty(valid_types='observed-data', spec_version='2.0'))), ('observed_data_refs', ListProperty(ReferenceProperty(valid_types='observed-data', spec_version='2.0'))),
('where_sighted_refs', ListProperty(ReferenceProperty(valid_types='identity', spec_version='2.0'))), ('where_sighted_refs', ListProperty(ReferenceProperty(valid_types='identity', spec_version='2.0'))),
('summary', BooleanProperty(default=lambda: False)), ('summary', BooleanProperty(default=lambda: False)),

View File

@ -77,7 +77,7 @@ class LanguageContent(_STIXBase):
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')), ('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('object_ref', ReferenceProperty(valid_types=None, spec_version='2.1', required=True)), ('object_ref', ReferenceProperty(invalid_types=[""], spec_version='2.1', required=True)),
# TODO: 'object_modified' it MUST be an exact match for the modified time of the STIX Object (SRO or SDO) being referenced. # TODO: 'object_modified' it MUST be an exact match for the modified time of the STIX Object (SRO or SDO) being referenced.
('object_modified', TimestampProperty(precision='millisecond')), ('object_modified', TimestampProperty(precision='millisecond')),
# TODO: 'contents' https://docs.google.com/document/d/1ShNq4c3e1CkfANmD9O--mdZ5H0O_GLnjN28a_yrEaco/edit#heading=h.cfz5hcantmvx # TODO: 'contents' https://docs.google.com/document/d/1ShNq4c3e1CkfANmD9O--mdZ5H0O_GLnjN28a_yrEaco/edit#heading=h.cfz5hcantmvx

View File

@ -385,7 +385,7 @@ class File(_Observable):
('mtime', TimestampProperty()), ('mtime', TimestampProperty()),
('atime', TimestampProperty()), ('atime', TimestampProperty()),
('parent_directory_ref', ReferenceProperty(valid_types='directory')), ('parent_directory_ref', ReferenceProperty(valid_types='directory')),
('contains_refs', ListProperty(ReferenceProperty())), ('contains_refs', ListProperty(ReferenceProperty(invalid_types=[""]))),
('content_ref', ReferenceProperty(valid_types='artifact')), ('content_ref', ReferenceProperty(valid_types='artifact')),
('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)), ('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
('spec_version', StringProperty(fixed='2.1')), ('spec_version', StringProperty(fixed='2.1')),

View File

@ -444,7 +444,7 @@ class Malware(STIXDomainObject):
('architecture_execution_envs', ListProperty(StringProperty)), ('architecture_execution_envs', ListProperty(StringProperty)),
('implementation_languages', ListProperty(StringProperty)), ('implementation_languages', ListProperty(StringProperty)),
('capabilities', ListProperty(StringProperty)), ('capabilities', ListProperty(StringProperty)),
('sample_refs', ListProperty(ReferenceProperty(valid_types=None, spec_version='2.1'))), ('sample_refs', ListProperty(ReferenceProperty(valid_types=['artifact', 'file'], spec_version='2.1'))),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)), ('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()), ('confidence', IntegerProperty()),

View File

@ -17,6 +17,8 @@ class Relationship(STIXRelationshipObject):
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <link here>`__.
""" """
_invalid_source_target_types = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting']
_type = 'relationship' _type = 'relationship'
_properties = OrderedDict([ _properties = OrderedDict([
('type', TypeProperty(_type)), ('type', TypeProperty(_type)),
@ -27,8 +29,8 @@ class Relationship(STIXRelationshipObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('relationship_type', StringProperty(required=True)), ('relationship_type', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('source_ref', ReferenceProperty(valid_types=None, spec_version='2.1', required=True)), ('source_ref', ReferenceProperty(valid_types=_invalid_source_target_types, spec_version='2.1', required=True)),
('target_ref', ReferenceProperty(valid_types=None, spec_version='2.1', required=True)), ('target_ref', ReferenceProperty(valid_types=_invalid_source_target_types, spec_version='2.1', required=True)),
('start_time', TimestampProperty()), ('start_time', TimestampProperty()),
('stop_time', TimestampProperty()), ('stop_time', TimestampProperty()),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
@ -84,7 +86,7 @@ class Sighting(STIXRelationshipObject):
('first_seen', TimestampProperty()), ('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()), ('last_seen', TimestampProperty()),
('count', IntegerProperty(min=0, max=999999999)), ('count', IntegerProperty(min=0, max=999999999)),
('sighting_of_ref', ReferenceProperty(valid_types=None, spec_version='2.1', required=True)), ('sighting_of_ref', ReferenceProperty(valid_types="Left to user", spec_version='2.1', required=True)),
('observed_data_refs', ListProperty(ReferenceProperty(valid_types='observed-data', spec_version='2.1'))), ('observed_data_refs', ListProperty(ReferenceProperty(valid_types='observed-data', spec_version='2.1'))),
('where_sighted_refs', ListProperty(ReferenceProperty(valid_types='identity', spec_version='2.1'))), ('where_sighted_refs', ListProperty(ReferenceProperty(valid_types='identity', spec_version='2.1'))),
('summary', BooleanProperty()), ('summary', BooleanProperty()),