cti-python-stix2/stix2/v21/sdo.py

634 lines
27 KiB
Python

"""STIX 2.1 Domain Objects."""
from collections import OrderedDict
import itertools
from six.moves.urllib.parse import quote_plus
from ..core import STIXDomainObject
from ..custom import _custom_object_builder
from ..properties import (
BooleanProperty, EnumProperty, FloatProperty, IDProperty, IntegerProperty,
ListProperty, ObservableProperty, PatternProperty, ReferenceProperty,
StringProperty, TimestampProperty, TypeProperty,
)
from ..utils import NOW
from .common import ExternalReference, GranularMarking, KillChainPhase
class AttackPattern(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'attack-pattern'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('kill_chain_phases', ListProperty(KillChainPhase)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Campaign(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'campaign'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('aliases', ListProperty(StringProperty)),
('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()),
('objective', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def _check_object_constraints(self):
super(self.__class__, self)._check_object_constraints()
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))
class CourseOfAction(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'course-of-action'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Identity(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'identity'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('roles', ListProperty(StringProperty)),
('identity_class', StringProperty(required=True)),
('sectors', ListProperty(StringProperty)),
('contact_information', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Indicator(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'indicator'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty()),
('description', StringProperty()),
('indicator_types', ListProperty(StringProperty, required=True)),
('pattern', PatternProperty(required=True)),
('valid_from', TimestampProperty(default=lambda: NOW)),
('valid_until', TimestampProperty()),
('kill_chain_phases', ListProperty(KillChainPhase)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def _check_object_constraints(self):
super(self.__class__, self)._check_object_constraints()
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))
class IntrusionSet(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'intrusion-set'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('aliases', ListProperty(StringProperty)),
('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()),
('goals', ListProperty(StringProperty)),
('resource_level', StringProperty()),
('primary_motivation', StringProperty()),
('secondary_motivations', ListProperty(StringProperty)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def _check_object_constraints(self):
super(self.__class__, self)._check_object_constraints()
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))
class Location(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'location'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('description', StringProperty()),
('latitude', FloatProperty(min=-90.0, max=90.0)),
('longitude', FloatProperty(min=-180.0, max=180.0)),
('precision', FloatProperty(min=0.0)),
('region', StringProperty()),
('country', StringProperty()),
('administrative_area', StringProperty()),
('city', StringProperty()),
('street_address', StringProperty()),
('postal_code', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def _check_object_constraints(self):
super(self.__class__, self)._check_object_constraints()
if self.get('precision') is not None:
self._check_properties_dependency(['longitude', 'latitude'], ['precision'])
self._check_properties_dependency(['latitude'], ['longitude'])
self._check_properties_dependency(['longitude'], ['latitude'])
def to_maps_url(self, map_engine="Google Maps"):
"""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.
"""
params = []
latitude = self.get('latitude', None)
longitude = self.get('longitude', None)
if latitude is not None and longitude is not None:
params.extend([str(latitude), str(longitude)])
else:
properties = ['street_address', 'city', 'country', 'region', 'administrative_area', 'postal_code']
params = [self.get(prop) for prop in properties if self.get(prop) is not None]
return self._to_maps_url_dispatcher(map_engine, params)
def _to_maps_url_dispatcher(self, map_engine, params):
if map_engine == "Google Maps":
return self._to_google_maps_url(params)
elif map_engine == "Bing Maps":
return self._to_bing_maps_url(params)
else:
raise ValueError(map_engine + " is not a valid or currently-supported map engine")
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
class Malware(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'malware'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('malware_types', ListProperty(StringProperty, required=True)),
('kill_chain_phases', ListProperty(KillChainPhase)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Note(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'note'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('abstract', StringProperty()),
('content', StringProperty(required=True)),
('authors', ListProperty(StringProperty)),
('object_refs', ListProperty(ReferenceProperty, required=True)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class ObservedData(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'observed-data'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('first_observed', TimestampProperty(required=True)),
('last_observed', TimestampProperty(required=True)),
('number_observed', IntegerProperty(min=1, max=999999999, required=True)),
('objects', ObservableProperty(spec_version='2.1', required=True)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def __init__(self, *args, **kwargs):
self.__allow_custom = kwargs.get('allow_custom', False)
self._properties['objects'].allow_custom = kwargs.get('allow_custom', False)
super(ObservedData, self).__init__(*args, **kwargs)
def _check_object_constraints(self):
super(self.__class__, self)._check_object_constraints()
if self.get('number_observed', 1) == 1:
self._check_properties_dependency(['first_observed'], ['last_observed'])
self._check_properties_dependency(['last_observed'], ['first_observed'])
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))
class Opinion(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'opinion'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('explanation', StringProperty()),
('authors', ListProperty(StringProperty)),
('object_refs', ListProperty(ReferenceProperty, required=True)),
(
'opinion', EnumProperty(
allowed=[
'strongly-disagree',
'disagree',
'neutral',
'agree',
'strongly-agree',
], required=True,
),
),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Report(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'report'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('report_types', ListProperty(StringProperty, required=True)),
('published', TimestampProperty(required=True)),
('object_refs', ListProperty(ReferenceProperty, required=True)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class ThreatActor(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'threat-actor'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('threat_actor_types', ListProperty(StringProperty, required=True)),
('aliases', ListProperty(StringProperty)),
('roles', ListProperty(StringProperty)),
('goals', ListProperty(StringProperty)),
('sophistication', StringProperty()),
('resource_level', StringProperty()),
('primary_motivation', StringProperty()),
('secondary_motivations', ListProperty(StringProperty)),
('personal_motivations', ListProperty(StringProperty)),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Tool(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'tool'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('tool_types', ListProperty(StringProperty, required=True)),
('kill_chain_phases', ListProperty(KillChainPhase)),
('tool_version', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
class Vulnerability(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__.
"""
_type = 'vulnerability'
_properties = OrderedDict([
('type', TypeProperty(_type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(_type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)),
('description', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()),
('lang', StringProperty()),
('external_references', ListProperty(ExternalReference)),
('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
])
def CustomObject(type='x-custom-type', properties=None):
"""Custom STIX Object type decorator.
Example:
>>> from stix2.v21 import CustomObject
>>> from stix2.properties import IntegerProperty, StringProperty
>>> @CustomObject('x-type-name', [
... ('property1', StringProperty(required=True)),
... ('property2', IntegerProperty()),
... ])
... class MyNewObjectType():
... pass
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.
Example:
>>> from stix2.v21 import CustomObject
>>> from stix2.properties import IntegerProperty, StringProperty
>>> @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.")
"""
def wrapper(cls):
_properties = list(itertools.chain.from_iterable([
[
('type', TypeProperty(type)),
('spec_version', StringProperty(fixed='2.1')),
('id', IDProperty(type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
],
[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(type='marking-definition'))),
('granular_markings', ListProperty(GranularMarking)),
],
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
]))
return _custom_object_builder(cls, type, _properties, '2.1')
return wrapper