diff --git a/stix2/base.py b/stix2/base.py index 229f78f..bae1f2c 100644 --- a/stix2/base.py +++ b/stix2/base.py @@ -327,7 +327,8 @@ class _Observable(_STIXBase): return # don't check if refs are valid if ref not in self._STIXBase__valid_refs: - raise InvalidObjRefError(self.__class__, prop_name, "'%s' is not a valid object in local scope" % ref) + if ref[:ref.index('--') + 2] not in self._STIXBase__valid_refs: + raise InvalidObjRefError(self.__class__, prop_name, "'%s' is not a valid object in local scope" % ref) try: allowed_types = prop.contained.valid_types diff --git a/stix2/properties.py b/stix2/properties.py index a217950..e8c8442 100644 --- a/stix2/properties.py +++ b/stix2/properties.py @@ -452,15 +452,22 @@ class ReferenceProperty(Property): possible_prefix = value[:value.index('--') + 2] if self.valid_types: - if possible_prefix in self.valid_types: + if self.valid_types == ["only_SDO"]: + self.valid_types = STIX2_OBJ_MAPS['v21']['objects'].keys() + elif self.valid_types == ["only_SCO"]: + self.valid_types = STIX2_OBJ_MAPS['v21']['observables'].keys() + elif self.valid_types == ["only_SCO_&_SRO"]: + self.valid_types = STIX2_OBJ_MAPS['v21']['observables'].keys() + ['relationship', 'sighting'] + + if possible_prefix[:-2] in self.valid_types: required_prefix = possible_prefix else: - raise ValueError("The type-specifying prefix for this identifier is invalid") + raise ValueError("The type-specifying prefix for this identifier is not valid") elif self.invalid_types: - if possible_prefix not in self.invalid_types: + if possible_prefix[:-2] not in self.invalid_types: required_prefix = possible_prefix else: - raise ValueError("The type-specifying prefix for this identifier is invalid") + raise ValueError("An invalid type-specifying prefix was specified for this identifier") _validate_id(value, self.spec_version, required_prefix) diff --git a/stix2/test/v21/test_utils.py b/stix2/test/v21/test_utils.py index dec3294..5cf88e4 100644 --- a/stix2/test/v21/test_utils.py +++ b/stix2/test/v21/test_utils.py @@ -135,14 +135,16 @@ def test_deduplicate(stix_objs1): "0": { "name": "foo.exe", "type": "file", + "id": "file--5956efbb-a7b0-566d-a7f9-a202eb05c70f", }, "1": { "type": "ipv4-addr", "value": "198.51.100.3", + "id": "ipv4-addr--1f8f4d63-9f33-5353-a3e3-e1b84c83a7b5", }, "2": { "type": "network-traffic", - "src_ref": "1", + "src_ref": "ipv4-addr--1f8f4d63-9f33-5353-a3e3-e1b84c83a7b5", "protocols": [ "tcp", "http", @@ -161,7 +163,7 @@ def test_deduplicate(stix_objs1): }, }, }, - ), ('1', {"type": "ipv4-addr", "value": "198.51.100.3"}), 1, + ), ('1', {"type": "ipv4-addr", "value": "198.51.100.3", "id": "ipv4-addr--1f8f4d63-9f33-5353-a3e3-e1b84c83a7b5"}), 1, ), ( { diff --git a/stix2/v20/sro.py b/stix2/v20/sro.py index 3b1e582..3f561b8 100644 --- a/stix2/v20/sro.py +++ b/stix2/v20/sro.py @@ -67,7 +67,7 @@ class Sighting(STIXRelationshipObject): ('first_seen', TimestampProperty()), ('last_seen', TimestampProperty()), ('count', IntegerProperty(min=0, max=999999999)), - ('sighting_of_ref', ReferenceProperty(valid_types="Left to user", spec_version='2.0', required=True)), + ('sighting_of_ref', ReferenceProperty(valid_types="only_SDO", 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)), diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py index cb7eff3..3062659 100644 --- a/stix2/v21/sdo.py +++ b/stix2/v21/sdo.py @@ -6,9 +6,11 @@ import warnings from six.moves.urllib.parse import quote_plus -from ..core import STIXDomainObject +from ..core import STIX2_OBJ_MAPS, STIXDomainObject from ..custom import _custom_object_builder -from ..exceptions import PropertyPresenceError, STIXDeprecationWarning +from ..exceptions import ( + InvalidValueError, PropertyPresenceError, STIXDeprecationWarning, +) from ..properties import ( BinaryProperty, BooleanProperty, EmbeddedObjectProperty, EnumProperty, FloatProperty, IDProperty, IntegerProperty, ListProperty, @@ -149,7 +151,7 @@ class Grouping(STIXDomainObject): ('name', StringProperty()), ('description', StringProperty()), ('context', StringProperty(required=True)), - ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('object_refs', ListProperty(ReferenceProperty(invalid_types=[""]), required=True)), ]) @@ -505,7 +507,7 @@ class MalwareAnalysis(STIXDomainObject): ('analysis_started', TimestampProperty()), ('analysis_ended', TimestampProperty()), ('av_result', StringProperty()), - ('analysis_sco_refs', ListProperty(ReferenceProperty(valid_types=None, spec_version='2.1'))), + ('analysis_sco_refs', ListProperty(ReferenceProperty(valid_types="only_SCO", spec_version='2.1'))), ]) def _check_object_constraints(self): @@ -531,7 +533,7 @@ class Note(STIXDomainObject): ('abstract', StringProperty()), ('content', StringProperty(required=True)), ('authors', ListProperty(StringProperty)), - ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('object_refs', ListProperty(ReferenceProperty(invalid_types=[""]), required=True)), ('revoked', BooleanProperty(default=lambda: False)), ('labels', ListProperty(StringProperty)), ('confidence', IntegerProperty()), @@ -560,7 +562,7 @@ class ObservedData(STIXDomainObject): ('last_observed', TimestampProperty(required=True)), ('number_observed', IntegerProperty(min=1, max=999999999, required=True)), ('objects', ObservableProperty(spec_version='2.1')), - ('object_refs', ListProperty(ReferenceProperty(valid_types=None, spec_version="2.1"))), + ('object_refs', ListProperty(ReferenceProperty(valid_types="only_SCO_&_SRO", spec_version="2.1"))), ('revoked', BooleanProperty(default=lambda: False)), ('labels', ListProperty(StringProperty)), ('confidence', IntegerProperty()), @@ -597,6 +599,14 @@ class ObservedData(STIXDomainObject): ["objects", "object_refs"], ) + if self.get('object_refs'): + for identifier in self.get('object_refs'): + identifier_prefix = identifier[:identifier.index('--') + 2] + if identifier_prefix in STIX2_OBJ_MAPS['v21']['observables'].keys(): + break + else: + raise InvalidValueError(self.__class__, 'object_refs', "At least one identifier must be of a SCO type if this property specified") + class Opinion(STIXDomainObject): # TODO: Add link @@ -625,7 +635,7 @@ class Opinion(STIXDomainObject): ], required=True, ), ), - ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('object_refs', ListProperty(ReferenceProperty(invalid_types=[""]), required=True)), ('revoked', BooleanProperty(default=lambda: False)), ('labels', ListProperty(StringProperty)), ('confidence', IntegerProperty()), @@ -654,7 +664,7 @@ class Report(STIXDomainObject): ('description', StringProperty()), ('report_types', ListProperty(StringProperty, required=True)), ('published', TimestampProperty(required=True)), - ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('object_refs', ListProperty(ReferenceProperty(invalid_types=[""]), required=True)), ('revoked', BooleanProperty(default=lambda: False)), ('labels', ListProperty(StringProperty)), ('confidence', IntegerProperty()), diff --git a/stix2/v21/sro.py b/stix2/v21/sro.py index 31f9c4c..57c7719 100644 --- a/stix2/v21/sro.py +++ b/stix2/v21/sro.py @@ -29,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=_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)), + ('source_ref', ReferenceProperty(invalid_types=_invalid_source_target_types, spec_version='2.1', required=True)), + ('target_ref', ReferenceProperty(invalid_types=_invalid_source_target_types, spec_version='2.1', required=True)), ('start_time', TimestampProperty()), ('stop_time', TimestampProperty()), ('revoked', BooleanProperty(default=lambda: False)), @@ -86,7 +86,7 @@ class Sighting(STIXRelationshipObject): ('first_seen', TimestampProperty()), ('last_seen', TimestampProperty()), ('count', IntegerProperty(min=0, max=999999999)), - ('sighting_of_ref', ReferenceProperty(valid_types="Left to user", spec_version='2.1', required=True)), + ('sighting_of_ref', ReferenceProperty(valid_types="only_SDO", 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()),