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 .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
ERROR_INVALID_ID = (
@ -417,15 +420,27 @@ class HexProperty(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
"""
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:
valid_types = [valid_types]
elif invalid_types and type(invalid_types) is not list:
invalid_types = [invalid_types]
self.valid_types = valid_types
self.invalid_types = invalid_types
super(ReferenceProperty, self).__init__(**kwargs)
@ -434,8 +449,18 @@ class ReferenceProperty(Property):
value = value.id
value = str(value)
if self.valid_types and value[:value.index('--')] in self.valid_types:
required_prefix = value[:value.index('--') + 2]
possible_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)

View File

@ -276,7 +276,7 @@ def test_boolean_property_invalid(value):
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")
with pytest.raises(ValueError):

View File

@ -271,7 +271,7 @@ def test_boolean_property_invalid(value):
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")
with pytest.raises(ValueError):

View File

@ -233,7 +233,7 @@ class Report(STIXDomainObject):
('name', StringProperty(required=True)),
('description', StringProperty()),
('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)),
('labels', ListProperty(StringProperty, required=True)),
('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>`__.
"""
_invalid_source_target_types = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting']
_type = 'relationship'
_properties = OrderedDict([
('type', TypeProperty(_type)),
@ -25,8 +27,8 @@ class Relationship(STIXRelationshipObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('relationship_type', StringProperty(required=True)),
('description', StringProperty()),
('source_ref', ReferenceProperty(valid_types=None, spec_version='2.0', required=True)),
('target_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(invalid_types=_invalid_source_target_types, spec_version='2.0', required=True)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('external_references', ListProperty(ExternalReference)),
@ -65,7 +67,7 @@ class Sighting(STIXRelationshipObject):
('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()),
('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'))),
('where_sighted_refs', ListProperty(ReferenceProperty(valid_types='identity', spec_version='2.0'))),
('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', 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.
('object_modified', TimestampProperty(precision='millisecond')),
# 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()),
('atime', TimestampProperty()),
('parent_directory_ref', ReferenceProperty(valid_types='directory')),
('contains_refs', ListProperty(ReferenceProperty())),
('contains_refs', ListProperty(ReferenceProperty(invalid_types=[""]))),
('content_ref', ReferenceProperty(valid_types='artifact')),
('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=_type)),
('spec_version', StringProperty(fixed='2.1')),

View File

@ -444,7 +444,7 @@ class Malware(STIXDomainObject):
('architecture_execution_envs', ListProperty(StringProperty)),
('implementation_languages', 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)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),

View File

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