Some more updates, primarily to ReferenceProperty (and related code)
parent
5825118ad4
commit
f69b13a006
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')),
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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()),
|
||||
|
|
Loading…
Reference in New Issue