2018-11-28 22:51:00 +01:00
|
|
|
"""STIX 2.1 Domain Objects."""
|
2017-02-10 22:35:02 +01:00
|
|
|
|
2017-09-01 22:37:49 +02:00
|
|
|
from collections import OrderedDict
|
2018-07-10 21:22:21 +02:00
|
|
|
import itertools
|
2021-02-18 18:26:54 +01:00
|
|
|
from urllib.parse import quote_plus
|
2019-07-29 22:35:38 +02:00
|
|
|
import warnings
|
2017-08-11 21:12:45 +02:00
|
|
|
|
2020-01-03 18:26:38 +01:00
|
|
|
from stix2patterns.validator import run_validator
|
2019-02-06 22:16:50 +01:00
|
|
|
|
2018-07-11 14:11:47 +02:00
|
|
|
from ..custom import _custom_object_builder
|
2020-01-03 18:26:38 +01:00
|
|
|
from ..exceptions import (
|
|
|
|
InvalidValueError, PropertyPresenceError, STIXDeprecationWarning,
|
|
|
|
)
|
2018-07-13 17:10:05 +02:00
|
|
|
from ..properties import (
|
2020-02-19 15:34:23 +01:00
|
|
|
BooleanProperty, EnumProperty, FloatProperty, IDProperty, IntegerProperty,
|
2020-07-10 02:13:53 +02:00
|
|
|
ListProperty, ObservableProperty, OpenVocabProperty, PatternProperty,
|
|
|
|
ReferenceProperty, StringProperty, TimestampProperty, TypeProperty,
|
2018-07-13 17:10:05 +02:00
|
|
|
)
|
2018-07-10 21:22:21 +02:00
|
|
|
from ..utils import NOW
|
2020-03-27 07:40:42 +01:00
|
|
|
from .base import _DomainObject
|
2018-06-26 18:23:53 +02:00
|
|
|
from .common import ExternalReference, GranularMarking, KillChainPhase
|
2020-07-10 02:13:53 +02:00
|
|
|
from .vocab import (
|
|
|
|
ATTACK_MOTIVATION, ATTACK_RESOURCE_LEVEL, GROUPING_CONTEXT, IDENTITY_CLASS,
|
|
|
|
IMPLEMENTATION_LANGUAGE, INDICATOR_TYPE, INDUSTRY_SECTOR,
|
|
|
|
INFRASTRUCTURE_TYPE, MALWARE_CAPABILITIES, MALWARE_RESULT, MALWARE_TYPE,
|
|
|
|
OPINION, PATTERN_TYPE, PROCESSOR_ARCHITECTURE, REGION, REPORT_TYPE,
|
|
|
|
THREAT_ACTOR_ROLE, THREAT_ACTOR_SOPHISTICATION, THREAT_ACTOR_TYPE,
|
|
|
|
TOOL_TYPE,
|
|
|
|
)
|
2017-10-03 21:01:55 +02:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class AttackPattern(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_4ohsa4pay4h4>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-22 16:06:35 +01:00
|
|
|
|
|
|
|
_type = 'attack-pattern'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2019-07-14 21:34:31 +02:00
|
|
|
('aliases', ListProperty(StringProperty)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('kill_chain_phases', ListProperty(KillChainPhase)),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-22 16:06:35 +01:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Campaign(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vvysvm8mt434>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'campaign'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
|
|
|
('aliases', ListProperty(StringProperty)),
|
|
|
|
('first_seen', TimestampProperty()),
|
|
|
|
('last_seen', TimestampProperty()),
|
|
|
|
('objective', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
2018-10-15 21:02:59 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(Campaign, self)._check_object_constraints()
|
2018-10-15 21:02:59 +02:00
|
|
|
|
|
|
|
first_seen = self.get('first_seen')
|
|
|
|
last_seen = self.get('last_seen')
|
|
|
|
|
|
|
|
if first_seen and last_seen and last_seen < first_seen:
|
|
|
|
msg = "{0.id} 'last_seen' must be greater than or equal 'first_seen'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2017-02-23 16:11:56 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class CourseOfAction(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_d5yf99f0a230>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'course-of-action'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Grouping(_DomainObject):
|
2019-07-01 17:52:55 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_9e3uldaqqha2>`__.
|
2019-07-01 17:52:55 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
_type = 'grouping'
|
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2019-07-01 17:52:55 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2020-11-19 01:01:12 +01:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2020-11-19 01:01:12 +01:00
|
|
|
('name', StringProperty()),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('context', OpenVocabProperty(GROUPING_CONTEXT, required=True)),
|
2020-11-19 01:01:12 +01:00
|
|
|
('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SDO", "SRO"], spec_version='2.1'), required=True)),
|
2019-07-01 17:52:55 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2019-07-01 17:52:55 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Identity(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ru8fmldl2p6w>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'identity'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2018-10-15 21:02:59 +02:00
|
|
|
('roles', ListProperty(StringProperty)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('identity_class', OpenVocabProperty(IDENTITY_CLASS)),
|
|
|
|
('sectors', ListProperty(OpenVocabProperty(INDUSTRY_SECTOR))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('contact_information', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Indicator(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wfiae74706sw>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-10 22:35:02 +01:00
|
|
|
|
|
|
|
_type = 'indicator'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty()),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('indicator_types', ListProperty(OpenVocabProperty(INDICATOR_TYPE))),
|
2020-01-03 18:26:38 +01:00
|
|
|
('pattern', PatternProperty(required=True)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('pattern_type', OpenVocabProperty(PATTERN_TYPE, required=True)),
|
2019-07-14 21:34:31 +02:00
|
|
|
('pattern_version', StringProperty()),
|
2020-06-12 20:31:01 +02:00
|
|
|
('valid_from', TimestampProperty(default=lambda: NOW)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('valid_until', TimestampProperty()),
|
|
|
|
('kill_chain_phases', ListProperty(KillChainPhase)),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2018-07-12 20:31:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-10 22:35:02 +01:00
|
|
|
|
2019-11-25 21:52:50 +01:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
|
|
|
if kwargs.get('pattern') and kwargs.get('pattern_type') == 'stix' and not kwargs.get('pattern_version'):
|
|
|
|
kwargs['pattern_version'] = '2.1'
|
|
|
|
|
2020-06-30 19:58:19 +02:00
|
|
|
super(Indicator, self).__init__(*args, **kwargs)
|
2019-11-25 21:52:50 +01:00
|
|
|
|
2018-10-15 21:02:59 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(Indicator, self)._check_object_constraints()
|
2018-10-15 21:02:59 +02:00
|
|
|
|
|
|
|
valid_from = self.get('valid_from')
|
|
|
|
valid_until = self.get('valid_until')
|
|
|
|
|
|
|
|
if valid_from and valid_until and valid_until <= valid_from:
|
|
|
|
msg = "{0.id} 'valid_until' must be greater than 'valid_from'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2020-01-03 18:26:38 +01:00
|
|
|
if self.get('pattern_type') == "stix":
|
|
|
|
try:
|
|
|
|
pat_ver = self.get('pattern_version')
|
|
|
|
except AttributeError:
|
|
|
|
pat_ver = '2.1'
|
|
|
|
|
|
|
|
errors = run_validator(self.get('pattern'), pat_ver)
|
|
|
|
if errors:
|
|
|
|
raise InvalidValueError(self.__class__, 'pattern', str(errors[0]))
|
|
|
|
|
2017-02-10 22:35:02 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Infrastructure(_DomainObject):
|
2019-07-01 17:52:55 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_l2alfbbcmfep>`__.
|
2019-07-01 17:52:55 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
_type = 'infrastructure'
|
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2019-07-01 17:52:55 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2019-07-01 17:52:55 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('infrastructure_types', ListProperty(OpenVocabProperty(INFRASTRUCTURE_TYPE))),
|
2019-07-14 21:34:31 +02:00
|
|
|
('aliases', ListProperty(StringProperty)),
|
2019-07-01 17:52:55 +02:00
|
|
|
('kill_chain_phases', ListProperty(KillChainPhase)),
|
|
|
|
('first_seen', TimestampProperty()),
|
|
|
|
('last_seen', TimestampProperty()),
|
2020-11-19 01:01:12 +01:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
2019-07-01 17:52:55 +02:00
|
|
|
])
|
|
|
|
|
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(Infrastructure, self)._check_object_constraints()
|
2019-07-01 17:52:55 +02:00
|
|
|
|
|
|
|
first_seen = self.get('first_seen')
|
|
|
|
last_seen = self.get('last_seen')
|
|
|
|
|
|
|
|
if first_seen and last_seen and last_seen < first_seen:
|
|
|
|
msg = "{0.id} 'last_seen' must be greater than or equal to 'first_seen'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class IntrusionSet(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ticprjb32bc4>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-22 16:06:35 +01:00
|
|
|
|
|
|
|
_type = 'intrusion-set'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
|
|
|
('aliases', ListProperty(StringProperty)),
|
|
|
|
('first_seen', TimestampProperty()),
|
2018-02-23 14:24:26 +01:00
|
|
|
('last_seen', TimestampProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('goals', ListProperty(StringProperty)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('resource_level', OpenVocabProperty(ATTACK_RESOURCE_LEVEL)),
|
|
|
|
('primary_motivation', OpenVocabProperty(ATTACK_MOTIVATION)),
|
|
|
|
('secondary_motivations', ListProperty(OpenVocabProperty(ATTACK_MOTIVATION))),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-10-06 21:09:14 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
|
|
|
|
2018-10-15 21:02:59 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(IntrusionSet, self)._check_object_constraints()
|
2018-10-15 21:02:59 +02:00
|
|
|
|
|
|
|
first_seen = self.get('first_seen')
|
|
|
|
last_seen = self.get('last_seen')
|
|
|
|
|
|
|
|
if first_seen and last_seen and last_seen < first_seen:
|
|
|
|
msg = "{0.id} 'last_seen' must be greater than or equal to 'first_seen'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2017-10-06 21:09:14 +02:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Location(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_sqez6sri9vtz>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-10-06 21:09:14 +02:00
|
|
|
|
|
|
|
_type = 'location'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-14 02:09:07 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2019-07-14 21:34:31 +02:00
|
|
|
('name', StringProperty()),
|
2017-10-06 21:09:14 +02:00
|
|
|
('description', StringProperty()),
|
2018-10-15 21:02:59 +02:00
|
|
|
('latitude', FloatProperty(min=-90.0, max=90.0)),
|
|
|
|
('longitude', FloatProperty(min=-180.0, max=180.0)),
|
|
|
|
('precision', FloatProperty(min=0.0)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('region', OpenVocabProperty(REGION)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('country', StringProperty()),
|
|
|
|
('administrative_area', StringProperty()),
|
|
|
|
('city', StringProperty()),
|
|
|
|
('street_address', StringProperty()),
|
|
|
|
('postal_code', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-22 16:06:35 +01:00
|
|
|
|
2018-07-25 18:43:57 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(Location, self)._check_object_constraints()
|
2018-10-15 21:02:59 +02:00
|
|
|
|
2018-07-25 19:32:22 +02:00
|
|
|
if self.get('precision') is not None:
|
2018-07-25 18:43:57 +02:00
|
|
|
self._check_properties_dependency(['longitude', 'latitude'], ['precision'])
|
|
|
|
|
|
|
|
self._check_properties_dependency(['latitude'], ['longitude'])
|
2018-10-15 21:02:59 +02:00
|
|
|
self._check_properties_dependency(['longitude'], ['latitude'])
|
2018-07-25 18:43:57 +02:00
|
|
|
|
2019-07-14 21:34:31 +02:00
|
|
|
if not (
|
|
|
|
'region' in self
|
|
|
|
or 'country' in self
|
|
|
|
or (
|
|
|
|
'latitude' in self
|
|
|
|
and 'longitude' in self
|
|
|
|
)
|
|
|
|
):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
raise PropertyPresenceError(
|
2019-07-14 21:34:31 +02:00
|
|
|
"Location objects must have the properties 'region', "
|
|
|
|
"'country', or 'latitude' and 'longitude'",
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
Location,
|
2019-07-14 21:34:31 +02:00
|
|
|
)
|
|
|
|
|
2019-02-06 22:16:50 +01:00
|
|
|
def to_maps_url(self, map_engine="Google Maps"):
|
2019-02-08 20:41:54 +01:00
|
|
|
"""Return URL to this location in an online map engine.
|
|
|
|
|
|
|
|
Google Maps is the default, but Bing maps are also supported.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
map_engine (str): Which map engine to find the location in
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
The URL of the location in the given map engine.
|
|
|
|
|
|
|
|
"""
|
2019-02-06 22:16:50 +01:00
|
|
|
params = []
|
2019-02-07 16:31:51 +01:00
|
|
|
|
|
|
|
latitude = self.get('latitude', None)
|
|
|
|
longitude = self.get('longitude', None)
|
|
|
|
if latitude is not None and longitude is not None:
|
2019-02-06 22:16:50 +01:00
|
|
|
params.extend([str(latitude), str(longitude)])
|
|
|
|
else:
|
2019-02-07 16:31:51 +01:00
|
|
|
properties = ['street_address', 'city', 'country', 'region', 'administrative_area', 'postal_code']
|
2019-02-06 22:16:50 +01:00
|
|
|
params = [self.get(prop) for prop in properties if self.get(prop) is not None]
|
|
|
|
|
2019-02-08 15:37:27 +01:00
|
|
|
return self._to_maps_url_dispatcher(map_engine, params)
|
2019-02-06 22:16:50 +01:00
|
|
|
|
2019-02-08 15:37:27 +01:00
|
|
|
def _to_maps_url_dispatcher(self, map_engine, params):
|
2019-02-06 22:16:50 +01:00
|
|
|
if map_engine == "Google Maps":
|
2019-02-08 15:37:27 +01:00
|
|
|
return self._to_google_maps_url(params)
|
|
|
|
elif map_engine == "Bing Maps":
|
|
|
|
return self._to_bing_maps_url(params)
|
2019-02-06 22:16:50 +01:00
|
|
|
else:
|
2019-02-07 16:31:51 +01:00
|
|
|
raise ValueError(map_engine + " is not a valid or currently-supported map engine")
|
2019-02-06 22:16:50 +01:00
|
|
|
|
2019-02-08 15:37:27 +01:00
|
|
|
def _to_google_maps_url(self, params):
|
|
|
|
url_base = "https://www.google.com/maps/search/?api=1&query="
|
|
|
|
url_ending = params[0]
|
|
|
|
for i in range(1, len(params)):
|
|
|
|
url_ending = url_ending + "," + params[i]
|
|
|
|
|
|
|
|
final_url = url_base + quote_plus(url_ending)
|
|
|
|
return final_url
|
|
|
|
|
|
|
|
def _to_bing_maps_url(self, params):
|
|
|
|
url_base = "https://bing.com/maps/default.aspx?where1="
|
|
|
|
url_ending = params[0]
|
|
|
|
for i in range(1, len(params)):
|
|
|
|
url_ending = url_ending + "," + params[i]
|
|
|
|
|
|
|
|
final_url = url_base + quote_plus(url_ending) + "&lvl=16" # level 16 zoom so long/lat searches shown more clearly
|
|
|
|
return final_url
|
|
|
|
|
2017-02-22 16:06:35 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Malware(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_gc4ooz6oaz7y>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-10 22:35:02 +01:00
|
|
|
|
|
|
|
_type = 'malware'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-09 03:44:20 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2019-07-14 21:34:31 +02:00
|
|
|
('name', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('malware_types', ListProperty(OpenVocabProperty(MALWARE_TYPE))),
|
2019-07-01 17:52:55 +02:00
|
|
|
('is_family', BooleanProperty(required=True)),
|
|
|
|
('aliases', ListProperty(StringProperty)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('kill_chain_phases', ListProperty(KillChainPhase)),
|
2019-07-01 17:52:55 +02:00
|
|
|
('first_seen', TimestampProperty()),
|
|
|
|
('last_seen', TimestampProperty()),
|
2020-03-07 00:48:40 +01:00
|
|
|
('operating_system_refs', ListProperty(ReferenceProperty(valid_types='software', spec_version='2.1'))),
|
2020-07-10 02:13:53 +02:00
|
|
|
('architecture_execution_envs', ListProperty(OpenVocabProperty(PROCESSOR_ARCHITECTURE))),
|
|
|
|
('implementation_languages', ListProperty(OpenVocabProperty(IMPLEMENTATION_LANGUAGE))),
|
|
|
|
('capabilities', ListProperty(OpenVocabProperty(MALWARE_CAPABILITIES))),
|
2019-08-29 23:15:51 +02:00
|
|
|
('sample_refs', ListProperty(ReferenceProperty(valid_types=['artifact', 'file'], spec_version='2.1'))),
|
2018-07-12 20:31:14 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2018-07-13 17:10:05 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
2017-10-06 21:09:14 +02:00
|
|
|
])
|
|
|
|
|
2019-07-01 17:52:55 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(Malware, self)._check_object_constraints()
|
2019-07-01 17:52:55 +02:00
|
|
|
|
|
|
|
first_seen = self.get('first_seen')
|
|
|
|
last_seen = self.get('last_seen')
|
|
|
|
|
|
|
|
if first_seen and last_seen and last_seen < first_seen:
|
|
|
|
msg = "{0.id} 'last_seen' must be greater than or equal to 'first_seen'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2019-07-14 21:34:31 +02:00
|
|
|
if self.is_family and "name" not in self:
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
raise PropertyPresenceError(
|
2019-07-14 21:34:31 +02:00
|
|
|
"'name' is a required property for malware families",
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
Malware,
|
2019-07-14 21:34:31 +02:00
|
|
|
)
|
|
|
|
|
2017-10-06 21:09:14 +02:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class MalwareAnalysis(_DomainObject):
|
2019-06-26 23:06:26 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_dw67pa20zss5>`__.
|
2019-06-26 23:06:26 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
_type = 'malware-analysis'
|
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2019-06-26 23:06:26 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2020-11-19 01:01:12 +01:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2019-06-26 23:06:26 +02:00
|
|
|
('product', StringProperty(required=True)),
|
|
|
|
('version', StringProperty()),
|
2019-08-27 23:36:45 +02:00
|
|
|
('host_vm_ref', ReferenceProperty(valid_types='software', spec_version='2.1')),
|
|
|
|
('operating_system_ref', ReferenceProperty(valid_types='software', spec_version='2.1')),
|
|
|
|
('installed_software_refs', ListProperty(ReferenceProperty(valid_types='software', spec_version='2.1'))),
|
2019-06-26 23:06:26 +02:00
|
|
|
('configuration_version', StringProperty()),
|
2019-07-14 21:34:31 +02:00
|
|
|
('modules', ListProperty(StringProperty)),
|
2019-06-26 23:06:26 +02:00
|
|
|
('analysis_engine_version', StringProperty()),
|
|
|
|
('analysis_definition_version', StringProperty()),
|
|
|
|
('submitted', TimestampProperty()),
|
|
|
|
('analysis_started', TimestampProperty()),
|
|
|
|
('analysis_ended', TimestampProperty()),
|
2020-02-27 23:26:04 +01:00
|
|
|
('result_name', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('result', OpenVocabProperty(MALWARE_RESULT)),
|
2019-11-06 16:11:12 +01:00
|
|
|
('analysis_sco_refs', ListProperty(ReferenceProperty(valid_types="SCO", spec_version='2.1'))),
|
2020-11-19 01:01:12 +01:00
|
|
|
('sample_ref', ReferenceProperty(valid_types="SCO", spec_version='2.1')),
|
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
2019-06-26 23:06:26 +02:00
|
|
|
])
|
|
|
|
|
|
|
|
def _check_object_constraints(self):
|
|
|
|
super(MalwareAnalysis, self)._check_object_constraints()
|
|
|
|
|
2020-02-27 23:26:04 +01:00
|
|
|
self._check_at_least_one_property(["result", "analysis_sco_refs"])
|
2019-06-26 23:06:26 +02:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Note(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_hr77jvcbs9jk>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-10-06 21:09:14 +02:00
|
|
|
|
|
|
|
_type = 'note'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-09 03:44:20 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2018-10-15 21:02:59 +02:00
|
|
|
('abstract', StringProperty()),
|
|
|
|
('content', StringProperty(required=True)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('authors', ListProperty(StringProperty)),
|
2019-11-06 16:11:12 +01:00
|
|
|
('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SDO", "SRO"], spec_version='2.1'), required=True)),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-10 22:35:02 +01:00
|
|
|
|
2017-02-22 16:06:35 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class ObservedData(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_h1590esrzg5f>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'observed-data'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('first_observed', TimestampProperty(required=True)),
|
|
|
|
('last_observed', TimestampProperty(required=True)),
|
2018-10-15 21:02:59 +02:00
|
|
|
('number_observed', IntegerProperty(min=1, max=999999999, required=True)),
|
2019-06-13 03:19:50 +02:00
|
|
|
('objects', ObservableProperty(spec_version='2.1')),
|
2019-11-06 16:11:12 +01:00
|
|
|
('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SRO"], spec_version="2.1"))),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-10-06 21:09:14 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
|
|
|
|
2018-06-11 20:37:45 +02:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
2019-07-29 22:35:38 +02:00
|
|
|
if "objects" in kwargs:
|
|
|
|
warnings.warn(
|
|
|
|
"The 'objects' property of observed-data is deprecated in "
|
|
|
|
"STIX 2.1.",
|
2019-08-07 16:16:18 +02:00
|
|
|
STIXDeprecationWarning,
|
2019-07-29 22:35:38 +02:00
|
|
|
)
|
|
|
|
|
2018-06-11 20:37:45 +02:00
|
|
|
super(ObservedData, self).__init__(*args, **kwargs)
|
|
|
|
|
2018-10-15 21:02:59 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(ObservedData, self)._check_object_constraints()
|
2018-10-15 21:02:59 +02:00
|
|
|
|
|
|
|
first_observed = self.get('first_observed')
|
|
|
|
last_observed = self.get('last_observed')
|
|
|
|
|
|
|
|
if first_observed and last_observed and last_observed < first_observed:
|
|
|
|
msg = "{0.id} 'last_observed' must be greater than or equal to 'first_observed'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2019-06-13 03:19:50 +02:00
|
|
|
self._check_mutually_exclusive_properties(
|
|
|
|
["objects", "object_refs"],
|
|
|
|
)
|
|
|
|
|
2017-10-06 21:09:14 +02:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Opinion(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_sr2hswmu5t1>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-10-06 21:09:14 +02:00
|
|
|
|
|
|
|
_type = 'opinion'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-14 02:09:07 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2018-10-15 21:02:59 +02:00
|
|
|
('explanation', StringProperty()),
|
2017-10-06 21:09:14 +02:00
|
|
|
('authors', ListProperty(StringProperty)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('opinion', EnumProperty(OPINION, required=True)),
|
2019-11-06 16:11:12 +01:00
|
|
|
('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SDO", "SRO"], spec_version='2.1'), required=True)),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Report(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ha4fpad0r9pf>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'report'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('report_types', ListProperty(OpenVocabProperty(REPORT_TYPE))),
|
2017-10-06 16:29:30 +02:00
|
|
|
('published', TimestampProperty(required=True)),
|
2020-06-19 17:40:36 +02:00
|
|
|
('object_refs', ListProperty(ReferenceProperty(invalid_types=[], spec_version='2.1'), required=True)),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2018-07-12 20:31:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class ThreatActor(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_2wowmlcbkqst>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'threat-actor'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('threat_actor_types', ListProperty(OpenVocabProperty(THREAT_ACTOR_TYPE))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('aliases', ListProperty(StringProperty)),
|
2019-07-14 21:34:31 +02:00
|
|
|
('first_seen', TimestampProperty()),
|
|
|
|
('last_seen', TimestampProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('roles', ListProperty(OpenVocabProperty(THREAT_ACTOR_ROLE))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('goals', ListProperty(StringProperty)),
|
2020-07-10 02:13:53 +02:00
|
|
|
('sophistication', OpenVocabProperty(THREAT_ACTOR_SOPHISTICATION)),
|
|
|
|
('resource_level', OpenVocabProperty(ATTACK_RESOURCE_LEVEL)),
|
|
|
|
('primary_motivation', OpenVocabProperty(ATTACK_MOTIVATION)),
|
|
|
|
('secondary_motivations', ListProperty(OpenVocabProperty(ATTACK_MOTIVATION))),
|
|
|
|
('personal_motivations', ListProperty(OpenVocabProperty(ATTACK_MOTIVATION))),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2018-07-12 20:31:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-23 16:11:56 +01:00
|
|
|
|
2019-07-14 21:34:31 +02:00
|
|
|
def _check_object_constraints(self):
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
super(ThreatActor, self)._check_object_constraints()
|
2019-07-14 21:34:31 +02:00
|
|
|
|
|
|
|
first_observed = self.get('first_seen')
|
|
|
|
last_observed = self.get('last_seen')
|
|
|
|
|
|
|
|
if first_observed and last_observed and last_observed < first_observed:
|
|
|
|
msg = "{0.id} 'last_seen' must be greater than or equal to 'first_seen'"
|
|
|
|
raise ValueError(msg.format(self))
|
|
|
|
|
2017-02-23 16:11:56 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Tool(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_m21z3a1f3lou>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-22 16:06:35 +01:00
|
|
|
|
|
|
|
_type = 'tool'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2020-07-10 02:13:53 +02:00
|
|
|
('tool_types', ListProperty(OpenVocabProperty(TOOL_TYPE))),
|
2019-07-01 21:26:30 +02:00
|
|
|
('aliases', ListProperty(StringProperty)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('kill_chain_phases', ListProperty(KillChainPhase)),
|
|
|
|
('tool_version', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2018-07-12 20:31:14 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
2017-02-22 16:06:35 +01:00
|
|
|
|
2017-02-23 16:11:56 +01:00
|
|
|
|
2020-03-27 07:40:42 +01:00
|
|
|
class Vulnerability(_DomainObject):
|
2018-06-11 20:37:45 +02:00
|
|
|
"""For more detailed information on this object's properties, see
|
2020-03-25 16:36:29 +01:00
|
|
|
`the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_d9f0iay06wtx>`__.
|
2018-06-11 20:37:45 +02:00
|
|
|
"""
|
2017-02-23 16:11:56 +01:00
|
|
|
|
|
|
|
_type = 'vulnerability'
|
2018-06-30 00:38:04 +02:00
|
|
|
_properties = OrderedDict([
|
2020-04-02 03:52:04 +02:00
|
|
|
('type', TypeProperty(_type, spec_version='2.1')),
|
2018-06-30 00:48:41 +02:00
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
2019-06-14 23:58:51 +02:00
|
|
|
('id', IDProperty(_type, spec_version='2.1')),
|
2019-08-27 23:36:45 +02:00
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
2020-03-17 01:25:38 +01:00
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
2017-08-11 21:12:45 +02:00
|
|
|
('name', StringProperty(required=True)),
|
|
|
|
('description', StringProperty()),
|
2018-06-11 20:37:45 +02:00
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
2017-08-11 21:12:45 +02:00
|
|
|
('labels', ListProperty(StringProperty)),
|
2017-10-06 21:09:14 +02:00
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
2017-08-11 21:12:45 +02:00
|
|
|
('external_references', ListProperty(ExternalReference)),
|
2019-08-27 23:36:45 +02:00
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
2017-08-11 21:12:45 +02:00
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
def CustomObject(type='x-custom-type', properties=None):
|
2017-09-22 16:01:00 +02:00
|
|
|
"""Custom STIX Object type decorator.
|
2017-06-13 16:26:43 +02:00
|
|
|
|
2017-09-22 16:01:00 +02:00
|
|
|
Example:
|
2018-07-10 21:22:21 +02:00
|
|
|
>>> from stix2.v21 import CustomObject
|
|
|
|
>>> from stix2.properties import IntegerProperty, StringProperty
|
2017-09-22 16:01:00 +02:00
|
|
|
>>> @CustomObject('x-type-name', [
|
|
|
|
... ('property1', StringProperty(required=True)),
|
|
|
|
... ('property2', IntegerProperty()),
|
|
|
|
... ])
|
|
|
|
... class MyNewObjectType():
|
|
|
|
... pass
|
2017-06-13 16:26:43 +02:00
|
|
|
|
2017-09-22 17:03:25 +02:00
|
|
|
Supply an ``__init__()`` function to add any special validations to the custom
|
|
|
|
type. Don't call ``super().__init__()`` though - doing so will cause an error.
|
2017-06-13 16:26:43 +02:00
|
|
|
|
2017-09-22 16:01:00 +02:00
|
|
|
Example:
|
2018-07-10 21:22:21 +02:00
|
|
|
>>> from stix2.v21 import CustomObject
|
|
|
|
>>> from stix2.properties import IntegerProperty, StringProperty
|
2017-09-22 16:01:00 +02:00
|
|
|
>>> @CustomObject('x-type-name', [
|
|
|
|
... ('property1', StringProperty(required=True)),
|
|
|
|
... ('property2', IntegerProperty()),
|
|
|
|
... ])
|
|
|
|
... class MyNewObjectType():
|
|
|
|
... def __init__(self, property2=None, **kwargs):
|
|
|
|
... if property2 and property2 < 10:
|
|
|
|
... raise ValueError("'property2' is too small.")
|
2018-06-11 20:37:45 +02:00
|
|
|
|
2018-07-10 21:22:21 +02:00
|
|
|
"""
|
|
|
|
def wrapper(cls):
|
2021-01-13 23:52:15 +01:00
|
|
|
_properties = list(
|
|
|
|
itertools.chain.from_iterable([
|
|
|
|
[
|
|
|
|
('type', TypeProperty(type, spec_version='2.1')),
|
|
|
|
('spec_version', StringProperty(fixed='2.1')),
|
|
|
|
('id', IDProperty(type, spec_version='2.1')),
|
|
|
|
('created_by_ref', ReferenceProperty(valid_types='identity', spec_version='2.1')),
|
|
|
|
('created', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond', precision_constraint='min')),
|
|
|
|
],
|
|
|
|
[x for x in properties if not x[0].startswith('x_')],
|
|
|
|
[
|
|
|
|
('revoked', BooleanProperty(default=lambda: False)),
|
|
|
|
('labels', ListProperty(StringProperty)),
|
|
|
|
('confidence', IntegerProperty()),
|
|
|
|
('lang', StringProperty()),
|
|
|
|
('external_references', ListProperty(ExternalReference)),
|
|
|
|
('object_marking_refs', ListProperty(ReferenceProperty(valid_types='marking-definition', spec_version='2.1'))),
|
|
|
|
('granular_markings', ListProperty(GranularMarking)),
|
|
|
|
],
|
|
|
|
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
|
|
|
|
]),
|
|
|
|
)
|
2020-03-27 07:40:42 +01:00
|
|
|
return _custom_object_builder(cls, type, _properties, '2.1', _DomainObject)
|
2018-07-10 21:22:21 +02:00
|
|
|
|
|
|
|
return wrapper
|