Add support in ReferenceProperty for hybrid object type

constraints (i.e. both generic type categories and specific
types).  Also:
- more expansion/refinement of reference property unit tests
- bugfix: SROs are in OBJ_MAP too, it's not just SDOs!  Oops...
- pre-commit stylistic fixes
pull/1/head
Michael Chisholm 2020-06-27 20:03:33 -04:00
parent 986404b7b7
commit 414694d8fa
6 changed files with 222 additions and 149 deletions

View File

@ -8,10 +8,7 @@ import re
import uuid
from .base import _STIXBase
from .exceptions import (
CustomContentError, DictionaryKeyError, MissingPropertiesError,
MutuallyExclusivePropertiesError, STIXError,
)
from .exceptions import CustomContentError, DictionaryKeyError, STIXError
from .parsing import parse, parse_observable
from .registry import STIX2_OBJ_MAPS
from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
@ -503,7 +500,7 @@ class ReferenceProperty(Property):
(valid_types is None and invalid_types is None):
raise ValueError(
"Exactly one of 'valid_types' and 'invalid_types' must be "
"given"
"given",
)
if valid_types and not isinstance(valid_types, list):
@ -517,21 +514,6 @@ class ReferenceProperty(Property):
self.types = set(valid_types or invalid_types)
self.auth_type = self._WHITELIST if valid_types else self._BLACKLIST
# Handling both generic and non-generic types in the same constraint
# complicates life... let's keep it simple unless we really need the
# complexity.
self.generic_constraint = any(
t in self._OBJECT_CATEGORIES for t in self.types
)
if self.generic_constraint and any(
t not in self._OBJECT_CATEGORIES for t in self.types
):
raise ValueError(
"Generic type categories and specific types may not both be "
"given"
)
super(ReferenceProperty, self).__init__(**kwargs)
def clean(self, value, allow_custom):
@ -543,10 +525,19 @@ class ReferenceProperty(Property):
obj_type = value[:value.index('--')]
types = self.types
# Only comes into play when inverting a hybrid whitelist.
# E.g. if the possible generic categories are A, B, C, then the
# inversion of whitelist constraint "A or x" (where x is a specific
# type) is something like "[not (B or C)] or x". In other words, we
# invert the generic categories to produce a blacklist, but leave the
# specific categories alone; they essentially become exceptions to our
# blacklist.
blacklist_exceptions = set()
generics = self.types & self._OBJECT_CATEGORIES
specifics = self.types - generics
auth_type = self.auth_type
if allow_custom and auth_type == self._WHITELIST and \
self.generic_constraint:
if allow_custom and auth_type == self._WHITELIST and generics:
# If allowing customization and using a whitelist, and if generic
# "category" types were given, we need to allow custom object types
# of those categories. Unless registered, it's impossible to know
@ -554,60 +545,40 @@ class ReferenceProperty(Property):
# permissive approach and allow any type which is not known to be
# in the wrong category. I.e. flip the whitelist set to a
# blacklist of a complementary set.
types = self._OBJECT_CATEGORIES - types
auth_type = self._BLACKLIST
generics = self._OBJECT_CATEGORIES - generics
blacklist_exceptions, specifics = specifics, blacklist_exceptions
if auth_type == self._WHITELIST:
# allow_custom is not applicable to "whitelist" style object type
# constraints, so we ignore it.
has_custom = False
if self.generic_constraint:
type_ok = _type_in_generic_set(
obj_type, types, self.spec_version
)
else:
type_ok = obj_type in types
if not type_ok:
raise ValueError(
"The type-specifying prefix '%s' for this property is not "
"valid" % obj_type
)
type_ok = _type_in_generic_set(
obj_type, generics, self.spec_version
) or obj_type in specifics
else:
# A type "blacklist" was used to describe legal object types. We
# must enforce the type blacklist regardless of allow_custom.
if self.generic_constraint:
type_ok = not _type_in_generic_set(
obj_type, types, self.spec_version
type_ok = (
not _type_in_generic_set(
obj_type, generics, self.spec_version,
)
else:
type_ok = obj_type not in types
and obj_type not in specifics
) or obj_type in blacklist_exceptions
if not type_ok:
raise ValueError(
"The type-specifying prefix '%s' for this property is not "
"valid" % obj_type
)
if not type_ok:
raise ValueError(
"The type-specifying prefix '%s' for this property is not "
"valid" % obj_type,
)
# allow_custom=True only allows references to custom objects which
# are not otherwise blacklisted. We need to figure out whether
# the referenced object is custom or not. No good way to do that
# at present... just check if unregistered and for the "x-" type
# prefix, for now?
type_maps = STIX2_OBJ_MAPS[self.spec_version]
# We need to figure out whether the referenced object is custom or
# not. No good way to do that at present... just check if
# unregistered and for the "x-" type prefix, for now?
has_custom = not _type_in_generic_set(
obj_type, self._OBJECT_CATEGORIES, self.spec_version,
) or obj_type.startswith("x-")
has_custom = obj_type not in type_maps["objects"] \
and obj_type not in type_maps["observables"] \
and obj_type not in ["relationship", "sighting"]
has_custom = has_custom or obj_type.startswith("x-")
if not allow_custom and has_custom:
raise CustomContentError(
"reference to custom object type: " + obj_type,
)
if not allow_custom and has_custom:
raise CustomContentError(
"reference to custom object type: " + obj_type,
)
return value, has_custom
@ -624,7 +595,9 @@ def _type_in_generic_set(type_, type_set, spec_version):
result = False
for type_id in type_set:
if type_id == "SDO":
result = type_ in type_maps["objects"]
result = type_ in type_maps["objects"] and type_ not in [
"relationship", "sighting",
] # sigh
elif type_id == "SCO":
result = type_ in type_maps["observables"]
elif type_id == "SRO":

View File

@ -84,19 +84,21 @@ def test_id_property_default():
assert ID_PROP.clean(default) == (default, False)
def test_reference_property():
ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.0")
def test_reference_property_whitelist_standard_type():
ref_prop = ReferenceProperty(valid_types="identity", spec_version="2.0")
result = ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
assert result == ("identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000", False)
with pytest.raises(ValueError):
ref_prop.clean("foo", False)
ref_prop.clean("foo--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
# This is not a valid V4 UUID
with pytest.raises(ValueError):
ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000", False)
ref_prop.clean("foo--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
def test_reference_property_whitelist_type():
def test_reference_property_whitelist_custom_type():
ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.0")
with pytest.raises(ValueError):
@ -105,16 +107,18 @@ def test_reference_property_whitelist_type():
with pytest.raises(ValueError):
ref_prop.clean("not-my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
# This is the whitelisted type, but it's still custom, and
# customization is disallowed here.
ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_whitelist_generic_type():
ref_prop = ReferenceProperty(
valid_types=["SCO", "SRO"], spec_version="2.0"
valid_types=["SCO", "SRO"], spec_version="2.0",
)
result = ref_prop.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
@ -124,12 +128,19 @@ def test_reference_property_whitelist_generic_type():
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean(
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
assert result == ("sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# The prop assumes some-type is a custom type of one of the generic
# type categories.
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
@ -143,7 +154,7 @@ def test_reference_property_whitelist_generic_type():
ref_prop.clean("identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_blacklist_type():
def test_reference_property_blacklist_standard_type():
ref_prop = ReferenceProperty(invalid_types="identity", spec_version="2.0")
result = ref_prop.clean(
"malware--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
@ -155,6 +166,11 @@ def test_reference_property_blacklist_type():
)
assert result == ("malware--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
@ -170,15 +186,10 @@ def test_reference_property_blacklist_type():
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
def test_reference_property_blacklist_generic_type():
ref_prop = ReferenceProperty(
invalid_types=["SDO", "SRO"], spec_version="2.0"
invalid_types=["SDO", "SRO"], spec_version="2.0",
)
result = ref_prop.clean(
@ -191,16 +202,16 @@ def test_reference_property_blacklist_generic_type():
)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(ValueError):
ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
@ -208,7 +219,7 @@ def test_reference_property_blacklist_generic_type():
with pytest.raises(ValueError):
ref_prop.clean(
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(ValueError):
@ -216,18 +227,57 @@ def test_reference_property_blacklist_generic_type():
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
with pytest.raises(CustomContentError):
with pytest.raises(ValueError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
def test_reference_property_hybrid_constraint_type():
with pytest.raises(ValueError):
ReferenceProperty(valid_types=["a", "SCO"], spec_version="2.0")
def test_reference_property_whitelist_hybrid_type():
p = ReferenceProperty(valid_types=["a", "SCO"], spec_version="2.0")
result = p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
# although whitelisted, "a" is a custom type
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
ReferenceProperty(invalid_types=["a", "SCO"], spec_version="2.0")
p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# should just assume "b" is a custom SCO type.
result = p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_blacklist_hybrid_type():
p = ReferenceProperty(invalid_types=["a", "SCO"], spec_version="2.0")
with pytest.raises(ValueError):
p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(ValueError):
p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(ValueError):
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(CustomContentError):
p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# should just assume "b" is a custom type which is not an SCO
result = p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_impossible_constraint():

View File

@ -144,8 +144,8 @@ def test_report_on_custom():
published="2016-01-20T17:00:00Z",
object_refs=[
"indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7"
]
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7",
],
)
report = stix2.v20.Report(
@ -154,10 +154,10 @@ def test_report_on_custom():
published="2016-01-20T17:00:00Z",
object_refs=[
"indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7"
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7",
],
allow_custom=True,
)
assert "some-type--2672975a-ce1e-4473-a1c6-0d79868930c7" \
in report.object_refs
in report.object_refs

View File

@ -91,7 +91,7 @@ def test_malware_analysis_custom_sco_refs():
product="super scanner",
analysis_sco_refs=[
"file--6e8c78cf-4bcc-4729-9265-86a97bfc91ba",
"some-object--f6bfc147-e844-4578-ae01-847979890239"
"some-object--f6bfc147-e844-4578-ae01-847979890239",
],
allow_custom=True,
)
@ -105,8 +105,8 @@ def test_malware_analysis_custom_sco_refs():
product="super scanner",
analysis_sco_refs=[
"file--6e8c78cf-4bcc-4729-9265-86a97bfc91ba",
"some-object--f6bfc147-e844-4578-ae01-847979890239"
]
"some-object--f6bfc147-e844-4578-ae01-847979890239",
],
)
with pytest.raises(stix2.exceptions.InvalidValueError):
@ -115,7 +115,7 @@ def test_malware_analysis_custom_sco_refs():
analysis_sco_refs=[
"file--6e8c78cf-4bcc-4729-9265-86a97bfc91ba",
# standard object type; wrong category (not SCO)
"identity--56977a19-49ef-49d7-b259-f733fa4b7bbc"
"identity--56977a19-49ef-49d7-b259-f733fa4b7bbc",
],
allow_custom=True,
)

View File

@ -8,7 +8,7 @@ from stix2.exceptions import (
from stix2.properties import (
DictionaryProperty, EmbeddedObjectProperty, ExtensionsProperty,
HashesProperty, IDProperty, ListProperty, ObservableProperty,
ReferenceProperty, STIXObjectProperty, StringProperty, TypeProperty,
ReferenceProperty, STIXObjectProperty, StringProperty,
)
from stix2.v21.common import MarkingProperty
@ -87,19 +87,21 @@ def test_id_property_default():
assert ID_PROP.clean(default) == (default, False)
def test_reference_property():
ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.1")
def test_reference_property_whitelist_standard_type():
ref_prop = ReferenceProperty(valid_types="identity", spec_version="2.1")
result = ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
assert result == ("identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert ref_prop.clean("my-type--00000000-0000-4000-8000-000000000000", False)
with pytest.raises(ValueError):
ref_prop.clean("foo", False)
ref_prop.clean("foo--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
# This is not a valid RFC 4122 UUID
with pytest.raises(ValueError):
ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000", False)
ref_prop.clean("foo--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
def test_reference_property_whitelist_type():
def test_reference_property_whitelist_custom_type():
ref_prop = ReferenceProperty(valid_types="my-type", spec_version="2.1")
with pytest.raises(ValueError):
@ -108,16 +110,18 @@ def test_reference_property_whitelist_type():
with pytest.raises(ValueError):
ref_prop.clean("not-my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
# This is the whitelisted type, but it's still custom, and
# customization is disallowed here.
ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("my-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_whitelist_generic_type():
ref_prop = ReferenceProperty(
valid_types=["SCO", "SRO"], spec_version="2.1"
valid_types=["SCO", "SRO"], spec_version="2.1",
)
result = ref_prop.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
@ -127,12 +131,19 @@ def test_reference_property_whitelist_generic_type():
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean(
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
assert result == ("sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True
"sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("sighting--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# The prop assumes some-type is a custom type of one of the generic
# type categories.
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
@ -146,7 +157,7 @@ def test_reference_property_whitelist_generic_type():
ref_prop.clean("identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_blacklist_type():
def test_reference_property_blacklist_standard_type():
ref_prop = ReferenceProperty(invalid_types="identity", spec_version="2.1")
result = ref_prop.clean(
"location--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
@ -158,6 +169,11 @@ def test_reference_property_blacklist_type():
)
assert result == ("location--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
@ -173,15 +189,10 @@ def test_reference_property_blacklist_type():
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
def test_reference_property_blacklist_generic_type():
ref_prop = ReferenceProperty(
invalid_types=["SDO", "SRO"], spec_version="2.1"
invalid_types=["SDO", "SRO"], spec_version="2.1",
)
result = ref_prop.clean(
@ -194,16 +205,16 @@ def test_reference_property_blacklist_generic_type():
)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
result = ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
assert result == ("some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(ValueError):
ref_prop.clean(
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
@ -211,7 +222,7 @@ def test_reference_property_blacklist_generic_type():
with pytest.raises(ValueError):
ref_prop.clean(
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
"identity--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
with pytest.raises(ValueError):
@ -219,18 +230,57 @@ def test_reference_property_blacklist_generic_type():
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
)
with pytest.raises(CustomContentError):
with pytest.raises(ValueError):
ref_prop.clean(
"some-type--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False,
"relationship--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True,
)
def test_reference_property_hybrid_constraint_type():
with pytest.raises(ValueError):
ReferenceProperty(valid_types=["a", "SCO"], spec_version="2.1")
def test_reference_property_whitelist_hybrid_type():
p = ReferenceProperty(valid_types=["a", "SCO"], spec_version="2.1")
result = p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(CustomContentError):
# although whitelisted, "a" is a custom type
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
result = p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
ReferenceProperty(invalid_types=["a", "SCO"], spec_version="2.1")
p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# should just assume "b" is a custom SCO type.
result = p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_blacklist_hybrid_type():
p = ReferenceProperty(invalid_types=["a", "SCO"], spec_version="2.1")
with pytest.raises(ValueError):
p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(ValueError):
p.clean("file--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(ValueError):
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
with pytest.raises(ValueError):
p.clean("a--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
with pytest.raises(CustomContentError):
p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", False)
# should just assume "b" is a custom type which is not an SCO
result = p.clean("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
assert result == ("b--8a8e8758-f92c-4058-ba38-f061cd42a0cf", True)
def test_reference_property_impossible_constraint():

View File

@ -4,12 +4,12 @@ import pytest
import pytz
import stix2
from stix2.exceptions import InvalidValueError
from .constants import (
CAMPAIGN_ID, IDENTITY_ID, INDICATOR_ID, INDICATOR_KWARGS, RELATIONSHIP_ID,
REPORT_ID,
)
from stix2.exceptions import InvalidValueError
EXPECTED = """{
"type": "report",
@ -144,8 +144,8 @@ def test_report_on_custom():
published="2016-01-20T17:00:00Z",
object_refs=[
"indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7"
]
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7",
],
)
report = stix2.v21.Report(
@ -153,10 +153,10 @@ def test_report_on_custom():
published="2016-01-20T17:00:00Z",
object_refs=[
"indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7"
"some-type--2672975a-ce1e-4473-a1c6-0d79868930c7",
],
allow_custom=True,
)
assert "some-type--2672975a-ce1e-4473-a1c6-0d79868930c7" \
in report.object_refs
in report.object_refs