Merge branch 'master' into parsing
commit
76acd8c0c2
|
@ -10,6 +10,7 @@ from .sdo import AttackPattern, Campaign, CourseOfAction, Identity, Indicator, \
|
||||||
Vulnerability
|
Vulnerability
|
||||||
from .sro import Relationship, Sighting
|
from .sro import Relationship, Sighting
|
||||||
from .utils import get_dict
|
from .utils import get_dict
|
||||||
|
from . import exceptions
|
||||||
|
|
||||||
|
|
||||||
def parse(data):
|
def parse(data):
|
||||||
|
|
|
@ -4,6 +4,8 @@ import collections
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from .exceptions import ExtraFieldsError, ImmutableError, InvalidValueError, \
|
||||||
|
MissingFieldsError
|
||||||
from .utils import format_datetime, get_timestamp, NOW
|
from .utils import format_datetime, get_timestamp, NOW
|
||||||
|
|
||||||
__all__ = ['STIXJSONEncoder', '_STIXBase']
|
__all__ = ['STIXJSONEncoder', '_STIXBase']
|
||||||
|
@ -41,14 +43,10 @@ class _STIXBase(collections.Mapping):
|
||||||
try:
|
try:
|
||||||
kwargs[prop_name] = prop.clean(kwargs[prop_name])
|
kwargs[prop_name] = prop.clean(kwargs[prop_name])
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
msg = "Invalid value for {0} '{1}': {2}"
|
raise InvalidValueError(self.__class__, prop_name, reason=str(exc))
|
||||||
raise ValueError(msg.format(self.__class__.__name__,
|
|
||||||
prop_name,
|
|
||||||
exc))
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
cls = self.__class__
|
cls = self.__class__
|
||||||
class_name = cls.__name__
|
|
||||||
|
|
||||||
# Use the same timestamp for any auto-generated datetimes
|
# Use the same timestamp for any auto-generated datetimes
|
||||||
self.__now = get_timestamp()
|
self.__now = get_timestamp()
|
||||||
|
@ -56,15 +54,13 @@ class _STIXBase(collections.Mapping):
|
||||||
# Detect any keyword arguments not allowed for a specific type
|
# Detect any keyword arguments not allowed for a specific type
|
||||||
extra_kwargs = list(set(kwargs) - set(cls._properties))
|
extra_kwargs = list(set(kwargs) - set(cls._properties))
|
||||||
if extra_kwargs:
|
if extra_kwargs:
|
||||||
raise TypeError("unexpected keyword arguments: " + str(extra_kwargs))
|
raise ExtraFieldsError(cls, extra_kwargs)
|
||||||
|
|
||||||
# Detect any missing required fields
|
# Detect any missing required fields
|
||||||
required_fields = get_required_properties(cls._properties)
|
required_fields = get_required_properties(cls._properties)
|
||||||
missing_kwargs = set(required_fields) - set(kwargs)
|
missing_kwargs = set(required_fields) - set(kwargs)
|
||||||
if missing_kwargs:
|
if missing_kwargs:
|
||||||
msg = "Missing required field(s) for {type}: ({fields})."
|
raise MissingFieldsError(cls, missing_kwargs)
|
||||||
field_list = ", ".join(x for x in sorted(list(missing_kwargs)))
|
|
||||||
raise ValueError(msg.format(type=class_name, fields=field_list))
|
|
||||||
|
|
||||||
for prop_name, prop_metadata in cls._properties.items():
|
for prop_name, prop_metadata in cls._properties.items():
|
||||||
self._check_property(prop_name, prop_metadata, kwargs)
|
self._check_property(prop_name, prop_metadata, kwargs)
|
||||||
|
@ -91,8 +87,7 @@ class _STIXBase(collections.Mapping):
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name != '_inner' and not name.startswith("_STIXBase__"):
|
if name != '_inner' and not name.startswith("_STIXBase__"):
|
||||||
print(name)
|
raise ImmutableError
|
||||||
raise ValueError("Cannot modify properties after creation.")
|
|
||||||
super(_STIXBase, self).__setattr__(name, value)
|
super(_STIXBase, self).__setattr__(name, value)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
class STIXError(Exception):
|
||||||
|
"""Base class for errors generated in the stix2 library."""
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidValueError(STIXError, ValueError):
|
||||||
|
"""An invalid value was provided to a STIX object's __init__."""
|
||||||
|
|
||||||
|
def __init__(self, cls, prop_name, reason):
|
||||||
|
super(InvalidValueError, self).__init__()
|
||||||
|
self.cls = cls
|
||||||
|
self.prop_name = prop_name
|
||||||
|
self.reason = reason
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "Invalid value for {0.cls.__name__} '{0.prop_name}': {0.reason}"
|
||||||
|
return msg.format(self)
|
||||||
|
|
||||||
|
|
||||||
|
class MissingFieldsError(STIXError, ValueError):
|
||||||
|
"""Missing required field(s) when constructing STIX object."""
|
||||||
|
|
||||||
|
def __init__(self, cls, fields):
|
||||||
|
super(MissingFieldsError, self).__init__()
|
||||||
|
self.cls = cls
|
||||||
|
self.fields = sorted(list(fields))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "Missing required field(s) for {0}: ({1})."
|
||||||
|
return msg.format(self.cls.__name__,
|
||||||
|
", ".join(x for x in self.fields))
|
||||||
|
|
||||||
|
|
||||||
|
class ExtraFieldsError(STIXError, TypeError):
|
||||||
|
"""Extra field(s) were provided when constructing STIX object."""
|
||||||
|
|
||||||
|
def __init__(self, cls, fields):
|
||||||
|
super(ExtraFieldsError, self).__init__()
|
||||||
|
self.cls = cls
|
||||||
|
self.fields = sorted(list(fields))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = "Unexpected field(s) for {0}: ({1})."
|
||||||
|
return msg.format(self.cls.__name__,
|
||||||
|
", ".join(x for x in self.fields))
|
||||||
|
|
||||||
|
|
||||||
|
class ImmutableError(STIXError, ValueError):
|
||||||
|
"""Attempted to modify an object after creation"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(ImmutableError, self).__init__("Cannot modify properties after creation.")
|
|
@ -240,5 +240,5 @@ class SelectorProperty(Property):
|
||||||
|
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
if not SELECTOR_REGEX.match(value):
|
if not SELECTOR_REGEX.match(value):
|
||||||
raise ValueError("values must adhere to selector syntax")
|
raise ValueError("must adhere to selector syntax.")
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -51,23 +51,32 @@ def test_empty_bundle():
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_with_wrong_type():
|
def test_bundle_with_wrong_type():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Bundle(type="not-a-bundle")
|
stix2.Bundle(type="not-a-bundle")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'bundle'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'type': must equal 'bundle'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'type': must equal 'bundle'."
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_id_must_start_with_bundle():
|
def test_bundle_id_must_start_with_bundle():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Bundle(id='my-prefix--')
|
stix2.Bundle(id='my-prefix--')
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'bundle--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'id': must start with 'bundle--'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'id': must start with 'bundle--'."
|
||||||
|
|
||||||
|
|
||||||
def test_bundle_with_wrong_spec_version():
|
def test_bundle_with_wrong_spec_version():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Bundle(spec_version="1.2")
|
stix2.Bundle(spec_version="1.2")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Bundle
|
||||||
|
assert excinfo.value.prop_name == "spec_version"
|
||||||
|
assert excinfo.value.reason == "must equal '2.0'."
|
||||||
assert str(excinfo.value) == "Invalid value for Bundle 'spec_version': must equal '2.0'."
|
assert str(excinfo.value) == "Invalid value for Bundle 'spec_version': must equal '2.0'."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,9 @@ def test_external_reference_offline():
|
||||||
|
|
||||||
|
|
||||||
def test_external_reference_source_required():
|
def test_external_reference_source_required():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.ExternalReference()
|
stix2.ExternalReference()
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.ExternalReference
|
||||||
|
assert excinfo.value.fields == ["source_name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for ExternalReference: (source_name)."
|
assert str(excinfo.value) == "Missing required field(s) for ExternalReference: (source_name)."
|
||||||
|
|
|
@ -69,54 +69,76 @@ def test_indicator_autogenerated_fields(indicator):
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_type_must_be_indicator():
|
def test_indicator_type_must_be_indicator():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Indicator(type='xxx', **INDICATOR_KWARGS)
|
stix2.Indicator(type='xxx', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'indicator'."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'type': must equal 'indicator'."
|
assert str(excinfo.value) == "Invalid value for Indicator 'type': must equal 'indicator'."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_id_must_start_with_indicator():
|
def test_indicator_id_must_start_with_indicator():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Indicator(id='my-prefix--', **INDICATOR_KWARGS)
|
stix2.Indicator(id='my-prefix--', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'indicator--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'id': must start with 'indicator--'."
|
assert str(excinfo.value) == "Invalid value for Indicator 'id': must start with 'indicator--'."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_required_fields():
|
def test_indicator_required_fields():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Indicator()
|
stix2.Indicator()
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.fields == ["labels", "pattern"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Indicator: (labels, pattern)."
|
assert str(excinfo.value) == "Missing required field(s) for Indicator: (labels, pattern)."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_required_field_pattern():
|
def test_indicator_required_field_pattern():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Indicator(labels=['malicious-activity'])
|
stix2.Indicator(labels=['malicious-activity'])
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.fields == ["pattern"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Indicator: (pattern)."
|
assert str(excinfo.value) == "Missing required field(s) for Indicator: (pattern)."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_created_ref_invalid_format():
|
def test_indicator_created_ref_invalid_format():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Indicator(created_by_ref='myprefix--12345678', **INDICATOR_KWARGS)
|
stix2.Indicator(created_by_ref='myprefix--12345678', **INDICATOR_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "created_by_ref"
|
||||||
|
assert excinfo.value.reason == "must start with 'identity'."
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
|
assert str(excinfo.value) == "Invalid value for Indicator 'created_by_ref': must start with 'identity'."
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_revoked_invalid():
|
def test_indicator_revoked_invalid():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Indicator(revoked='no', **INDICATOR_KWARGS)
|
stix2.Indicator(revoked='no', **INDICATOR_KWARGS)
|
||||||
assert str(excinfo.value) == "Invalid value for Indicator 'revoked': must be a boolean value."
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.prop_name == "revoked"
|
||||||
|
assert excinfo.value.reason == "must be a boolean value."
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_assign_to_indicator_attributes(indicator):
|
def test_cannot_assign_to_indicator_attributes(indicator):
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
indicator.valid_from = dt.datetime.now()
|
indicator.valid_from = dt.datetime.now()
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify properties after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_indicator():
|
def test_invalid_kwarg_to_indicator():
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo:
|
||||||
stix2.Indicator(my_custom_property="foo", **INDICATOR_KWARGS)
|
stix2.Indicator(my_custom_property="foo", **INDICATOR_KWARGS)
|
||||||
assert str(excinfo.value) == "unexpected keyword arguments: ['my_custom_property']"
|
|
||||||
|
assert excinfo.value.cls == stix2.Indicator
|
||||||
|
assert excinfo.value.fields == ['my_custom_property']
|
||||||
|
assert str(excinfo.value) == "Unexpected field(s) for Indicator: (my_custom_property)."
|
||||||
|
|
||||||
|
|
||||||
def test_created_modified_time_are_identical_by_default():
|
def test_created_modified_time_are_identical_by_default():
|
||||||
|
|
|
@ -36,23 +36,29 @@ def test_kill_chain_example():
|
||||||
|
|
||||||
def test_kill_chain_required_fields():
|
def test_kill_chain_required_fields():
|
||||||
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.KillChainPhase()
|
stix2.KillChainPhase()
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.KillChainPhase
|
||||||
|
assert excinfo.value.fields == ["kill_chain_name", "phase_name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (kill_chain_name, phase_name)."
|
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (kill_chain_name, phase_name)."
|
||||||
|
|
||||||
|
|
||||||
def test_kill_chain_required_field_chain_name():
|
def test_kill_chain_required_field_chain_name():
|
||||||
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.KillChainPhase(phase_name="weaponization")
|
stix2.KillChainPhase(phase_name="weaponization")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.KillChainPhase
|
||||||
|
assert excinfo.value.fields == ["kill_chain_name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (kill_chain_name)."
|
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (kill_chain_name)."
|
||||||
|
|
||||||
|
|
||||||
def test_kill_chain_required_field_phase_name():
|
def test_kill_chain_required_field_phase_name():
|
||||||
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.KillChainPhase(kill_chain_name="lockheed-martin-cyber-kill-chain")
|
stix2.KillChainPhase(kill_chain_name="lockheed-martin-cyber-kill-chain")
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.KillChainPhase
|
||||||
|
assert excinfo.value.fields == ["phase_name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (phase_name)."
|
assert str(excinfo.value) == "Missing required field(s) for KillChainPhase: (phase_name)."
|
||||||
|
|
|
@ -52,42 +52,57 @@ def test_malware_autogenerated_fields(malware):
|
||||||
|
|
||||||
|
|
||||||
def test_malware_type_must_be_malware():
|
def test_malware_type_must_be_malware():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Malware(type='xxx', **MALWARE_KWARGS)
|
stix2.Malware(type='xxx', **MALWARE_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'malware'."
|
||||||
assert str(excinfo.value) == "Invalid value for Malware 'type': must equal 'malware'."
|
assert str(excinfo.value) == "Invalid value for Malware 'type': must equal 'malware'."
|
||||||
|
|
||||||
|
|
||||||
def test_malware_id_must_start_with_malware():
|
def test_malware_id_must_start_with_malware():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Malware(id='my-prefix--', **MALWARE_KWARGS)
|
stix2.Malware(id='my-prefix--', **MALWARE_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'malware--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Malware 'id': must start with 'malware--'."
|
assert str(excinfo.value) == "Invalid value for Malware 'id': must start with 'malware--'."
|
||||||
|
|
||||||
|
|
||||||
def test_malware_required_fields():
|
def test_malware_required_fields():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Malware()
|
stix2.Malware()
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.fields == ["labels", "name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Malware: (labels, name)."
|
assert str(excinfo.value) == "Missing required field(s) for Malware: (labels, name)."
|
||||||
|
|
||||||
|
|
||||||
def test_malware_required_field_name():
|
def test_malware_required_field_name():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Malware(labels=['ransomware'])
|
stix2.Malware(labels=['ransomware'])
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.fields == ["name"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Malware: (name)."
|
assert str(excinfo.value) == "Missing required field(s) for Malware: (name)."
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_assign_to_malware_attributes(malware):
|
def test_cannot_assign_to_malware_attributes(malware):
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
malware.name = "Cryptolocker II"
|
malware.name = "Cryptolocker II"
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify properties after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_malware():
|
def test_invalid_kwarg_to_malware():
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo:
|
||||||
stix2.Malware(my_custom_property="foo", **MALWARE_KWARGS)
|
stix2.Malware(my_custom_property="foo", **MALWARE_KWARGS)
|
||||||
assert str(excinfo.value) == "unexpected keyword arguments: ['my_custom_property']"
|
|
||||||
|
assert excinfo.value.cls == stix2.Malware
|
||||||
|
assert excinfo.value.fields == ['my_custom_property']
|
||||||
|
assert str(excinfo.value) == "Unexpected field(s) for Malware: (my_custom_property)."
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("data", [
|
@pytest.mark.parametrize("data", [
|
||||||
|
|
|
@ -91,13 +91,16 @@ def test_granular_example():
|
||||||
|
|
||||||
|
|
||||||
def test_granular_example_with_bad_selector():
|
def test_granular_example_with_bad_selector():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.GranularMarking(
|
stix2.GranularMarking(
|
||||||
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
|
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
|
||||||
selectors=["abc[0]"] # missing "."
|
selectors=["abc[0]"] # missing "."
|
||||||
)
|
)
|
||||||
|
|
||||||
assert str(excinfo.value) == "Invalid value for GranularMarking 'selectors': values must adhere to selector syntax"
|
assert excinfo.value.cls == stix2.GranularMarking
|
||||||
|
assert excinfo.value.prop_name == "selectors"
|
||||||
|
assert excinfo.value.reason == "must adhere to selector syntax."
|
||||||
|
assert str(excinfo.value) == "Invalid value for GranularMarking 'selectors': must adhere to selector syntax."
|
||||||
|
|
||||||
|
|
||||||
def test_campaign_with_granular_markings_example():
|
def test_campaign_with_granular_markings_example():
|
||||||
|
|
|
@ -54,51 +54,63 @@ def test_relationship_autogenerated_fields(relationship):
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_type_must_be_relationship():
|
def test_relationship_type_must_be_relationship():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS)
|
stix2.Relationship(type='xxx', **RELATIONSHIP_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'relationship'."
|
||||||
assert str(excinfo.value) == "Invalid value for Relationship 'type': must equal 'relationship'."
|
assert str(excinfo.value) == "Invalid value for Relationship 'type': must equal 'relationship'."
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_id_must_start_with_relationship():
|
def test_relationship_id_must_start_with_relationship():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS)
|
stix2.Relationship(id='my-prefix--', **RELATIONSHIP_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.prop_name == "id"
|
||||||
|
assert excinfo.value.reason == "must start with 'relationship--'."
|
||||||
assert str(excinfo.value) == "Invalid value for Relationship 'id': must start with 'relationship--'."
|
assert str(excinfo.value) == "Invalid value for Relationship 'id': must start with 'relationship--'."
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_required_field_relationship_type():
|
def test_relationship_required_field_relationship_type():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Relationship()
|
stix2.Relationship()
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Relationship: (relationship_type, source_ref, target_ref)."
|
assert str(excinfo.value) == "Missing required field(s) for Relationship: (relationship_type, source_ref, target_ref)."
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_missing_some_required_fields():
|
def test_relationship_missing_some_required_fields():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Relationship(relationship_type='indicates')
|
stix2.Relationship(relationship_type='indicates')
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Relationship: (source_ref, target_ref)."
|
assert str(excinfo.value) == "Missing required field(s) for Relationship: (source_ref, target_ref)."
|
||||||
|
|
||||||
|
|
||||||
def test_relationship_required_field_target_ref():
|
def test_relationship_required_field_target_ref():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.MissingFieldsError) as excinfo:
|
||||||
stix2.Relationship(
|
stix2.Relationship(
|
||||||
relationship_type='indicates',
|
relationship_type='indicates',
|
||||||
source_ref=INDICATOR_ID
|
source_ref=INDICATOR_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.fields == ["target_ref"]
|
||||||
assert str(excinfo.value) == "Missing required field(s) for Relationship: (target_ref)."
|
assert str(excinfo.value) == "Missing required field(s) for Relationship: (target_ref)."
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_assign_to_relationship_attributes(relationship):
|
def test_cannot_assign_to_relationship_attributes(relationship):
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.ImmutableError) as excinfo:
|
||||||
relationship.relationship_type = "derived-from"
|
relationship.relationship_type = "derived-from"
|
||||||
|
|
||||||
assert str(excinfo.value) == "Cannot modify properties after creation."
|
assert str(excinfo.value) == "Cannot modify properties after creation."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_relationship():
|
def test_invalid_kwarg_to_relationship():
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo:
|
||||||
stix2.Relationship(my_custom_property="foo", **RELATIONSHIP_KWARGS)
|
stix2.Relationship(my_custom_property="foo", **RELATIONSHIP_KWARGS)
|
||||||
assert str(excinfo.value) == "unexpected keyword arguments: ['my_custom_property']" in str(excinfo)
|
|
||||||
|
assert excinfo.value.cls == stix2.Relationship
|
||||||
|
assert excinfo.value.fields == ['my_custom_property']
|
||||||
|
assert str(excinfo.value) == "Unexpected field(s) for Relationship: (my_custom_property)."
|
||||||
|
|
||||||
|
|
||||||
def test_create_relationship_from_objects_rather_than_ids(indicator, malware):
|
def test_create_relationship_from_objects_rather_than_ids(indicator, malware):
|
||||||
|
|
|
@ -65,7 +65,7 @@ def test_report_example_objects_in_object_refs():
|
||||||
|
|
||||||
|
|
||||||
def test_report_example_objects_in_object_refs_with_bad_id():
|
def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Report(
|
stix2.Report(
|
||||||
id="report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
|
id="report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
|
||||||
created_by_ref="identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
|
created_by_ref="identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
|
||||||
|
@ -82,6 +82,9 @@ def test_report_example_objects_in_object_refs_with_bad_id():
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Report
|
||||||
|
assert excinfo.value.prop_name == "object_refs"
|
||||||
|
assert excinfo.value.reason == "must match <object-type>--<guid>."
|
||||||
assert str(excinfo.value) == "Invalid value for Report 'object_refs': must match <object-type>--<guid>."
|
assert str(excinfo.value) == "Invalid value for Report 'object_refs': must match <object-type>--<guid>."
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ def test_sighting_all_required_fields():
|
||||||
def test_sighting_bad_where_sighted_refs():
|
def test_sighting_bad_where_sighted_refs():
|
||||||
now = dt.datetime(2016, 4, 6, 20, 6, 37, tzinfo=pytz.utc)
|
now = dt.datetime(2016, 4, 6, 20, 6, 37, tzinfo=pytz.utc)
|
||||||
|
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Sighting(
|
stix2.Sighting(
|
||||||
type='sighting',
|
type='sighting',
|
||||||
id=SIGHTING_ID,
|
id=SIGHTING_ID,
|
||||||
|
@ -58,20 +58,29 @@ def test_sighting_bad_where_sighted_refs():
|
||||||
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
|
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Sighting
|
||||||
|
assert excinfo.value.prop_name == "where_sighted_refs"
|
||||||
|
assert excinfo.value.reason == "must start with 'identity'."
|
||||||
assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
|
assert str(excinfo.value) == "Invalid value for Sighting 'where_sighted_refs': must start with 'identity'."
|
||||||
|
|
||||||
|
|
||||||
def test_sighting_type_must_be_sightings():
|
def test_sighting_type_must_be_sightings():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.Sighting(type='xxx', **SIGHTING_KWARGS)
|
stix2.Sighting(type='xxx', **SIGHTING_KWARGS)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.Sighting
|
||||||
|
assert excinfo.value.prop_name == "type"
|
||||||
|
assert excinfo.value.reason == "must equal 'sighting'."
|
||||||
assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'."
|
assert str(excinfo.value) == "Invalid value for Sighting 'type': must equal 'sighting'."
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_kwarg_to_sighting():
|
def test_invalid_kwarg_to_sighting():
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(stix2.exceptions.ExtraFieldsError) as excinfo:
|
||||||
stix2.Sighting(my_custom_property="foo", **SIGHTING_KWARGS)
|
stix2.Sighting(my_custom_property="foo", **SIGHTING_KWARGS)
|
||||||
assert str(excinfo.value) == "unexpected keyword arguments: ['my_custom_property']" in str(excinfo)
|
|
||||||
|
assert excinfo.value.cls == stix2.Sighting
|
||||||
|
assert excinfo.value.fields == ['my_custom_property']
|
||||||
|
assert str(excinfo.value) == "Unexpected field(s) for Sighting: (my_custom_property)."
|
||||||
|
|
||||||
|
|
||||||
def test_create_sighting_from_objects_rather_than_ids(malware): # noqa: F811
|
def test_create_sighting_from_objects_rather_than_ids(malware): # noqa: F811
|
||||||
|
|
Loading…
Reference in New Issue