Formatting changes made by the new pre-commit hook 'add trailing commas'

closes #189
stix2.1
Emmanuelle Vargas-Gonzalez 2018-07-13 11:10:05 -04:00
parent e0aa8abd0c
commit 51a499cb33
106 changed files with 4759 additions and 3569 deletions

View File

@ -49,7 +49,7 @@ html_sidebars = {
'navigation.html',
'relations.html',
'searchbox.html',
]
],
}
latex_elements = {}

View File

@ -7,8 +7,10 @@ import stix2
def main():
collection = Collection("http://127.0.0.1:5000/trustgroup1/collections/52892447-4d7e-4f70-b94d-d7f22742ff63/",
user="admin", password="Password0")
collection = Collection(
"http://127.0.0.1:5000/trustgroup1/collections/52892447-4d7e-4f70-b94d-d7f22742ff63/",
user="admin", password="Password0",
)
# instantiate TAXII data source
taxii = stix2.TAXIICollectionSource(collection)

View File

@ -55,6 +55,6 @@ setup(
'stix2-patterns',
],
extras_require={
'taxii': ['taxii2-client']
}
'taxii': ['taxii2-client'],
},
)

View File

@ -37,34 +37,42 @@
from .core import _collect_stix2_mappings, parse, parse_observable
from .v21 import * # This import will always be the latest STIX 2.X version
from .datastore import CompositeDataSource
from .datastore.filesystem import (FileSystemSink, FileSystemSource,
FileSystemStore)
from .datastore.filesystem import (
FileSystemSink, FileSystemSource,
FileSystemStore
)
from .datastore.filters import Filter
from .datastore.memory import MemorySink, MemorySource, MemoryStore
from .datastore.taxii import (TAXIICollectionSink, TAXIICollectionSource,
TAXIICollectionStore)
from .datastore.taxii import (
TAXIICollectionSink, TAXIICollectionSource,
TAXIICollectionStore
)
from .environment import Environment, ObjectFactory
from .markings import (add_markings, clear_markings, get_markings, is_marked,
remove_markings, set_markings)
from .patterns import (AndBooleanExpression, AndObservationExpression,
BasicObjectPathComponent, BinaryConstant,
BooleanConstant, EqualityComparisonExpression,
FloatConstant, FollowedByObservationExpression,
GreaterThanComparisonExpression,
GreaterThanEqualComparisonExpression, HashConstant,
HexConstant, InComparisonExpression, IntegerConstant,
IsSubsetComparisonExpression,
IsSupersetComparisonExpression,
LessThanComparisonExpression,
LessThanEqualComparisonExpression,
LikeComparisonExpression, ListConstant,
ListObjectPathComponent, MatchesComparisonExpression,
ObjectPath, ObservationExpression, OrBooleanExpression,
OrObservationExpression, ParentheticalExpression,
QualifiedObservationExpression,
ReferenceObjectPathComponent, RepeatQualifier,
StartStopQualifier, StringConstant, TimestampConstant,
WithinQualifier)
from .markings import (
add_markings, clear_markings, get_markings, is_marked,
remove_markings, set_markings
)
from .patterns import (
AndBooleanExpression, AndObservationExpression,
BasicObjectPathComponent, BinaryConstant,
BooleanConstant, EqualityComparisonExpression,
FloatConstant, FollowedByObservationExpression,
GreaterThanComparisonExpression,
GreaterThanEqualComparisonExpression, HashConstant,
HexConstant, InComparisonExpression, IntegerConstant,
IsSubsetComparisonExpression,
IsSupersetComparisonExpression,
LessThanComparisonExpression,
LessThanEqualComparisonExpression,
LikeComparisonExpression, ListConstant,
ListObjectPathComponent, MatchesComparisonExpression,
ObjectPath, ObservationExpression, OrBooleanExpression,
OrObservationExpression, ParentheticalExpression,
QualifiedObservationExpression,
ReferenceObjectPathComponent, RepeatQualifier,
StartStopQualifier, StringConstant, TimestampConstant,
WithinQualifier
)
from .utils import new_version, revoke
from .version import __version__

View File

@ -6,11 +6,12 @@ import datetime as dt
import simplejson as json
from .exceptions import (AtLeastOnePropertyError, CustomContentError,
DependentPropertiesError, ExtraPropertiesError,
ImmutableError, InvalidObjRefError, InvalidValueError,
MissingPropertiesError,
MutuallyExclusivePropertiesError)
from .exceptions import (
AtLeastOnePropertyError, CustomContentError, DependentPropertiesError,
ExtraPropertiesError, ImmutableError, InvalidObjRefError,
InvalidValueError, MissingPropertiesError,
MutuallyExclusivePropertiesError,
)
from .markings.utils import validate
from .utils import NOW, find_property_index, format_datetime, get_timestamp
from .utils import new_version as _new_version
@ -206,8 +207,10 @@ class _STIXBase(collections.Mapping):
def __repr__(self):
props = [(k, self[k]) for k in self.object_properties() if self.get(k)]
return '{0}({1})'.format(self.__class__.__name__,
', '.join(['{0!s}={1!r}'.format(k, v) for k, v in props]))
return '{0}({1})'.format(
self.__class__.__name__,
', '.join(['{0!s}={1!r}'.format(k, v) for k, v in props]),
)
def __deepcopy__(self, memo):
# Assume: we can ignore the memo argument, because no object will ever contain the same sub-object multiple times.

View File

@ -254,8 +254,10 @@ def _register_observable_extension(observable, new_extension, version=None):
try:
observable_type = observable._type
except AttributeError:
raise ValueError("Unknown observable type. Custom observables must be "
"created with the @CustomObservable decorator.")
raise ValueError(
"Unknown observable type. Custom observables must be "
"created with the @CustomObservable decorator.",
)
OBJ_MAP_OBSERVABLE = STIX2_OBJ_MAPS[v]['observables']
EXT_MAP = STIX2_OBJ_MAPS[v]['observable-extensions']
@ -264,9 +266,11 @@ def _register_observable_extension(observable, new_extension, version=None):
EXT_MAP[observable_type][new_extension._type] = new_extension
except KeyError:
if observable_type not in OBJ_MAP_OBSERVABLE:
raise ValueError("Unknown observable type '%s'. Custom observables "
"must be created with the @CustomObservable decorator."
% observable_type)
raise ValueError(
"Unknown observable type '%s'. Custom observables "
"must be created with the @CustomObservable decorator."
% observable_type,
)
else:
EXT_MAP[observable_type] = {new_extension._type: new_extension}

View File

@ -2,8 +2,10 @@ from collections import OrderedDict
import re
from .base import _Extension, _Observable, _STIXBase
from .core import (STIXDomainObject, _register_marking, _register_object,
_register_observable, _register_observable_extension)
from .core import (
STIXDomainObject, _register_marking, _register_object,
_register_observable, _register_observable_extension,
)
from .utils import TYPE_REGEX, get_class_hierarchy_names
@ -11,11 +13,14 @@ def _custom_object_builder(cls, type, properties, version):
class _CustomObject(cls, STIXDomainObject):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
raise ValueError(
"Invalid type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type,
)
elif len(type) < 3 or len(type) > 250:
raise ValueError(
"Invalid type name '%s': must be between 3 and 250 characters." % type)
"Invalid type name '%s': must be between 3 and 250 characters." % type,
)
if not properties or not isinstance(properties, list):
raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]")
@ -29,8 +34,10 @@ def _custom_object_builder(cls, type, properties, version):
cls.__init__(self, **kwargs)
except (AttributeError, TypeError) as e:
# Don't accidentally catch errors raised in a custom __init__()
if ("has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"):
if (
"has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"
):
return
raise e
@ -53,8 +60,10 @@ def _custom_marking_builder(cls, type, properties, version):
cls.__init__(self, **kwargs)
except (AttributeError, TypeError) as e:
# Don't accidentally catch errors raised in a custom __init__()
if ("has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"):
if (
"has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"
):
return
raise e
@ -66,8 +75,10 @@ def _custom_observable_builder(cls, type, properties, version):
class _CustomObservable(cls, _Observable):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid observable type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
raise ValueError(
"Invalid observable type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type,
)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type)
@ -77,12 +88,16 @@ def _custom_observable_builder(cls, type, properties, version):
# Check properties ending in "_ref/s" are ObjectReferenceProperties
for prop_name, prop in properties:
if prop_name.endswith('_ref') and ('ObjectReferenceProperty' not in get_class_hierarchy_names(prop)):
raise ValueError("'%s' is named like an object reference property but "
"is not an ObjectReferenceProperty." % prop_name)
raise ValueError(
"'%s' is named like an object reference property but "
"is not an ObjectReferenceProperty." % prop_name,
)
elif (prop_name.endswith('_refs') and ('ListProperty' not in get_class_hierarchy_names(prop)
or 'ObjectReferenceProperty' not in get_class_hierarchy_names(prop.contained))):
raise ValueError("'%s' is named like an object reference list property but "
"is not a ListProperty containing ObjectReferenceProperty." % prop_name)
raise ValueError(
"'%s' is named like an object reference list property but "
"is not a ListProperty containing ObjectReferenceProperty." % prop_name,
)
_type = type
_properties = OrderedDict(properties)
@ -93,8 +108,10 @@ def _custom_observable_builder(cls, type, properties, version):
cls.__init__(self, **kwargs)
except (AttributeError, TypeError) as e:
# Don't accidentally catch errors raised in a custom __init__()
if ("has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"):
if (
"has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"
):
return
raise e
@ -109,8 +126,10 @@ def _custom_extension_builder(cls, observable, type, properties, version):
class _CustomExtension(cls, _Extension):
if not re.match(TYPE_REGEX, type):
raise ValueError("Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
raise ValueError(
"Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type,
)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
@ -126,8 +145,10 @@ def _custom_extension_builder(cls, observable, type, properties, version):
cls.__init__(self, **kwargs)
except (AttributeError, TypeError) as e:
# Don't accidentally catch errors raised in a custom __init__()
if ("has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"):
if (
"has no attribute '__init__'" in str(e) or
str(e) == "object.__init__() takes no parameters"
):
return
raise e

View File

@ -41,7 +41,7 @@ class FileSystemStore(DataStoreMixin):
super(FileSystemStore, self).__init__(
source=FileSystemSource(stix_dir=stix_dir, allow_custom=allow_custom_source),
sink=FileSystemSink(stix_dir=stix_dir, allow_custom=allow_custom_sink, bundlify=bundlify)
sink=FileSystemSink(stix_dir=stix_dir, allow_custom=allow_custom_sink, bundlify=bundlify),
)
@ -134,9 +134,11 @@ class FileSystemSink(DataSink):
self.add(stix_obj)
else:
raise TypeError("stix_data must be a STIX object (or list of), "
"JSON formatted STIX (or list of), "
"or a JSON formatted STIX bundle")
raise TypeError(
"stix_data must be a STIX object (or list of), "
"JSON formatted STIX (or list of), "
"or a JSON formatted STIX bundle",
)
class FileSystemSource(DataSource):

View File

@ -81,7 +81,7 @@ class MemoryStore(DataStoreMixin):
super(MemoryStore, self).__init__(
source=MemorySource(stix_data=self._data, allow_custom=allow_custom, _store=True),
sink=MemorySink(stix_data=self._data, allow_custom=allow_custom, _store=True)
sink=MemorySink(stix_data=self._data, allow_custom=allow_custom, _store=True),
)
def save_to_file(self, *args, **kwargs):

View File

@ -4,8 +4,9 @@ from requests.exceptions import HTTPError
from stix2 import Bundle, v20
from stix2.base import _STIXBase
from stix2.core import parse
from stix2.datastore import (DataSink, DataSource, DataSourceError,
DataStoreMixin)
from stix2.datastore import (
DataSink, DataSource, DataSourceError, DataStoreMixin,
)
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
from stix2.utils import deduplicate
@ -42,7 +43,7 @@ class TAXIICollectionStore(DataStoreMixin):
super(TAXIICollectionStore, self).__init__(
source=TAXIICollectionSource(collection, allow_custom=allow_custom_source),
sink=TAXIICollectionSink(collection, allow_custom=allow_custom_sink)
sink=TAXIICollectionSink(collection, allow_custom=allow_custom_sink),
)
@ -65,12 +66,16 @@ class TAXIICollectionSink(DataSink):
if collection.can_write:
self.collection = collection
else:
raise DataSourceError("The TAXII Collection object provided does not have write access"
" to the underlying linked Collection resource")
raise DataSourceError(
"The TAXII Collection object provided does not have write access"
" to the underlying linked Collection resource",
)
except (HTTPError, ValidationError) as e:
raise DataSourceError("The underlying TAXII Collection resource defined in the supplied TAXII"
" Collection object provided could not be reached. Receved error:", e)
raise DataSourceError(
"The underlying TAXII Collection resource defined in the supplied TAXII"
" Collection object provided could not be reached. Receved error:", e,
)
self.allow_custom = allow_custom
@ -146,12 +151,16 @@ class TAXIICollectionSource(DataSource):
if collection.can_read:
self.collection = collection
else:
raise DataSourceError("The TAXII Collection object provided does not have read access"
" to the underlying linked Collection resource")
raise DataSourceError(
"The TAXII Collection object provided does not have read access"
" to the underlying linked Collection resource",
)
except (HTTPError, ValidationError) as e:
raise DataSourceError("The underlying TAXII Collection resource defined in the supplied TAXII"
" Collection object provided could not be reached. Recieved error:", e)
raise DataSourceError(
"The underlying TAXII Collection resource defined in the supplied TAXII"
" Collection object provided could not be reached. Recieved error:", e,
)
self.allow_custom = allow_custom
@ -218,7 +227,7 @@ class TAXIICollectionSource(DataSource):
# make query in TAXII query format since 'id' is TAXII field
query = [
Filter('id', '=', stix_id),
Filter('version', '=', 'all')
Filter('version', '=', 'all'),
]
all_data = self.query(query=query, _composite_filters=_composite_filters)
@ -277,9 +286,11 @@ class TAXIICollectionSource(DataSource):
except HTTPError as e:
# if resources not found or access is denied from TAXII server, return empty list
if e.response.status_code == 404:
raise DataSourceError("The requested STIX objects for the TAXII Collection resource defined in"
" the supplied TAXII Collection object are either not found or access is"
" denied. Received error: ", e)
raise DataSourceError(
"The requested STIX objects for the TAXII Collection resource defined in"
" the supplied TAXII Collection object are either not found or access is"
" denied. Received error: ", e,
)
# parse python STIX objects from the STIX object dicts
stix_objs = [parse(stix_obj_dict, allow_custom=self.allow_custom) for stix_obj_dict in all_data]

View File

@ -27,9 +27,11 @@ class ObjectFactory(object):
default. Defaults to True.
"""
def __init__(self, created_by_ref=None, created=None,
external_references=None, object_marking_refs=None,
list_append=True):
def __init__(
self, created_by_ref=None, created=None,
external_references=None, object_marking_refs=None,
list_append=True,
):
self._defaults = {}
if created_by_ref:

View File

@ -30,8 +30,10 @@ class MissingPropertiesError(STIXError, ValueError):
def __str__(self):
msg = "No values for required properties for {0}: ({1})."
return msg.format(self.cls.__name__,
", ".join(x for x in self.properties))
return msg.format(
self.cls.__name__,
", ".join(x for x in self.properties),
)
class ExtraPropertiesError(STIXError, TypeError):
@ -44,8 +46,10 @@ class ExtraPropertiesError(STIXError, TypeError):
def __str__(self):
msg = "Unexpected properties for {0}: ({1})."
return msg.format(self.cls.__name__,
", ".join(x for x in self.properties))
return msg.format(
self.cls.__name__,
", ".join(x for x in self.properties),
)
class ImmutableError(STIXError, ValueError):
@ -110,8 +114,10 @@ class MutuallyExclusivePropertiesError(STIXError, TypeError):
def __str__(self):
msg = "The ({1}) properties for {0} are mutually exclusive."
return msg.format(self.cls.__name__,
", ".join(x for x in self.properties))
return msg.format(
self.cls.__name__,
", ".join(x for x in self.properties),
)
class DependentPropertiesError(STIXError, TypeError):
@ -124,8 +130,10 @@ class DependentPropertiesError(STIXError, TypeError):
def __str__(self):
msg = "The property dependencies for {0}: ({1}) are not met."
return msg.format(self.cls.__name__,
", ".join(name for x in self.dependencies for name in x))
return msg.format(
self.cls.__name__,
", ".join(name for x in self.dependencies for name in x),
)
class AtLeastOnePropertyError(STIXError, TypeError):
@ -138,8 +146,10 @@ class AtLeastOnePropertyError(STIXError, TypeError):
def __str__(self):
msg = "At least one of the ({1}) properties for {0} must be populated."
return msg.format(self.cls.__name__,
", ".join(x for x in self.properties))
return msg.format(
self.cls.__name__,
", ".join(x for x in self.properties),
)
class RevokeError(STIXError, ValueError):

View File

@ -51,7 +51,7 @@ def get_markings(obj, selectors=None, inherited=False, descendants=False):
obj,
selectors,
inherited,
descendants
descendants,
)
if inherited:
@ -208,7 +208,7 @@ def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=Fa
marking,
selectors,
inherited,
descendants
descendants,
)
if inherited:
@ -221,7 +221,7 @@ def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=Fa
granular_marks,
selectors,
inherited,
descendants
descendants,
)
result = result or object_markings.is_marked(obj, object_marks)

View File

@ -39,9 +39,11 @@ def get_markings(obj, selectors, inherited=False, descendants=False):
for marking in granular_markings:
for user_selector in selectors:
for marking_selector in marking.get('selectors', []):
if any([(user_selector == marking_selector), # Catch explicit selectors.
(user_selector.startswith(marking_selector) and inherited), # Catch inherited selectors.
(marking_selector.startswith(user_selector) and descendants)]): # Catch descendants selectors
if any([
(user_selector == marking_selector), # Catch explicit selectors.
(user_selector.startswith(marking_selector) and inherited), # Catch inherited selectors.
(marking_selector.startswith(user_selector) and descendants),
]): # Catch descendants selectors
refs = marking.get('marking_ref', [])
results.update([refs])
@ -184,16 +186,17 @@ def clear_markings(obj, selectors):
granular_markings = utils.expand_markings(granular_markings)
sdo = utils.build_granular_marking(
[{'selectors': selectors, 'marking_ref': 'N/A'}]
[{'selectors': selectors, 'marking_ref': 'N/A'}],
)
clear = sdo.get('granular_markings', [])
if not any(clear_selector in sdo_selectors.get('selectors', [])
for sdo_selectors in granular_markings
for clear_marking in clear
for clear_selector in clear_marking.get('selectors', [])
):
if not any(
clear_selector in sdo_selectors.get('selectors', [])
for sdo_selectors in granular_markings
for clear_marking in clear
for clear_selector in clear_marking.get('selectors', [])
):
raise exceptions.MarkingNotFoundError(obj, clear)
for granular_marking in granular_markings:
@ -254,9 +257,11 @@ def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=Fa
for user_selector in selectors:
for marking_selector in granular_marking.get('selectors', []):
if any([(user_selector == marking_selector), # Catch explicit selectors.
(user_selector.startswith(marking_selector) and inherited), # Catch inherited selectors.
(marking_selector.startswith(user_selector) and descendants)]): # Catch descendants selectors
if any([
(user_selector == marking_selector), # Catch explicit selectors.
(user_selector.startswith(marking_selector) and inherited), # Catch inherited selectors.
(marking_selector.startswith(user_selector) and descendants),
]): # Catch descendants selectors
marking_ref = granular_marking.get('marking_ref', '')
if marking and any(x == marking_ref for x in marking):

View File

@ -180,7 +180,7 @@ def expand_markings(granular_markings):
[
{'marking_ref': marking_ref, 'selectors': [selector]}
for selector in selectors
]
],
)
return expanded

View File

@ -211,9 +211,11 @@ class ReferenceObjectPathComponent(_ObjectPathComponent):
class ObjectPath(object):
def __init__(self, object_type_name, property_path):
self.object_type_name = object_type_name
self.property_path = [x if isinstance(x, _ObjectPathComponent) else
_ObjectPathComponent.create_ObjectPathComponent(x)
for x in property_path]
self.property_path = [
x if isinstance(x, _ObjectPathComponent) else
_ObjectPathComponent.create_ObjectPathComponent(x)
for x in property_path
]
def __str__(self):
return "%s:%s" % (self.object_type_name, ".".join(["%s" % x for x in self.property_path]))

View File

@ -20,12 +20,14 @@ from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
# 8-4-4-4-12 hexadecimal representation, the first hex digit of the third
# component must be a 4, and the first hex digit of the fourth component
# must be 8, 9, a, or b (10xx bit pattern).
ID_REGEX = re.compile("^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type
"[0-9a-fA-F]{8}-"
"[0-9a-fA-F]{4}-"
"4[0-9a-fA-F]{3}-"
"[89abAB][0-9a-fA-F]{3}-"
"[0-9a-fA-F]{12}$")
ID_REGEX = re.compile(
"^[a-z0-9][a-z0-9-]+[a-z0-9]--" # object type
"[0-9a-fA-F]{8}-"
"[0-9a-fA-F]{4}-"
"4[0-9a-fA-F]{3}-"
"[89abAB][0-9a-fA-F]{3}-"
"[0-9a-fA-F]{12}$",
)
ERROR_INVALID_ID = (
"not a valid STIX identifier, must match <object-type>--<UUIDv4>"
@ -271,9 +273,11 @@ class DictionaryProperty(Property):
if len(k) > 250:
raise DictionaryKeyError(k, "longer than 250 characters")
if not re.match('^[a-zA-Z0-9_-]+$', k):
msg = ("contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or "
"underscore (_)")
msg = (
"contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or "
"underscore (_)"
)
raise DictionaryKeyError(k, msg)
return dictified
@ -435,10 +439,12 @@ class ObservableProperty(Property):
valid_refs = dict((k, v['type']) for (k, v) in dictified.items())
for key, obj in dictified.items():
parsed_obj = parse_observable(obj,
valid_refs,
allow_custom=self.allow_custom,
version=self.spec_version)
parsed_obj = parse_observable(
obj,
valid_refs,
allow_custom=self.allow_custom,
version=self.spec_version,
)
dictified[key] = parsed_obj
return dictified
@ -509,9 +515,11 @@ class STIXObjectProperty(Property):
# (spec_version). So this is a hack, and not technically spec-
# compliant.
if 'spec_version' in value and self.spec_version == '2.0':
raise ValueError("Spec version 2.0 bundles don't yet support "
"containing objects of a different spec "
"version.")
raise ValueError(
"Spec version 2.0 bundles don't yet support "
"containing objects of a different spec "
"version.",
)
return value
try:
dictified = _get_dict(value)
@ -523,8 +531,10 @@ class STIXObjectProperty(Property):
raise ValueError("This property may not contain a Bundle object")
if 'spec_version' in dictified and self.spec_version == '2.0':
# See above comment regarding spec_version.
raise ValueError("Spec version 2.0 bundles don't yet support "
"containing objects of a different spec version.")
raise ValueError(
"Spec version 2.0 bundles don't yet support "
"containing objects of a different spec version.",
)
parsed_obj = parse(dictified, allow_custom=self.allow_custom)

View File

@ -4,8 +4,9 @@ import pytest
import stix2
from .constants import (FAKE_TIME, INDICATOR_KWARGS, MALWARE_KWARGS,
RELATIONSHIP_KWARGS)
from .constants import (
FAKE_TIME, INDICATOR_KWARGS, MALWARE_KWARGS, RELATIONSHIP_KWARGS,
)
# Inspired by: http://stackoverflow.com/a/24006251
@ -54,61 +55,61 @@ def stix_objs1():
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind2 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind3 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.936Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind4 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind5 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
return [ind1, ind2, ind3, ind4, ind5]
@ -119,37 +120,37 @@ def stix_objs2():
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-31T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind7 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind8 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
return [ind6, ind7, ind8]

View File

@ -32,7 +32,7 @@ MARKING_IDS = [
RELATIONSHIP_IDS = [
'relationship--06520621-5352-4e6a-b976-e8fa3d437ffd',
'relationship--181c9c09-43e6-45dd-9374-3bec192f05ef',
'relationship--a0cbb21c-8daf-4a7f-96aa-7155a4ef8f70'
'relationship--a0cbb21c-8daf-4a7f-96aa-7155a4ef8f70',
]
# *_KWARGS contains all required arguments to create an instance of that STIX object
@ -77,7 +77,7 @@ INTRUSION_SET_KWARGS = dict(
MALWARE_KWARGS = dict(
labels=['ransomware'],
name="Cryptolocker"
name="Cryptolocker",
)
MALWARE_MORE_KWARGS = dict(
@ -87,7 +87,7 @@ MALWARE_MORE_KWARGS = dict(
modified="2016-04-06T20:03:00.000Z",
labels=['ransomware'],
name="Cryptolocker",
description="A ransomware related to ..."
description="A ransomware related to ...",
)
OBSERVED_DATA_KWARGS = dict(
@ -98,8 +98,8 @@ OBSERVED_DATA_KWARGS = dict(
"0": {
"type": "windows-registry-key",
"key": "HKEY_LOCAL_MACHINE\\System\\Foo\\Bar",
}
}
},
},
)
REPORT_KWARGS = dict(

View File

@ -31,7 +31,7 @@ def test_attack_pattern_example():
name="Spear Phishing",
external_references=[{
"source_name": "capec",
"external_id": "CAPEC-163"
"external_id": "CAPEC-163",
}],
description="...",
)
@ -39,23 +39,25 @@ def test_attack_pattern_example():
assert str(ap) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "attack-pattern",
"id": "attack-pattern--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": "...",
"external_references": [
{
"external_id": "CAPEC-163",
"source_name": "capec"
}
],
"name": "Spear Phishing",
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "attack-pattern",
"id": "attack-pattern--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": "...",
"external_references": [
{
"external_id": "CAPEC-163",
"source_name": "capec",
},
],
"name": "Spear Phishing",
},
],
)
def test_parse_attack_pattern(data):
ap = stix2.parse(data, version="2.0")
@ -76,7 +78,7 @@ def test_attack_pattern_invalid_labels():
created="2016-05-12T08:17:27Z",
modified="2016-05-12T08:17:27Z",
name="Spear Phishing",
labels=1
labels=1,
)
# TODO: Add other examples

View File

@ -55,8 +55,8 @@ EXPECTED_BUNDLE_DICT = {
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "2017-01-01T12:34:56Z",
"labels": [
"malicious-activity"
]
"malicious-activity",
],
},
{
"type": "malware",
@ -65,8 +65,8 @@ EXPECTED_BUNDLE_DICT = {
"modified": "2017-01-01T12:34:56.000Z",
"name": "Cryptolocker",
"labels": [
"ransomware"
]
"ransomware",
],
},
{
"type": "relationship",
@ -75,9 +75,9 @@ EXPECTED_BUNDLE_DICT = {
"modified": "2017-01-01T12:34:56.000Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e"
}
]
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
},
],
}

View File

@ -25,24 +25,26 @@ def test_campaign_example():
created="2016-04-06T20:03:00Z",
modified="2016-04-06T20:03:00Z",
name="Green Group Attacks Against Finance",
description="Campaign by Green Group against a series of targets in the financial services sector."
description="Campaign by Green Group against a series of targets in the financial services sector.",
)
assert str(campaign) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "campaign",
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2016-04-06T20:03:00Z",
"modified": "2016-04-06T20:03:00Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Campaign by Green Group against a series of targets in the financial services sector.",
"name": "Green Group Attacks Against Finance",
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "campaign",
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2016-04-06T20:03:00Z",
"modified": "2016-04-06T20:03:00Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Campaign by Green Group against a series of targets in the financial services sector.",
"name": "Green Group Attacks Against Finance",
},
],
)
def test_parse_campaign(data):
cmpn = stix2.parse(data, version="2.0")

View File

@ -25,24 +25,26 @@ def test_course_of_action_example():
created="2016-04-06T20:03:48.000Z",
modified="2016-04-06T20:03:48.000Z",
name="Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
description="This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ..."
description="This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
)
assert str(coa) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
"id": "course-of-action--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"type": "course-of-action"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
"id": "course-of-action--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"type": "course-of-action",
},
],
)
def test_parse_course_of_action(data):
coa = stix2.parse(data, version="2.0")

View File

@ -79,8 +79,9 @@ def test_identity_custom_property_allowed():
assert identity.x_foo == "bar"
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "identity",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"created": "2015-12-21T19:59:11Z",
@ -89,7 +90,8 @@ def test_identity_custom_property_allowed():
"identity_class": "individual",
"foo": "bar"
}""",
])
],
)
def test_parse_identity_custom_property(data):
with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo:
stix2.parse(data, version="2.0")
@ -114,7 +116,7 @@ def test_custom_properties_object_in_bundled_object():
identity_class="individual",
custom_properties={
"x_foo": "bar",
}
},
)
bundle = stix2.v20.Bundle(obj, allow_custom=True)
@ -160,7 +162,7 @@ def test_custom_property_in_observed_data():
artifact = stix2.v20.File(
allow_custom=True,
name='test',
x_foo='bar'
x_foo='bar',
)
observed_data = stix2.v20.ObservedData(
allow_custom=True,
@ -204,7 +206,7 @@ def test_custom_property_dict_in_observable_extension():
'ntfs-ext': {
'sid': 1,
'x_foo': 'bar',
}
},
},
)
@ -216,7 +218,7 @@ def test_custom_property_dict_in_observable_extension():
'allow_custom': True,
'sid': 1,
'x_foo': 'bar',
}
},
},
)
observed_data = stix2.v20.ObservedData(
@ -240,12 +242,12 @@ def test_identity_custom_property_edit_markings():
marking_obj = stix2.v20.MarkingDefinition(
id=MARKING_DEFINITION_ID,
definition_type="statement",
definition=stix2.v20.StatementMarking(statement="Copyright 2016, Example Corp")
definition=stix2.v20.StatementMarking(statement="Copyright 2016, Example Corp"),
)
marking_obj2 = stix2.v20.MarkingDefinition(
id=MARKING_DEFINITION_ID,
definition_type="statement",
definition=stix2.v20.StatementMarking(statement="Another one")
definition=stix2.v20.StatementMarking(statement="Another one"),
)
# None of the following should throw exceptions
@ -258,9 +260,11 @@ def test_identity_custom_property_edit_markings():
def test_custom_marking_no_init_1():
@stix2.v20.CustomMarking('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomMarking(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass
@ -269,9 +273,11 @@ def test_custom_marking_no_init_1():
def test_custom_marking_no_init_2():
@stix2.v20.CustomMarking('x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomMarking(
'x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass
@ -279,10 +285,12 @@ def test_custom_marking_no_init_2():
assert no2.property1 == 'something'
@stix2.v20.CustomObject('x-new-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v20.CustomObject(
'x-new-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewType(object):
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -312,9 +320,11 @@ def test_custom_object_type():
def test_custom_object_no_init_1():
@stix2.v20.CustomObject('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomObject(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass
@ -323,9 +333,11 @@ def test_custom_object_no_init_1():
def test_custom_object_no_init_2():
@stix2.v20.CustomObject('x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomObject(
'x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass
@ -335,17 +347,21 @@ def test_custom_object_no_init_2():
def test_custom_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObject('x', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomObject(
'x', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj(object):
pass # pragma: no cover
assert "Invalid type name 'x': " in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObject('x_new_object', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomObject(
'x_new_object', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass # pragma: no cover
assert "Invalid type name 'x_new_object':" in str(excinfo.value)
@ -389,11 +405,13 @@ def test_parse_unregistered_custom_object_type_w_allow_custom():
assert custom_obj["type"] == "x-foobar-observable"
@stix2.v20.CustomObservable('x-new-observable', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
('x_property3', stix2.properties.BooleanProperty()),
])
@stix2.v20.CustomObservable(
'x-new-observable', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
('x_property3', stix2.properties.BooleanProperty()),
],
)
class NewObservable():
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -428,9 +446,11 @@ def test_custom_observable_raises_exception():
def test_custom_observable_object_no_init_1():
@stix2.v20.CustomObservable('x-new-observable', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x-new-observable', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
@ -439,9 +459,11 @@ def test_custom_observable_object_no_init_1():
def test_custom_observable_object_no_init_2():
@stix2.v20.CustomObservable('x-new-obs2', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x-new-obs2', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs2(object):
pass
@ -451,17 +473,21 @@ def test_custom_observable_object_no_init_2():
def test_custom_observable_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable('x', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs(object):
pass # pragma: no cover
assert "Invalid observable type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable('x_new_obs', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x_new_obs', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs2(object):
pass # pragma: no cover
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
@ -469,9 +495,11 @@ def test_custom_observable_object_invalid_type_name():
def test_custom_observable_object_invalid_ref_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable('x-new-obs', [
('property_ref', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x-new-obs', [
('property_ref', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
assert "is named like an object reference property but is not an ObjectReferenceProperty" in str(excinfo.value)
@ -479,9 +507,11 @@ def test_custom_observable_object_invalid_ref_property():
def test_custom_observable_object_invalid_refs_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable('x-new-obs', [
('property_refs', stix2.properties.StringProperty()),
])
@stix2.v20.CustomObservable(
'x-new-obs', [
('property_refs', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
assert "is named like an object reference list property but is not a ListProperty containing ObjectReferenceProperty" in str(excinfo.value)
@ -489,26 +519,32 @@ def test_custom_observable_object_invalid_refs_property():
def test_custom_observable_object_invalid_refs_list_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomObservable('x-new-obs', [
('property_refs', stix2.properties.ListProperty(stix2.properties.StringProperty)),
])
@stix2.v20.CustomObservable(
'x-new-obs', [
('property_refs', stix2.properties.ListProperty(stix2.properties.StringProperty)),
],
)
class NewObs():
pass
assert "is named like an object reference list property but is not a ListProperty containing ObjectReferenceProperty" in str(excinfo.value)
def test_custom_observable_object_invalid_valid_refs():
@stix2.v20.CustomObservable('x-new-obs', [
('property1', stix2.properties.StringProperty(required=True)),
('property_ref', stix2.properties.ObjectReferenceProperty(valid_types='email-addr')),
])
@stix2.v20.CustomObservable(
'x-new-obs', [
('property1', stix2.properties.StringProperty(required=True)),
('property_ref', stix2.properties.ObjectReferenceProperty(valid_types='email-addr')),
],
)
class NewObs():
pass
with pytest.raises(Exception) as excinfo:
NewObs(_valid_refs=['1'],
property1='something',
property_ref='1')
NewObs(
_valid_refs=['1'],
property1='something',
property_ref='1',
)
assert "must be created with _valid_refs as a dict, not a list" in str(excinfo.value)
@ -644,10 +680,12 @@ def test_observed_data_with_custom_observable_object():
assert ob_data.objects['0'].property1 == 'something'
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v20.CustomExtension(
stix2.v20.DomainName, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewExtension():
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -685,13 +723,15 @@ def test_custom_extension_wrong_observable_type():
name="abc.txt",
extensions={
"ntfs-ext": ext,
})
},
)
assert 'Cannot determine extension type' in excinfo.value.reason
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"keys": [
{
"test123": 123,
@ -699,11 +739,14 @@ def test_custom_extension_wrong_observable_type():
}
]
}""",
])
],
)
def test_custom_extension_with_list_and_dict_properties_observable_type(data):
@stix2.v20.CustomExtension(stix2.v20.UserAccount, 'some-extension', [
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True))
])
@stix2.v20.CustomExtension(
stix2.v20.UserAccount, 'some-extension', [
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True)),
],
)
class SomeCustomExtension:
pass
@ -717,9 +760,11 @@ def test_custom_extension_invalid_observable():
class Foo(object):
pass
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(Foo, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomExtension(
Foo, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class FooExtension():
pass # pragma: no cover
assert str(excinfo.value) == "'observable' must be a valid Observable class!"
@ -727,9 +772,11 @@ def test_custom_extension_invalid_observable():
class Bar(stix2.v20.observables._Observable):
pass
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(Bar, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomExtension(
Bar, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class BarExtension():
pass
assert "Unknown observable type" in str(excinfo.value)
@ -738,9 +785,11 @@ def test_custom_extension_invalid_observable():
class Baz(stix2.v20.observables._Observable):
_type = 'Baz'
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(Baz, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomExtension(
Baz, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class BazExtension():
pass
assert "Unknown observable type" in str(excinfo.value)
@ -749,17 +798,21 @@ def test_custom_extension_invalid_observable():
def test_custom_extension_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(stix2.v20.File, 'x', {
'property1': stix2.properties.StringProperty(required=True),
})
@stix2.v20.CustomExtension(
stix2.v20.File, 'x', {
'property1': stix2.properties.StringProperty(required=True),
},
)
class FooExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v20.CustomExtension(stix2.File, 'x_new_ext', {
'property1': stix2.properties.StringProperty(required=True),
})
@stix2.v20.CustomExtension(
stix2.File, 'x_new_ext', {
'property1': stix2.properties.StringProperty(required=True),
},
)
class BlaExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
@ -790,9 +843,11 @@ def test_custom_extension_dict_properties():
def test_custom_extension_no_init_1():
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-extension', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomExtension(
stix2.v20.DomainName, 'x-new-extension', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewExt():
pass
@ -801,9 +856,11 @@ def test_custom_extension_no_init_1():
def test_custom_extension_no_init_2():
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomExtension(
stix2.v20.DomainName, 'x-new-ext2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewExt2(object):
pass
@ -863,8 +920,9 @@ def test_extension_property_location():
assert 'extensions' not in stix2.v20.EXT_MAP['domain-name']['x-new-ext']._properties
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "x-example",
"id": "x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d",
"created": "2018-06-12T16:20:58.059Z",
@ -876,18 +934,23 @@ def test_extension_property_location():
}
}
}""",
])
],
)
def test_custom_object_nested_dictionary(data):
@stix2.v20.CustomObject('x-example', [
('dictionary', stix2.properties.DictionaryProperty()),
])
@stix2.v20.CustomObject(
'x-example', [
('dictionary', stix2.properties.DictionaryProperty()),
],
)
class Example(object):
def __init__(self, **kwargs):
pass
example = Example(id='x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d',
created='2018-06-12T16:20:58.059Z',
modified='2018-06-12T16:20:58.059Z',
dictionary={'key': {'key_b': 'value', 'key_a': 'value'}})
example = Example(
id='x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d',
created='2018-06-12T16:20:58.059Z',
modified='2018-06-12T16:20:58.059Z',
dictionary={'key': {'key_b': 'value', 'key_a': 'value'}},
)
assert data == str(example)

View File

@ -1,7 +1,8 @@
import pytest
from stix2.datastore import (CompositeDataSource, DataSink, DataSource,
DataStoreMixin)
from stix2.datastore import (
CompositeDataSource, DataSink, DataSource, DataStoreMixin,
)
from stix2.datastore.filters import Filter
from stix2.test.v20.constants import CAMPAIGN_MORE_KWARGS
@ -46,15 +47,19 @@ def test_datastore_creator_of_raises():
def test_datastore_relationships_raises():
with pytest.raises(AttributeError) as excinfo:
DataStoreMixin().relationships(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
DataStoreMixin().relationships(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
def test_datastore_related_to_raises():
with pytest.raises(AttributeError) as excinfo:
DataStoreMixin().related_to(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
DataStoreMixin().related_to(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
@ -84,15 +89,19 @@ def test_composite_datastore_query_raises_error():
def test_composite_datastore_relationships_raises_error():
with pytest.raises(AttributeError) as excinfo:
CompositeDataSource().relationships(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
CompositeDataSource().relationships(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "CompositeDataSource has no data sources" == str(excinfo.value)
def test_composite_datastore_related_to_raises_error():
with pytest.raises(AttributeError) as excinfo:
CompositeDataSource().related_to(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
CompositeDataSource().related_to(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "CompositeDataSource has no data sources" == str(excinfo.value)

View File

@ -13,8 +13,10 @@ def test_add_remove_composite_datasource():
with pytest.raises(TypeError) as excinfo:
cds.add_data_sources([ds1, ds2, ds1, ds3])
assert str(excinfo.value) == ("DataSource (to be added) is not of type "
"stix2.DataSource. DataSource type is '<class 'stix2.datastore.memory.MemorySink'>'")
assert str(excinfo.value) == (
"DataSource (to be added) is not of type "
"stix2.DataSource. DataSource type is '<class 'stix2.datastore.memory.MemorySink'>'"
)
cds.add_data_sources([ds1, ds2, ds1])
@ -26,10 +28,12 @@ def test_add_remove_composite_datasource():
def test_composite_datasource_operations(stix_objs1, stix_objs2):
BUNDLE1 = dict(id="bundle--%s" % make_id(),
objects=stix_objs1,
spec_version="2.0",
type="bundle")
BUNDLE1 = dict(
id="bundle--%s" % make_id(),
objects=stix_objs1,
spec_version="2.0",
type="bundle",
)
cds1 = CompositeDataSource()
ds1_1 = MemorySource(stix_data=BUNDLE1)
ds1_2 = MemorySource(stix_data=stix_objs2)
@ -55,11 +59,11 @@ def test_composite_datasource_operations(stix_objs1, stix_objs2):
assert indicator["type"] == "indicator"
query1 = [
Filter("type", "=", "indicator")
Filter("type", "=", "indicator"),
]
query2 = [
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z")
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z"),
]
cds1.filters.add(query2)

View File

@ -5,11 +5,10 @@ import shutil
import pytest
import stix2
from stix2.test.v20.constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS,
IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS,
RELATIONSHIP_IDS)
from stix2.test.v20.constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID, IDENTITY_KWARGS, INDICATOR_ID,
INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS,
)
FS_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "stix2_data")
@ -68,7 +67,7 @@ def bad_stix_files():
# bad STIX object
stix_obj = {
"id": "intrusion-set--test-bad-stix",
"spec_version": "2.0"
"spec_version": "2.0",
# no "type" field
}
@ -178,7 +177,8 @@ def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
camp1 = stix2.v20.Campaign(
name="Hannibal",
objective="Targeting Italian and Spanish Diplomat internet accounts",
aliases=["War Elephant"])
aliases=["War Elephant"],
)
fs_sink.add(camp1)
@ -200,7 +200,7 @@ def test_filesystem_sink_add_stix_object_dict(fs_sink, fs_source):
"objective": "German and French Intelligence Services",
"aliases": ["Purple Robes"],
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2017-05-31T21:31:53.197755Z"
"created": "2017-05-31T21:31:53.197755Z",
}
fs_sink.add(camp2)
@ -228,9 +228,9 @@ def test_filesystem_sink_add_stix_bundle_dict(fs_sink, fs_source):
"objective": "Bulgarian, Albanian and Romanian Intelligence Services",
"aliases": ["Huns"],
"id": "campaign--b8f86161-ccae-49de-973a-4ca320c62478",
"created": "2017-05-31T21:31:53.197755Z"
}
]
"created": "2017-05-31T21:31:53.197755Z",
},
],
}
fs_sink.add(bund)
@ -282,7 +282,8 @@ def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
camp6 = stix2.v20.Campaign(
name="Comanche",
objective="US Midwest manufacturing firms, oil refineries, and businesses",
aliases=["Horse Warrior"])
aliases=["Horse Warrior"],
)
camp7 = {
"name": "Napolean",
@ -290,7 +291,7 @@ def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
"objective": "Central and Eastern Europe military commands and departments",
"aliases": ["The Frenchmen"],
"id": "campaign--122818b6-1112-4fb0-b11b-b111107ca70a",
"created": "2017-05-31T21:31:53.197755Z"
"created": "2017-05-31T21:31:53.197755Z",
}
fs_sink.add([camp6, camp7])
@ -370,7 +371,8 @@ def test_filesystem_store_add(fs_store):
camp1 = stix2.v20.Campaign(
name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"])
aliases=["Ragnar"],
)
fs_store.add(camp1)
camp1_r = fs_store.get(camp1.id)
@ -387,7 +389,8 @@ def test_filesystem_store_add_as_bundle():
camp1 = stix2.v20.Campaign(
name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"])
aliases=["Ragnar"],
)
fs_store.add(camp1)
with open(os.path.join(FS_PATH, "campaign", camp1.id + ".json")) as bundle_file:
@ -420,7 +423,8 @@ def test_filesystem_object_with_custom_property(fs_store):
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
allow_custom=True,
)
fs_store.add(camp)
@ -434,7 +438,8 @@ def test_filesystem_object_with_custom_property_in_bundle(fs_store):
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
allow_custom=True,
)
bundle = stix2.v20.Bundle(camp, allow_custom=True)
fs_store.add(bundle)
@ -445,9 +450,11 @@ def test_filesystem_object_with_custom_property_in_bundle(fs_store):
def test_filesystem_custom_object(fs_store):
@stix2.v20.CustomObject('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v20.CustomObject(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass

View File

@ -10,23 +10,23 @@ stix_objs = [
"description": "\n\nTITLE:\n\tPoison Ivy",
"id": "malware--fdd60b30-b67c-41e3-b0b9-f01faf20d111",
"labels": [
"remote-access-trojan"
"remote-access-trojan",
],
"modified": "2017-01-27T13:49:53.997Z",
"name": "Poison Ivy",
"type": "malware"
"type": "malware",
},
{
"created": "2014-05-08T09:00:00.000Z",
"id": "indicator--a932fcc6-e032-476c-826f-cb970a5a1ade",
"labels": [
"file-hash-watchlist"
"file-hash-watchlist",
],
"modified": "2014-05-08T09:00:00.000Z",
"name": "File hash for Poison Ivy variant",
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"type": "indicator",
"valid_from": "2014-05-08T09:00:00.000000Z"
"valid_from": "2014-05-08T09:00:00.000000Z",
},
{
"created": "2014-05-08T09:00:00.000Z",
@ -34,20 +34,20 @@ stix_objs = [
{
"marking_ref": "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed",
"selectors": [
"relationship_type"
]
}
"relationship_type",
],
},
],
"id": "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463",
"modified": "2014-05-08T09:00:00.000Z",
"object_marking_refs": [
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
],
"relationship_type": "indicates",
"revoked": True,
"source_ref": "indicator--a932fcc6-e032-476c-826f-cb970a5a1ade",
"target_ref": "malware--fdd60b30-b67c-41e3-b0b9-f01faf20d111",
"type": "relationship"
"type": "relationship",
},
{
"id": "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef",
@ -60,10 +60,10 @@ stix_objs = [
"external_references": [
{
"source_name": "cve",
"external_id": "CVE-2014-0160"
}
"external_id": "CVE-2014-0160",
},
],
"labels": ["heartbleed", "has-logo"]
"labels": ["heartbleed", "has-logo"],
},
{
"type": "observed-data",
@ -77,11 +77,11 @@ stix_objs = [
"objects": {
"0": {
"type": "file",
"name": "HAL 9000.exe"
}
}
"name": "HAL 9000.exe",
},
},
}
},
]
@ -414,8 +414,10 @@ def test_filters4():
# Assert invalid Filter cannot be created
with pytest.raises(ValueError) as excinfo:
Filter("modified", "?", "2017-01-27T13:49:53.935Z")
assert str(excinfo.value) == ("Filter operator '?' not supported "
"for specified property: 'modified'")
assert str(excinfo.value) == (
"Filter operator '?' not supported "
"for specified property: 'modified'"
)
def test_filters5(stix_objs2, real_stix_objs2):
@ -455,7 +457,7 @@ def test_filters7(stix_objs2, real_stix_objs2):
"0": {
"type": "file",
"hashes": {
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f",
},
"extensions": {
"pdf-ext": {
@ -465,14 +467,14 @@ def test_filters7(stix_objs2, real_stix_objs2):
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
"pdfid0": "DFCE52BD827ECF765649852119D",
"pdfid1": "57A1E0F9ED2AE523E313C"
}
}
}
}
"pdfid1": "57A1E0F9ED2AE523E313C",
},
},
},
},
}
stix_objects = list(stix_objs2) + [obsvd_data_obj]

View File

@ -5,108 +5,110 @@ import pytest
from stix2 import Filter, MemorySource, MemoryStore, properties
from stix2.datastore import make_id
from stix2.v20 import (Bundle, Campaign, CustomObject, Identity, Indicator,
Malware, Relationship)
from stix2.v20 import (
Bundle, Campaign, CustomObject, Identity, Indicator, Malware, Relationship,
)
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID,
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS)
from .constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID, IDENTITY_KWARGS, INDICATOR_ID,
INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS,
)
IND1 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND2 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND3 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.936Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND4 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND5 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND6 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-31T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND7 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND8 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"labels": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
STIX_OBJS2 = [IND6, IND7, IND8]
@ -161,10 +163,12 @@ def test_memory_source_get_nonexistant_object(mem_source):
def test_memory_store_all_versions(mem_store):
# Add bundle of items to sink
mem_store.add(dict(id="bundle--%s" % make_id(),
objects=STIX_OBJS2,
spec_version="2.0",
type="bundle"))
mem_store.add(dict(
id="bundle--%s" % make_id(),
objects=STIX_OBJS2,
spec_version="2.0",
type="bundle",
))
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
assert len(resp) == 1 # MemoryStore can only store 1 version of each object
@ -227,10 +231,12 @@ def test_memory_store_add_invalid_object(mem_store):
def test_memory_store_object_with_custom_property(mem_store):
camp = Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
mem_store.add(camp)
@ -240,10 +246,12 @@ def test_memory_store_object_with_custom_property(mem_store):
def test_memory_store_object_with_custom_property_in_bundle(mem_store):
camp = Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
bundle = Bundle(camp, allow_custom=True)
mem_store.add(bundle)
@ -254,9 +262,11 @@ def test_memory_store_object_with_custom_property_in_bundle(mem_store):
def test_memory_store_custom_object(mem_store):
@CustomObject('x-new-obj', [
('property1', properties.StringProperty(required=True)),
])
@CustomObject(
'x-new-obj', [
('property1', properties.StringProperty(required=True)),
],
)
class NewObj():
pass

View File

@ -36,7 +36,7 @@ class MockTAXIICollectionEndpoint(Collection):
objs = full_filter.process_filter(
self.objects,
("id", "type", "version"),
[]
[],
)
if objs:
return stix2.v20.Bundle(objects=objs)
@ -56,7 +56,7 @@ class MockTAXIICollectionEndpoint(Collection):
objs = full_filter.process_filter(
self.objects,
("version",),
[]
[],
)
if objs:
return stix2.v20.Bundle(objects=objs)
@ -68,16 +68,18 @@ class MockTAXIICollectionEndpoint(Collection):
@pytest.fixture
def collection(stix_objs1):
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Writable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": True,
"can_write": True,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
})
mock = MockTAXIICollectionEndpoint(
COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Writable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": True,
"can_write": True,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0",
],
}
)
mock.objects.extend(stix_objs1)
return mock
@ -85,16 +87,18 @@ def collection(stix_objs1):
@pytest.fixture
def collection_no_rw_access(stix_objs1):
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Not writeable or readable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": False,
"can_write": False,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
})
mock = MockTAXIICollectionEndpoint(
COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Not writeable or readable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": False,
"can_write": False,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0",
],
}
)
mock.objects.extend(stix_objs1)
return mock
@ -117,7 +121,8 @@ def test_add_stix2_object(collection):
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
],
)
tc_sink.add(ta)
@ -136,7 +141,8 @@ def test_add_stix2_with_custom_object(collection):
"water-hole attacks geared towards energy sector",
],
foo="bar",
allow_custom=True)
allow_custom=True,
)
tc_sink.add(ta)
@ -153,7 +159,8 @@ def test_add_list_object(collection, indicator):
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
],
)
tc_sink.add([ta, indicator])
@ -170,7 +177,8 @@ def test_add_stix2_bundle_object(collection):
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
],
)
tc_sink.add(stix2.v20.Bundle(objects=[ta]))
@ -210,13 +218,13 @@ def test_add_dict_object(collection):
"name": "Teddy Bear",
"goals": [
"compromising environment NGOs",
"water-hole attacks geared towards energy sector"
"water-hole attacks geared towards energy sector",
],
"sophistication": "innovator",
"resource_level": "government",
"labels": [
"nation-state"
]
"nation-state",
],
}
tc_sink.add(ta)
@ -237,15 +245,15 @@ def test_add_dict_bundle_object(collection):
"name": "Teddy Bear",
"goals": [
"compromising environment NGOs",
"water-hole attacks geared towards energy sector"
"water-hole attacks geared towards energy sector",
],
"sophistication": "innovator",
"resource_level": "government",
"labels": [
"nation-state"
]
}
]
"nation-state",
],
},
],
}
tc_sink.add(ta)
@ -272,7 +280,7 @@ def test_parse_taxii_filters(collection):
Filter("added_after", "=", "2016-02-01T00:00:01.000Z"),
Filter("id", "=", "taxii stix object ID"),
Filter("type", "=", "taxii stix object ID"),
Filter("version", "=", "first")
Filter("version", "=", "first"),
]
ds = stix2.TAXIICollectionSource(collection)

View File

@ -2,9 +2,11 @@ import pytest
import stix2
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, FAKE_TIME, IDENTITY_ID,
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS)
from .constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, FAKE_TIME, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS,
RELATIONSHIP_IDS,
)
@pytest.fixture
@ -50,7 +52,8 @@ def test_object_factory_created():
def test_object_factory_external_reference():
ext_ref = stix2.v20.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report")
description="Threat report",
)
factory = stix2.ObjectFactory(external_references=ext_ref)
ind = factory.create(stix2.v20.Indicator, **INDICATOR_KWARGS)
assert ind.external_references[0].source_name == "ACME Threat Intel"
@ -64,7 +67,8 @@ def test_object_factory_obj_markings():
stmt_marking = stix2.v20.StatementMarking("Copyright 2016, Example Corp")
mark_def = stix2.v20.MarkingDefinition(
definition_type="statement",
definition=stmt_marking)
definition=stmt_marking,
)
factory = stix2.ObjectFactory(object_marking_refs=[mark_def, stix2.v20.TLP_AMBER])
ind = factory.create(stix2.v20.Indicator, **INDICATOR_KWARGS)
assert mark_def.id in ind.object_marking_refs
@ -78,13 +82,16 @@ def test_object_factory_obj_markings():
def test_object_factory_list_append():
ext_ref = stix2.v20.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report from ACME")
description="Threat report from ACME",
)
ext_ref2 = stix2.v20.ExternalReference(
source_name="Yet Another Threat Report",
description="Threat report from YATR")
description="Threat report from YATR",
)
ext_ref3 = stix2.v20.ExternalReference(
source_name="Threat Report #3",
description="One more threat report")
description="One more threat report",
)
factory = stix2.ObjectFactory(external_references=ext_ref)
ind = factory.create(stix2.v20.Indicator, external_references=ext_ref2, **INDICATOR_KWARGS)
assert ind.external_references[1].source_name == "Yet Another Threat Report"
@ -96,10 +103,12 @@ def test_object_factory_list_append():
def test_object_factory_list_replace():
ext_ref = stix2.v20.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report from ACME")
description="Threat report from ACME",
)
ext_ref2 = stix2.v20.ExternalReference(
source_name="Yet Another Threat Report",
description="Threat report from YATR")
description="Threat report from YATR",
)
factory = stix2.ObjectFactory(external_references=ext_ref, list_append=False)
ind = factory.create(stix2.v20.Indicator, external_references=ext_ref2, **INDICATOR_KWARGS)
assert len(ind.external_references) == 1
@ -107,8 +116,10 @@ def test_object_factory_list_replace():
def test_environment_functions():
env = stix2.Environment(stix2.ObjectFactory(created_by_ref=IDENTITY_ID),
stix2.MemoryStore())
env = stix2.Environment(
stix2.ObjectFactory(created_by_ref=IDENTITY_ID),
stix2.MemoryStore(),
)
# Create a STIX object
ind = env.create(stix2.v20.Indicator, id=INDICATOR_ID, **INDICATOR_KWARGS)
@ -132,8 +143,10 @@ def test_environment_functions():
assert len(resp) == 0
# See different results after adding filters to the environment
env.add_filters([stix2.Filter('type', '=', 'indicator'),
stix2.Filter('created_by_ref', '=', IDENTITY_ID)])
env.add_filters([
stix2.Filter('type', '=', 'indicator'),
stix2.Filter('created_by_ref', '=', IDENTITY_ID),
])
env.add_filter(stix2.Filter('labels', '=', 'benign')) # should be 'malicious-activity'
resp = env.get(INDICATOR_ID)
assert resp['labels'][0] == 'benign' # should be 'malicious-activity'
@ -147,8 +160,10 @@ def test_environment_source_and_sink():
def test_environment_datastore_and_sink():
with pytest.raises(ValueError) as excinfo:
stix2.Environment(factory=stix2.ObjectFactory(),
store=stix2.MemoryStore(), sink=stix2.MemorySink)
stix2.Environment(
factory=stix2.ObjectFactory(),
store=stix2.MemoryStore(), sink=stix2.MemorySink,
)
assert 'Data store already provided' in str(excinfo.value)
@ -269,7 +284,7 @@ def test_relationships_no_id(ds):
env = stix2.Environment(store=ds)
mal = {
"type": "malware",
"name": "some variant"
"name": "some variant",
}
with pytest.raises(ValueError) as excinfo:
env.relationships(mal)
@ -333,7 +348,7 @@ def test_related_to_no_id(ds):
env = stix2.Environment(store=ds)
mal = {
"type": "malware",
"name": "some variant"
"name": "some variant",
}
with pytest.raises(ValueError) as excinfo:
env.related_to(mal)

View File

@ -21,7 +21,7 @@ def test_external_reference_veris():
source_name="veris",
external_id="0001AA7F-C601-424A-B2B8-BE6C9F5164E7",
hashes={
"SHA-256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"
"SHA-256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b",
},
url="https://github.com/vz-risk/VCDB/blob/master/data/json/0001AA7F-C601-424A-B2B8-BE6C9F5164E7.json",
)

View File

@ -21,11 +21,11 @@ def test_add_marking_mark_one_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
@ -36,44 +36,49 @@ def test_add_marking_mark_one_selector_multiple_refs():
assert m in after["granular_markings"]
@pytest.mark.parametrize("data", [
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
},
],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
},
],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": TLP_RED.id,
},
],
**MALWARE_KWARGS),
TLP_RED,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": TLP_RED.id,
},
],
**MALWARE_KWARGS
),
TLP_RED,
),
],
)
def test_add_marking_mark_multiple_selector_one_refs(data):
before = data[0]
after = data[1]
@ -92,12 +97,12 @@ def test_add_marking_mark_multiple_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -112,7 +117,7 @@ def test_add_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -121,7 +126,7 @@ def test_add_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -137,7 +142,7 @@ def test_add_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -146,7 +151,7 @@ def test_add_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -157,17 +162,22 @@ def test_add_marking_mark_same_property_same_marking():
assert m in after["granular_markings"]
@pytest.mark.parametrize("data,marking", [
({"description": "test description"},
[["title"], ["marking-definition--1", "marking-definition--2"],
"", ["marking-definition--1", "marking-definition--2"],
[], ["marking-definition--1", "marking-definition--2"],
[""], ["marking-definition--1", "marking-definition--2"],
["description"], [""],
["description"], [],
["description"], ["marking-definition--1", 456]
])
])
@pytest.mark.parametrize(
"data,marking", [
(
{"description": "test description"},
[
["title"], ["marking-definition--1", "marking-definition--2"],
"", ["marking-definition--1", "marking-definition--2"],
[], ["marking-definition--1", "marking-definition--2"],
[""], ["marking-definition--1", "marking-definition--2"],
["description"], [""],
["description"], [],
["description"], ["marking-definition--1", 456],
],
),
],
)
def test_add_marking_bad_selector(data, marking):
with pytest.raises(AssertionError):
markings.add_markings(data, marking[0], marking[1])
@ -181,61 +191,61 @@ GET_MARKINGS_TEST_DATA = {
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
@ -246,10 +256,12 @@ def test_get_markings_smoke(data):
assert markings.get_markings(data, "a") == ["1"]
@pytest.mark.parametrize("data", [
GET_MARKINGS_TEST_DATA,
{"b": 1234},
])
@pytest.mark.parametrize(
"data", [
GET_MARKINGS_TEST_DATA,
{"b": 1234},
],
)
def test_get_markings_not_marked(data):
"""Test selector that is not marked returns empty list."""
results = markings.get_markings(data, "b")
@ -268,21 +280,23 @@ def test_get_markings_multiple_selectors(data):
assert set(xy_markings).union(xz_markings).issuperset(total)
@pytest.mark.parametrize("data,selector", [
(GET_MARKINGS_TEST_DATA, "foo"),
(GET_MARKINGS_TEST_DATA, ""),
(GET_MARKINGS_TEST_DATA, []),
(GET_MARKINGS_TEST_DATA, [""]),
(GET_MARKINGS_TEST_DATA, "x.z.[-2]"),
(GET_MARKINGS_TEST_DATA, "c.f"),
(GET_MARKINGS_TEST_DATA, "c.[2].i"),
(GET_MARKINGS_TEST_DATA, "c.[3]"),
(GET_MARKINGS_TEST_DATA, "d"),
(GET_MARKINGS_TEST_DATA, "x.[0]"),
(GET_MARKINGS_TEST_DATA, "z.y.w"),
(GET_MARKINGS_TEST_DATA, "x.z.[1]"),
(GET_MARKINGS_TEST_DATA, "x.z.foo3")
])
@pytest.mark.parametrize(
"data,selector", [
(GET_MARKINGS_TEST_DATA, "foo"),
(GET_MARKINGS_TEST_DATA, ""),
(GET_MARKINGS_TEST_DATA, []),
(GET_MARKINGS_TEST_DATA, [""]),
(GET_MARKINGS_TEST_DATA, "x.z.[-2]"),
(GET_MARKINGS_TEST_DATA, "c.f"),
(GET_MARKINGS_TEST_DATA, "c.[2].i"),
(GET_MARKINGS_TEST_DATA, "c.[3]"),
(GET_MARKINGS_TEST_DATA, "d"),
(GET_MARKINGS_TEST_DATA, "x.[0]"),
(GET_MARKINGS_TEST_DATA, "z.y.w"),
(GET_MARKINGS_TEST_DATA, "x.z.[1]"),
(GET_MARKINGS_TEST_DATA, "x.z.foo3"),
],
)
def test_get_markings_bad_selector(data, selector):
"""Test bad selectors raise exception"""
with pytest.raises(AssertionError):
@ -363,40 +377,42 @@ def test_get_markings_positional_arguments_combinations(data):
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
@pytest.mark.parametrize("data", [
(
Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
},
],
**MALWARE_KWARGS
@pytest.mark.parametrize(
"data", [
(
Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
(
dict(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
},
],
**MALWARE_KWARGS
(
dict(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
])
],
)
def test_remove_marking_remove_one_selector_with_multiple_refs(data):
before = markings.remove_markings(data[0], data[1], ["description"])
assert "granular_markings" not in before
@ -407,8 +423,8 @@ def test_remove_marking_remove_multiple_selector_one_ref():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -421,8 +437,8 @@ def test_remove_marking_mark_one_selector_from_multiple_ones():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -430,8 +446,8 @@ def test_remove_marking_mark_one_selector_from_multiple_ones():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -445,12 +461,12 @@ def test_remove_marking_mark_one_selector_markings_from_multiple_ones():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -458,12 +474,12 @@ def test_remove_marking_mark_one_selector_markings_from_multiple_ones():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -477,12 +493,12 @@ def test_remove_marking_mark_mutilple_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -495,8 +511,8 @@ def test_remove_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -504,12 +520,12 @@ def test_remove_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -523,8 +539,8 @@ def test_remove_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -553,8 +569,8 @@ def test_remove_marking_not_present():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -567,15 +583,15 @@ IS_MARKED_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["labels", "description"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["labels", "description"],
"marking_ref": MARKING_IDS[3]
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
@ -584,15 +600,15 @@ IS_MARKED_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["labels", "description"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["labels", "description"],
"marking_ref": MARKING_IDS[3]
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
@ -607,21 +623,23 @@ def test_is_marked_smoke(data):
assert markings.is_marked(data, selectors=["modified"]) is False
@pytest.mark.parametrize("data,selector", [
(IS_MARKED_TEST_DATA[0], "foo"),
(IS_MARKED_TEST_DATA[0], ""),
(IS_MARKED_TEST_DATA[0], []),
(IS_MARKED_TEST_DATA[0], [""]),
(IS_MARKED_TEST_DATA[0], "x.z.[-2]"),
(IS_MARKED_TEST_DATA[0], "c.f"),
(IS_MARKED_TEST_DATA[0], "c.[2].i"),
(IS_MARKED_TEST_DATA[1], "c.[3]"),
(IS_MARKED_TEST_DATA[1], "d"),
(IS_MARKED_TEST_DATA[1], "x.[0]"),
(IS_MARKED_TEST_DATA[1], "z.y.w"),
(IS_MARKED_TEST_DATA[1], "x.z.[1]"),
(IS_MARKED_TEST_DATA[1], "x.z.foo3")
])
@pytest.mark.parametrize(
"data,selector", [
(IS_MARKED_TEST_DATA[0], "foo"),
(IS_MARKED_TEST_DATA[0], ""),
(IS_MARKED_TEST_DATA[0], []),
(IS_MARKED_TEST_DATA[0], [""]),
(IS_MARKED_TEST_DATA[0], "x.z.[-2]"),
(IS_MARKED_TEST_DATA[0], "c.f"),
(IS_MARKED_TEST_DATA[0], "c.[2].i"),
(IS_MARKED_TEST_DATA[1], "c.[3]"),
(IS_MARKED_TEST_DATA[1], "d"),
(IS_MARKED_TEST_DATA[1], "x.[0]"),
(IS_MARKED_TEST_DATA[1], "z.y.w"),
(IS_MARKED_TEST_DATA[1], "x.z.[1]"),
(IS_MARKED_TEST_DATA[1], "x.z.foo3"),
],
)
def test_is_marked_invalid_selector(data, selector):
"""Test invalid selector raises an error."""
with pytest.raises(AssertionError):
@ -689,61 +707,61 @@ def test_is_marked_positional_arguments_combinations():
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
assert markings.is_marked(test_sdo, ["1"], "a", False, False)
@ -823,8 +841,8 @@ def test_create_sdo_with_invalid_marking():
granular_markings=[
{
"selectors": ["foo"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -839,12 +857,12 @@ def test_set_marking_mark_one_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -858,8 +876,8 @@ def test_set_marking_mark_multiple_selector_one_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -867,8 +885,8 @@ def test_set_marking_mark_multiple_selector_one_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -885,12 +903,12 @@ def test_set_marking_mark_multiple_selector_multiple_refs_from_none():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -904,8 +922,8 @@ def test_set_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -913,12 +931,12 @@ def test_set_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[2]
}
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
)
@ -928,19 +946,21 @@ def test_set_marking_mark_another_property_same_marking():
assert m in after["granular_markings"]
@pytest.mark.parametrize("marking", [
([MARKING_IDS[4], MARKING_IDS[5]], ["foo"]),
([MARKING_IDS[4], MARKING_IDS[5]], ""),
([MARKING_IDS[4], MARKING_IDS[5]], []),
([MARKING_IDS[4], MARKING_IDS[5]], [""]),
])
@pytest.mark.parametrize(
"marking", [
([MARKING_IDS[4], MARKING_IDS[5]], ["foo"]),
([MARKING_IDS[4], MARKING_IDS[5]], ""),
([MARKING_IDS[4], MARKING_IDS[5]], []),
([MARKING_IDS[4], MARKING_IDS[5]], [""]),
],
)
def test_set_marking_bad_selector(marking):
before = Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -948,8 +968,8 @@ def test_set_marking_bad_selector(marking):
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -965,8 +985,8 @@ def test_set_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -974,8 +994,8 @@ def test_set_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -989,15 +1009,15 @@ CLEAR_MARKINGS_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified", "description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["modified", "description", "type"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
@ -1006,19 +1026,19 @@ CLEAR_MARKINGS_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified", "description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["modified", "description", "type"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
)
),
]
@ -1050,12 +1070,14 @@ def test_clear_marking_all_selectors(data):
assert "granular_markings" not in data
@pytest.mark.parametrize("data,selector", [
(CLEAR_MARKINGS_TEST_DATA[0], "foo"),
(CLEAR_MARKINGS_TEST_DATA[0], ""),
(CLEAR_MARKINGS_TEST_DATA[1], []),
(CLEAR_MARKINGS_TEST_DATA[1], [""]),
])
@pytest.mark.parametrize(
"data,selector", [
(CLEAR_MARKINGS_TEST_DATA[0], "foo"),
(CLEAR_MARKINGS_TEST_DATA[0], ""),
(CLEAR_MARKINGS_TEST_DATA[1], []),
(CLEAR_MARKINGS_TEST_DATA[1], [""]),
],
)
def test_clear_marking_bad_selector(data, selector):
"""Test bad selector raises exception."""
with pytest.raises(AssertionError):

View File

@ -29,17 +29,19 @@ def test_identity_example():
assert str(identity) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"identity_class": "individual",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"type": "identity"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"identity_class": "individual",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"type": "identity",
},
],
)
def test_parse_identity(data):
identity = stix2.parse(data, version="2.0")
@ -52,21 +54,23 @@ def test_parse_identity(data):
def test_parse_no_type():
with pytest.raises(stix2.exceptions.ParseError):
stix2.parse("""
stix2.parse(
"""
{
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"created": "2015-12-21T19:59:11.000Z",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"identity_class": "individual"
}""", version="2.0")
}""", version="2.0",
)
def test_identity_with_custom():
identity = stix2.v20.Identity(
name="John Smith",
identity_class="individual",
custom_properties={'x_foo': 'bar'}
custom_properties={'x_foo': 'bar'},
)
assert identity.x_foo == "bar"

View File

@ -148,20 +148,22 @@ def test_created_modified_time_are_identical_by_default():
assert ind.created == ind.modified
@pytest.mark.parametrize("data", [
EXPECTED_INDICATOR,
{
"type": "indicator",
"id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"created": "2017-01-01T00:00:01Z",
"modified": "2017-01-01T00:00:01Z",
"labels": [
"malicious-activity"
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "1970-01-01T00:00:01Z"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_INDICATOR,
{
"type": "indicator",
"id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"created": "2017-01-01T00:00:01Z",
"modified": "2017-01-01T00:00:01Z",
"labels": [
"malicious-activity",
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "1970-01-01T00:00:01Z",
},
],
)
def test_parse_indicator(data):
idctr = stix2.parse(data, version="2.0")

View File

@ -35,32 +35,34 @@ def test_intrusion_set_example():
name="Bobcat Breakin",
description="Incidents usually feature a shared TTP of a bobcat being released...",
aliases=["Zookeeper"],
goals=["acquisition-theft", "harassment", "damage"]
goals=["acquisition-theft", "harassment", "damage"],
)
assert str(intrusion_set) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"aliases": [
"Zookeeper"
],
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Incidents usually feature a shared TTP of a bobcat being released...",
"goals": [
"acquisition-theft",
"harassment",
"damage"
],
"id": "intrusion-set--4e78f46f-a023-4e5f-bc24-71b3ca22ec29",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Bobcat Breakin",
"type": "intrusion-set"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"aliases": [
"Zookeeper",
],
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Incidents usually feature a shared TTP of a bobcat being released...",
"goals": [
"acquisition-theft",
"harassment",
"damage",
],
"id": "intrusion-set--4e78f46f-a023-4e5f-bc24-71b3ca22ec29",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Bobcat Breakin",
"type": "intrusion-set",
},
],
)
def test_parse_intrusion_set(data):
intset = stix2.parse(data, version="2.0")

View File

@ -29,7 +29,7 @@ def test_malware_with_all_required_properties():
created=now,
modified=now,
labels=["ransomware"],
name="Cryptolocker"
name="Cryptolocker",
)
assert str(mal) == EXPECTED_MALWARE
@ -103,17 +103,19 @@ def test_invalid_kwarg_to_malware():
assert str(excinfo.value) == "Unexpected properties for Malware: (my_custom_property)."
@pytest.mark.parametrize("data", [
EXPECTED_MALWARE,
{
"type": "malware",
"id": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"labels": ["ransomware"],
"name": "Cryptolocker"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_MALWARE,
{
"type": "malware",
"id": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"labels": ["ransomware"],
"name": "Cryptolocker",
},
],
)
def test_parse_malware(data):
mal = stix2.parse(data, version="2.0")

View File

@ -79,7 +79,7 @@ def test_marking_def_example_with_statement_positional_argument():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="statement",
definition=stix2.v20.StatementMarking(statement="Copyright 2016, Example Corp")
definition=stix2.v20.StatementMarking(statement="Copyright 2016, Example Corp"),
)
assert str(marking_definition) == EXPECTED_STATEMENT_MARKING_DEFINITION
@ -91,7 +91,7 @@ def test_marking_def_example_with_kwargs_statement():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="statement",
definition=stix2.v20.StatementMarking(**kwargs)
definition=stix2.v20.StatementMarking(**kwargs),
)
assert str(marking_definition) == EXPECTED_STATEMENT_MARKING_DEFINITION
@ -103,7 +103,7 @@ def test_marking_def_invalid_type():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="my-definition-type",
definition=stix2.v20.StatementMarking("Copyright 2016, Example Corp")
definition=stix2.v20.StatementMarking("Copyright 2016, Example Corp"),
)
@ -115,7 +115,7 @@ def test_campaign_with_markings_example():
modified="2016-04-06T20:03:00Z",
name="Green Group Attacks Against Finance",
description="Campaign by Green Group against a series of targets in the financial services sector.",
object_marking_refs=TLP_WHITE
object_marking_refs=TLP_WHITE,
)
assert str(campaign) == EXPECTED_CAMPAIGN_WITH_OBJECT_MARKING
@ -123,7 +123,7 @@ def test_campaign_with_markings_example():
def test_granular_example():
granular_marking = stix2.v20.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["abc", "abc.[23]", "abc.def", "abc.[2].efg"]
selectors=["abc", "abc.[23]", "abc.def", "abc.[2].efg"],
)
assert str(granular_marking) == EXPECTED_GRANULAR_MARKING
@ -133,7 +133,7 @@ def test_granular_example_with_bad_selector():
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
stix2.v20.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["abc[0]"] # missing "."
selectors=["abc[0]"], # missing "."
)
assert excinfo.value.cls == stix2.v20.GranularMarking
@ -153,23 +153,27 @@ def test_campaign_with_granular_markings_example():
granular_markings=[
stix2.v20.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["description"])
])
selectors=["description"],
),
],
)
assert str(campaign) == EXPECTED_CAMPAIGN_WITH_GRANULAR_MARKINGS
@pytest.mark.parametrize("data", [
EXPECTED_TLP_MARKING_DEFINITION,
{
"id": "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
"type": "marking-definition",
"created": "2017-01-20T00:00:00Z",
"definition": {
"tlp": "white"
@pytest.mark.parametrize(
"data", [
EXPECTED_TLP_MARKING_DEFINITION,
{
"id": "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
"type": "marking-definition",
"created": "2017-01-20T00:00:00Z",
"definition": {
"tlp": "white",
},
"definition_type": "tlp",
},
"definition_type": "tlp",
},
])
],
)
def test_parse_marking_definition(data):
gm = stix2.parse(data, version="2.0")
@ -180,10 +184,12 @@ def test_parse_marking_definition(data):
assert gm.definition_type == "tlp"
@stix2.v20.CustomMarking('x-new-marking-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v20.CustomMarking(
'x-new-marking-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewMarking(object):
def __init__(self, property2=None, **kwargs):
if "property3" in kwargs and not isinstance(kwargs.get("property3"), int):
@ -197,7 +203,7 @@ def test_registered_custom_marking():
id="marking-definition--00000000-0000-4000-8000-000000000012",
created="2017-01-22T00:00:00.000Z",
definition_type="x-new-marking-type",
definition=nm
definition=nm,
)
assert marking_def.type == "marking-definition"
@ -218,10 +224,12 @@ def test_registered_custom_marking_raises_exception():
def test_not_registered_marking_raises_exception():
with pytest.raises(ValueError) as excinfo:
# Used custom object on purpose to demonstrate a not-registered marking
@stix2.v20.CustomObject('x-new-marking-type2', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v20.CustomObject(
'x-new-marking-type2', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewObject2(object):
def __init__(self, property2=None, **kwargs):
return
@ -232,7 +240,7 @@ def test_not_registered_marking_raises_exception():
id="marking-definition--00000000-0000-4000-8000-000000000012",
created="2017-01-22T00:00:00.000Z",
definition_type="x-new-marking-type2",
definition=no
definition=no,
)
assert str(excinfo.value) == "definition_type must be a valid marking type"

View File

@ -18,26 +18,34 @@ MALWARE_KWARGS.update({
})
@pytest.mark.parametrize("data", [
(
Malware(**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(object_marking_refs=[TLP_AMBER.id],
**MALWARE_KWARGS),
TLP_AMBER,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(**MALWARE_KWARGS),
Malware(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
object_marking_refs=[TLP_AMBER.id],
**MALWARE_KWARGS
),
TLP_AMBER,
),
],
)
def test_add_markings_one_marking(data):
before = data[0]
after = data[1]
@ -73,12 +81,12 @@ def test_add_markings_combination():
granular_markings=[
{
"selectors": ["labels"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["name"],
"marking_ref": MARKING_IDS[3]
}
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
)
@ -95,12 +103,14 @@ def test_add_markings_combination():
assert m in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([""]),
(""),
([]),
([MARKING_IDS[0], 456])
])
@pytest.mark.parametrize(
"data", [
([""]),
(""),
([]),
([MARKING_IDS[0], 456]),
],
)
def test_add_markings_bad_markings(data):
before = Malware(
**MALWARE_KWARGS
@ -120,62 +130,62 @@ GET_MARKINGS_TEST_DATA = \
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"object_marking_refs": ["11"],
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
@ -258,18 +268,24 @@ def test_get_markings_object_and_granular_combinations(data):
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_remove_markings_object_level(data):
before = data[0]
after = data[1]
@ -284,29 +300,43 @@ def test_remove_markings_object_level(data):
modified == after['modified']
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
dict(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], TLP_AMBER],
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
dict(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
**MALWARE_KWARGS
),
Malware(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], TLP_AMBER],
),
],
)
def test_remove_markings_multiple(data):
before = data[0]
after = data[1]
@ -326,18 +356,24 @@ def test_remove_markings_bad_markings():
assert str(excinfo.value) == "Marking ['%s'] was not found in Malware!" % MARKING_IDS[4]
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_clear_markings(data):
before = data[0]
after = data[1]
@ -359,62 +395,62 @@ def test_is_marked_object_and_granular_combinations():
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"object_marking_refs": "11",
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
assert markings.is_marked(test_sdo, ["1"], "a", False, False)
@ -491,18 +527,24 @@ def test_is_marked_object_and_granular_combinations():
assert markings.is_marked(test_sdo, ["2"], None, True, True) is False
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_is_marked_no_markings(data):
marked = data[0]
nonmarked = data[1]
@ -532,12 +574,14 @@ def test_set_marking():
assert x in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([]),
([""]),
(""),
([MARKING_IDS[4], 687])
])
@pytest.mark.parametrize(
"data", [
([]),
([""]),
(""),
([MARKING_IDS[4], 687]),
],
)
def test_set_marking_bad_input(data):
before = Malware(
object_marking_refs=[MARKING_IDS[0]],

View File

@ -41,7 +41,7 @@ def test_observed_data_example():
objects={
"0": {
"name": "foo.exe",
"type": "file"
"type": "file",
},
},
)
@ -86,13 +86,13 @@ def test_observed_data_example_with_refs():
objects={
"0": {
"name": "foo.exe",
"type": "file"
"type": "file",
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["0"]
}
"contains_refs": ["0"],
},
},
)
@ -112,13 +112,13 @@ def test_observed_data_example_with_bad_refs():
objects={
"0": {
"type": "file",
"name": "foo.exe"
"name": "foo.exe",
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["2"]
}
"contains_refs": ["2"],
},
},
)
@ -163,25 +163,27 @@ def test_observed_data_example_with_empty_dictionary():
assert 'must contain a non-empty dictionary' in excinfo.value.reason
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "observed-data",
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
"created": "2016-04-06T19:58:16.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"first_observed": "2015-12-21T19:00:00Z",
"last_observed": "2015-12-21T19:00:00Z",
"modified": "2016-04-06T19:58:16.000Z",
"number_observed": 50,
"objects": {
"0": {
"name": "foo.exe",
"type": "file"
}
}
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "observed-data",
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
"created": "2016-04-06T19:58:16.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"first_observed": "2015-12-21T19:00:00Z",
"last_observed": "2015-12-21T19:00:00Z",
"modified": "2016-04-06T19:58:16.000Z",
"number_observed": 50,
"objects": {
"0": {
"name": "foo.exe",
"type": "file",
},
},
},
],
)
def test_parse_observed_data(data):
odata = stix2.parse(data, version="2.0")
@ -195,13 +197,14 @@ def test_parse_observed_data(data):
assert odata.objects["0"].type == "file"
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"payload_bin": "VBORw0KGgoAAAANSUhEUgAAADI=="
}""",
""""0": {
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"url": "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
@ -209,20 +212,22 @@ def test_parse_observed_data(data):
"MD5": "6826f9a05da08134006557758bb3afbb"
}
}""",
])
],
)
def test_parse_artifact_valid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.0")
assert odata.objects["0"].type == "artifact"
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"payload_bin": "abcVBORw0KGgoAAAANSUhEUgAAADI=="
}""",
""""0": {
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"url": "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
@ -230,7 +235,8 @@ def test_parse_artifact_valid(data):
"MD5": "a"
}
}""",
])
],
)
def test_parse_artifact_invalid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
with pytest.raises(ValueError):
@ -245,14 +251,16 @@ def test_artifact_example_dependency_error():
assert str(excinfo.value) == "The property dependencies for Artifact: (hashes, url) are not met."
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "autonomous-system",
"number": 15139,
"name": "Slime Industries",
"rir": "ARIN"
}""",
])
],
)
def test_parse_autonomous_system_valid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.0")
@ -262,14 +270,16 @@ def test_parse_autonomous_system_valid(data):
assert odata.objects["0"].rir == "ARIN"
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "email-addr",
"value": "john@example.com",
"display_name": "John Doe",
"belongs_to_ref": "0"
}""",
])
],
)
def test_parse_email_address(data):
odata = stix2.parse_observable(data, {"0": "user-account"}, version='2.0')
assert odata.type == "email-addr"
@ -279,8 +289,9 @@ def test_parse_email_address(data):
stix2.parse_observable(odata_str, {"0": "user-account"}, version='2.0')
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"is_multipart": true,
@ -317,8 +328,9 @@ def test_parse_email_address(data):
}
]
}
"""
])
""",
],
)
def test_parse_email_message(data):
valid_refs = {
"0": "email-message",
@ -333,8 +345,9 @@ def test_parse_email_message(data):
assert odata.body_multipart[0].content_disposition == "inline"
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"from_ref": "0",
@ -344,8 +357,9 @@ def test_parse_email_message(data):
"subject": "Saying Hello",
"body": "Cats are funny!"
}
"""
])
""",
],
)
def test_parse_email_message_not_multipart(data):
valid_refs = {
"0": "email-addr",
@ -358,8 +372,9 @@ def test_parse_email_message_not_multipart(data):
assert excinfo.value.dependencies == [("is_multipart", "body")]
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "file",
"hashes": {
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a"
@ -395,15 +410,17 @@ def test_parse_email_message_not_multipart(data):
}
}
}""",
])
],
)
def test_parse_file_archive(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.0")
assert odata.objects["3"].extensions['archive-ext'].version == "5.0"
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"is_multipart": true,
@ -439,8 +456,9 @@ def test_parse_file_archive(data):
}
]
}
"""
])
""",
],
)
def test_parse_email_message_with_at_least_one_error(data):
valid_refs = {
"0": "email-message",
@ -459,8 +477,9 @@ def test_parse_email_message_with_at_least_one_error(data):
assert "must be populated" in str(excinfo.value)
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "network-traffic",
"src_ref": "0",
@ -469,11 +488,14 @@ def test_parse_email_message_with_at_least_one_error(data):
"tcp"
]
}
"""
])
""",
],
)
def test_parse_basic_tcp_traffic(data):
odata = stix2.parse_observable(data, {"0": "ipv4-addr", "1": "ipv4-addr"},
version='2.0')
odata = stix2.parse_observable(
data, {"0": "ipv4-addr", "1": "ipv4-addr"},
version='2.0',
)
assert odata.type == "network-traffic"
assert odata.src_ref == "0"
@ -481,8 +503,9 @@ def test_parse_basic_tcp_traffic(data):
assert odata.protocols == ["tcp"]
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "network-traffic",
"src_port": 2487,
@ -497,8 +520,9 @@ def test_parse_basic_tcp_traffic(data):
"4"
]
}
"""
])
""",
],
)
def test_parse_basic_tcp_traffic_with_error(data):
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.parse_observable(data, {"4": "network-traffic"}, version='2.0')
@ -550,7 +574,7 @@ def test_observed_data_with_process_example():
"0": {
"type": "file",
"hashes": {
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f",
},
},
"1": {
@ -559,11 +583,12 @@ def test_observed_data_with_process_example():
"name": "gedit-bin",
"created": "2016-01-20T14:11:25.55Z",
"arguments": [
"--new-window"
"--new-window",
],
"binary_ref": "0"
}
})
"binary_ref": "0",
},
},
)
assert observed_data.objects["0"].type == "file"
assert observed_data.objects["0"].hashes["SHA-256"] == "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
@ -580,8 +605,9 @@ def test_artifact_example():
mime_type="image/jpeg",
url="https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
hashes={
"MD5": "6826f9a05da08134006557758bb3afbb"
})
"MD5": "6826f9a05da08134006557758bb3afbb",
},
)
assert art.mime_type == "image/jpeg"
assert art.url == "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg"
assert art.hashes["MD5"] == "6826f9a05da08134006557758bb3afbb"
@ -593,9 +619,10 @@ def test_artifact_mutual_exclusion_error():
mime_type="image/jpeg",
url="https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
hashes={
"MD5": "6826f9a05da08134006557758bb3afbb"
"MD5": "6826f9a05da08134006557758bb3afbb",
},
payload_bin="VBORw0KGgoAAAANSUhEUgAAADI==")
payload_bin="VBORw0KGgoAAAANSUhEUgAAADI==",
)
assert excinfo.value.cls == stix2.v20.Artifact
assert excinfo.value.properties == ["payload_bin", "url"]
@ -609,7 +636,8 @@ def test_directory_example():
created="2015-12-21T19:00:00Z",
modified="2015-12-24T19:00:00Z",
accessed="2015-12-21T20:00:00Z",
contains_refs=["1"])
contains_refs=["1"],
)
assert dir.path == '/usr/lib'
assert dir.created == dt.datetime(2015, 12, 21, 19, 0, 0, tzinfo=pytz.utc)
@ -626,7 +654,8 @@ def test_directory_example_ref_error():
created="2015-12-21T19:00:00Z",
modified="2015-12-24T19:00:00Z",
accessed="2015-12-21T20:00:00Z",
contains_refs=["1"])
contains_refs=["1"],
)
assert excinfo.value.cls == stix2.v20.Directory
assert excinfo.value.prop_name == "contains_refs"
@ -636,7 +665,8 @@ def test_domain_name_example():
dn = stix2.v20.DomainName(
_valid_refs={"1": 'domain-name'},
value="example.com",
resolves_to_refs=["1"])
resolves_to_refs=["1"],
)
assert dn.value == "example.com"
assert dn.resolves_to_refs == ["1"]
@ -647,7 +677,8 @@ def test_domain_name_example_invalid_ref_type():
stix2.v20.DomainName(
_valid_refs={"1": "file"},
value="example.com",
resolves_to_refs=["1"])
resolves_to_refs=["1"],
)
assert excinfo.value.cls == stix2.v20.DomainName
assert excinfo.value.prop_name == "resolves_to_refs"
@ -657,7 +688,7 @@ def test_file_example():
f = stix2.v20.File(
name="qwerty.dll",
hashes={
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a"
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a",
},
size=100,
magic_number_hex="1C",
@ -667,7 +698,8 @@ def test_file_example():
accessed="2016-12-21T20:00:00Z",
is_encrypted=True,
encryption_algorithm="AES128-CBC",
decryption_key="fred")
decryption_key="fred",
)
assert f.name == "qwerty.dll"
assert f.size == 100
@ -690,11 +722,12 @@ def test_file_example_with_NTFSExt():
"alternate_data_streams": [
{
"name": "second.stream",
"size": 25536
}
]
}
})
"size": 25536,
},
],
},
},
)
assert f.name == "abc.txt"
assert f.extensions["ntfs-ext"].alternate_data_streams[0].size == 25536
@ -705,8 +738,9 @@ def test_file_example_with_empty_NTFSExt():
stix2.v20.File(
name="abc.txt",
extensions={
"ntfs-ext": {}
})
"ntfs-ext": {},
},
)
assert excinfo.value.cls == stix2.v20.NTFSExt
assert excinfo.value.properties == sorted(list(stix2.NTFSExt._properties.keys()))
@ -723,12 +757,13 @@ def test_file_example_with_PDFExt():
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
"pdfid0": "DFCE52BD827ECF765649852119D",
"pdfid1": "57A1E0F9ED2AE523E313C"
}
})
"pdfid1": "57A1E0F9ED2AE523E313C",
},
},
)
assert f.name == "qwerty.dll"
assert f.extensions["pdf-ext"].version == "1.7"
@ -746,11 +781,13 @@ def test_file_example_with_PDFExt_Object():
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
pdfid0="DFCE52BD827ECF765649852119D",
pdfid1="57A1E0F9ED2AE523E313C")
})
pdfid1="57A1E0F9ED2AE523E313C",
),
},
)
assert f.name == "qwerty.dll"
assert f.extensions["pdf-ext"].version == "1.7"
@ -767,10 +804,11 @@ def test_file_example_with_RasterImageExt_Object():
"Make": "Nikon",
"Model": "D7000",
"XResolution": 4928,
"YResolution": 3264
}
}
})
"YResolution": 3264,
},
},
},
)
assert f.name == "qwerty.jpeg"
assert f.extensions["raster-image-ext"].bits_per_pixel == 123
assert f.extensions["raster-image-ext"].exif_tags["XResolution"] == 4928
@ -864,28 +902,29 @@ def test_file_example_with_WindowsPEBinaryExt():
"size_of_heap_reserve": 100000,
"size_of_heap_commit": 4096,
"loader_flags_hex": "abdbffde",
"number_of_rva_and_sizes": 3758087646
"number_of_rva_and_sizes": 3758087646,
},
"sections": [
{
"name": "CODE",
"entropy": 0.061089
"entropy": 0.061089,
},
{
"name": "DATA",
"entropy": 7.980693
"entropy": 7.980693,
},
{
"name": "NicolasB",
"entropy": 0.607433
"entropy": 0.607433,
},
{
"name": ".idata",
"entropy": 0.607433
}
]
}
})
"entropy": 0.607433,
},
],
},
},
)
assert f.name == "qwerty.dll"
assert f.extensions["windows-pebinary-ext"].sections[2].entropy == 0.607433
@ -895,7 +934,8 @@ def test_file_example_encryption_error():
stix2.v20.File(
name="qwerty.dll",
is_encrypted=False,
encryption_algorithm="AES128-CBC")
encryption_algorithm="AES128-CBC",
)
assert excinfo.value.cls == stix2.v20.File
assert excinfo.value.dependencies == [("is_encrypted", "encryption_algorithm")]
@ -905,14 +945,16 @@ def test_file_example_encryption_error():
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
stix2.v20.File(
name="qwerty.dll",
encryption_algorithm="AES128-CBC")
encryption_algorithm="AES128-CBC",
)
def test_ip4_address_example():
ip4 = stix2.v20.IPv4Address(
_valid_refs={"4": "mac-addr", "5": "mac-addr"},
value="198.51.100.3",
resolves_to_refs=["4", "5"])
resolves_to_refs=["4", "5"],
)
assert ip4.value == "198.51.100.3"
assert ip4.resolves_to_refs == ["4", "5"]
@ -941,7 +983,8 @@ def test_network_traffic_example():
_valid_refs={"0": "ipv4-addr", "1": "ipv4-addr"},
protocols="tcp",
src_ref="0",
dst_ref="1")
dst_ref="1",
)
assert nt.protocols == ["tcp"]
assert nt.src_ref == "0"
assert nt.dst_ref == "1"
@ -955,13 +998,15 @@ def test_network_traffic_http_request_example():
request_header={
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com"
})
"Host": "www.example.com",
},
)
nt = stix2.v20.NetworkTraffic(
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'http-request-ext': h})
extensions={'http-request-ext': h},
)
assert nt.extensions['http-request-ext'].request_method == "get"
assert nt.extensions['http-request-ext'].request_value == "/download.html"
assert nt.extensions['http-request-ext'].request_version == "http/1.1"
@ -976,7 +1021,8 @@ def test_network_traffic_icmp_example():
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'icmp-ext': h})
extensions={'icmp-ext': h},
)
assert nt.extensions['icmp-ext'].icmp_type_hex == "08"
assert nt.extensions['icmp-ext'].icmp_code_hex == "00"
@ -986,12 +1032,14 @@ def test_network_traffic_socket_example():
is_listening=True,
address_family="AF_INET",
protocol_family="PF_INET",
socket_type="SOCK_STREAM")
socket_type="SOCK_STREAM",
)
nt = stix2.v20.NetworkTraffic(
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'socket-ext': h})
extensions={'socket-ext': h},
)
assert nt.extensions['socket-ext'].is_listening
assert nt.extensions['socket-ext'].address_family == "AF_INET"
assert nt.extensions['socket-ext'].protocol_family == "PF_INET"
@ -1004,7 +1052,8 @@ def test_network_traffic_tcp_example():
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'tcp-ext': h})
extensions={'tcp-ext': h},
)
assert nt.extensions['tcp-ext'].src_flags_hex == "00000002"
@ -1021,7 +1070,8 @@ def test_process_example():
name="gedit-bin",
created="2016-01-20T14:11:25.55Z",
arguments=["--new-window"],
binary_ref="0")
binary_ref="0",
)
assert p.name == "gedit-bin"
assert p.arguments == ["--new-window"]
@ -1036,8 +1086,10 @@ def test_process_example_empty_error():
properties_of_process.remove("type")
assert excinfo.value.properties == sorted(properties_of_process)
msg = "At least one of the ({1}) properties for {0} must be populated."
msg = msg.format(stix2.v20.Process.__name__,
", ".join(sorted(properties_of_process)))
msg = msg.format(
stix2.v20.Process.__name__,
", ".join(sorted(properties_of_process)),
)
assert str(excinfo.value) == msg
@ -1045,8 +1097,9 @@ def test_process_example_empty_with_extensions():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.v20.Process(
extensions={
"windows-process-ext": {}
})
"windows-process-ext": {},
},
)
assert excinfo.value.cls == stix2.v20.WindowsProcessExt
properties_of_extension = list(stix2.v20.WindowsProcessExt._properties.keys())
@ -1062,9 +1115,10 @@ def test_process_example_windows_process_ext():
"aslr_enabled": True,
"dep_enabled": True,
"priority": "HIGH_PRIORITY_CLASS",
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309"
}
})
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
},
},
)
assert proc.extensions["windows-process-ext"].aslr_enabled
assert proc.extensions["windows-process-ext"].dep_enabled
assert proc.extensions["windows-process-ext"].priority == "HIGH_PRIORITY_CLASS"
@ -1077,8 +1131,9 @@ def test_process_example_windows_process_ext_empty():
pid=1221,
name="gedit-bin",
extensions={
"windows-process-ext": {}
})
"windows-process-ext": {},
},
)
assert excinfo.value.cls == stix2.v20.WindowsProcessExt
properties_of_extension = list(stix2.v20.WindowsProcessExt._properties.keys())
@ -1100,7 +1155,8 @@ def test_process_example_with_WindowsProcessExt_Object():
aslr_enabled=True,
dep_enabled=True,
priority="HIGH_PRIORITY_CLASS",
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309") # noqa
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
), # noqa
})
assert p.extensions["windows-process-ext"].dep_enabled
@ -1114,8 +1170,8 @@ def test_process_example_with_WindowsServiceExt():
"display_name": "Sirvizio",
"start_type": "SERVICE_AUTO_START",
"service_type": "SERVICE_WIN32_OWN_PROCESS",
"service_status": "SERVICE_RUNNING"
}
"service_status": "SERVICE_RUNNING",
},
})
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
@ -1129,14 +1185,14 @@ def test_process_example_with_WindowsProcessServiceExt():
"display_name": "Sirvizio",
"start_type": "SERVICE_AUTO_START",
"service_type": "SERVICE_WIN32_OWN_PROCESS",
"service_status": "SERVICE_RUNNING"
"service_status": "SERVICE_RUNNING",
},
"windows-process-ext": {
"aslr_enabled": True,
"dep_enabled": True,
"priority": "HIGH_PRIORITY_CLASS",
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309"
}
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
},
})
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
@ -1150,7 +1206,8 @@ def test_software_example():
name="Word",
cpe="cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*",
version="2002",
vendor="Microsoft")
vendor="Microsoft",
)
assert s.name == "Word"
assert s.cpe == "cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*"
@ -1177,7 +1234,8 @@ def test_user_account_example():
account_created="2016-01-20T12:31:12Z",
password_last_changed="2016-01-20T14:27:43Z",
account_first_login="2016-01-20T14:26:07Z",
account_last_login="2016-07-22T16:08:28Z")
account_last_login="2016-07-22T16:08:28Z",
)
assert a.user_id == "1001"
assert a.account_login == "jdoe"
@ -1197,12 +1255,14 @@ def test_user_account_unix_account_ext_example():
gid=1001,
groups=["wheel"],
home_dir="/home/jdoe",
shell="/bin/bash")
shell="/bin/bash",
)
a = stix2.v20.UserAccount(
user_id="1001",
account_login="jdoe",
account_type="unix",
extensions={'unix-account-ext': u})
extensions={'unix-account-ext': u},
)
assert a.extensions['unix-account-ext'].gid == 1001
assert a.extensions['unix-account-ext'].groups == ["wheel"]
assert a.extensions['unix-account-ext'].home_dir == "/home/jdoe"
@ -1214,15 +1274,18 @@ def test_windows_registry_key_example():
stix2.v20.WindowsRegistryValueType(
name="Foo",
data="qwerty",
data_type="string")
data_type="string",
)
v = stix2.v20.WindowsRegistryValueType(
name="Foo",
data="qwerty",
data_type="REG_SZ")
data_type="REG_SZ",
)
w = stix2.v20.WindowsRegistryKey(
key="hkey_local_machine\\system\\bar\\foo",
values=[v])
values=[v],
)
assert w.key == "hkey_local_machine\\system\\bar\\foo"
assert w.values[0].name == "Foo"
assert w.values[0].data == "qwerty"
@ -1234,7 +1297,8 @@ def test_x509_certificate_example():
issuer="C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com", # noqa
validity_not_before="2016-03-12T12:00:00Z",
validity_not_after="2016-08-21T12:00:00Z",
subject="C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org") # noqa
subject="C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org",
) # noqa
assert x509.type == "x509-certificate"
assert x509.issuer == "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com" # noqa
@ -1249,14 +1313,14 @@ def test_new_version_with_related_objects():
objects={
'src_ip': {
'type': 'ipv4-addr',
'value': '127.0.0.1/32'
'value': '127.0.0.1/32',
},
'domain': {
'type': 'domain-name',
'value': 'example.com',
'resolves_to_refs': ['src_ip']
}
}
'resolves_to_refs': ['src_ip'],
},
},
)
new_version = data.new_version(last_observed="2017-12-12T12:00:00Z")
assert new_version.last_observed.year == 2017

View File

@ -7,37 +7,55 @@ import stix2
def test_create_comparison_expression():
exp = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant("aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", "SHA-256")) # noqa
exp = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant("aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", "SHA-256"),
) # noqa
assert str(exp) == "file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'"
def test_boolean_expression():
exp1 = stix2.MatchesComparisonExpression("email-message:from_ref.value",
stix2.StringConstant(".+\\@example\\.com$"))
exp2 = stix2.MatchesComparisonExpression("email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"))
exp1 = stix2.MatchesComparisonExpression(
"email-message:from_ref.value",
stix2.StringConstant(".+\\@example\\.com$"),
)
exp2 = stix2.MatchesComparisonExpression(
"email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"),
)
exp = stix2.AndBooleanExpression([exp1, exp2])
assert str(exp) == "email-message:from_ref.value MATCHES '.+\\\\@example\\\\.com$' AND email-message:body_multipart[*].body_raw_ref.name MATCHES '^Final Report.+\\\\.exe$'" # noqa
def test_boolean_expression_with_parentheses():
exp1 = stix2.MatchesComparisonExpression(stix2.ObjectPath("email-message",
[stix2.ReferenceObjectPathComponent("from_ref"),
stix2.BasicObjectPathComponent("value")]),
stix2.StringConstant(".+\\@example\\.com$"))
exp2 = stix2.MatchesComparisonExpression("email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"))
exp1 = stix2.MatchesComparisonExpression(
stix2.ObjectPath(
"email-message",
[
stix2.ReferenceObjectPathComponent("from_ref"),
stix2.BasicObjectPathComponent("value"),
],
),
stix2.StringConstant(".+\\@example\\.com$"),
)
exp2 = stix2.MatchesComparisonExpression(
"email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"),
)
exp = stix2.ParentheticalExpression(stix2.AndBooleanExpression([exp1, exp2]))
assert str(exp) == "(email-message:from_ref.value MATCHES '.+\\\\@example\\\\.com$' AND email-message:body_multipart[*].body_raw_ref.name MATCHES '^Final Report.+\\\\.exe$')" # noqa
def test_hash_followed_by_registryKey_expression_python_constant():
hash_exp = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"))
hash_exp = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"),
)
o_exp1 = stix2.ObservationExpression(hash_exp)
reg_exp = stix2.EqualityComparisonExpression(stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"))
reg_exp = stix2.EqualityComparisonExpression(
stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"),
)
o_exp2 = stix2.ObservationExpression(reg_exp)
fb_exp = stix2.FollowedByObservationExpression([o_exp1, o_exp2])
para_exp = stix2.ParentheticalExpression(fb_exp)
@ -47,11 +65,15 @@ def test_hash_followed_by_registryKey_expression_python_constant():
def test_hash_followed_by_registryKey_expression():
hash_exp = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"))
hash_exp = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"),
)
o_exp1 = stix2.ObservationExpression(hash_exp)
reg_exp = stix2.EqualityComparisonExpression(stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"))
reg_exp = stix2.EqualityComparisonExpression(
stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"),
)
o_exp2 = stix2.ObservationExpression(reg_exp)
fb_exp = stix2.FollowedByObservationExpression([o_exp1, o_exp2])
para_exp = stix2.ParentheticalExpression(fb_exp)
@ -61,32 +83,45 @@ def test_hash_followed_by_registryKey_expression():
def test_file_observable_expression():
exp1 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256'))
exp1 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256',
),
)
exp2 = stix2.EqualityComparisonExpression("file:mime_type", stix2.StringConstant("application/x-pdf"))
bool_exp = stix2.AndBooleanExpression([exp1, exp2])
exp = stix2.ObservationExpression(bool_exp)
assert str(exp) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f' AND file:mime_type = 'application/x-pdf']" # noqa
@pytest.mark.parametrize("observation_class, op", [
(stix2.AndObservationExpression, 'AND'),
(stix2.OrObservationExpression, 'OR'),
])
@pytest.mark.parametrize(
"observation_class, op", [
(stix2.AndObservationExpression, 'AND'),
(stix2.OrObservationExpression, 'OR'),
],
)
def test_multiple_file_observable_expression(observation_class, op):
exp1 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c",
'SHA-256'))
exp2 = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("cead3f77f6cda6ec00f57d76c9a6879f", "MD5"))
exp1 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c",
'SHA-256',
),
)
exp2 = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("cead3f77f6cda6ec00f57d76c9a6879f", "MD5"),
)
bool1_exp = stix2.OrBooleanExpression([exp1, exp2])
exp3 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256'))
exp3 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256',
),
)
op1_exp = stix2.ObservationExpression(bool1_exp)
op2_exp = stix2.ObservationExpression(exp3)
exp = observation_class([op1_exp, op2_exp])
@ -96,111 +131,177 @@ def test_multiple_file_observable_expression(observation_class, op):
def test_root_types():
ast = stix2.ObservationExpression(
stix2.AndBooleanExpression(
[stix2.ParentheticalExpression(
stix2.OrBooleanExpression([
stix2.EqualityComparisonExpression("a:b", stix2.StringConstant("1")),
stix2.EqualityComparisonExpression("b:c", stix2.StringConstant("2"))])),
stix2.EqualityComparisonExpression(u"b:d", stix2.StringConstant("3"))]))
[
stix2.ParentheticalExpression(
stix2.OrBooleanExpression([
stix2.EqualityComparisonExpression("a:b", stix2.StringConstant("1")),
stix2.EqualityComparisonExpression("b:c", stix2.StringConstant("2")),
]),
),
stix2.EqualityComparisonExpression(u"b:d", stix2.StringConstant("3")),
],
),
)
assert str(ast) == "[(a:b = '1' OR b:c = '2') AND b:d = '3']"
def test_artifact_payload():
exp1 = stix2.EqualityComparisonExpression("artifact:mime_type",
"application/vnd.tcpdump.pcap")
exp2 = stix2.MatchesComparisonExpression("artifact:payload_bin",
stix2.StringConstant("\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00"))
exp1 = stix2.EqualityComparisonExpression(
"artifact:mime_type",
"application/vnd.tcpdump.pcap",
)
exp2 = stix2.MatchesComparisonExpression(
"artifact:payload_bin",
stix2.StringConstant("\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00"),
)
and_exp = stix2.AndBooleanExpression([exp1, exp2])
exp = stix2.ObservationExpression(and_exp)
assert str(exp) == "[artifact:mime_type = 'application/vnd.tcpdump.pcap' AND artifact:payload_bin MATCHES '\\\\xd4\\\\xc3\\\\xb2\\\\xa1\\\\x02\\\\x00\\\\x04\\\\x00']" # noqa
def test_greater_than_python_constant():
exp1 = stix2.GreaterThanComparisonExpression("file:extensions.windows-pebinary-ext.sections[*].entropy",
7.0)
exp1 = stix2.GreaterThanComparisonExpression(
"file:extensions.windows-pebinary-ext.sections[*].entropy",
7.0,
)
exp = stix2.ObservationExpression(exp1)
assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
def test_greater_than():
exp1 = stix2.GreaterThanComparisonExpression("file:extensions.windows-pebinary-ext.sections[*].entropy",
stix2.FloatConstant(7.0))
exp1 = stix2.GreaterThanComparisonExpression(
"file:extensions.windows-pebinary-ext.sections[*].entropy",
stix2.FloatConstant(7.0),
)
exp = stix2.ObservationExpression(exp1)
assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
def test_less_than():
exp = stix2.LessThanComparisonExpression("file:size",
1024)
exp = stix2.LessThanComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size < 1024"
def test_greater_than_or_equal():
exp = stix2.GreaterThanEqualComparisonExpression("file:size",
1024)
exp = stix2.GreaterThanEqualComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size >= 1024"
def test_less_than_or_equal():
exp = stix2.LessThanEqualComparisonExpression("file:size",
1024)
exp = stix2.LessThanEqualComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size <= 1024"
def test_not():
exp = stix2.LessThanComparisonExpression("file:size",
1024,
negated=True)
exp = stix2.LessThanComparisonExpression(
"file:size",
1024,
negated=True,
)
assert str(exp) == "file:size NOT < 1024"
def test_and_observable_expression():
exp1 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1007")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Peter")])
exp2 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1008")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Paul")])
exp3 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1009")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Mary")])
exp = stix2.AndObservationExpression([stix2.ObservationExpression(exp1),
stix2.ObservationExpression(exp2),
stix2.ObservationExpression(exp3)])
exp1 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1007"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Peter",
),
])
exp2 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1008"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Paul",
),
])
exp3 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1009"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Mary",
),
])
exp = stix2.AndObservationExpression([
stix2.ObservationExpression(exp1),
stix2.ObservationExpression(exp2),
stix2.ObservationExpression(exp3),
])
assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1009' AND user-account:account_login = 'Mary']" # noqa
def test_invalid_and_observable_expression():
with pytest.raises(ValueError) as excinfo:
stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:display_name",
"admin"),
stix2.EqualityComparisonExpression("email-addr:display_name",
stix2.StringConstant("admin"))])
stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:display_name",
"admin",
),
stix2.EqualityComparisonExpression(
"email-addr:display_name",
stix2.StringConstant("admin"),
),
])
assert "All operands to an 'AND' expression must have the same object type" in str(excinfo)
def test_hex():
exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("file:mime_type",
"image/bmp"),
stix2.EqualityComparisonExpression("file:magic_number_hex",
stix2.HexConstant("ffd8"))])
exp_and = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"file:mime_type",
"image/bmp",
),
stix2.EqualityComparisonExpression(
"file:magic_number_hex",
stix2.HexConstant("ffd8"),
),
])
exp = stix2.ObservationExpression(exp_and)
assert str(exp) == "[file:mime_type = 'image/bmp' AND file:magic_number_hex = h'ffd8']"
def test_multiple_qualifiers():
exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("network-traffic:dst_ref.type",
"domain-name"),
stix2.EqualityComparisonExpression("network-traffic:dst_ref.value",
"example.com")])
exp_and = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"network-traffic:dst_ref.type",
"domain-name",
),
stix2.EqualityComparisonExpression(
"network-traffic:dst_ref.value",
"example.com",
),
])
exp_ob = stix2.ObservationExpression(exp_and)
qual_rep = stix2.RepeatQualifier(5)
qual_within = stix2.WithinQualifier(stix2.IntegerConstant(1800))
@ -209,8 +310,10 @@ def test_multiple_qualifiers():
def test_set_op():
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression("network-traffic:dst_ref.value",
"2001:0db8:dead:beef:0000:0000:0000:0000/64"))
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression(
"network-traffic:dst_ref.value",
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
))
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
@ -220,35 +323,45 @@ def test_timestamp():
def test_boolean():
exp = stix2.EqualityComparisonExpression("email-message:is_multipart",
True)
exp = stix2.EqualityComparisonExpression(
"email-message:is_multipart",
True,
)
assert str(exp) == "email-message:is_multipart = true"
def test_binary():
const = stix2.BinaryConstant("dGhpcyBpcyBhIHRlc3Q=")
exp = stix2.EqualityComparisonExpression("artifact:payload_bin",
const)
exp = stix2.EqualityComparisonExpression(
"artifact:payload_bin",
const,
)
assert str(exp) == "artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q='"
def test_list():
exp = stix2.InComparisonExpression("process:name",
['proccy', 'proximus', 'badproc'])
exp = stix2.InComparisonExpression(
"process:name",
['proccy', 'proximus', 'badproc'],
)
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
def test_list2():
# alternate way to construct an "IN" Comparison Expression
exp = stix2.EqualityComparisonExpression("process:name",
['proccy', 'proximus', 'badproc'])
exp = stix2.EqualityComparisonExpression(
"process:name",
['proccy', 'proximus', 'badproc'],
)
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
def test_invalid_constant_type():
with pytest.raises(ValueError) as excinfo:
stix2.EqualityComparisonExpression("artifact:payload_bin",
{'foo': 'bar'})
stix2.EqualityComparisonExpression(
"artifact:payload_bin",
{'foo': 'bar'},
)
assert 'Unable to create a constant' in str(excinfo)
@ -270,20 +383,22 @@ def test_invalid_float_constant():
assert 'must be a float' in str(excinfo)
@pytest.mark.parametrize("data, result", [
(True, True),
(False, False),
('True', True),
('False', False),
('true', True),
('false', False),
('t', True),
('f', False),
('T', True),
('F', False),
(1, True),
(0, False),
])
@pytest.mark.parametrize(
"data, result", [
(True, True),
(False, False),
('True', True),
('False', False),
('true', True),
('false', False),
('t', True),
('f', False),
('T', True),
('F', False),
(1, True),
(0, False),
],
)
def test_boolean_constant(data, result):
boolean = stix2.BooleanConstant(data)
assert boolean.value == result
@ -295,10 +410,12 @@ def test_invalid_boolean_constant():
assert 'must be a boolean' in str(excinfo)
@pytest.mark.parametrize("hashtype, data", [
('MD5', 'zzz'),
('ssdeep', 'zzz=='),
])
@pytest.mark.parametrize(
"hashtype, data", [
('MD5', 'zzz'),
('ssdeep', 'zzz=='),
],
)
def test_invalid_hash_constant(hashtype, data):
with pytest.raises(ValueError) as excinfo:
stix2.HashConstant(data, hashtype)
@ -318,20 +435,26 @@ def test_invalid_binary_constant():
def test_escape_quotes_and_backslashes():
exp = stix2.MatchesComparisonExpression("file:name",
"^Final Report.+\\.exe$")
exp = stix2.MatchesComparisonExpression(
"file:name",
"^Final Report.+\\.exe$",
)
assert str(exp) == "file:name MATCHES '^Final Report.+\\\\.exe$'"
def test_like():
exp = stix2.LikeComparisonExpression("directory:path",
"C:\\Windows\\%\\foo")
exp = stix2.LikeComparisonExpression(
"directory:path",
"C:\\Windows\\%\\foo",
)
assert str(exp) == "directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo'"
def test_issuperset():
exp = stix2.IsSupersetComparisonExpression("ipv4-addr:value",
"198.51.100.0/24")
exp = stix2.IsSupersetComparisonExpression(
"ipv4-addr:value",
"198.51.100.0/24",
)
assert str(exp) == "ipv4-addr:value ISSUPERSET '198.51.100.0/24'"
@ -353,24 +476,32 @@ def test_invalid_within_qualifier():
def test_startstop_qualifier():
qual = stix2.StartStopQualifier(stix2.TimestampConstant('2016-06-01T00:00:00Z'),
datetime.datetime(2017, 3, 12, 8, 30, 0))
qual = stix2.StartStopQualifier(
stix2.TimestampConstant('2016-06-01T00:00:00Z'),
datetime.datetime(2017, 3, 12, 8, 30, 0),
)
assert str(qual) == "START t'2016-06-01T00:00:00Z' STOP t'2017-03-12T08:30:00Z'"
qual2 = stix2.StartStopQualifier(datetime.date(2016, 6, 1),
stix2.TimestampConstant('2016-07-01T00:00:00Z'))
qual2 = stix2.StartStopQualifier(
datetime.date(2016, 6, 1),
stix2.TimestampConstant('2016-07-01T00:00:00Z'),
)
assert str(qual2) == "START t'2016-06-01T00:00:00Z' STOP t'2016-07-01T00:00:00Z'"
def test_invalid_startstop_qualifier():
with pytest.raises(ValueError) as excinfo:
stix2.StartStopQualifier('foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'))
stix2.StartStopQualifier(
'foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'),
)
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
with pytest.raises(ValueError) as excinfo:
stix2.StartStopQualifier(datetime.date(2016, 6, 1),
'foo')
stix2.StartStopQualifier(
datetime.date(2016, 6, 1),
'foo',
)
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)

View File

@ -11,7 +11,7 @@ def test_pickling():
id="identity--d66cb89d-5228-4983-958c-fa84ef75c88c",
name="alice",
description="this is a pickle test",
identity_class="some_class"
identity_class="some_class",
)
pickle.loads(pickle.dumps(identity))

View File

@ -4,14 +4,13 @@ import pytest
import stix2
from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
from stix2.properties import (ERROR_INVALID_ID, BinaryProperty,
BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty,
ExtensionsProperty, FloatProperty,
HashesProperty, HexProperty, IDProperty,
IntegerProperty, ListProperty, Property,
ReferenceProperty, StringProperty,
TimestampProperty, TypeProperty)
from stix2.properties import (
ERROR_INVALID_ID, BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty,
Property, ReferenceProperty, StringProperty, TimestampProperty,
TypeProperty,
)
from . import constants
@ -93,10 +92,12 @@ ID_PROP = IDProperty('my-type')
MY_ID = 'my-type--232c9d3f-49fc-4440-bb01-607f638778e7'
@pytest.mark.parametrize("value", [
MY_ID,
'my-type--00000000-0000-4000-8000-000000000000',
])
@pytest.mark.parametrize(
"value", [
MY_ID,
'my-type--00000000-0000-4000-8000-000000000000',
],
)
def test_id_property_valid(value):
assert ID_PROP.clean(value) == value
@ -134,14 +135,16 @@ def test_id_property_wrong_type():
assert str(excinfo.value) == "must start with 'my-type--'."
@pytest.mark.parametrize("value", [
'my-type--foo',
# Not a v4 UUID
'my-type--00000000-0000-0000-0000-000000000000',
'my-type--' + str(uuid.uuid1()),
'my-type--' + str(uuid.uuid3(uuid.NAMESPACE_DNS, "example.org")),
'my-type--' + str(uuid.uuid5(uuid.NAMESPACE_DNS, "example.org")),
])
@pytest.mark.parametrize(
"value", [
'my-type--foo',
# Not a v4 UUID
'my-type--00000000-0000-0000-0000-000000000000',
'my-type--' + str(uuid.uuid1()),
'my-type--' + str(uuid.uuid3(uuid.NAMESPACE_DNS, "example.org")),
'my-type--' + str(uuid.uuid5(uuid.NAMESPACE_DNS, "example.org")),
],
)
def test_id_property_not_a_valid_hex_uuid(value):
with pytest.raises(ValueError) as excinfo:
ID_PROP.clean(value)
@ -153,77 +156,89 @@ def test_id_property_default():
assert ID_PROP.clean(default) == default
@pytest.mark.parametrize("value", [
2,
-1,
3.14,
False,
])
@pytest.mark.parametrize(
"value", [
2,
-1,
3.14,
False,
],
)
def test_integer_property_valid(value):
int_prop = IntegerProperty()
assert int_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
"something",
StringProperty(),
])
@pytest.mark.parametrize(
"value", [
"something",
StringProperty(),
],
)
def test_integer_property_invalid(value):
int_prop = IntegerProperty()
with pytest.raises(ValueError):
int_prop.clean(value)
@pytest.mark.parametrize("value", [
2,
-1,
3.14,
False,
])
@pytest.mark.parametrize(
"value", [
2,
-1,
3.14,
False,
],
)
def test_float_property_valid(value):
int_prop = FloatProperty()
assert int_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
"something",
StringProperty(),
])
@pytest.mark.parametrize(
"value", [
"something",
StringProperty(),
],
)
def test_float_property_invalid(value):
int_prop = FloatProperty()
with pytest.raises(ValueError):
int_prop.clean(value)
@pytest.mark.parametrize("value", [
True,
False,
'True',
'False',
'true',
'false',
'TRUE',
'FALSE',
'T',
'F',
't',
'f',
1,
0,
])
@pytest.mark.parametrize(
"value", [
True,
False,
'True',
'False',
'true',
'false',
'TRUE',
'FALSE',
'T',
'F',
't',
'f',
1,
0,
],
)
def test_boolean_property_valid(value):
bool_prop = BooleanProperty()
assert bool_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
'abc',
['false'],
{'true': 'true'},
2,
-1,
])
@pytest.mark.parametrize(
"value", [
'abc',
['false'],
{'true': 'true'},
2,
-1,
],
)
def test_boolean_property_invalid(value):
bool_prop = BooleanProperty()
with pytest.raises(ValueError):
@ -242,11 +257,13 @@ def test_reference_property():
ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000")
@pytest.mark.parametrize("value", [
'2017-01-01T12:34:56Z',
'2017-01-01 12:34:56',
'Jan 1 2017 12:34:56',
])
@pytest.mark.parametrize(
"value", [
'2017-01-01T12:34:56Z',
'2017-01-01 12:34:56',
'Jan 1 2017 12:34:56',
],
)
def test_timestamp_property_valid(value):
ts_prop = TimestampProperty()
assert ts_prop.clean(value) == constants.FAKE_TIME
@ -276,25 +293,33 @@ def test_hex_property():
hex_prop.clean("foobar")
@pytest.mark.parametrize("d", [
{'description': 'something'},
[('abc', 1), ('bcd', 2), ('cde', 3)],
])
@pytest.mark.parametrize(
"d", [
{'description': 'something'},
[('abc', 1), ('bcd', 2), ('cde', 3)],
],
)
def test_dictionary_property_valid(d):
dict_prop = DictionaryProperty()
assert dict_prop.clean(d)
@pytest.mark.parametrize("d", [
[{'a': 'something'}, "Invalid dictionary key a: (shorter than 3 characters)."],
[{'a'*300: 'something'}, "Invalid dictionary key aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaa: (longer than 256 characters)."],
[{'Hey!': 'something'}, "Invalid dictionary key Hey!: (contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or underscore (_))."],
])
@pytest.mark.parametrize(
"d", [
[{'a': 'something'}, "Invalid dictionary key a: (shorter than 3 characters)."],
[
{'a'*300: 'something'}, "Invalid dictionary key aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaa: (longer than 256 characters).",
],
[
{'Hey!': 'something'}, "Invalid dictionary key Hey!: (contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or underscore (_)).",
],
],
)
def test_dictionary_property_invalid_key(d):
dict_prop = DictionaryProperty()
@ -304,18 +329,20 @@ def test_dictionary_property_invalid_key(d):
assert str(excinfo.value) == d[1]
@pytest.mark.parametrize("d", [
({}, "The dictionary property must contain a non-empty dictionary"),
# TODO: This error message could be made more helpful. The error is caused
# because `json.loads()` doesn't like the *single* quotes around the key
# name, even though they are valid in a Python dictionary. While technically
# accurate (a string is not a dictionary), if we want to be able to load
# string-encoded "dictionaries" that are, we need a better error message
# or an alternative to `json.loads()` ... and preferably *not* `eval()`. :-)
# Changing the following to `'{"description": "something"}'` does not cause
# any ValueError to be raised.
("{'description': 'something'}", "The dictionary property must contain a dictionary"),
])
@pytest.mark.parametrize(
"d", [
({}, "The dictionary property must contain a non-empty dictionary"),
# TODO: This error message could be made more helpful. The error is caused
# because `json.loads()` doesn't like the *single* quotes around the key
# name, even though they are valid in a Python dictionary. While technically
# accurate (a string is not a dictionary), if we want to be able to load
# string-encoded "dictionaries" that are, we need a better error message
# or an alternative to `json.loads()` ... and preferably *not* `eval()`. :-)
# Changing the following to `'{"description": "something"}'` does not cause
# any ValueError to be raised.
("{'description': 'something'}", "The dictionary property must contain a dictionary"),
],
)
def test_dictionary_property_invalid(d):
dict_prop = DictionaryProperty()
@ -325,9 +352,11 @@ def test_dictionary_property_invalid(d):
def test_property_list_of_dictionary():
@stix2.v20.CustomObject('x-new-obj', [
('property1', ListProperty(DictionaryProperty(), required=True)),
])
@stix2.v20.CustomObject(
'x-new-obj', [
('property1', ListProperty(DictionaryProperty(), required=True)),
],
)
class NewObj():
pass
@ -335,19 +364,23 @@ def test_property_list_of_dictionary():
assert test_obj.property1[0]['foo'] == 'bar'
@pytest.mark.parametrize("value", [
{"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"},
[('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')],
])
@pytest.mark.parametrize(
"value", [
{"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"},
[('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')],
],
)
def test_hashes_property_valid(value):
hash_prop = HashesProperty()
assert hash_prop.clean(value)
@pytest.mark.parametrize("value", [
{"MD5": "a"},
{"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"},
])
@pytest.mark.parametrize(
"value", [
{"MD5": "a"},
{"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"},
],
)
def test_hashes_property_invalid(value):
hash_prop = HashesProperty()
@ -360,7 +393,7 @@ def test_embedded_property():
mime = stix2.v20.EmailMIMEComponent(
content_type="text/plain; charset=utf-8",
content_disposition="inline",
body="Cats are funny!"
body="Cats are funny!",
)
assert emb_prop.clean(mime)
@ -368,11 +401,13 @@ def test_embedded_property():
emb_prop.clean("string")
@pytest.mark.parametrize("value", [
['a', 'b', 'c'],
('a', 'b', 'c'),
'b',
])
@pytest.mark.parametrize(
"value", [
['a', 'b', 'c'],
('a', 'b', 'c'),
'b',
],
)
def test_enum_property_valid(value):
enum_prop = EnumProperty(value)
assert enum_prop.clean('b')
@ -388,17 +423,19 @@ def test_extension_property_valid():
ext_prop = ExtensionsProperty(enclosing_type='file')
assert ext_prop({
'windows-pebinary-ext': {
'pe_type': 'exe'
'pe_type': 'exe',
},
})
@pytest.mark.parametrize("data", [
1,
{'foobar-ext': {
'pe_type': 'exe'
}},
])
@pytest.mark.parametrize(
"data", [
1,
{'foobar-ext': {
'pe_type': 'exe',
}},
],
)
def test_extension_property_invalid(data):
ext_prop = ExtensionsProperty(enclosing_type='file')
with pytest.raises(ValueError):
@ -408,10 +445,12 @@ def test_extension_property_invalid(data):
def test_extension_property_invalid_type():
ext_prop = ExtensionsProperty(enclosing_type='indicator')
with pytest.raises(ValueError) as excinfo:
ext_prop.clean({
'windows-pebinary-ext': {
'pe_type': 'exe'
}}
ext_prop.clean(
{
'windows-pebinary-ext': {
'pe_type': 'exe',
},
},
)
assert 'no extensions defined' in str(excinfo.value)

View File

@ -5,8 +5,9 @@ import pytz
import stix2
from .constants import (FAKE_TIME, INDICATOR_ID, MALWARE_ID, RELATIONSHIP_ID,
RELATIONSHIP_KWARGS)
from .constants import (
FAKE_TIME, INDICATOR_ID, MALWARE_ID, RELATIONSHIP_ID, RELATIONSHIP_KWARGS,
)
EXPECTED_RELATIONSHIP = """{
"type": "relationship",
@ -91,7 +92,7 @@ def test_relationship_required_properties_target_ref():
with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo:
stix2.v20.Relationship(
relationship_type='indicates',
source_ref=INDICATOR_ID
source_ref=INDICATOR_ID,
)
assert excinfo.value.cls == stix2.v20.Relationship
@ -136,18 +137,20 @@ def test_create_relationship_with_positional_args(indicator, malware):
assert rel.id == 'relationship--00000000-0000-4000-8000-000000000005'
@pytest.mark.parametrize("data", [
EXPECTED_RELATIONSHIP,
{
"created": "2016-04-06T20:06:37Z",
"id": "relationship--df7c87eb-75d2-4948-af81-9d49d246f301",
"modified": "2016-04-06T20:06:37Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"type": "relationship"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_RELATIONSHIP,
{
"created": "2016-04-06T20:06:37Z",
"id": "relationship--df7c87eb-75d2-4948-af81-9d49d246f301",
"modified": "2016-04-06T20:06:37Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"type": "relationship",
},
],
)
def test_parse_relationship(data):
rel = stix2.parse(data, version="2.0")

View File

@ -40,7 +40,7 @@ def test_report_example():
object_refs=[
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -60,7 +60,7 @@ def test_report_example_objects_in_object_refs():
object_refs=[
stix2.v20.Indicator(id="indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2", **INDICATOR_KWARGS),
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -81,7 +81,7 @@ def test_report_example_objects_in_object_refs_with_bad_id():
object_refs=[
stix2.v20.Indicator(id="indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2", **INDICATOR_KWARGS),
"campaign-83422c77-904c-4dc1-aff5-5c38f3a2c55c", # the "bad" id, missing a "-"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -91,27 +91,29 @@ def test_report_example_objects_in_object_refs_with_bad_id():
assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"created_by_ref": "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
"description": "A simple report with an indicator and campaign",
"id": "report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
"labels": [
"campaign"
],
"modified": "2015-12-21T19:59:11.000Z",
"name": "The Black Vine Cyberespionage Group",
"object_refs": [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
],
"published": "2016-01-20T17:00:00Z",
"type": "report"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"created_by_ref": "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
"description": "A simple report with an indicator and campaign",
"id": "report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
"labels": [
"campaign",
],
"modified": "2015-12-21T19:59:11.000Z",
"name": "The Black Vine Cyberespionage Group",
"object_refs": [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
"published": "2016-01-20T17:00:00Z",
"type": "report",
},
],
)
def test_parse_report(data):
rept = stix2.parse(data, version="2.0")
@ -120,9 +122,11 @@ def test_parse_report(data):
assert rept.created == dt.datetime(2015, 12, 21, 19, 59, 11, tzinfo=pytz.utc)
assert rept.modified == dt.datetime(2015, 12, 21, 19, 59, 11, tzinfo=pytz.utc)
assert rept.created_by_ref == "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283"
assert rept.object_refs == ["indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"]
assert rept.object_refs == [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
]
assert rept.description == "A simple report with an indicator and campaign"
assert rept.labels == ["campaign"]
assert rept.name == "The Black Vine Cyberespionage Group"

View File

@ -39,7 +39,7 @@ def test_sighting_all_required_properties():
created=now,
modified=now,
sighting_of_ref=INDICATOR_ID,
where_sighted_refs=["identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
where_sighted_refs=["identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"],
)
assert str(s) == EXPECTED_SIGHTING
@ -54,7 +54,7 @@ def test_sighting_bad_where_sighted_refs():
created=now,
modified=now,
sighting_of_ref=INDICATOR_ID,
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"],
)
assert excinfo.value.cls == stix2.v20.Sighting
@ -89,19 +89,21 @@ def test_create_sighting_from_objects_rather_than_ids(malware): # noqa: F811
assert rel.id == 'sighting--00000000-0000-4000-8000-000000000003'
@pytest.mark.parametrize("data", [
EXPECTED_SIGHTING,
{
"created": "2016-04-06T20:06:37Z",
"id": "sighting--bfbc19db-ec35-4e45-beed-f8bde2a772fb",
"modified": "2016-04-06T20:06:37Z",
"sighting_of_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"type": "sighting",
"where_sighted_refs": [
"identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"
]
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_SIGHTING,
{
"created": "2016-04-06T20:06:37Z",
"id": "sighting--bfbc19db-ec35-4e45-beed-f8bde2a772fb",
"modified": "2016-04-06T20:06:37Z",
"sighting_of_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"type": "sighting",
"where_sighted_refs": [
"identity--8cc7afd6-5455-4d2b-a736-e614ee631d99",
],
},
],
)
def test_parse_sighting(data):
sighting = stix2.parse(data, version="2.0")

View File

@ -35,21 +35,23 @@ def test_threat_actor_example():
assert str(threat_actor) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "The Evil Org threat actor group",
"id": "threat-actor--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"labels": [
"crime-syndicate"
],
"modified": "2016-04-06T20:03:48.000Z",
"name": "Evil Org",
"type": "threat-actor"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "The Evil Org threat actor group",
"id": "threat-actor--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"labels": [
"crime-syndicate",
],
"modified": "2016-04-06T20:03:48.000Z",
"name": "Evil Org",
"type": "threat-actor",
},
],
)
def test_parse_threat_actor(data):
actor = stix2.parse(data, version="2.0")

View File

@ -46,20 +46,22 @@ def test_tool_example():
assert str(tool) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"id": "tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"labels": [
"remote-access"
],
"modified": "2016-04-06T20:03:48Z",
"name": "VNC",
"type": "tool"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"id": "tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"labels": [
"remote-access",
],
"modified": "2016-04-06T20:03:48Z",
"name": "VNC",
"type": "tool",
},
],
)
def test_parse_tool(data):
tool = stix2.parse(data, version="2.0")

View File

@ -12,76 +12,90 @@ amsterdam = pytz.timezone('Europe/Amsterdam')
eastern = pytz.timezone('US/Eastern')
@pytest.mark.parametrize('dttm, timestamp', [
(dt.datetime(2017, 1, 1, tzinfo=pytz.utc), '2017-01-01T00:00:00Z'),
(amsterdam.localize(dt.datetime(2017, 1, 1)), '2016-12-31T23:00:00Z'),
(eastern.localize(dt.datetime(2017, 1, 1, 12, 34, 56)), '2017-01-01T17:34:56Z'),
(eastern.localize(dt.datetime(2017, 7, 1)), '2017-07-01T04:00:00Z'),
(dt.datetime(2017, 7, 1), '2017-07-01T00:00:00Z'),
(dt.datetime(2017, 7, 1, 0, 0, 0, 1), '2017-07-01T00:00:00.000001Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='millisecond'), '2017-07-01T00:00:00.000Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='second'), '2017-07-01T00:00:00Z'),
])
@pytest.mark.parametrize(
'dttm, timestamp', [
(dt.datetime(2017, 1, 1, tzinfo=pytz.utc), '2017-01-01T00:00:00Z'),
(amsterdam.localize(dt.datetime(2017, 1, 1)), '2016-12-31T23:00:00Z'),
(eastern.localize(dt.datetime(2017, 1, 1, 12, 34, 56)), '2017-01-01T17:34:56Z'),
(eastern.localize(dt.datetime(2017, 7, 1)), '2017-07-01T04:00:00Z'),
(dt.datetime(2017, 7, 1), '2017-07-01T00:00:00Z'),
(dt.datetime(2017, 7, 1, 0, 0, 0, 1), '2017-07-01T00:00:00.000001Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='millisecond'), '2017-07-01T00:00:00.000Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='second'), '2017-07-01T00:00:00Z'),
],
)
def test_timestamp_formatting(dttm, timestamp):
assert stix2.utils.format_datetime(dttm) == timestamp
@pytest.mark.parametrize('timestamp, dttm', [
(dt.datetime(2017, 1, 1, 0, tzinfo=pytz.utc), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
(dt.date(2017, 1, 1), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00Z', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T02:00:00+2:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
])
@pytest.mark.parametrize(
'timestamp, dttm', [
(dt.datetime(2017, 1, 1, 0, tzinfo=pytz.utc), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
(dt.date(2017, 1, 1), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00Z', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T02:00:00+2:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
],
)
def test_parse_datetime(timestamp, dttm):
assert stix2.utils.parse_into_datetime(timestamp) == dttm
@pytest.mark.parametrize('timestamp, dttm, precision', [
('2017-01-01T01:02:03.000001', dt.datetime(2017, 1, 1, 1, 2, 3, 0, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.001', dt.datetime(2017, 1, 1, 1, 2, 3, 1000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.1', dt.datetime(2017, 1, 1, 1, 2, 3, 100000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, 450000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, tzinfo=pytz.utc), 'second'),
])
@pytest.mark.parametrize(
'timestamp, dttm, precision', [
('2017-01-01T01:02:03.000001', dt.datetime(2017, 1, 1, 1, 2, 3, 0, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.001', dt.datetime(2017, 1, 1, 1, 2, 3, 1000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.1', dt.datetime(2017, 1, 1, 1, 2, 3, 100000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, 450000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, tzinfo=pytz.utc), 'second'),
],
)
def test_parse_datetime_precision(timestamp, dttm, precision):
assert stix2.utils.parse_into_datetime(timestamp, precision) == dttm
@pytest.mark.parametrize('ts', [
'foobar',
1,
])
@pytest.mark.parametrize(
'ts', [
'foobar',
1,
],
)
def test_parse_datetime_invalid(ts):
with pytest.raises(ValueError):
stix2.utils.parse_into_datetime('foobar')
@pytest.mark.parametrize('data', [
{"a": 1},
'{"a": 1}',
StringIO(u'{"a": 1}'),
[("a", 1,)],
])
@pytest.mark.parametrize(
'data', [
{"a": 1},
'{"a": 1}',
StringIO(u'{"a": 1}'),
[("a", 1,)],
],
)
def test_get_dict(data):
assert stix2.utils._get_dict(data)
@pytest.mark.parametrize('data', [
1,
[1],
['a', 1],
"foobar",
])
@pytest.mark.parametrize(
'data', [
1,
[1],
['a', 1],
"foobar",
],
)
def test_get_dict_invalid(data):
with pytest.raises(ValueError):
stix2.utils._get_dict(data)
@pytest.mark.parametrize('stix_id, type', [
('malware--d69c8146-ab35-4d50-8382-6fc80e641d43', 'malware'),
('intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542', 'intrusion-set')
])
@pytest.mark.parametrize(
'stix_id, type', [
('malware--d69c8146-ab35-4d50-8382-6fc80e641d43', 'malware'),
('intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542', 'intrusion-set'),
],
)
def test_get_type_from_id(stix_id, type):
assert stix2.utils.get_type_from_id(stix_id) == type
@ -104,77 +118,85 @@ def test_deduplicate(stix_objs1):
assert "2017-01-27T13:49:53.936Z" in mods
@pytest.mark.parametrize('object, tuple_to_find, expected_index', [
(stix2.v20.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file"
},
"1": {
"type": "ipv4-addr",
"value": "198.51.100.3"
},
"2": {
"type": "network-traffic",
"src_ref": "1",
"protocols": [
"tcp",
"http"
],
"extensions": {
"http-request-ext": {
"request_method": "get",
"request_value": "/download.html",
"request_version": "http/1.1",
"request_header": {
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com"
}
}
}
}
},
), ('1', {"type": "ipv4-addr", "value": "198.51.100.3"}), 1),
({
"type": "x-example",
"id": "x-example--d5413db2-c26c-42e0-b0e0-ec800a310bfb",
"created": "2018-06-11T01:25:22.063Z",
"modified": "2018-06-11T01:25:22.063Z",
"dictionary": {
"key": {
"key_one": "value",
"key_two": "value"
}
}
}, ('key', {'key_one': 'value', 'key_two': 'value'}), 0),
({
"type": "language-content",
"id": "language-content--b86bd89f-98bb-4fa9-8cb2-9ad421da981d",
"created": "2017-02-08T21:31:22.007Z",
"modified": "2017-02-08T21:31:22.007Z",
"object_ref": "campaign--12a111f0-b824-4baf-a224-83b80237a094",
"object_modified": "2017-02-08T21:31:22.007Z",
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall"
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire"
}
}
}, ('fr', {"name": "Attaque Bank 1", "description": "Plus d'informations sur la crise bancaire"}), 1)
])
@pytest.mark.parametrize(
'object, tuple_to_find, expected_index', [
(
stix2.v20.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file",
},
"1": {
"type": "ipv4-addr",
"value": "198.51.100.3",
},
"2": {
"type": "network-traffic",
"src_ref": "1",
"protocols": [
"tcp",
"http",
],
"extensions": {
"http-request-ext": {
"request_method": "get",
"request_value": "/download.html",
"request_version": "http/1.1",
"request_header": {
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com",
},
},
},
},
},
), ('1', {"type": "ipv4-addr", "value": "198.51.100.3"}), 1,
),
(
{
"type": "x-example",
"id": "x-example--d5413db2-c26c-42e0-b0e0-ec800a310bfb",
"created": "2018-06-11T01:25:22.063Z",
"modified": "2018-06-11T01:25:22.063Z",
"dictionary": {
"key": {
"key_one": "value",
"key_two": "value",
},
},
}, ('key', {'key_one': 'value', 'key_two': 'value'}), 0,
),
(
{
"type": "language-content",
"id": "language-content--b86bd89f-98bb-4fa9-8cb2-9ad421da981d",
"created": "2017-02-08T21:31:22.007Z",
"modified": "2017-02-08T21:31:22.007Z",
"object_ref": "campaign--12a111f0-b824-4baf-a224-83b80237a094",
"object_modified": "2017-02-08T21:31:22.007Z",
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall",
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire",
},
},
}, ('fr', {"name": "Attaque Bank 1", "description": "Plus d'informations sur la crise bancaire"}), 1,
),
],
)
def test_find_property_index(object, tuple_to_find, expected_index):
assert stix2.utils.find_property_index(
object,
@ -182,29 +204,35 @@ def test_find_property_index(object, tuple_to_find, expected_index):
) == expected_index
@pytest.mark.parametrize('dict_value, tuple_to_find, expected_index', [
({
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall"
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire"
},
"es": {
"name": "Ataque al Banco",
"description": "Mas informacion sobre el ataque al banco"
}
}
}, ('es', {"name": "Ataque al Banco", "description": "Mas informacion sobre el ataque al banco"}), 1), # Sorted alphabetically
({
'my_list': [
{"key_one": 1},
{"key_two": 2}
]
}, ('key_one', 1), 0)
])
@pytest.mark.parametrize(
'dict_value, tuple_to_find, expected_index', [
(
{
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall",
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire",
},
"es": {
"name": "Ataque al Banco",
"description": "Mas informacion sobre el ataque al banco",
},
},
}, ('es', {"name": "Ataque al Banco", "description": "Mas informacion sobre el ataque al banco"}), 1,
), # Sorted alphabetically
(
{
'my_list': [
{"key_one": 1},
{"key_two": 2},
],
}, ('key_one', 1), 0,
),
],
)
def test_iterate_over_values(dict_value, tuple_to_find, expected_index):
assert stix2.utils._find_property_in_seq(dict_value.values(), *tuple_to_find) == expected_index

View File

@ -37,15 +37,15 @@ def test_making_new_version_with_embedded_object():
campaign_v1 = stix2.v20.Campaign(
external_references=[{
"source_name": "capec",
"external_id": "CAPEC-163"
"external_id": "CAPEC-163",
}],
**CAMPAIGN_MORE_KWARGS
)
campaign_v2 = campaign_v1.new_version(external_references=[{
"source_name": "capec",
"external_id": "CAPEC-164"
}])
"external_id": "CAPEC-164",
}])
assert campaign_v1.id == campaign_v2.id
assert campaign_v1.created_by_ref == campaign_v2.created_by_ref
@ -93,10 +93,12 @@ def test_versioning_error_bad_modified_value():
"but have the same id and modified timestamp do not have defined consumer behavior."
msg = "Invalid value for {0} '{1}': {2}"
msg = msg.format(stix2.v20.Campaign.__name__, "modified",
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.")
msg = msg.format(
stix2.v20.Campaign.__name__, "modified",
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.",
)
assert str(excinfo.value) == msg
@ -215,10 +217,12 @@ def test_revoke_invalid_cls():
def test_remove_custom_stix_property():
mal = stix2.v20.Malware(name="ColePowers",
labels=["rootkit"],
x_custom="armada",
allow_custom=True)
mal = stix2.v20.Malware(
name="ColePowers",
labels=["rootkit"],
x_custom="armada",
allow_custom=True,
)
mal_nc = stix2.utils.remove_custom_stix(mal)
@ -228,10 +232,12 @@ def test_remove_custom_stix_property():
def test_remove_custom_stix_object():
@stix2.v20.CustomObject("x-animal", [
("species", stix2.properties.StringProperty(required=True)),
("animal_class", stix2.properties.StringProperty()),
])
@stix2.v20.CustomObject(
"x-animal", [
("species", stix2.properties.StringProperty(required=True)),
("animal_class", stix2.properties.StringProperty()),
],
)
class Animal(object):
pass

View File

@ -29,30 +29,34 @@ def test_vulnerability_example():
modified="2016-05-12T08:17:27.000Z",
name="CVE-2016-1234",
external_references=[
stix2.v20.ExternalReference(source_name='cve',
external_id="CVE-2016-1234"),
stix2.v20.ExternalReference(
source_name='cve',
external_id="CVE-2016-1234",
),
],
)
assert str(vulnerability) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-05-12T08:17:27Z",
"external_references": [
{
"external_id": "CVE-2016-1234",
"source_name": "cve"
}
],
"id": "vulnerability--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"modified": "2016-05-12T08:17:27Z",
"name": "CVE-2016-1234",
"type": "vulnerability"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-05-12T08:17:27Z",
"external_references": [
{
"external_id": "CVE-2016-1234",
"source_name": "cve",
},
],
"id": "vulnerability--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"modified": "2016-05-12T08:17:27Z",
"name": "CVE-2016-1234",
"type": "vulnerability",
},
],
)
def test_parse_vulnerability(data):
vuln = stix2.parse(data, version="2.0")

View File

@ -3,29 +3,25 @@ import os
import pytest
import stix2
from stix2.workbench import (AttackPattern, Campaign, CourseOfAction,
ExternalReference, FileSystemSource, Filter,
Identity, Indicator, IntrusionSet, Malware,
MarkingDefinition, ObservedData, Relationship,
Report, StatementMarking, ThreatActor, Tool,
Vulnerability, add_data_source, all_versions,
attack_patterns, campaigns, courses_of_action,
create, get, identities, indicators,
intrusion_sets, malware, observed_data, query,
reports, save, set_default_created,
set_default_creator, set_default_external_refs,
set_default_object_marking_refs, threat_actors,
tools, vulnerabilities)
from stix2.workbench import (
AttackPattern, Campaign, CourseOfAction, ExternalReference,
FileSystemSource, Filter, Identity, Indicator, IntrusionSet, Malware,
MarkingDefinition, ObservedData, Relationship, Report, StatementMarking,
ThreatActor, Tool, Vulnerability, add_data_source, all_versions,
attack_patterns, campaigns, courses_of_action, create, get, identities,
indicators, intrusion_sets, malware, observed_data, query, reports, save,
set_default_created, set_default_creator, set_default_external_refs,
set_default_object_marking_refs, threat_actors, tools, vulnerabilities,
)
from .constants import (ATTACK_PATTERN_ID, ATTACK_PATTERN_KWARGS, CAMPAIGN_ID,
CAMPAIGN_KWARGS, COURSE_OF_ACTION_ID,
COURSE_OF_ACTION_KWARGS, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, INTRUSION_SET_ID,
INTRUSION_SET_KWARGS, MALWARE_ID, MALWARE_KWARGS,
OBSERVED_DATA_ID, OBSERVED_DATA_KWARGS, REPORT_ID,
REPORT_KWARGS, THREAT_ACTOR_ID, THREAT_ACTOR_KWARGS,
TOOL_ID, TOOL_KWARGS, VULNERABILITY_ID,
VULNERABILITY_KWARGS)
from .constants import (
ATTACK_PATTERN_ID, ATTACK_PATTERN_KWARGS, CAMPAIGN_ID, CAMPAIGN_KWARGS,
COURSE_OF_ACTION_ID, COURSE_OF_ACTION_KWARGS, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, INTRUSION_SET_ID, INTRUSION_SET_KWARGS,
MALWARE_ID, MALWARE_KWARGS, OBSERVED_DATA_ID, OBSERVED_DATA_KWARGS,
REPORT_ID, REPORT_KWARGS, THREAT_ACTOR_ID, THREAT_ACTOR_KWARGS, TOOL_ID,
TOOL_KWARGS, VULNERABILITY_ID, VULNERABILITY_KWARGS,
)
@pytest.mark.skip(reason='The workbench is not working correctly for 2.0')
@ -240,8 +236,10 @@ def test_additional_filter():
@pytest.mark.skip(reason='The workbench is not working correctly for 2.0')
def test_additional_filters_list():
resp = tools([Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'),
Filter('name', '=', 'Windows Credential Editor')])
resp = tools([
Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'),
Filter('name', '=', 'Windows Credential Editor'),
])
assert len(resp) == 1
@ -264,8 +262,10 @@ def test_default_created_timestamp():
def test_default_external_refs():
ext_ref = ExternalReference(source_name="ACME Threat Intel",
description="Threat report")
ext_ref = ExternalReference(
source_name="ACME Threat Intel",
description="Threat report",
)
set_default_external_refs(ext_ref)
campaign = Campaign(**CAMPAIGN_KWARGS)
@ -275,8 +275,10 @@ def test_default_external_refs():
def test_default_object_marking_refs():
stmt_marking = StatementMarking("Copyright 2016, Example Corp")
mark_def = MarkingDefinition(definition_type="statement",
definition=stmt_marking)
mark_def = MarkingDefinition(
definition_type="statement",
definition=stmt_marking,
)
set_default_object_marking_refs(mark_def)
campaign = Campaign(**CAMPAIGN_KWARGS)
@ -314,7 +316,7 @@ def test_workbench_custom_property_dict_in_observable_extension():
'allow_custom': True,
'sid': 1,
'x_foo': 'bar',
}
},
},
)
observed_data = ObservedData(

View File

@ -4,8 +4,9 @@ import pytest
import stix2
from .constants import (FAKE_TIME, INDICATOR_KWARGS, MALWARE_KWARGS,
RELATIONSHIP_KWARGS)
from .constants import (
FAKE_TIME, INDICATOR_KWARGS, MALWARE_KWARGS, RELATIONSHIP_KWARGS,
)
# Inspired by: http://stackoverflow.com/a/24006251
@ -54,66 +55,66 @@ def stix_objs1():
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind2 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind3 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.936Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind4 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind5 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
return [ind1, ind2, ind3, ind4, ind5]
@ -124,40 +125,40 @@ def stix_objs2():
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-31T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind7 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
ind8 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
return [ind6, ind7, ind8]

View File

@ -34,7 +34,7 @@ MARKING_IDS = [
RELATIONSHIP_IDS = [
'relationship--06520621-5352-4e6a-b976-e8fa3d437ffd',
'relationship--181c9c09-43e6-45dd-9374-3bec192f05ef',
'relationship--a0cbb21c-8daf-4a7f-96aa-7155a4ef8f70'
'relationship--a0cbb21c-8daf-4a7f-96aa-7155a4ef8f70',
]
# *_KWARGS contains all required arguments to create an instance of that STIX object
@ -81,7 +81,7 @@ INTRUSION_SET_KWARGS = dict(
MALWARE_KWARGS = dict(
malware_types=['ransomware'],
name="Cryptolocker",
is_family=True
is_family=True,
)
MALWARE_MORE_KWARGS = dict(
@ -92,7 +92,7 @@ MALWARE_MORE_KWARGS = dict(
malware_types=['ransomware'],
name="Cryptolocker",
description="A ransomware related to ...",
is_family=False
is_family=False,
)
OBSERVED_DATA_KWARGS = dict(
@ -103,8 +103,8 @@ OBSERVED_DATA_KWARGS = dict(
"0": {
"type": "windows-registry-key",
"key": "HKEY_LOCAL_MACHINE\\System\\Foo\\Bar",
}
}
},
},
)
REPORT_KWARGS = dict(

View File

@ -32,7 +32,7 @@ def test_attack_pattern_example():
name="Spear Phishing",
external_references=[{
"source_name": "capec",
"external_id": "CAPEC-163"
"external_id": "CAPEC-163",
}],
description="...",
)
@ -40,24 +40,26 @@ def test_attack_pattern_example():
assert str(ap) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "attack-pattern",
"spec_version": "2.1",
"id": "attack-pattern--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": "...",
"external_references": [
{
"external_id": "CAPEC-163",
"source_name": "capec"
}
],
"name": "Spear Phishing",
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "attack-pattern",
"spec_version": "2.1",
"id": "attack-pattern--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": "...",
"external_references": [
{
"external_id": "CAPEC-163",
"source_name": "capec",
},
],
"name": "Spear Phishing",
},
],
)
def test_parse_attack_pattern(data):
ap = stix2.parse(data, version="2.1")
@ -79,7 +81,7 @@ def test_attack_pattern_invalid_labels():
created="2016-05-12T08:17:27Z",
modified="2016-05-12T08:17:27Z",
name="Spear Phishing",
labels=1
labels=1,
)
# TODO: Add other examples

View File

@ -58,8 +58,8 @@ EXPECTED_BUNDLE_DICT = {
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "2017-01-01T12:34:56Z",
"indicator_types": [
"malicious-activity"
]
"malicious-activity",
],
},
{
"type": "malware",
@ -69,9 +69,9 @@ EXPECTED_BUNDLE_DICT = {
"modified": "2017-01-01T12:34:56.000Z",
"name": "Cryptolocker",
"malware_types": [
"ransomware"
"ransomware",
],
"is_family": True
"is_family": True,
},
{
"type": "relationship",
@ -81,9 +81,9 @@ EXPECTED_BUNDLE_DICT = {
"modified": "2017-01-01T12:34:56.000Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e"
}
]
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
},
],
}

View File

@ -26,25 +26,27 @@ def test_campaign_example():
created="2016-04-06T20:03:00Z",
modified="2016-04-06T20:03:00Z",
name="Green Group Attacks Against Finance",
description="Campaign by Green Group against a series of targets in the financial services sector."
description="Campaign by Green Group against a series of targets in the financial services sector.",
)
assert str(campaign) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "campaign",
"spec_version": "2.1",
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2016-04-06T20:03:00Z",
"modified": "2016-04-06T20:03:00Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Campaign by Green Group against a series of targets in the financial services sector.",
"name": "Green Group Attacks Against Finance",
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "campaign",
"spec_version": "2.1",
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2016-04-06T20:03:00Z",
"modified": "2016-04-06T20:03:00Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Campaign by Green Group against a series of targets in the financial services sector.",
"name": "Green Group Attacks Against Finance",
},
],
)
def test_parse_campaign(data):
cmpn = stix2.parse(data, version="2.1")

View File

@ -1,12 +1,11 @@
import pytest
from stix2.confidence.scales import (admiralty_credibility_to_value,
dni_to_value, none_low_med_high_to_value,
value_to_admiralty_credibility,
value_to_dni,
value_to_none_low_medium_high,
value_to_wep, value_to_zero_ten,
wep_to_value, zero_ten_to_value)
from stix2.confidence.scales import (
admiralty_credibility_to_value, dni_to_value, none_low_med_high_to_value,
value_to_admiralty_credibility, value_to_dni,
value_to_none_low_medium_high, value_to_wep, value_to_zero_ten,
wep_to_value, zero_ten_to_value,
)
CONFIDENCE_ERROR_STR = "STIX Confidence value cannot be determined for %s"
RANGE_ERROR_STR = "Range of values out of bounds: %s"
@ -39,22 +38,26 @@ def test_confidence_range_none_low_med_high():
pytest.fail("Unexpected behavior %s" % val)
@pytest.mark.parametrize("scale_value,result", [
("None", 0),
("Low", 15),
("Med", 50),
("High", 85)
])
@pytest.mark.parametrize(
"scale_value,result", [
("None", 0),
("Low", 15),
("Med", 50),
("High", 85),
],
)
def test_confidence_scale_valid_none_low_med_high(scale_value, result):
val = none_low_med_high_to_value(scale_value)
assert val == result
@pytest.mark.parametrize("scale_value", [
"Super",
"none",
""
])
@pytest.mark.parametrize(
"scale_value", [
"Super",
"none",
"",
],
)
def test_confidence_scale_invalid_none_low_med_high(scale_value):
with pytest.raises(ValueError) as excinfo:
none_low_med_high_to_value(scale_value)
@ -99,29 +102,33 @@ def test_confidence_range_zero_ten():
pytest.fail("Unexpected behavior %s" % val)
@pytest.mark.parametrize("scale_value,result", [
("0", 0),
("1", 10),
("2", 20),
("3", 30),
("4", 40),
("5", 50),
("6", 60),
("7", 70),
("8", 80),
("9", 90),
("10", 100)
])
@pytest.mark.parametrize(
"scale_value,result", [
("0", 0),
("1", 10),
("2", 20),
("3", 30),
("4", 40),
("5", 50),
("6", 60),
("7", 70),
("8", 80),
("9", 90),
("10", 100),
],
)
def test_confidence_scale_valid_zero_ten(scale_value, result):
val = zero_ten_to_value(scale_value)
assert val == result
@pytest.mark.parametrize("scale_value", [
"11",
8,
""
])
@pytest.mark.parametrize(
"scale_value", [
"11",
8,
"",
],
)
def test_confidence_scale_invalid_zero_ten(scale_value):
with pytest.raises(ValueError) as excinfo:
zero_ten_to_value(scale_value)
@ -154,23 +161,27 @@ def test_confidence_range_admiralty_credibility():
pytest.fail("Unexpected behavior %s" % val)
@pytest.mark.parametrize("scale_value,result", [
("5 - Improbable", 10),
("4 - Doubtful", 30),
("3 - Possibly True", 50),
("2 - Probably True", 70),
("1 - Confirmed by other sources", 90)
])
@pytest.mark.parametrize(
"scale_value,result", [
("5 - Improbable", 10),
("4 - Doubtful", 30),
("3 - Possibly True", 50),
("2 - Probably True", 70),
("1 - Confirmed by other sources", 90),
],
)
def test_confidence_scale_valid_admiralty_credibility(scale_value, result):
val = admiralty_credibility_to_value(scale_value)
assert val == result
@pytest.mark.parametrize("scale_value", [
"5 - improbable",
"6 - Truth cannot be judged",
""
])
@pytest.mark.parametrize(
"scale_value", [
"5 - improbable",
"6 - Truth cannot be judged",
"",
],
)
def test_confidence_scale_invalid_admiralty_credibility(scale_value):
with pytest.raises(ValueError) as excinfo:
admiralty_credibility_to_value(scale_value)
@ -207,25 +218,29 @@ def test_confidence_range_wep():
pytest.fail("Unexpected behavior %s" % val)
@pytest.mark.parametrize("scale_value,result", [
("Impossible", 0),
("Highly Unlikely/Almost Certainly Not", 10),
("Unlikely/Probably Not", 30),
("Even Chance", 50),
("Likely/Probable", 70),
("Highly likely/Almost Certain", 90),
("Certain", 100)
])
@pytest.mark.parametrize(
"scale_value,result", [
("Impossible", 0),
("Highly Unlikely/Almost Certainly Not", 10),
("Unlikely/Probably Not", 30),
("Even Chance", 50),
("Likely/Probable", 70),
("Highly likely/Almost Certain", 90),
("Certain", 100),
],
)
def test_confidence_scale_valid_wep(scale_value, result):
val = wep_to_value(scale_value)
assert val == result
@pytest.mark.parametrize("scale_value", [
"Unlikely / Probably Not",
"Almost certain",
""
])
@pytest.mark.parametrize(
"scale_value", [
"Unlikely / Probably Not",
"Almost certain",
"",
],
)
def test_confidence_scale_invalid_wep(scale_value):
with pytest.raises(ValueError) as excinfo:
wep_to_value(scale_value)
@ -262,25 +277,29 @@ def test_confidence_range_dni():
pytest.fail("Unexpected behavior %s" % val)
@pytest.mark.parametrize("scale_value,result", [
("Almost No Chance / Remote", 5),
("Very Unlikely / Highly Improbable", 15),
("Unlikely / Improbable", 30),
("Roughly Even Change / Roughly Even Odds", 50),
("Likely / Probable", 70),
("Very Likely / Highly Probable", 85),
("Almost Certain / Nearly Certain", 95)
])
@pytest.mark.parametrize(
"scale_value,result", [
("Almost No Chance / Remote", 5),
("Very Unlikely / Highly Improbable", 15),
("Unlikely / Improbable", 30),
("Roughly Even Change / Roughly Even Odds", 50),
("Likely / Probable", 70),
("Very Likely / Highly Probable", 85),
("Almost Certain / Nearly Certain", 95),
],
)
def test_confidence_scale_valid_dni(scale_value, result):
val = dni_to_value(scale_value)
assert val == result
@pytest.mark.parametrize("scale_value", [
"Almost Certain/Nearly Certain",
"Almost Certain / nearly Certain",
""
])
@pytest.mark.parametrize(
"scale_value", [
"Almost Certain/Nearly Certain",
"Almost Certain / nearly Certain",
"",
],
)
def test_confidence_scale_invalid_none_dni(scale_value):
with pytest.raises(ValueError) as excinfo:
dni_to_value(scale_value)

View File

@ -26,25 +26,27 @@ def test_course_of_action_example():
created="2016-04-06T20:03:48.000Z",
modified="2016-04-06T20:03:48.000Z",
name="Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
description="This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ..."
description="This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
)
assert str(coa) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
"id": "course-of-action--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"spec_version": "2.1",
"type": "course-of-action"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...",
"id": "course-of-action--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"spec_version": "2.1",
"type": "course-of-action",
},
],
)
def test_parse_course_of_action(data):
coa = stix2.parse(data, version="2.1")

View File

@ -36,7 +36,7 @@ def test_identity_custom_property():
"foo": "bar",
},
foo="bar",
)
)
assert "Unexpected properties for Identity" in str(excinfo.value)
identity = stix2.v21.Identity(
@ -80,8 +80,9 @@ def test_identity_custom_property_allowed():
assert identity.x_foo == "bar"
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "identity",
"spec_version": "2.1",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
@ -91,7 +92,8 @@ def test_identity_custom_property_allowed():
"identity_class": "individual",
"foo": "bar"
}""",
])
],
)
def test_parse_identity_custom_property(data):
with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo:
stix2.parse(data, version="2.1")
@ -116,7 +118,7 @@ def test_custom_properties_object_in_bundled_object():
identity_class="individual",
custom_properties={
"x_foo": "bar",
}
},
)
bundle = stix2.v21.Bundle(obj, allow_custom=True)
@ -164,7 +166,7 @@ def test_custom_property_in_observed_data():
artifact = stix2.v21.File(
allow_custom=True,
name='test',
x_foo='bar'
x_foo='bar',
)
observed_data = stix2.v21.ObservedData(
allow_custom=True,
@ -208,7 +210,7 @@ def test_custom_property_dict_in_observable_extension():
'ntfs-ext': {
'sid': 1,
'x_foo': 'bar',
}
},
},
)
@ -220,7 +222,7 @@ def test_custom_property_dict_in_observable_extension():
'allow_custom': True,
'sid': 1,
'x_foo': 'bar',
}
},
},
)
observed_data = stix2.v21.ObservedData(
@ -244,12 +246,12 @@ def test_identity_custom_property_edit_markings():
marking_obj = stix2.v21.MarkingDefinition(
id=MARKING_DEFINITION_ID,
definition_type="statement",
definition=stix2.v21.StatementMarking(statement="Copyright 2016, Example Corp")
definition=stix2.v21.StatementMarking(statement="Copyright 2016, Example Corp"),
)
marking_obj2 = stix2.v21.MarkingDefinition(
id=MARKING_DEFINITION_ID,
definition_type="statement",
definition=stix2.v21.StatementMarking(statement="Another one")
definition=stix2.v21.StatementMarking(statement="Another one"),
)
# None of the following should throw exceptions
@ -262,9 +264,11 @@ def test_identity_custom_property_edit_markings():
def test_custom_marking_no_init_1():
@stix2.v21.CustomMarking('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomMarking(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass
@ -273,9 +277,11 @@ def test_custom_marking_no_init_1():
def test_custom_marking_no_init_2():
@stix2.v21.CustomMarking('x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomMarking(
'x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass
@ -283,10 +289,12 @@ def test_custom_marking_no_init_2():
assert no2.property1 == 'something'
@stix2.v21.CustomObject('x-new-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v21.CustomObject(
'x-new-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewType(object):
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -316,9 +324,11 @@ def test_custom_object_type():
def test_custom_object_no_init_1():
@stix2.v21.CustomObject('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomObject(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass
@ -327,9 +337,11 @@ def test_custom_object_no_init_1():
def test_custom_object_no_init_2():
@stix2.v21.CustomObject('x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomObject(
'x-new-obj2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass
@ -339,17 +351,21 @@ def test_custom_object_no_init_2():
def test_custom_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObject('x', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomObject(
'x', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj(object):
pass # pragma: no cover
assert "Invalid type name 'x': " in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObject('x_new_object', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomObject(
'x_new_object', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2(object):
pass # pragma: no cover
assert "Invalid type name 'x_new_object':" in str(excinfo.value)
@ -393,11 +409,13 @@ def test_parse_unregistered_custom_object_type_w_allow_custom():
assert custom_obj["type"] == "x-foobar-observable"
@stix2.v21.CustomObservable('x-new-observable', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
('x_property3', stix2.properties.BooleanProperty()),
])
@stix2.v21.CustomObservable(
'x-new-observable', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
('x_property3', stix2.properties.BooleanProperty()),
],
)
class NewObservable():
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -432,9 +450,11 @@ def test_custom_observable_raises_exception():
def test_custom_observable_object_no_init_1():
@stix2.v21.CustomObservable('x-new-observable', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x-new-observable', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
@ -443,9 +463,11 @@ def test_custom_observable_object_no_init_1():
def test_custom_observable_object_no_init_2():
@stix2.v21.CustomObservable('x-new-obs2', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x-new-obs2', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs2(object):
pass
@ -455,17 +477,21 @@ def test_custom_observable_object_no_init_2():
def test_custom_observable_object_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable('x', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs(object):
pass # pragma: no cover
assert "Invalid observable type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable('x_new_obs', [
('property1', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x_new_obs', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObs2(object):
pass # pragma: no cover
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
@ -473,9 +499,11 @@ def test_custom_observable_object_invalid_type_name():
def test_custom_observable_object_invalid_ref_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable('x-new-obs', [
('property_ref', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x-new-obs', [
('property_ref', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
assert "is named like an object reference property but is not an ObjectReferenceProperty" in str(excinfo.value)
@ -483,9 +511,11 @@ def test_custom_observable_object_invalid_ref_property():
def test_custom_observable_object_invalid_refs_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable('x-new-obs', [
('property_refs', stix2.properties.StringProperty()),
])
@stix2.v21.CustomObservable(
'x-new-obs', [
('property_refs', stix2.properties.StringProperty()),
],
)
class NewObs():
pass
assert "is named like an object reference list property but is not a ListProperty containing ObjectReferenceProperty" in str(excinfo.value)
@ -493,26 +523,32 @@ def test_custom_observable_object_invalid_refs_property():
def test_custom_observable_object_invalid_refs_list_property():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomObservable('x-new-obs', [
('property_refs', stix2.properties.ListProperty(stix2.properties.StringProperty)),
])
@stix2.v21.CustomObservable(
'x-new-obs', [
('property_refs', stix2.properties.ListProperty(stix2.properties.StringProperty)),
],
)
class NewObs():
pass
assert "is named like an object reference list property but is not a ListProperty containing ObjectReferenceProperty" in str(excinfo.value)
def test_custom_observable_object_invalid_valid_refs():
@stix2.v21.CustomObservable('x-new-obs', [
('property1', stix2.properties.StringProperty(required=True)),
('property_ref', stix2.properties.ObjectReferenceProperty(valid_types='email-addr')),
])
@stix2.v21.CustomObservable(
'x-new-obs', [
('property1', stix2.properties.StringProperty(required=True)),
('property_ref', stix2.properties.ObjectReferenceProperty(valid_types='email-addr')),
],
)
class NewObs():
pass
with pytest.raises(Exception) as excinfo:
NewObs(_valid_refs=['1'],
property1='something',
property_ref='1')
NewObs(
_valid_refs=['1'],
property1='something',
property_ref='1',
)
assert "must be created with _valid_refs as a dict, not a list" in str(excinfo.value)
@ -648,10 +684,12 @@ def test_observed_data_with_custom_observable_object():
assert ob_data.objects['0'].property1 == 'something'
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v21.CustomExtension(
stix2.v21.DomainName, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewExtension():
def __init__(self, property2=None, **kwargs):
if property2 and property2 < 10:
@ -689,13 +727,15 @@ def test_custom_extension_wrong_observable_type():
name="abc.txt",
extensions={
"ntfs-ext": ext,
})
},
)
assert 'Cannot determine extension type' in excinfo.value.reason
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"keys": [
{
"test123": 123,
@ -703,11 +743,14 @@ def test_custom_extension_wrong_observable_type():
}
]
}""",
])
],
)
def test_custom_extension_with_list_and_dict_properties_observable_type(data):
@stix2.v21.CustomExtension(stix2.v21.UserAccount, 'some-extension', [
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True))
])
@stix2.v21.CustomExtension(
stix2.v21.UserAccount, 'some-extension', [
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True)),
],
)
class SomeCustomExtension:
pass
@ -721,9 +764,11 @@ def test_custom_extension_invalid_observable():
class Foo(object):
pass
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(Foo, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomExtension(
Foo, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class FooExtension():
pass # pragma: no cover
assert str(excinfo.value) == "'observable' must be a valid Observable class!"
@ -731,9 +776,11 @@ def test_custom_extension_invalid_observable():
class Bar(stix2.v21.observables._Observable):
pass
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(Bar, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomExtension(
Bar, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class BarExtension():
pass
assert "Unknown observable type" in str(excinfo.value)
@ -742,9 +789,11 @@ def test_custom_extension_invalid_observable():
class Baz(stix2.v21.observables._Observable):
_type = 'Baz'
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(Baz, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomExtension(
Baz, 'x-new-ext', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class BazExtension():
pass
assert "Unknown observable type" in str(excinfo.value)
@ -753,17 +802,21 @@ def test_custom_extension_invalid_observable():
def test_custom_extension_invalid_type_name():
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(stix2.v21.File, 'x', {
'property1': stix2.properties.StringProperty(required=True),
})
@stix2.v21.CustomExtension(
stix2.v21.File, 'x', {
'property1': stix2.properties.StringProperty(required=True),
},
)
class FooExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x':" in str(excinfo.value)
with pytest.raises(ValueError) as excinfo:
@stix2.v21.CustomExtension(stix2.v21.File, 'x_new_ext', {
'property1': stix2.properties.StringProperty(required=True),
})
@stix2.v21.CustomExtension(
stix2.v21.File, 'x_new_ext', {
'property1': stix2.properties.StringProperty(required=True),
},
)
class BlaExtension():
pass # pragma: no cover
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
@ -794,9 +847,11 @@ def test_custom_extension_dict_properties():
def test_custom_extension_no_init_1():
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-extension', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomExtension(
stix2.v21.DomainName, 'x-new-extension', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewExt():
pass
@ -805,9 +860,11 @@ def test_custom_extension_no_init_1():
def test_custom_extension_no_init_2():
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-ext2', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomExtension(
stix2.v21.DomainName, 'x-new-ext2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewExt2(object):
pass
@ -867,8 +924,9 @@ def test_extension_property_location():
assert 'extensions' not in stix2.v21.EXT_MAP['domain-name']['x-new-ext']._properties
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "x-example",
"spec_version": "2.1",
"id": "x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d",
@ -881,18 +939,23 @@ def test_extension_property_location():
}
}
}""",
])
],
)
def test_custom_object_nested_dictionary(data):
@stix2.v21.CustomObject('x-example', [
('dictionary', stix2.properties.DictionaryProperty()),
])
@stix2.v21.CustomObject(
'x-example', [
('dictionary', stix2.properties.DictionaryProperty()),
],
)
class Example(object):
def __init__(self, **kwargs):
pass
example = Example(id='x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d',
created='2018-06-12T16:20:58.059Z',
modified='2018-06-12T16:20:58.059Z',
dictionary={'key': {'key_b': 'value', 'key_a': 'value'}})
example = Example(
id='x-example--336d8a9f-91f1-46c5-b142-6441bb9f8b8d',
created='2018-06-12T16:20:58.059Z',
modified='2018-06-12T16:20:58.059Z',
dictionary={'key': {'key_b': 'value', 'key_a': 'value'}},
)
assert data == str(example)

View File

@ -1,7 +1,8 @@
import pytest
from stix2.datastore import (CompositeDataSource, DataSink, DataSource,
DataStoreMixin)
from stix2.datastore import (
CompositeDataSource, DataSink, DataSource, DataStoreMixin,
)
from stix2.datastore.filters import Filter
from stix2.test.v21.constants import CAMPAIGN_MORE_KWARGS
@ -46,15 +47,19 @@ def test_datastore_creator_of_raises():
def test_datastore_relationships_raises():
with pytest.raises(AttributeError) as excinfo:
DataStoreMixin().relationships(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
DataStoreMixin().relationships(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
def test_datastore_related_to_raises():
with pytest.raises(AttributeError) as excinfo:
DataStoreMixin().related_to(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
DataStoreMixin().related_to(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
@ -84,15 +89,19 @@ def test_composite_datastore_query_raises_error():
def test_composite_datastore_relationships_raises_error():
with pytest.raises(AttributeError) as excinfo:
CompositeDataSource().relationships(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
CompositeDataSource().relationships(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "CompositeDataSource has no data sources" == str(excinfo.value)
def test_composite_datastore_related_to_raises_error():
with pytest.raises(AttributeError) as excinfo:
CompositeDataSource().related_to(obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True)
CompositeDataSource().related_to(
obj="indicator--00000000-0000-4000-8000-000000000001",
target_only=True,
)
assert "CompositeDataSource has no data sources" == str(excinfo.value)

View File

@ -13,8 +13,10 @@ def test_add_remove_composite_datasource():
with pytest.raises(TypeError) as excinfo:
cds.add_data_sources([ds1, ds2, ds1, ds3])
assert str(excinfo.value) == ("DataSource (to be added) is not of type "
"stix2.DataSource. DataSource type is '<class 'stix2.datastore.memory.MemorySink'>'")
assert str(excinfo.value) == (
"DataSource (to be added) is not of type "
"stix2.DataSource. DataSource type is '<class 'stix2.datastore.memory.MemorySink'>'"
)
cds.add_data_sources([ds1, ds2, ds1])
@ -26,9 +28,11 @@ def test_add_remove_composite_datasource():
def test_composite_datasource_operations(stix_objs1, stix_objs2):
BUNDLE1 = dict(id="bundle--%s" % make_id(),
objects=stix_objs1,
type="bundle")
BUNDLE1 = dict(
id="bundle--%s" % make_id(),
objects=stix_objs1,
type="bundle",
)
cds1 = CompositeDataSource()
ds1_1 = MemorySource(stix_data=BUNDLE1)
ds1_2 = MemorySource(stix_data=stix_objs2)
@ -54,11 +58,11 @@ def test_composite_datasource_operations(stix_objs1, stix_objs2):
assert indicator["type"] == "indicator"
query1 = [
Filter("type", "=", "indicator")
Filter("type", "=", "indicator"),
]
query2 = [
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z")
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z"),
]
cds1.filters.add(query2)

View File

@ -5,11 +5,10 @@ import shutil
import pytest
import stix2
from stix2.test.v21.constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS,
IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS,
RELATIONSHIP_IDS)
from stix2.test.v21.constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID, IDENTITY_KWARGS, INDICATOR_ID,
INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS,
)
FS_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "stix2_data")
@ -68,7 +67,7 @@ def bad_stix_files():
# bad STIX object
stix_obj = {
"id": "intrusion-set--test-bad-stix",
"spec_version": "2.0"
"spec_version": "2.0",
# no "type" field
}
@ -175,9 +174,11 @@ def test_filesytem_source_query_multiple(fs_source):
def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
# add python stix object
camp1 = stix2.v21.Campaign(name="Hannibal",
objective="Targeting Italian and Spanish Diplomat internet accounts",
aliases=["War Elephant"])
camp1 = stix2.v21.Campaign(
name="Hannibal",
objective="Targeting Italian and Spanish Diplomat internet accounts",
aliases=["War Elephant"],
)
fs_sink.add(camp1)
@ -199,7 +200,7 @@ def test_filesystem_sink_add_stix_object_dict(fs_sink, fs_source):
"objective": "German and French Intelligence Services",
"aliases": ["Purple Robes"],
"id": "campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"created": "2017-05-31T21:31:53.197755Z"
"created": "2017-05-31T21:31:53.197755Z",
}
fs_sink.add(camp2)
@ -226,9 +227,9 @@ def test_filesystem_sink_add_stix_bundle_dict(fs_sink, fs_source):
"objective": "Bulgarian, Albanian and Romanian Intelligence Services",
"aliases": ["Huns"],
"id": "campaign--b8f86161-ccae-49de-973a-4ca320c62478",
"created": "2017-05-31T21:31:53.197755Z"
}
]
"created": "2017-05-31T21:31:53.197755Z",
},
],
}
fs_sink.add(bund)
@ -277,9 +278,11 @@ def test_filesystem_sink_json_stix_bundle(fs_sink, fs_source):
def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
# add list of objects
camp6 = stix2.v21.Campaign(name="Comanche",
objective="US Midwest manufacturing firms, oil refineries, and businesses",
aliases=["Horse Warrior"])
camp6 = stix2.v21.Campaign(
name="Comanche",
objective="US Midwest manufacturing firms, oil refineries, and businesses",
aliases=["Horse Warrior"],
)
camp7 = {
"name": "Napolean",
@ -288,7 +291,7 @@ def test_filesystem_sink_add_objects_list(fs_sink, fs_source):
"objective": "Central and Eastern Europe military commands and departments",
"aliases": ["The Frenchmen"],
"id": "campaign--122818b6-1112-4fb0-b11b-b111107ca70a",
"created": "2017-05-31T21:31:53.197755Z"
"created": "2017-05-31T21:31:53.197755Z",
}
fs_sink.add([camp6, camp7])
@ -365,9 +368,11 @@ def test_filesystem_store_query_dont_include_type_folder(fs_store):
def test_filesystem_store_add(fs_store):
# add()
camp1 = stix2.v21.Campaign(name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"])
camp1 = stix2.v21.Campaign(
name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"],
)
fs_store.add(camp1)
camp1_r = fs_store.get(camp1.id)
@ -381,9 +386,11 @@ def test_filesystem_store_add(fs_store):
def test_filesystem_store_add_as_bundle():
fs_store = stix2.FileSystemStore(FS_PATH, bundlify=True)
camp1 = stix2.v21.Campaign(name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"])
camp1 = stix2.v21.Campaign(
name="Great Heathen Army",
objective="Targeting the government of United Kingdom and insitutions affiliated with the Church Of England",
aliases=["Ragnar"],
)
fs_store.add(camp1)
with open(os.path.join(FS_PATH, "campaign", camp1.id + ".json")) as bundle_file:
@ -412,10 +419,12 @@ def test_filesystem_store_add_invalid_object(fs_store):
def test_filesystem_object_with_custom_property(fs_store):
camp = stix2.v21.Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = stix2.v21.Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
fs_store.add(camp)
@ -425,10 +434,12 @@ def test_filesystem_object_with_custom_property(fs_store):
def test_filesystem_object_with_custom_property_in_bundle(fs_store):
camp = stix2.v21.Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = stix2.v21.Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
bundle = stix2.v21.Bundle(camp, allow_custom=True)
fs_store.add(bundle)
@ -439,9 +450,11 @@ def test_filesystem_object_with_custom_property_in_bundle(fs_store):
def test_filesystem_custom_object(fs_store):
@stix2.v21.CustomObject('x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
])
@stix2.v21.CustomObject(
'x-new-obj', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj():
pass

View File

@ -11,25 +11,25 @@ stix_objs = [
"id": "malware--fdd60b30-b67c-41e3-b0b9-f01faf20d111",
"spec_version": "2.1",
"malware_types": [
"remote-access-trojan"
"remote-access-trojan",
],
"modified": "2017-01-27T13:49:53.997Z",
"name": "Poison Ivy",
"type": "malware",
"is_family": False
"is_family": False,
},
{
"created": "2014-05-08T09:00:00.000Z",
"id": "indicator--a932fcc6-e032-476c-826f-cb970a5a1ade",
"indicator_types": [
"file-hash-watchlist"
"file-hash-watchlist",
],
"modified": "2014-05-08T09:00:00.000Z",
"name": "File hash for Poison Ivy variant",
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2014-05-08T09:00:00.000000Z"
"valid_from": "2014-05-08T09:00:00.000000Z",
},
{
"created": "2014-05-08T09:00:00.000Z",
@ -37,21 +37,21 @@ stix_objs = [
{
"marking_ref": "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed",
"selectors": [
"relationship_type"
]
}
"relationship_type",
],
},
],
"id": "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463",
"modified": "2014-05-08T09:00:00.000Z",
"object_marking_refs": [
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
],
"relationship_type": "indicates",
"revoked": True,
"source_ref": "indicator--a932fcc6-e032-476c-826f-cb970a5a1ade",
"spec_version": "2.1",
"target_ref": "malware--fdd60b30-b67c-41e3-b0b9-f01faf20d111",
"type": "relationship"
"type": "relationship",
},
{
"id": "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef",
@ -65,10 +65,10 @@ stix_objs = [
"external_references": [
{
"source_name": "cve",
"external_id": "CVE-2014-0160"
}
"external_id": "CVE-2014-0160",
},
],
"labels": ["heartbleed", "has-logo"]
"labels": ["heartbleed", "has-logo"],
},
{
"type": "observed-data",
@ -83,11 +83,11 @@ stix_objs = [
"objects": {
"0": {
"type": "file",
"name": "HAL 9000.exe"
}
}
"name": "HAL 9000.exe",
},
},
}
},
]
@ -420,8 +420,10 @@ def test_filters4():
# Assert invalid Filter cannot be created
with pytest.raises(ValueError) as excinfo:
Filter("modified", "?", "2017-01-27T13:49:53.935Z")
assert str(excinfo.value) == ("Filter operator '?' not supported "
"for specified property: 'modified'")
assert str(excinfo.value) == (
"Filter operator '?' not supported "
"for specified property: 'modified'"
)
def test_filters5(stix_objs2, real_stix_objs2):
@ -462,7 +464,7 @@ def test_filters7(stix_objs2, real_stix_objs2):
"0": {
"type": "file",
"hashes": {
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f",
},
"extensions": {
"pdf-ext": {
@ -472,14 +474,14 @@ def test_filters7(stix_objs2, real_stix_objs2):
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
"pdfid0": "DFCE52BD827ECF765649852119D",
"pdfid1": "57A1E0F9ED2AE523E313C"
}
}
}
}
"pdfid1": "57A1E0F9ED2AE523E313C",
},
},
},
},
}
stix_objects = list(stix_objs2) + [obsvd_data_obj]

View File

@ -5,116 +5,118 @@ import pytest
from stix2 import Filter, MemorySource, MemoryStore, properties
from stix2.datastore import make_id
from stix2.v21 import (Bundle, Campaign, CustomObject, Identity, Indicator,
Malware, Relationship)
from stix2.v21 import (
Bundle, Campaign, CustomObject, Identity, Indicator, Malware, Relationship,
)
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID,
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS)
from .constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID, IDENTITY_KWARGS, INDICATOR_ID,
INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS,
)
IND1 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND2 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND3 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.936Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND4 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND5 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND6 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000001",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-31T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND7 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
IND8 = {
"created": "2017-01-27T13:49:53.935Z",
"id": "indicator--00000000-0000-4000-8000-000000000002",
"indicator_types": [
"url-watchlist"
"url-watchlist",
],
"modified": "2017-01-27T13:49:53.935Z",
"name": "Malicious site hosting downloader",
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
"spec_version": "2.1",
"type": "indicator",
"valid_from": "2017-01-27T13:49:53.935382Z"
"valid_from": "2017-01-27T13:49:53.935382Z",
}
STIX_OBJS2 = [IND6, IND7, IND8]
@ -169,10 +171,12 @@ def test_memory_source_get_nonexistant_object(mem_source):
def test_memory_store_all_versions(mem_store):
# Add bundle of items to sink
mem_store.add(dict(id="bundle--%s" % make_id(),
objects=STIX_OBJS2,
spec_version="2.0",
type="bundle"))
mem_store.add(dict(
id="bundle--%s" % make_id(),
objects=STIX_OBJS2,
spec_version="2.0",
type="bundle",
))
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
assert len(resp) == 1 # MemoryStore can only store 1 version of each object
@ -235,10 +239,12 @@ def test_memory_store_add_invalid_object(mem_store):
def test_memory_store_object_with_custom_property(mem_store):
camp = Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
mem_store.add(camp)
@ -248,10 +254,12 @@ def test_memory_store_object_with_custom_property(mem_store):
def test_memory_store_object_with_custom_property_in_bundle(mem_store):
camp = Campaign(name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True)
camp = Campaign(
name="Scipio Africanus",
objective="Defeat the Carthaginians",
x_empire="Roman",
allow_custom=True,
)
bundle = Bundle(camp, allow_custom=True)
mem_store.add(bundle)
@ -262,9 +270,11 @@ def test_memory_store_object_with_custom_property_in_bundle(mem_store):
def test_memory_store_custom_object(mem_store):
@CustomObject('x-new-obj', [
('property1', properties.StringProperty(required=True)),
])
@CustomObject(
'x-new-obj', [
('property1', properties.StringProperty(required=True)),
],
)
class NewObj():
pass

View File

@ -36,7 +36,7 @@ class MockTAXIICollectionEndpoint(Collection):
objs = full_filter.process_filter(
self.objects,
("id", "type", "version"),
[]
[],
)
if objs:
return stix2.v21.Bundle(objects=objs)
@ -56,7 +56,7 @@ class MockTAXIICollectionEndpoint(Collection):
objs = full_filter.process_filter(
self.objects,
("version",),
[]
[],
)
if objs:
return stix2.v21.Bundle(objects=objs)
@ -68,16 +68,18 @@ class MockTAXIICollectionEndpoint(Collection):
@pytest.fixture
def collection(stix_objs1):
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Writable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": True,
"can_write": True,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
})
mock = MockTAXIICollectionEndpoint(
COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Writable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": True,
"can_write": True,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0",
],
}
)
mock.objects.extend(stix_objs1)
return mock
@ -85,16 +87,18 @@ def collection(stix_objs1):
@pytest.fixture
def collection_no_rw_access(stix_objs1):
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Not writeable or readable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": False,
"can_write": False,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
})
mock = MockTAXIICollectionEndpoint(
COLLECTION_URL, **{
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
"title": "Not writeable or readable Collection",
"description": "This collection is a dropbox for submitting indicators",
"can_read": False,
"can_write": False,
"media_types": [
"application/vnd.oasis.stix+json; version=2.0",
],
}
)
mock.objects.extend(stix_objs1)
return mock
@ -109,14 +113,16 @@ def test_add_stix2_object(collection):
tc_sink = stix2.TAXIICollectionSink(collection)
# create new STIX threat-actor
ta = stix2.v21.ThreatActor(name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
ta = stix2.v21.ThreatActor(
name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
],
)
tc_sink.add(ta)
@ -125,16 +131,18 @@ def test_add_stix2_with_custom_object(collection):
tc_sink = stix2.TAXIICollectionStore(collection, allow_custom=True)
# create new STIX threat-actor
ta = stix2.v21.ThreatActor(name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
],
foo="bar",
allow_custom=True)
ta = stix2.v21.ThreatActor(
name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
],
foo="bar",
allow_custom=True,
)
tc_sink.add(ta)
@ -143,14 +151,16 @@ def test_add_list_object(collection, indicator):
tc_sink = stix2.TAXIICollectionSink(collection)
# create new STIX threat-actor
ta = stix2.v21.ThreatActor(name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
ta = stix2.v21.ThreatActor(
name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
],
)
tc_sink.add([ta, indicator])
@ -159,14 +169,16 @@ def test_add_stix2_bundle_object(collection):
tc_sink = stix2.TAXIICollectionSink(collection)
# create new STIX threat-actor
ta = stix2.v21.ThreatActor(name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
])
ta = stix2.v21.ThreatActor(
name="Teddy Bear",
threat_actor_types=["nation-state"],
sophistication="innovator",
resource_level="government",
goals=[
"compromising environment NGOs",
"water-hole attacks geared towards energy sector",
],
)
tc_sink.add(stix2.v21.Bundle(objects=[ta]))
@ -208,13 +220,13 @@ def test_add_dict_object(collection):
"name": "Teddy Bear",
"goals": [
"compromising environment NGOs",
"water-hole attacks geared towards energy sector"
"water-hole attacks geared towards energy sector",
],
"sophistication": "innovator",
"resource_level": "government",
"threat_actor_types": [
"nation-state"
]
"nation-state",
],
}
tc_sink.add(ta)
@ -236,15 +248,15 @@ def test_add_dict_bundle_object(collection):
"name": "Teddy Bear",
"goals": [
"compromising environment NGOs",
"water-hole attacks geared towards energy sector"
"water-hole attacks geared towards energy sector",
],
"sophistication": "innovator",
"resource_level": "government",
"threat_actor_types": [
"nation-state"
]
}
]
"nation-state",
],
},
],
}
tc_sink.add(ta)
@ -271,7 +283,7 @@ def test_parse_taxii_filters(collection):
Filter("added_after", "=", "2016-02-01T00:00:01.000Z"),
Filter("id", "=", "taxii stix object ID"),
Filter("type", "=", "taxii stix object ID"),
Filter("version", "=", "first")
Filter("version", "=", "first"),
]
ds = stix2.TAXIICollectionSource(collection)

View File

@ -2,9 +2,11 @@ import pytest
import stix2
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, FAKE_TIME, IDENTITY_ID,
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS)
from .constants import (
CAMPAIGN_ID, CAMPAIGN_KWARGS, FAKE_TIME, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS,
RELATIONSHIP_IDS,
)
@pytest.fixture
@ -48,8 +50,10 @@ def test_object_factory_created():
def test_object_factory_external_reference():
ext_ref = stix2.v21.ExternalReference(source_name="ACME Threat Intel",
description="Threat report")
ext_ref = stix2.v21.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report",
)
factory = stix2.ObjectFactory(external_references=ext_ref)
ind = factory.create(stix2.v21.Indicator, **INDICATOR_KWARGS)
assert ind.external_references[0].source_name == "ACME Threat Intel"
@ -61,8 +65,10 @@ def test_object_factory_external_reference():
def test_object_factory_obj_markings():
stmt_marking = stix2.v21.StatementMarking("Copyright 2016, Example Corp")
mark_def = stix2.v21.MarkingDefinition(definition_type="statement",
definition=stmt_marking)
mark_def = stix2.v21.MarkingDefinition(
definition_type="statement",
definition=stmt_marking,
)
factory = stix2.ObjectFactory(object_marking_refs=[mark_def, stix2.v21.TLP_AMBER])
ind = factory.create(stix2.v21.Indicator, **INDICATOR_KWARGS)
assert mark_def.id in ind.object_marking_refs
@ -74,12 +80,18 @@ def test_object_factory_obj_markings():
def test_object_factory_list_append():
ext_ref = stix2.v21.ExternalReference(source_name="ACME Threat Intel",
description="Threat report from ACME")
ext_ref2 = stix2.v21.ExternalReference(source_name="Yet Another Threat Report",
description="Threat report from YATR")
ext_ref3 = stix2.v21.ExternalReference(source_name="Threat Report #3",
description="One more threat report")
ext_ref = stix2.v21.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report from ACME",
)
ext_ref2 = stix2.v21.ExternalReference(
source_name="Yet Another Threat Report",
description="Threat report from YATR",
)
ext_ref3 = stix2.v21.ExternalReference(
source_name="Threat Report #3",
description="One more threat report",
)
factory = stix2.ObjectFactory(external_references=ext_ref)
ind = factory.create(stix2.v21.Indicator, external_references=ext_ref2, **INDICATOR_KWARGS)
assert ind.external_references[1].source_name == "Yet Another Threat Report"
@ -89,10 +101,14 @@ def test_object_factory_list_append():
def test_object_factory_list_replace():
ext_ref = stix2.v21.ExternalReference(source_name="ACME Threat Intel",
description="Threat report from ACME")
ext_ref2 = stix2.v21.ExternalReference(source_name="Yet Another Threat Report",
description="Threat report from YATR")
ext_ref = stix2.v21.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report from ACME",
)
ext_ref2 = stix2.v21.ExternalReference(
source_name="Yet Another Threat Report",
description="Threat report from YATR",
)
factory = stix2.ObjectFactory(external_references=ext_ref, list_append=False)
ind = factory.create(stix2.v21.Indicator, external_references=ext_ref2, **INDICATOR_KWARGS)
assert len(ind.external_references) == 1
@ -100,8 +116,10 @@ def test_object_factory_list_replace():
def test_environment_functions():
env = stix2.Environment(stix2.ObjectFactory(created_by_ref=IDENTITY_ID),
stix2.MemoryStore())
env = stix2.Environment(
stix2.ObjectFactory(created_by_ref=IDENTITY_ID),
stix2.MemoryStore(),
)
# Create a STIX object
ind = env.create(stix2.v21.Indicator, id=INDICATOR_ID, **INDICATOR_KWARGS)
@ -125,8 +143,10 @@ def test_environment_functions():
assert len(resp) == 0
# See different results after adding filters to the environment
env.add_filters([stix2.Filter('type', '=', 'indicator'),
stix2.Filter('created_by_ref', '=', IDENTITY_ID)])
env.add_filters([
stix2.Filter('type', '=', 'indicator'),
stix2.Filter('created_by_ref', '=', IDENTITY_ID),
])
env.add_filter(stix2.Filter('labels', '=', 'benign')) # should be 'malicious-activity'
resp = env.get(INDICATOR_ID)
assert resp['labels'][0] == 'benign' # should be 'malicious-activity'
@ -140,8 +160,10 @@ def test_environment_source_and_sink():
def test_environment_datastore_and_sink():
with pytest.raises(ValueError) as excinfo:
stix2.Environment(factory=stix2.ObjectFactory(),
store=stix2.MemoryStore(), sink=stix2.MemorySink)
stix2.Environment(
factory=stix2.ObjectFactory(),
store=stix2.MemoryStore(), sink=stix2.MemorySink,
)
assert 'Data store already provided' in str(excinfo.value)
@ -265,7 +287,7 @@ def test_relationships_no_id(ds):
env = stix2.Environment(store=ds)
mal = {
"type": "malware",
"name": "some variant"
"name": "some variant",
}
with pytest.raises(ValueError) as excinfo:
env.relationships(mal)
@ -329,7 +351,7 @@ def test_related_to_no_id(ds):
env = stix2.Environment(store=ds)
mal = {
"type": "malware",
"name": "some variant"
"name": "some variant",
}
with pytest.raises(ValueError) as excinfo:
env.related_to(mal)

View File

@ -21,7 +21,7 @@ def test_external_reference_veris():
source_name="veris",
external_id="0001AA7F-C601-424A-B2B8-BE6C9F5164E7",
hashes={
"SHA-256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"
"SHA-256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b",
},
url="https://github.com/vz-risk/VCDB/blob/master/data/json/0001AA7F-C601-424A-B2B8-BE6C9F5164E7.json",
)

View File

@ -20,11 +20,11 @@ def test_add_marking_mark_one_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
@ -35,44 +35,49 @@ def test_add_marking_mark_one_selector_multiple_refs():
assert m in after["granular_markings"]
@pytest.mark.parametrize("data", [
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
},
],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
},
],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": TLP_RED.id,
},
],
**MALWARE_KWARGS),
TLP_RED,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": TLP_RED.id,
},
],
**MALWARE_KWARGS
),
TLP_RED,
),
],
)
def test_add_marking_mark_multiple_selector_one_refs(data):
before = data[0]
after = data[1]
@ -91,12 +96,12 @@ def test_add_marking_mark_multiple_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -111,7 +116,7 @@ def test_add_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -120,7 +125,7 @@ def test_add_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description", "name"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -136,7 +141,7 @@ def test_add_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -145,7 +150,7 @@ def test_add_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
@ -156,17 +161,22 @@ def test_add_marking_mark_same_property_same_marking():
assert m in after["granular_markings"]
@pytest.mark.parametrize("data,marking", [
({"description": "test description"},
[["title"], ["marking-definition--1", "marking-definition--2"],
"", ["marking-definition--1", "marking-definition--2"],
[], ["marking-definition--1", "marking-definition--2"],
[""], ["marking-definition--1", "marking-definition--2"],
["description"], [""],
["description"], [],
["description"], ["marking-definition--1", 456]
])
])
@pytest.mark.parametrize(
"data,marking", [
(
{"description": "test description"},
[
["title"], ["marking-definition--1", "marking-definition--2"],
"", ["marking-definition--1", "marking-definition--2"],
[], ["marking-definition--1", "marking-definition--2"],
[""], ["marking-definition--1", "marking-definition--2"],
["description"], [""],
["description"], [],
["description"], ["marking-definition--1", 456],
],
),
],
)
def test_add_marking_bad_selector(data, marking):
with pytest.raises(AssertionError):
markings.add_markings(data, marking[0], marking[1])
@ -180,61 +190,61 @@ GET_MARKINGS_TEST_DATA = {
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
@ -245,10 +255,12 @@ def test_get_markings_smoke(data):
assert markings.get_markings(data, "a") == ["1"]
@pytest.mark.parametrize("data", [
GET_MARKINGS_TEST_DATA,
{"b": 1234},
])
@pytest.mark.parametrize(
"data", [
GET_MARKINGS_TEST_DATA,
{"b": 1234},
],
)
def test_get_markings_not_marked(data):
"""Test selector that is not marked returns empty list."""
results = markings.get_markings(data, "b")
@ -267,21 +279,23 @@ def test_get_markings_multiple_selectors(data):
assert set(xy_markings).union(xz_markings).issuperset(total)
@pytest.mark.parametrize("data,selector", [
(GET_MARKINGS_TEST_DATA, "foo"),
(GET_MARKINGS_TEST_DATA, ""),
(GET_MARKINGS_TEST_DATA, []),
(GET_MARKINGS_TEST_DATA, [""]),
(GET_MARKINGS_TEST_DATA, "x.z.[-2]"),
(GET_MARKINGS_TEST_DATA, "c.f"),
(GET_MARKINGS_TEST_DATA, "c.[2].i"),
(GET_MARKINGS_TEST_DATA, "c.[3]"),
(GET_MARKINGS_TEST_DATA, "d"),
(GET_MARKINGS_TEST_DATA, "x.[0]"),
(GET_MARKINGS_TEST_DATA, "z.y.w"),
(GET_MARKINGS_TEST_DATA, "x.z.[1]"),
(GET_MARKINGS_TEST_DATA, "x.z.foo3")
])
@pytest.mark.parametrize(
"data,selector", [
(GET_MARKINGS_TEST_DATA, "foo"),
(GET_MARKINGS_TEST_DATA, ""),
(GET_MARKINGS_TEST_DATA, []),
(GET_MARKINGS_TEST_DATA, [""]),
(GET_MARKINGS_TEST_DATA, "x.z.[-2]"),
(GET_MARKINGS_TEST_DATA, "c.f"),
(GET_MARKINGS_TEST_DATA, "c.[2].i"),
(GET_MARKINGS_TEST_DATA, "c.[3]"),
(GET_MARKINGS_TEST_DATA, "d"),
(GET_MARKINGS_TEST_DATA, "x.[0]"),
(GET_MARKINGS_TEST_DATA, "z.y.w"),
(GET_MARKINGS_TEST_DATA, "x.z.[1]"),
(GET_MARKINGS_TEST_DATA, "x.z.foo3"),
],
)
def test_get_markings_bad_selector(data, selector):
"""Test bad selectors raise exception"""
with pytest.raises(AssertionError):
@ -362,40 +376,42 @@ def test_get_markings_positional_arguments_combinations(data):
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
@pytest.mark.parametrize("data", [
(
Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
},
],
**MALWARE_KWARGS
@pytest.mark.parametrize(
"data", [
(
Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
(
dict(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
},
],
**MALWARE_KWARGS
(
dict(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
[MARKING_IDS[0], MARKING_IDS[1]],
),
])
],
)
def test_remove_marking_remove_one_selector_with_multiple_refs(data):
before = markings.remove_markings(data[0], data[1], ["description"])
assert "granular_markings" not in before
@ -406,8 +422,8 @@ def test_remove_marking_remove_multiple_selector_one_ref():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -420,8 +436,8 @@ def test_remove_marking_mark_one_selector_from_multiple_ones():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -429,8 +445,8 @@ def test_remove_marking_mark_one_selector_from_multiple_ones():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -444,12 +460,12 @@ def test_remove_marking_mark_one_selector_markings_from_multiple_ones():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -457,12 +473,12 @@ def test_remove_marking_mark_one_selector_markings_from_multiple_ones():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -476,12 +492,12 @@ def test_remove_marking_mark_mutilple_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -494,8 +510,8 @@ def test_remove_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -503,12 +519,12 @@ def test_remove_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -522,8 +538,8 @@ def test_remove_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -552,8 +568,8 @@ def test_remove_marking_not_present():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -566,15 +582,15 @@ IS_MARKED_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["malware_types", "description"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["malware_types", "description"],
"marking_ref": MARKING_IDS[3]
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
@ -583,15 +599,15 @@ IS_MARKED_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["malware_types", "description"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["malware_types", "description"],
"marking_ref": MARKING_IDS[3]
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
@ -606,21 +622,23 @@ def test_is_marked_smoke(data):
assert markings.is_marked(data, selectors=["modified"]) is False
@pytest.mark.parametrize("data,selector", [
(IS_MARKED_TEST_DATA[0], "foo"),
(IS_MARKED_TEST_DATA[0], ""),
(IS_MARKED_TEST_DATA[0], []),
(IS_MARKED_TEST_DATA[0], [""]),
(IS_MARKED_TEST_DATA[0], "x.z.[-2]"),
(IS_MARKED_TEST_DATA[0], "c.f"),
(IS_MARKED_TEST_DATA[0], "c.[2].i"),
(IS_MARKED_TEST_DATA[1], "c.[3]"),
(IS_MARKED_TEST_DATA[1], "d"),
(IS_MARKED_TEST_DATA[1], "x.[0]"),
(IS_MARKED_TEST_DATA[1], "z.y.w"),
(IS_MARKED_TEST_DATA[1], "x.z.[1]"),
(IS_MARKED_TEST_DATA[1], "x.z.foo3")
])
@pytest.mark.parametrize(
"data,selector", [
(IS_MARKED_TEST_DATA[0], "foo"),
(IS_MARKED_TEST_DATA[0], ""),
(IS_MARKED_TEST_DATA[0], []),
(IS_MARKED_TEST_DATA[0], [""]),
(IS_MARKED_TEST_DATA[0], "x.z.[-2]"),
(IS_MARKED_TEST_DATA[0], "c.f"),
(IS_MARKED_TEST_DATA[0], "c.[2].i"),
(IS_MARKED_TEST_DATA[1], "c.[3]"),
(IS_MARKED_TEST_DATA[1], "d"),
(IS_MARKED_TEST_DATA[1], "x.[0]"),
(IS_MARKED_TEST_DATA[1], "z.y.w"),
(IS_MARKED_TEST_DATA[1], "x.z.[1]"),
(IS_MARKED_TEST_DATA[1], "x.z.foo3"),
],
)
def test_is_marked_invalid_selector(data, selector):
"""Test invalid selector raises an error."""
with pytest.raises(AssertionError):
@ -688,61 +706,61 @@ def test_is_marked_positional_arguments_combinations():
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
assert markings.is_marked(test_sdo, ["1"], "a", False, False)
@ -822,8 +840,8 @@ def test_create_sdo_with_invalid_marking():
granular_markings=[
{
"selectors": ["foo"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -838,12 +856,12 @@ def test_set_marking_mark_one_selector_multiple_refs():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -857,8 +875,8 @@ def test_set_marking_mark_multiple_selector_one_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -866,8 +884,8 @@ def test_set_marking_mark_multiple_selector_one_refs():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -884,12 +902,12 @@ def test_set_marking_mark_multiple_selector_multiple_refs_from_none():
granular_markings=[
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["description", "modified"],
"marking_ref": MARKING_IDS[1]
}
"marking_ref": MARKING_IDS[1],
},
],
**MALWARE_KWARGS
)
@ -903,8 +921,8 @@ def test_set_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -912,12 +930,12 @@ def test_set_marking_mark_another_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[2]
}
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
)
@ -927,19 +945,21 @@ def test_set_marking_mark_another_property_same_marking():
assert m in after["granular_markings"]
@pytest.mark.parametrize("marking", [
([MARKING_IDS[4], MARKING_IDS[5]], ["foo"]),
([MARKING_IDS[4], MARKING_IDS[5]], ""),
([MARKING_IDS[4], MARKING_IDS[5]], []),
([MARKING_IDS[4], MARKING_IDS[5]], [""]),
])
@pytest.mark.parametrize(
"marking", [
([MARKING_IDS[4], MARKING_IDS[5]], ["foo"]),
([MARKING_IDS[4], MARKING_IDS[5]], ""),
([MARKING_IDS[4], MARKING_IDS[5]], []),
([MARKING_IDS[4], MARKING_IDS[5]], [""]),
],
)
def test_set_marking_bad_selector(marking):
before = Malware(
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -947,8 +967,8 @@ def test_set_marking_bad_selector(marking):
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -964,8 +984,8 @@ def test_set_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -973,8 +993,8 @@ def test_set_marking_mark_same_property_same_marking():
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
}
"marking_ref": MARKING_IDS[0],
},
],
**MALWARE_KWARGS
)
@ -988,15 +1008,15 @@ CLEAR_MARKINGS_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified", "description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["modified", "description", "type"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
@ -1005,19 +1025,19 @@ CLEAR_MARKINGS_TEST_DATA = [
granular_markings=[
{
"selectors": ["description"],
"marking_ref": MARKING_IDS[0]
"marking_ref": MARKING_IDS[0],
},
{
"selectors": ["modified", "description"],
"marking_ref": MARKING_IDS[1]
"marking_ref": MARKING_IDS[1],
},
{
"selectors": ["modified", "description", "type"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
],
**MALWARE_KWARGS
)
),
]
@ -1049,12 +1069,14 @@ def test_clear_marking_all_selectors(data):
assert "granular_markings" not in data
@pytest.mark.parametrize("data,selector", [
(CLEAR_MARKINGS_TEST_DATA[0], "foo"),
(CLEAR_MARKINGS_TEST_DATA[0], ""),
(CLEAR_MARKINGS_TEST_DATA[1], []),
(CLEAR_MARKINGS_TEST_DATA[1], [""]),
])
@pytest.mark.parametrize(
"data,selector", [
(CLEAR_MARKINGS_TEST_DATA[0], "foo"),
(CLEAR_MARKINGS_TEST_DATA[0], ""),
(CLEAR_MARKINGS_TEST_DATA[1], []),
(CLEAR_MARKINGS_TEST_DATA[1], [""]),
],
)
def test_clear_marking_bad_selector(data, selector):
"""Test bad selector raises exception."""
with pytest.raises(AssertionError):

View File

@ -30,18 +30,20 @@ def test_identity_example():
assert str(identity) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"identity_class": "individual",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"spec_version": "2.1",
"type": "identity"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"identity_class": "individual",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"spec_version": "2.1",
"type": "identity",
},
],
)
def test_parse_identity(data):
identity = stix2.parse(data, version="2.1")
@ -55,21 +57,23 @@ def test_parse_identity(data):
def test_parse_no_type():
with pytest.raises(stix2.exceptions.ParseError):
stix2.parse("""
stix2.parse(
"""
{
"id": "identity--311b2d2d-f010-4473-83ec-1edf84858f4c",
"created": "2015-12-21T19:59:11.000Z",
"modified": "2015-12-21T19:59:11.000Z",
"name": "John Smith",
"identity_class": "individual"
}""", version="2.1")
}""", version="2.1",
)
def test_identity_with_custom():
identity = stix2.v21.Identity(
name="John Smith",
identity_class="individual",
custom_properties={'x_foo': 'bar'}
custom_properties={'x_foo': 'bar'},
)
assert identity.x_foo == "bar"

View File

@ -152,20 +152,22 @@ def test_created_modified_time_are_identical_by_default():
assert ind.created == ind.modified
@pytest.mark.parametrize("data", [
EXPECTED_INDICATOR,
{
"type": "indicator",
"id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"created": "2017-01-01T00:00:01Z",
"modified": "2017-01-01T00:00:01Z",
"indicator_types": [
"malicious-activity"
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "1970-01-01T00:00:01Z"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_INDICATOR,
{
"type": "indicator",
"id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"created": "2017-01-01T00:00:01Z",
"modified": "2017-01-01T00:00:01Z",
"indicator_types": [
"malicious-activity",
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"valid_from": "1970-01-01T00:00:01Z",
},
],
)
def test_parse_indicator(data):
idctr = stix2.parse(data, version="2.1")

View File

@ -36,33 +36,35 @@ def test_intrusion_set_example():
name="Bobcat Breakin",
description="Incidents usually feature a shared TTP of a bobcat being released...",
aliases=["Zookeeper"],
goals=["acquisition-theft", "harassment", "damage"]
goals=["acquisition-theft", "harassment", "damage"],
)
assert str(intrusion_set) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"aliases": [
"Zookeeper"
],
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Incidents usually feature a shared TTP of a bobcat being released...",
"goals": [
"acquisition-theft",
"harassment",
"damage"
],
"id": "intrusion-set--4e78f46f-a023-4e5f-bc24-71b3ca22ec29",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Bobcat Breakin",
"spec_version": "2.1",
"type": "intrusion-set"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"aliases": [
"Zookeeper",
],
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "Incidents usually feature a shared TTP of a bobcat being released...",
"goals": [
"acquisition-theft",
"harassment",
"damage",
],
"id": "intrusion-set--4e78f46f-a023-4e5f-bc24-71b3ca22ec29",
"modified": "2016-04-06T20:03:48.000Z",
"name": "Bobcat Breakin",
"spec_version": "2.1",
"type": "intrusion-set",
},
],
)
def test_parse_intrusion_set(data):
intset = stix2.parse(data)

View File

@ -55,13 +55,13 @@ def test_language_content_campaign():
contents={
'de': {
'name': 'Bank Angriff 1',
'description': 'Weitere Informationen über Banküberfall'
'description': 'Weitere Informationen über Banküberfall',
},
'fr': {
'name': 'Attaque Bank 1',
'description': 'Plus d\'informations sur la crise bancaire'
}
}
'description': 'Plus d\'informations sur la crise bancaire',
},
},
)
camp = stix2.parse(TEST_CAMPAIGN, version='2.1')

View File

@ -55,7 +55,7 @@ def test_location_with_some_required_properties():
created=now,
modified=now,
latitude=48.8566,
longitude=2.3522
longitude=2.3522,
)
assert str(loc) == EXPECTED_LOCATION_1
@ -63,17 +63,19 @@ def test_location_with_some_required_properties():
assert rep == EXPECTED_LOCATION_1_REPR
@pytest.mark.parametrize("data", [
EXPECTED_LOCATION_2,
{
"type": "location",
"spec_version": "2.1",
"id": "location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64",
"created": "2016-04-06T20:03:00.000Z",
"modified": "2016-04-06T20:03:00.000Z",
"region": "north-america"
}
])
@pytest.mark.parametrize(
"data", [
EXPECTED_LOCATION_2,
{
"type": "location",
"spec_version": "2.1",
"id": "location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64",
"created": "2016-04-06T20:03:00.000Z",
"modified": "2016-04-06T20:03:00.000Z",
"region": "north-america",
},
],
)
def test_parse_location(data):
location = stix2.parse(data, version="2.1")

View File

@ -32,7 +32,7 @@ def test_malware_with_all_required_properties():
modified=now,
malware_types=["ransomware"],
name="Cryptolocker",
is_family=True
is_family=True,
)
assert str(mal) == EXPECTED_MALWARE
@ -106,19 +106,21 @@ def test_invalid_kwarg_to_malware():
assert str(excinfo.value) == "Unexpected properties for Malware: (my_custom_property)."
@pytest.mark.parametrize("data", [
EXPECTED_MALWARE,
{
"type": "malware",
"spec_version": "2.1",
"id": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"malware_types": ["ransomware"],
"name": "Cryptolocker",
"is_family": True
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_MALWARE,
{
"type": "malware",
"spec_version": "2.1",
"id": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"malware_types": ["ransomware"],
"name": "Cryptolocker",
"is_family": True,
},
],
)
def test_parse_malware(data):
mal = stix2.parse(data)

View File

@ -83,7 +83,7 @@ def test_marking_def_example_with_statement_positional_argument():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="statement",
definition=stix2.StatementMarking(statement="Copyright 2016, Example Corp")
definition=stix2.StatementMarking(statement="Copyright 2016, Example Corp"),
)
assert str(marking_definition) == EXPECTED_STATEMENT_MARKING_DEFINITION
@ -95,7 +95,7 @@ def test_marking_def_example_with_kwargs_statement():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="statement",
definition=stix2.StatementMarking(**kwargs)
definition=stix2.StatementMarking(**kwargs),
)
assert str(marking_definition) == EXPECTED_STATEMENT_MARKING_DEFINITION
@ -107,7 +107,7 @@ def test_marking_def_invalid_type():
id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
created="2017-01-20T00:00:00.000Z",
definition_type="my-definition-type",
definition=stix2.StatementMarking("Copyright 2016, Example Corp")
definition=stix2.StatementMarking("Copyright 2016, Example Corp"),
)
@ -119,7 +119,7 @@ def test_campaign_with_markings_example():
modified="2016-04-06T20:03:00Z",
name="Green Group Attacks Against Finance",
description="Campaign by Green Group against a series of targets in the financial services sector.",
object_marking_refs=TLP_WHITE
object_marking_refs=TLP_WHITE,
)
assert str(campaign) == EXPECTED_CAMPAIGN_WITH_OBJECT_MARKING
@ -127,7 +127,7 @@ def test_campaign_with_markings_example():
def test_granular_example():
granular_marking = stix2.v21.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["abc", "abc.[23]", "abc.def", "abc.[2].efg"]
selectors=["abc", "abc.[23]", "abc.def", "abc.[2].efg"],
)
assert str(granular_marking) == EXPECTED_GRANULAR_MARKING
@ -137,7 +137,7 @@ def test_granular_example_with_bad_selector():
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
stix2.v21.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["abc[0]"] # missing "."
selectors=["abc[0]"], # missing "."
)
assert excinfo.value.cls == stix2.v21.GranularMarking
@ -157,24 +157,28 @@ def test_campaign_with_granular_markings_example():
granular_markings=[
stix2.v21.GranularMarking(
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["description"])
])
selectors=["description"],
),
],
)
assert str(campaign) == EXPECTED_CAMPAIGN_WITH_GRANULAR_MARKINGS
@pytest.mark.parametrize("data", [
EXPECTED_TLP_MARKING_DEFINITION,
{
"id": "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
"spec_version": "2.1",
"type": "marking-definition",
"created": "2017-01-20T00:00:00Z",
"definition": {
"tlp": "white"
@pytest.mark.parametrize(
"data", [
EXPECTED_TLP_MARKING_DEFINITION,
{
"id": "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
"spec_version": "2.1",
"type": "marking-definition",
"created": "2017-01-20T00:00:00Z",
"definition": {
"tlp": "white",
},
"definition_type": "tlp",
},
"definition_type": "tlp",
},
])
],
)
def test_parse_marking_definition(data):
gm = stix2.parse(data, version="2.1")
@ -186,10 +190,12 @@ def test_parse_marking_definition(data):
assert gm.definition_type == "tlp"
@stix2.v21.CustomMarking('x-new-marking-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v21.CustomMarking(
'x-new-marking-type', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewMarking(object):
def __init__(self, property2=None, **kwargs):
if "property3" in kwargs and not isinstance(kwargs.get("property3"), int):
@ -203,7 +209,7 @@ def test_registered_custom_marking():
id="marking-definition--00000000-0000-4000-8000-000000000012",
created="2017-01-22T00:00:00.000Z",
definition_type="x-new-marking-type",
definition=nm
definition=nm,
)
assert marking_def.type == "marking-definition"
@ -224,10 +230,12 @@ def test_registered_custom_marking_raises_exception():
def test_not_registered_marking_raises_exception():
with pytest.raises(ValueError) as excinfo:
# Used custom object on purpose to demonstrate a not-registered marking
@stix2.v21.CustomObject('x-new-marking-type2', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
])
@stix2.v21.CustomObject(
'x-new-marking-type2', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewObject2(object):
def __init__(self, property2=None, **kwargs):
return
@ -238,7 +246,7 @@ def test_not_registered_marking_raises_exception():
id="marking-definition--00000000-0000-4000-8000-000000000012",
created="2017-01-22T00:00:00.000Z",
definition_type="x-new-marking-type2",
definition=no
definition=no,
)
assert str(excinfo.value) == "definition_type must be a valid marking type"

View File

@ -8,10 +8,12 @@ import stix2
from .constants import CAMPAIGN_ID, NOTE_ID
DESCRIPTION = ('This note indicates the various steps taken by the threat'
' analyst team to investigate this specific campaign. Step'
' 1) Do a scan 2) Review scanned results for identified '
'hosts not known by external intel... etc')
DESCRIPTION = (
'This note indicates the various steps taken by the threat'
' analyst team to investigate this specific campaign. Step'
' 1) Do a scan 2) Review scanned results for identified '
'hosts not known by external intel... etc'
)
EXPECTED_NOTE = """{
"type": "note",
@ -35,7 +37,8 @@ EXPECTED_NOTE = """{
]
}""" % DESCRIPTION
EXPECTED_OPINION_REPR = "Note(" + " ".join(("""
EXPECTED_OPINION_REPR = "Note(" + " ".join((
"""
type='note',
spec_version='2.1',
id='note--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061',
@ -46,7 +49,8 @@ EXPECTED_OPINION_REPR = "Note(" + " ".join(("""
authors=['John Doe'],
object_refs=['campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f'],
external_references=[ExternalReference(source_name='job-tracker', external_id='job-id-1234')]
""" % DESCRIPTION).split()) + ")"
""" % DESCRIPTION
).split()) + ")"
def test_note_with_required_properties():
@ -64,9 +68,9 @@ def test_note_with_required_properties():
external_references=[
{
'source_name': 'job-tracker',
'external_id': 'job-id-1234'
}
]
'external_id': 'job-id-1234',
},
],
)
assert str(note) == EXPECTED_NOTE
@ -74,30 +78,32 @@ def test_note_with_required_properties():
assert rep == EXPECTED_OPINION_REPR
@pytest.mark.parametrize("data", [
EXPECTED_NOTE,
{
"type": "note",
"spec_version": "2.1",
"id": "note--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"summary": "Tracking Team Note#1",
"description": DESCRIPTION,
"authors": [
"John Doe"
],
"object_refs": [
"campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f"
],
"external_references": [
{
"source_name": "job-tracker",
"external_id": "job-id-1234"
}
]
}
])
@pytest.mark.parametrize(
"data", [
EXPECTED_NOTE,
{
"type": "note",
"spec_version": "2.1",
"id": "note--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"summary": "Tracking Team Note#1",
"description": DESCRIPTION,
"authors": [
"John Doe",
],
"object_refs": [
"campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
],
"external_references": [
{
"source_name": "job-tracker",
"external_id": "job-id-1234",
},
],
},
],
)
def test_parse_note(data):
note = stix2.parse(data, version="2.1")

View File

@ -17,26 +17,34 @@ MALWARE_KWARGS.update({
})
@pytest.mark.parametrize("data", [
(
Malware(**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(object_marking_refs=[TLP_AMBER.id],
**MALWARE_KWARGS),
TLP_AMBER,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(**MALWARE_KWARGS),
Malware(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MARKING_IDS[0],
),
(
Malware(**MALWARE_KWARGS),
Malware(
object_marking_refs=[TLP_AMBER.id],
**MALWARE_KWARGS
),
TLP_AMBER,
),
],
)
def test_add_markings_one_marking(data):
before = data[0]
after = data[1]
@ -72,12 +80,12 @@ def test_add_markings_combination():
granular_markings=[
{
"selectors": ["malware_types"],
"marking_ref": MARKING_IDS[2]
"marking_ref": MARKING_IDS[2],
},
{
"selectors": ["name"],
"marking_ref": MARKING_IDS[3]
}
"marking_ref": MARKING_IDS[3],
},
],
**MALWARE_KWARGS
)
@ -94,12 +102,14 @@ def test_add_markings_combination():
assert m in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([""]),
(""),
([]),
([MARKING_IDS[0], 456])
])
@pytest.mark.parametrize(
"data", [
([""]),
(""),
([]),
([MARKING_IDS[0], 456]),
],
)
def test_add_markings_bad_markings(data):
before = Malware(
**MALWARE_KWARGS
@ -119,62 +129,62 @@ GET_MARKINGS_TEST_DATA = \
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"object_marking_refs": ["11"],
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
@ -257,18 +267,24 @@ def test_get_markings_object_and_granular_combinations(data):
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_remove_markings_object_level(data):
before = data[0]
after = data[1]
@ -283,29 +299,43 @@ def test_remove_markings_object_level(data):
modified == after['modified']
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
dict(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
[MARKING_IDS[0], TLP_AMBER],
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
dict(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], MARKING_IDS[2]],
),
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
**MALWARE_KWARGS
),
Malware(
object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS
),
[MARKING_IDS[0], TLP_AMBER],
),
],
)
def test_remove_markings_multiple(data):
before = data[0]
after = data[1]
@ -325,18 +355,24 @@ def test_remove_markings_bad_markings():
assert str(excinfo.value) == "Marking ['%s'] was not found in Malware!" % MARKING_IDS[4]
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_clear_markings(data):
before = data[0]
after = data[1]
@ -358,62 +394,62 @@ def test_is_marked_object_and_granular_combinations():
"list value",
{
"g": "nested",
"h": 45
}
"h": 45,
},
],
"x": {
"y": [
"hello",
88
88,
],
"z": {
"foo1": "bar",
"foo2": 65
}
"foo2": 65,
},
},
"object_marking_refs": "11",
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
"selectors": ["a"],
},
{
"marking_ref": "2",
"selectors": ["c"]
"selectors": ["c"],
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
"selectors": ["c.[1]"],
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
"selectors": ["c.[2]"],
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
"selectors": ["c.[2].g"],
},
{
"marking_ref": "6",
"selectors": ["x"]
"selectors": ["x"],
},
{
"marking_ref": "7",
"selectors": ["x.y"]
"selectors": ["x.y"],
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
"selectors": ["x.y.[1]"],
},
{
"marking_ref": "9",
"selectors": ["x.z"]
"selectors": ["x.z"],
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
"selectors": ["x.z.foo2"],
},
]
],
}
assert markings.is_marked(test_sdo, ["1"], "a", False, False)
@ -490,18 +526,24 @@ def test_is_marked_object_and_granular_combinations():
assert markings.is_marked(test_sdo, ["2"], None, True, True) is False
@pytest.mark.parametrize("data", [
(
Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
Malware(**MALWARE_KWARGS),
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
MALWARE_KWARGS,
),
])
@pytest.mark.parametrize(
"data", [
(
Malware(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
Malware(**MALWARE_KWARGS),
),
(
dict(
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS
),
MALWARE_KWARGS,
),
],
)
def test_is_marked_no_markings(data):
marked = data[0]
nonmarked = data[1]
@ -531,12 +573,14 @@ def test_set_marking():
assert x in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([]),
([""]),
(""),
([MARKING_IDS[4], 687])
])
@pytest.mark.parametrize(
"data", [
([]),
([""]),
(""),
([MARKING_IDS[4], 687]),
],
)
def test_set_marking_bad_input(data):
before = Malware(
object_marking_refs=[MARKING_IDS[0]],

View File

@ -42,7 +42,7 @@ def test_observed_data_example():
objects={
"0": {
"name": "foo.exe",
"type": "file"
"type": "file",
},
},
)
@ -88,13 +88,13 @@ def test_observed_data_example_with_refs():
objects={
"0": {
"name": "foo.exe",
"type": "file"
"type": "file",
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["0"]
}
"contains_refs": ["0"],
},
},
)
@ -114,13 +114,13 @@ def test_observed_data_example_with_bad_refs():
objects={
"0": {
"type": "file",
"name": "foo.exe"
"name": "foo.exe",
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["2"]
}
"contains_refs": ["2"],
},
},
)
@ -165,26 +165,28 @@ def test_observed_data_example_with_empty_dictionary():
assert 'must contain a non-empty dictionary' in excinfo.value.reason
@pytest.mark.parametrize("data", [
EXPECTED,
{
"type": "observed-data",
"spec_version": "2.1",
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
"created": "2016-04-06T19:58:16.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"first_observed": "2015-12-21T19:00:00Z",
"last_observed": "2015-12-21T19:00:00Z",
"modified": "2016-04-06T19:58:16.000Z",
"number_observed": 50,
"objects": {
"0": {
"name": "foo.exe",
"type": "file"
}
}
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"type": "observed-data",
"spec_version": "2.1",
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
"created": "2016-04-06T19:58:16.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"first_observed": "2015-12-21T19:00:00Z",
"last_observed": "2015-12-21T19:00:00Z",
"modified": "2016-04-06T19:58:16.000Z",
"number_observed": 50,
"objects": {
"0": {
"name": "foo.exe",
"type": "file",
},
},
},
],
)
def test_parse_observed_data(data):
odata = stix2.parse(data, version="2.1")
@ -199,13 +201,14 @@ def test_parse_observed_data(data):
assert odata.objects["0"].type == "file"
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"payload_bin": "VBORw0KGgoAAAANSUhEUgAAADI=="
}""",
""""0": {
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"url": "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
@ -213,20 +216,22 @@ def test_parse_observed_data(data):
"MD5": "6826f9a05da08134006557758bb3afbb"
}
}""",
])
],
)
def test_parse_artifact_valid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.1")
assert odata.objects["0"].type == "artifact"
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"payload_bin": "abcVBORw0KGgoAAAANSUhEUgAAADI=="
}""",
""""0": {
""""0": {
"type": "artifact",
"mime_type": "image/jpeg",
"url": "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
@ -234,7 +239,8 @@ def test_parse_artifact_valid(data):
"MD5": "a"
}
}""",
])
],
)
def test_parse_artifact_invalid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
with pytest.raises(ValueError):
@ -249,14 +255,16 @@ def test_artifact_example_dependency_error():
assert str(excinfo.value) == "The property dependencies for Artifact: (hashes, url) are not met."
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "autonomous-system",
"number": 15139,
"name": "Slime Industries",
"rir": "ARIN"
}""",
])
],
)
def test_parse_autonomous_system_valid(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.1")
@ -266,14 +274,16 @@ def test_parse_autonomous_system_valid(data):
assert odata.objects["0"].rir == "ARIN"
@pytest.mark.parametrize("data", [
"""{
@pytest.mark.parametrize(
"data", [
"""{
"type": "email-addr",
"value": "john@example.com",
"display_name": "John Doe",
"belongs_to_ref": "0"
}""",
])
],
)
def test_parse_email_address(data):
odata = stix2.parse_observable(data, {"0": "user-account"}, version='2.1')
assert odata.type == "email-addr"
@ -283,8 +293,9 @@ def test_parse_email_address(data):
stix2.parse_observable(odata_str, {"0": "user-account"}, version='2.1')
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"is_multipart": true,
@ -321,8 +332,9 @@ def test_parse_email_address(data):
}
]
}
"""
])
""",
],
)
def test_parse_email_message(data):
valid_refs = {
"0": "email-message",
@ -337,8 +349,9 @@ def test_parse_email_message(data):
assert odata.body_multipart[0].content_disposition == "inline"
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"from_ref": "0",
@ -348,8 +361,9 @@ def test_parse_email_message(data):
"subject": "Saying Hello",
"body": "Cats are funny!"
}
"""
])
""",
],
)
def test_parse_email_message_not_multipart(data):
valid_refs = {
"0": "email-addr",
@ -362,8 +376,9 @@ def test_parse_email_message_not_multipart(data):
assert excinfo.value.dependencies == [("is_multipart", "body")]
@pytest.mark.parametrize("data", [
""""0": {
@pytest.mark.parametrize(
"data", [
""""0": {
"type": "file",
"hashes": {
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a"
@ -399,15 +414,17 @@ def test_parse_email_message_not_multipart(data):
}
}
}""",
])
],
)
def test_parse_file_archive(data):
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
odata = stix2.parse(odata_str, version="2.1")
assert odata.objects["3"].extensions['archive-ext'].version == "5.0"
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "email-message",
"is_multipart": true,
@ -443,8 +460,9 @@ def test_parse_file_archive(data):
}
]
}
"""
])
""",
],
)
def test_parse_email_message_with_at_least_one_error(data):
valid_refs = {
"0": "email-message",
@ -463,8 +481,9 @@ def test_parse_email_message_with_at_least_one_error(data):
assert "must be populated" in str(excinfo.value)
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "network-traffic",
"src_ref": "0",
@ -473,11 +492,14 @@ def test_parse_email_message_with_at_least_one_error(data):
"tcp"
]
}
"""
])
""",
],
)
def test_parse_basic_tcp_traffic(data):
odata = stix2.parse_observable(data, {"0": "ipv4-addr", "1": "ipv4-addr"},
version='2.1')
odata = stix2.parse_observable(
data, {"0": "ipv4-addr", "1": "ipv4-addr"},
version='2.1',
)
assert odata.type == "network-traffic"
assert odata.src_ref == "0"
@ -485,8 +507,9 @@ def test_parse_basic_tcp_traffic(data):
assert odata.protocols == ["tcp"]
@pytest.mark.parametrize("data", [
"""
@pytest.mark.parametrize(
"data", [
"""
{
"type": "network-traffic",
"src_port": 2487,
@ -501,8 +524,9 @@ def test_parse_basic_tcp_traffic(data):
"4"
]
}
"""
])
""",
],
)
def test_parse_basic_tcp_traffic_with_error(data):
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.parse_observable(data, {"4": "network-traffic"}, version='2.1')
@ -555,7 +579,7 @@ def test_observed_data_with_process_example():
"0": {
"type": "file",
"hashes": {
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f",
},
},
"1": {
@ -564,11 +588,12 @@ def test_observed_data_with_process_example():
"name": "gedit-bin",
"created": "2016-01-20T14:11:25.55Z",
"arguments": [
"--new-window"
"--new-window",
],
"image_ref": "0"
}
})
"image_ref": "0",
},
},
)
assert observed_data.objects["0"].type == "file"
assert observed_data.objects["0"].hashes["SHA-256"] == "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
@ -585,8 +610,9 @@ def test_artifact_example():
mime_type="image/jpeg",
url="https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
hashes={
"MD5": "6826f9a05da08134006557758bb3afbb"
})
"MD5": "6826f9a05da08134006557758bb3afbb",
},
)
assert art.mime_type == "image/jpeg"
assert art.url == "https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg"
assert art.hashes["MD5"] == "6826f9a05da08134006557758bb3afbb"
@ -598,9 +624,10 @@ def test_artifact_mutual_exclusion_error():
mime_type="image/jpeg",
url="https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg",
hashes={
"MD5": "6826f9a05da08134006557758bb3afbb"
"MD5": "6826f9a05da08134006557758bb3afbb",
},
payload_bin="VBORw0KGgoAAAANSUhEUgAAADI==")
payload_bin="VBORw0KGgoAAAANSUhEUgAAADI==",
)
assert excinfo.value.cls == stix2.v21.Artifact
assert excinfo.value.properties == ["payload_bin", "url"]
@ -614,7 +641,8 @@ def test_directory_example():
created="2015-12-21T19:00:00Z",
modified="2015-12-24T19:00:00Z",
accessed="2015-12-21T20:00:00Z",
contains_refs=["1"])
contains_refs=["1"],
)
assert dir.path == '/usr/lib'
assert dir.created == dt.datetime(2015, 12, 21, 19, 0, 0, tzinfo=pytz.utc)
@ -631,7 +659,8 @@ def test_directory_example_ref_error():
created="2015-12-21T19:00:00Z",
modified="2015-12-24T19:00:00Z",
accessed="2015-12-21T20:00:00Z",
contains_refs=["1"])
contains_refs=["1"],
)
assert excinfo.value.cls == stix2.v21.Directory
assert excinfo.value.prop_name == "contains_refs"
@ -641,7 +670,8 @@ def test_domain_name_example():
dn = stix2.v21.DomainName(
_valid_refs={"1": 'domain-name'},
value="example.com",
resolves_to_refs=["1"])
resolves_to_refs=["1"],
)
assert dn.value == "example.com"
assert dn.resolves_to_refs == ["1"]
@ -652,7 +682,8 @@ def test_domain_name_example_invalid_ref_type():
stix2.v21.DomainName(
_valid_refs={"1": "file"},
value="example.com",
resolves_to_refs=["1"])
resolves_to_refs=["1"],
)
assert excinfo.value.cls == stix2.v21.DomainName
assert excinfo.value.prop_name == "resolves_to_refs"
@ -662,14 +693,14 @@ def test_file_example():
f = stix2.v21.File(
name="qwerty.dll",
hashes={
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a"
"SHA-256": "ceafbfd424be2ca4a5f0402cae090dda2fb0526cf521b60b60077c0f622b285a",
},
size=100,
magic_number_hex="1C",
mime_type="application/msword",
created="2016-12-21T19:00:00Z",
modified="2016-12-24T19:00:00Z",
accessed="2016-12-21T20:00:00Z"
accessed="2016-12-21T20:00:00Z",
)
assert f.name == "qwerty.dll"
@ -690,11 +721,12 @@ def test_file_example_with_NTFSExt():
"alternate_data_streams": [
{
"name": "second.stream",
"size": 25536
}
]
}
})
"size": 25536,
},
],
},
},
)
assert f.name == "abc.txt"
assert f.extensions["ntfs-ext"].alternate_data_streams[0].size == 25536
@ -705,8 +737,9 @@ def test_file_example_with_empty_NTFSExt():
stix2.v21.File(
name="abc.txt",
extensions={
"ntfs-ext": {}
})
"ntfs-ext": {},
},
)
assert excinfo.value.cls == stix2.NTFSExt
assert excinfo.value.properties == sorted(list(stix2.NTFSExt._properties.keys()))
@ -723,12 +756,13 @@ def test_file_example_with_PDFExt():
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
"pdfid0": "DFCE52BD827ECF765649852119D",
"pdfid1": "57A1E0F9ED2AE523E313C"
}
})
"pdfid1": "57A1E0F9ED2AE523E313C",
},
},
)
assert f.name == "qwerty.dll"
assert f.extensions["pdf-ext"].version == "1.7"
@ -746,11 +780,13 @@ def test_file_example_with_PDFExt_Object():
"Author": "Adobe Systems Incorporated",
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
"CreationDate": "20070412090123-02"
"CreationDate": "20070412090123-02",
},
pdfid0="DFCE52BD827ECF765649852119D",
pdfid1="57A1E0F9ED2AE523E313C")
})
pdfid1="57A1E0F9ED2AE523E313C",
),
},
)
assert f.name == "qwerty.dll"
assert f.extensions["pdf-ext"].version == "1.7"
@ -767,10 +803,11 @@ def test_file_example_with_RasterImageExt_Object():
"Make": "Nikon",
"Model": "D7000",
"XResolution": 4928,
"YResolution": 3264
}
}
})
"YResolution": 3264,
},
},
},
)
assert f.name == "qwerty.jpeg"
assert f.extensions["raster-image-ext"].bits_per_pixel == 123
assert f.extensions["raster-image-ext"].exif_tags["XResolution"] == 4928
@ -865,28 +902,29 @@ def test_file_example_with_WindowsPEBinaryExt():
"size_of_heap_reserve": 100000,
"size_of_heap_commit": 4096,
"loader_flags_hex": "abdbffde",
"number_of_rva_and_sizes": 3758087646
"number_of_rva_and_sizes": 3758087646,
},
"sections": [
{
"name": "CODE",
"entropy": 0.061089
"entropy": 0.061089,
},
{
"name": "DATA",
"entropy": 7.980693
"entropy": 7.980693,
},
{
"name": "NicolasB",
"entropy": 0.607433
"entropy": 0.607433,
},
{
"name": ".idata",
"entropy": 0.607433
}
]
}
})
"entropy": 0.607433,
},
],
},
},
)
assert f.name == "qwerty.dll"
assert f.extensions["windows-pebinary-ext"].sections[2].entropy == 0.607433
@ -903,7 +941,8 @@ def test_ip4_address_example():
ip4 = stix2.v21.IPv4Address(
_valid_refs={"4": "mac-addr", "5": "mac-addr"},
value="198.51.100.3",
resolves_to_refs=["4", "5"])
resolves_to_refs=["4", "5"],
)
assert ip4.value == "198.51.100.3"
assert ip4.resolves_to_refs == ["4", "5"]
@ -932,7 +971,8 @@ def test_network_traffic_example():
_valid_refs={"0": "ipv4-addr", "1": "ipv4-addr"},
protocols="tcp",
src_ref="0",
dst_ref="1")
dst_ref="1",
)
assert nt.protocols == ["tcp"]
assert nt.src_ref == "0"
assert nt.dst_ref == "1"
@ -946,13 +986,15 @@ def test_network_traffic_http_request_example():
request_header={
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com"
})
"Host": "www.example.com",
},
)
nt = stix2.v21.NetworkTraffic(
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'http-request-ext': h})
extensions={'http-request-ext': h},
)
assert nt.extensions['http-request-ext'].request_method == "get"
assert nt.extensions['http-request-ext'].request_value == "/download.html"
assert nt.extensions['http-request-ext'].request_version == "http/1.1"
@ -967,7 +1009,8 @@ def test_network_traffic_icmp_example():
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'icmp-ext': h})
extensions={'icmp-ext': h},
)
assert nt.extensions['icmp-ext'].icmp_type_hex == "08"
assert nt.extensions['icmp-ext'].icmp_code_hex == "00"
@ -977,12 +1020,14 @@ def test_network_traffic_socket_example():
is_listening=True,
address_family="AF_INET",
protocol_family="PF_INET",
socket_type="SOCK_STREAM")
socket_type="SOCK_STREAM",
)
nt = stix2.v21.NetworkTraffic(
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'socket-ext': h})
extensions={'socket-ext': h},
)
assert nt.extensions['socket-ext'].is_listening
assert nt.extensions['socket-ext'].address_family == "AF_INET"
assert nt.extensions['socket-ext'].protocol_family == "PF_INET"
@ -995,7 +1040,8 @@ def test_network_traffic_tcp_example():
_valid_refs={"0": "ipv4-addr"},
protocols="tcp",
src_ref="0",
extensions={'tcp-ext': h})
extensions={'tcp-ext': h},
)
assert nt.extensions['tcp-ext'].src_flags_hex == "00000002"
@ -1012,7 +1058,8 @@ def test_process_example():
name="gedit-bin",
created="2016-01-20T14:11:25.55Z",
arguments=["--new-window"],
image_ref="0")
image_ref="0",
)
assert p.name == "gedit-bin"
assert p.arguments == ["--new-window"]
@ -1027,15 +1074,17 @@ def test_process_example_empty_error():
properties_of_process.remove("type")
assert excinfo.value.properties == sorted(properties_of_process)
msg = "At least one of the ({1}) properties for {0} must be populated."
msg = msg.format(stix2.v21.Process.__name__,
", ".join(sorted(properties_of_process)))
msg = msg.format(
stix2.v21.Process.__name__,
", ".join(sorted(properties_of_process)),
)
assert str(excinfo.value) == msg
def test_process_example_empty_with_extensions():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.v21.Process(extensions={
"windows-process-ext": {}
"windows-process-ext": {},
})
assert excinfo.value.cls == stix2.v21.WindowsProcessExt
@ -1052,9 +1101,10 @@ def test_process_example_windows_process_ext():
"aslr_enabled": True,
"dep_enabled": True,
"priority": "HIGH_PRIORITY_CLASS",
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309"
}
})
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
},
},
)
assert proc.extensions["windows-process-ext"].aslr_enabled
assert proc.extensions["windows-process-ext"].dep_enabled
assert proc.extensions["windows-process-ext"].priority == "HIGH_PRIORITY_CLASS"
@ -1067,8 +1117,9 @@ def test_process_example_windows_process_ext_empty():
pid=1221,
name="gedit-bin",
extensions={
"windows-process-ext": {}
})
"windows-process-ext": {},
},
)
assert excinfo.value.cls == stix2.v21.WindowsProcessExt
properties_of_extension = list(stix2.v21.WindowsProcessExt._properties.keys())
@ -1090,7 +1141,8 @@ def test_process_example_with_WindowsProcessExt_Object():
aslr_enabled=True,
dep_enabled=True,
priority="HIGH_PRIORITY_CLASS",
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309") # noqa
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
), # noqa
})
assert p.extensions["windows-process-ext"].dep_enabled
@ -1104,8 +1156,8 @@ def test_process_example_with_WindowsServiceExt():
"display_name": "Sirvizio",
"start_type": "SERVICE_AUTO_START",
"service_type": "SERVICE_WIN32_OWN_PROCESS",
"service_status": "SERVICE_RUNNING"
}
"service_status": "SERVICE_RUNNING",
},
})
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
@ -1119,14 +1171,14 @@ def test_process_example_with_WindowsProcessServiceExt():
"display_name": "Sirvizio",
"start_type": "SERVICE_AUTO_START",
"service_type": "SERVICE_WIN32_OWN_PROCESS",
"service_status": "SERVICE_RUNNING"
"service_status": "SERVICE_RUNNING",
},
"windows-process-ext": {
"aslr_enabled": True,
"dep_enabled": True,
"priority": "HIGH_PRIORITY_CLASS",
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309"
}
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
},
})
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
@ -1140,7 +1192,8 @@ def test_software_example():
name="Word",
cpe="cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*",
version="2002",
vendor="Microsoft")
vendor="Microsoft",
)
assert s.name == "Word"
assert s.cpe == "cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*"
@ -1167,7 +1220,8 @@ def test_user_account_example():
account_created="2016-01-20T12:31:12Z",
credential_last_changed="2016-01-20T14:27:43Z",
account_first_login="2016-01-20T14:26:07Z",
account_last_login="2016-07-22T16:08:28Z")
account_last_login="2016-07-22T16:08:28Z",
)
assert a.user_id == "1001"
assert a.account_login == "jdoe"
@ -1187,12 +1241,14 @@ def test_user_account_unix_account_ext_example():
gid=1001,
groups=["wheel"],
home_dir="/home/jdoe",
shell="/bin/bash")
shell="/bin/bash",
)
a = stix2.v21.UserAccount(
user_id="1001",
account_login="jdoe",
account_type="unix",
extensions={'unix-account-ext': u})
extensions={'unix-account-ext': u},
)
assert a.extensions['unix-account-ext'].gid == 1001
assert a.extensions['unix-account-ext'].groups == ["wheel"]
assert a.extensions['unix-account-ext'].home_dir == "/home/jdoe"
@ -1204,16 +1260,17 @@ def test_windows_registry_key_example():
stix2.v21.WindowsRegistryValueType(
name="Foo",
data="qwerty",
data_type="string")
data_type="string",
)
v = stix2.v21.WindowsRegistryValueType(
name="Foo",
data="qwerty",
data_type="REG_SZ"
data_type="REG_SZ",
)
w = stix2.v21.WindowsRegistryKey(
key="hkey_local_machine\\system\\bar\\foo",
values=[v]
values=[v],
)
assert w.key == "hkey_local_machine\\system\\bar\\foo"
assert w.values[0].name == "Foo"
@ -1226,7 +1283,8 @@ def test_x509_certificate_example():
issuer="C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com", # noqa
validity_not_before="2016-03-12T12:00:00Z",
validity_not_after="2016-08-21T12:00:00Z",
subject="C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org") # noqa
subject="C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=baccala@freesoft.org",
) # noqa
assert x509.type == "x509-certificate"
assert x509.issuer == "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com" # noqa
@ -1241,14 +1299,14 @@ def test_new_version_with_related_objects():
objects={
'src_ip': {
'type': 'ipv4-addr',
'value': '127.0.0.1/32'
'value': '127.0.0.1/32',
},
'domain': {
'type': 'domain-name',
'value': 'example.com',
'resolves_to_refs': ['src_ip']
}
}
'resolves_to_refs': ['src_ip'],
},
},
)
new_version = data.new_version(last_observed="2017-12-12T12:00:00Z")
assert new_version.last_observed.year == 2017

View File

@ -8,11 +8,13 @@ import stix2
from .constants import OPINION_ID
DESCRIPTION = ('This doesn\'t seem like it is feasible. We\'ve seen how '
'PandaCat has attacked Spanish infrastructure over the '
'last 3 years, so this change in targeting seems too great'
' to be viable. The methods used are more commonly '
'associated with the FlameDragonCrew.')
DESCRIPTION = (
'This doesn\'t seem like it is feasible. We\'ve seen how '
'PandaCat has attacked Spanish infrastructure over the '
'last 3 years, so this change in targeting seems too great'
' to be viable. The methods used are more commonly '
'associated with the FlameDragonCrew.'
)
EXPECTED_OPINION = """{
"type": "opinion",
@ -27,7 +29,8 @@ EXPECTED_OPINION = """{
"opinion": "strongly-disagree"
}""" % DESCRIPTION
EXPECTED_OPINION_REPR = "Opinion(" + " ".join(("""
EXPECTED_OPINION_REPR = "Opinion(" + " ".join((
"""
type='opinion',
spec_version='2.1',
id='opinion--b01efc25-77b4-4003-b18b-f6e24b5cd9f7',
@ -35,7 +38,8 @@ EXPECTED_OPINION_REPR = "Opinion(" + " ".join(("""
modified='2016-05-12T08:17:27.000Z',
description="%s",
object_refs=['relationship--16d2358f-3b0d-4c88-b047-0da2f7ed4471'],
opinion='strongly-disagree'""" % DESCRIPTION).split()) + ")"
opinion='strongly-disagree'""" % DESCRIPTION
).split()) + ")"
def test_opinion_with_required_properties():
@ -48,7 +52,7 @@ def test_opinion_with_required_properties():
modified=now,
object_refs=['relationship--16d2358f-3b0d-4c88-b047-0da2f7ed4471'],
opinion='strongly-disagree',
description=DESCRIPTION
description=DESCRIPTION,
)
assert str(opi) == EXPECTED_OPINION
@ -56,21 +60,23 @@ def test_opinion_with_required_properties():
assert rep == EXPECTED_OPINION_REPR
@pytest.mark.parametrize("data", [
EXPECTED_OPINION,
{
"type": "opinion",
"spec_version": "2.1",
"id": "opinion--b01efc25-77b4-4003-b18b-f6e24b5cd9f7",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": DESCRIPTION,
"object_refs": [
"relationship--16d2358f-3b0d-4c88-b047-0da2f7ed4471"
],
"opinion": "strongly-disagree"
}
])
@pytest.mark.parametrize(
"data", [
EXPECTED_OPINION,
{
"type": "opinion",
"spec_version": "2.1",
"id": "opinion--b01efc25-77b4-4003-b18b-f6e24b5cd9f7",
"created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z",
"description": DESCRIPTION,
"object_refs": [
"relationship--16d2358f-3b0d-4c88-b047-0da2f7ed4471",
],
"opinion": "strongly-disagree",
},
],
)
def test_parse_opinion(data):
opinion = stix2.parse(data, version="2.1")

View File

@ -7,37 +7,55 @@ import stix2
def test_create_comparison_expression():
exp = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant("aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", "SHA-256")) # noqa
exp = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant("aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f", "SHA-256"),
) # noqa
assert str(exp) == "file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'"
def test_boolean_expression():
exp1 = stix2.MatchesComparisonExpression("email-message:from_ref.value",
stix2.StringConstant(".+\\@example\\.com$"))
exp2 = stix2.MatchesComparisonExpression("email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"))
exp1 = stix2.MatchesComparisonExpression(
"email-message:from_ref.value",
stix2.StringConstant(".+\\@example\\.com$"),
)
exp2 = stix2.MatchesComparisonExpression(
"email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"),
)
exp = stix2.AndBooleanExpression([exp1, exp2])
assert str(exp) == "email-message:from_ref.value MATCHES '.+\\\\@example\\\\.com$' AND email-message:body_multipart[*].body_raw_ref.name MATCHES '^Final Report.+\\\\.exe$'" # noqa
def test_boolean_expression_with_parentheses():
exp1 = stix2.MatchesComparisonExpression(stix2.ObjectPath("email-message",
[stix2.ReferenceObjectPathComponent("from_ref"),
stix2.BasicObjectPathComponent("value")]),
stix2.StringConstant(".+\\@example\\.com$"))
exp2 = stix2.MatchesComparisonExpression("email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"))
exp1 = stix2.MatchesComparisonExpression(
stix2.ObjectPath(
"email-message",
[
stix2.ReferenceObjectPathComponent("from_ref"),
stix2.BasicObjectPathComponent("value"),
],
),
stix2.StringConstant(".+\\@example\\.com$"),
)
exp2 = stix2.MatchesComparisonExpression(
"email-message:body_multipart[*].body_raw_ref.name",
stix2.StringConstant("^Final Report.+\\.exe$"),
)
exp = stix2.ParentheticalExpression(stix2.AndBooleanExpression([exp1, exp2]))
assert str(exp) == "(email-message:from_ref.value MATCHES '.+\\\\@example\\\\.com$' AND email-message:body_multipart[*].body_raw_ref.name MATCHES '^Final Report.+\\\\.exe$')" # noqa
def test_hash_followed_by_registryKey_expression_python_constant():
hash_exp = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"))
hash_exp = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"),
)
o_exp1 = stix2.ObservationExpression(hash_exp)
reg_exp = stix2.EqualityComparisonExpression(stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"))
reg_exp = stix2.EqualityComparisonExpression(
stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"),
)
o_exp2 = stix2.ObservationExpression(reg_exp)
fb_exp = stix2.FollowedByObservationExpression([o_exp1, o_exp2])
para_exp = stix2.ParentheticalExpression(fb_exp)
@ -47,11 +65,15 @@ def test_hash_followed_by_registryKey_expression_python_constant():
def test_hash_followed_by_registryKey_expression():
hash_exp = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"))
hash_exp = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5"),
)
o_exp1 = stix2.ObservationExpression(hash_exp)
reg_exp = stix2.EqualityComparisonExpression(stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"))
reg_exp = stix2.EqualityComparisonExpression(
stix2.ObjectPath("windows-registry-key", ["key"]),
stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar"),
)
o_exp2 = stix2.ObservationExpression(reg_exp)
fb_exp = stix2.FollowedByObservationExpression([o_exp1, o_exp2])
para_exp = stix2.ParentheticalExpression(fb_exp)
@ -61,32 +83,45 @@ def test_hash_followed_by_registryKey_expression():
def test_file_observable_expression():
exp1 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256'))
exp1 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256',
),
)
exp2 = stix2.EqualityComparisonExpression("file:mime_type", stix2.StringConstant("application/x-pdf"))
bool_exp = stix2.AndBooleanExpression([exp1, exp2])
exp = stix2.ObservationExpression(bool_exp)
assert str(exp) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f' AND file:mime_type = 'application/x-pdf']" # noqa
@pytest.mark.parametrize("observation_class, op", [
(stix2.AndObservationExpression, 'AND'),
(stix2.OrObservationExpression, 'OR'),
])
@pytest.mark.parametrize(
"observation_class, op", [
(stix2.AndObservationExpression, 'AND'),
(stix2.OrObservationExpression, 'OR'),
],
)
def test_multiple_file_observable_expression(observation_class, op):
exp1 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c",
'SHA-256'))
exp2 = stix2.EqualityComparisonExpression("file:hashes.MD5",
stix2.HashConstant("cead3f77f6cda6ec00f57d76c9a6879f", "MD5"))
exp1 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c",
'SHA-256',
),
)
exp2 = stix2.EqualityComparisonExpression(
"file:hashes.MD5",
stix2.HashConstant("cead3f77f6cda6ec00f57d76c9a6879f", "MD5"),
)
bool1_exp = stix2.OrBooleanExpression([exp1, exp2])
exp3 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256'))
exp3 = stix2.EqualityComparisonExpression(
"file:hashes.'SHA-256'",
stix2.HashConstant(
"aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f",
'SHA-256',
),
)
op1_exp = stix2.ObservationExpression(bool1_exp)
op2_exp = stix2.ObservationExpression(exp3)
exp = observation_class([op1_exp, op2_exp])
@ -96,111 +131,177 @@ def test_multiple_file_observable_expression(observation_class, op):
def test_root_types():
ast = stix2.ObservationExpression(
stix2.AndBooleanExpression(
[stix2.ParentheticalExpression(
stix2.OrBooleanExpression([
stix2.EqualityComparisonExpression("a:b", stix2.StringConstant("1")),
stix2.EqualityComparisonExpression("b:c", stix2.StringConstant("2"))])),
stix2.EqualityComparisonExpression(u"b:d", stix2.StringConstant("3"))]))
[
stix2.ParentheticalExpression(
stix2.OrBooleanExpression([
stix2.EqualityComparisonExpression("a:b", stix2.StringConstant("1")),
stix2.EqualityComparisonExpression("b:c", stix2.StringConstant("2")),
]),
),
stix2.EqualityComparisonExpression(u"b:d", stix2.StringConstant("3")),
],
),
)
assert str(ast) == "[(a:b = '1' OR b:c = '2') AND b:d = '3']"
def test_artifact_payload():
exp1 = stix2.EqualityComparisonExpression("artifact:mime_type",
"application/vnd.tcpdump.pcap")
exp2 = stix2.MatchesComparisonExpression("artifact:payload_bin",
stix2.StringConstant("\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00"))
exp1 = stix2.EqualityComparisonExpression(
"artifact:mime_type",
"application/vnd.tcpdump.pcap",
)
exp2 = stix2.MatchesComparisonExpression(
"artifact:payload_bin",
stix2.StringConstant("\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00"),
)
and_exp = stix2.AndBooleanExpression([exp1, exp2])
exp = stix2.ObservationExpression(and_exp)
assert str(exp) == "[artifact:mime_type = 'application/vnd.tcpdump.pcap' AND artifact:payload_bin MATCHES '\\\\xd4\\\\xc3\\\\xb2\\\\xa1\\\\x02\\\\x00\\\\x04\\\\x00']" # noqa
def test_greater_than_python_constant():
exp1 = stix2.GreaterThanComparisonExpression("file:extensions.windows-pebinary-ext.sections[*].entropy",
7.0)
exp1 = stix2.GreaterThanComparisonExpression(
"file:extensions.windows-pebinary-ext.sections[*].entropy",
7.0,
)
exp = stix2.ObservationExpression(exp1)
assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
def test_greater_than():
exp1 = stix2.GreaterThanComparisonExpression("file:extensions.windows-pebinary-ext.sections[*].entropy",
stix2.FloatConstant(7.0))
exp1 = stix2.GreaterThanComparisonExpression(
"file:extensions.windows-pebinary-ext.sections[*].entropy",
stix2.FloatConstant(7.0),
)
exp = stix2.ObservationExpression(exp1)
assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
def test_less_than():
exp = stix2.LessThanComparisonExpression("file:size",
1024)
exp = stix2.LessThanComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size < 1024"
def test_greater_than_or_equal():
exp = stix2.GreaterThanEqualComparisonExpression("file:size",
1024)
exp = stix2.GreaterThanEqualComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size >= 1024"
def test_less_than_or_equal():
exp = stix2.LessThanEqualComparisonExpression("file:size",
1024)
exp = stix2.LessThanEqualComparisonExpression(
"file:size",
1024,
)
assert str(exp) == "file:size <= 1024"
def test_not():
exp = stix2.LessThanComparisonExpression("file:size",
1024,
negated=True)
exp = stix2.LessThanComparisonExpression(
"file:size",
1024,
negated=True,
)
assert str(exp) == "file:size NOT < 1024"
def test_and_observable_expression():
exp1 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1007")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Peter")])
exp2 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1008")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Paul")])
exp3 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
"unix"),
stix2.EqualityComparisonExpression("user-account:user_id",
stix2.StringConstant("1009")),
stix2.EqualityComparisonExpression("user-account:account_login",
"Mary")])
exp = stix2.AndObservationExpression([stix2.ObservationExpression(exp1),
stix2.ObservationExpression(exp2),
stix2.ObservationExpression(exp3)])
exp1 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1007"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Peter",
),
])
exp2 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1008"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Paul",
),
])
exp3 = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:account_type",
"unix",
),
stix2.EqualityComparisonExpression(
"user-account:user_id",
stix2.StringConstant("1009"),
),
stix2.EqualityComparisonExpression(
"user-account:account_login",
"Mary",
),
])
exp = stix2.AndObservationExpression([
stix2.ObservationExpression(exp1),
stix2.ObservationExpression(exp2),
stix2.ObservationExpression(exp3),
])
assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1009' AND user-account:account_login = 'Mary']" # noqa
def test_invalid_and_observable_expression():
with pytest.raises(ValueError) as excinfo:
stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:display_name",
"admin"),
stix2.EqualityComparisonExpression("email-addr:display_name",
stix2.StringConstant("admin"))])
stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"user-account:display_name",
"admin",
),
stix2.EqualityComparisonExpression(
"email-addr:display_name",
stix2.StringConstant("admin"),
),
])
assert "All operands to an 'AND' expression must have the same object type" in str(excinfo)
def test_hex():
exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("file:mime_type",
"image/bmp"),
stix2.EqualityComparisonExpression("file:magic_number_hex",
stix2.HexConstant("ffd8"))])
exp_and = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"file:mime_type",
"image/bmp",
),
stix2.EqualityComparisonExpression(
"file:magic_number_hex",
stix2.HexConstant("ffd8"),
),
])
exp = stix2.ObservationExpression(exp_and)
assert str(exp) == "[file:mime_type = 'image/bmp' AND file:magic_number_hex = h'ffd8']"
def test_multiple_qualifiers():
exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("network-traffic:dst_ref.type",
"domain-name"),
stix2.EqualityComparisonExpression("network-traffic:dst_ref.value",
"example.com")])
exp_and = stix2.AndBooleanExpression([
stix2.EqualityComparisonExpression(
"network-traffic:dst_ref.type",
"domain-name",
),
stix2.EqualityComparisonExpression(
"network-traffic:dst_ref.value",
"example.com",
),
])
exp_ob = stix2.ObservationExpression(exp_and)
qual_rep = stix2.RepeatQualifier(5)
qual_within = stix2.WithinQualifier(stix2.IntegerConstant(1800))
@ -209,8 +310,10 @@ def test_multiple_qualifiers():
def test_set_op():
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression("network-traffic:dst_ref.value",
"2001:0db8:dead:beef:0000:0000:0000:0000/64"))
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression(
"network-traffic:dst_ref.value",
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
))
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
@ -220,35 +323,45 @@ def test_timestamp():
def test_boolean():
exp = stix2.EqualityComparisonExpression("email-message:is_multipart",
True)
exp = stix2.EqualityComparisonExpression(
"email-message:is_multipart",
True,
)
assert str(exp) == "email-message:is_multipart = true"
def test_binary():
const = stix2.BinaryConstant("dGhpcyBpcyBhIHRlc3Q=")
exp = stix2.EqualityComparisonExpression("artifact:payload_bin",
const)
exp = stix2.EqualityComparisonExpression(
"artifact:payload_bin",
const,
)
assert str(exp) == "artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q='"
def test_list():
exp = stix2.InComparisonExpression("process:name",
['proccy', 'proximus', 'badproc'])
exp = stix2.InComparisonExpression(
"process:name",
['proccy', 'proximus', 'badproc'],
)
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
def test_list2():
# alternate way to construct an "IN" Comparison Expression
exp = stix2.EqualityComparisonExpression("process:name",
['proccy', 'proximus', 'badproc'])
exp = stix2.EqualityComparisonExpression(
"process:name",
['proccy', 'proximus', 'badproc'],
)
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
def test_invalid_constant_type():
with pytest.raises(ValueError) as excinfo:
stix2.EqualityComparisonExpression("artifact:payload_bin",
{'foo': 'bar'})
stix2.EqualityComparisonExpression(
"artifact:payload_bin",
{'foo': 'bar'},
)
assert 'Unable to create a constant' in str(excinfo)
@ -270,20 +383,22 @@ def test_invalid_float_constant():
assert 'must be a float' in str(excinfo)
@pytest.mark.parametrize("data, result", [
(True, True),
(False, False),
('True', True),
('False', False),
('true', True),
('false', False),
('t', True),
('f', False),
('T', True),
('F', False),
(1, True),
(0, False),
])
@pytest.mark.parametrize(
"data, result", [
(True, True),
(False, False),
('True', True),
('False', False),
('true', True),
('false', False),
('t', True),
('f', False),
('T', True),
('F', False),
(1, True),
(0, False),
],
)
def test_boolean_constant(data, result):
boolean = stix2.BooleanConstant(data)
assert boolean.value == result
@ -295,10 +410,12 @@ def test_invalid_boolean_constant():
assert 'must be a boolean' in str(excinfo)
@pytest.mark.parametrize("hashtype, data", [
('MD5', 'zzz'),
('ssdeep', 'zzz=='),
])
@pytest.mark.parametrize(
"hashtype, data", [
('MD5', 'zzz'),
('ssdeep', 'zzz=='),
],
)
def test_invalid_hash_constant(hashtype, data):
with pytest.raises(ValueError) as excinfo:
stix2.HashConstant(data, hashtype)
@ -318,20 +435,26 @@ def test_invalid_binary_constant():
def test_escape_quotes_and_backslashes():
exp = stix2.MatchesComparisonExpression("file:name",
"^Final Report.+\\.exe$")
exp = stix2.MatchesComparisonExpression(
"file:name",
"^Final Report.+\\.exe$",
)
assert str(exp) == "file:name MATCHES '^Final Report.+\\\\.exe$'"
def test_like():
exp = stix2.LikeComparisonExpression("directory:path",
"C:\\Windows\\%\\foo")
exp = stix2.LikeComparisonExpression(
"directory:path",
"C:\\Windows\\%\\foo",
)
assert str(exp) == "directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo'"
def test_issuperset():
exp = stix2.IsSupersetComparisonExpression("ipv4-addr:value",
"198.51.100.0/24")
exp = stix2.IsSupersetComparisonExpression(
"ipv4-addr:value",
"198.51.100.0/24",
)
assert str(exp) == "ipv4-addr:value ISSUPERSET '198.51.100.0/24'"
@ -353,24 +476,32 @@ def test_invalid_within_qualifier():
def test_startstop_qualifier():
qual = stix2.StartStopQualifier(stix2.TimestampConstant('2016-06-01T00:00:00Z'),
datetime.datetime(2017, 3, 12, 8, 30, 0))
qual = stix2.StartStopQualifier(
stix2.TimestampConstant('2016-06-01T00:00:00Z'),
datetime.datetime(2017, 3, 12, 8, 30, 0),
)
assert str(qual) == "START t'2016-06-01T00:00:00Z' STOP t'2017-03-12T08:30:00Z'"
qual2 = stix2.StartStopQualifier(datetime.date(2016, 6, 1),
stix2.TimestampConstant('2016-07-01T00:00:00Z'))
qual2 = stix2.StartStopQualifier(
datetime.date(2016, 6, 1),
stix2.TimestampConstant('2016-07-01T00:00:00Z'),
)
assert str(qual2) == "START t'2016-06-01T00:00:00Z' STOP t'2016-07-01T00:00:00Z'"
def test_invalid_startstop_qualifier():
with pytest.raises(ValueError) as excinfo:
stix2.StartStopQualifier('foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'))
stix2.StartStopQualifier(
'foo',
stix2.TimestampConstant('2016-06-01T00:00:00Z'),
)
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
with pytest.raises(ValueError) as excinfo:
stix2.StartStopQualifier(datetime.date(2016, 6, 1),
'foo')
stix2.StartStopQualifier(
datetime.date(2016, 6, 1),
'foo',
)
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)

View File

@ -11,7 +11,7 @@ def test_pickling():
id="identity--d66cb89d-5228-4983-958c-fa84ef75c88c",
name="alice",
description="this is a pickle test",
identity_class="some_class"
identity_class="some_class",
)
pickle.loads(pickle.dumps(identity))

View File

@ -4,14 +4,13 @@ import pytest
import stix2
from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
from stix2.properties import (ERROR_INVALID_ID, BinaryProperty,
BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty,
ExtensionsProperty, FloatProperty,
HashesProperty, HexProperty, IDProperty,
IntegerProperty, ListProperty, Property,
ReferenceProperty, StringProperty,
TimestampProperty, TypeProperty)
from stix2.properties import (
ERROR_INVALID_ID, BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty,
Property, ReferenceProperty, StringProperty, TimestampProperty,
TypeProperty,
)
from . import constants
@ -93,10 +92,12 @@ ID_PROP = IDProperty('my-type')
MY_ID = 'my-type--232c9d3f-49fc-4440-bb01-607f638778e7'
@pytest.mark.parametrize("value", [
MY_ID,
'my-type--00000000-0000-4000-8000-000000000000',
])
@pytest.mark.parametrize(
"value", [
MY_ID,
'my-type--00000000-0000-4000-8000-000000000000',
],
)
def test_id_property_valid(value):
assert ID_PROP.clean(value) == value
@ -134,14 +135,16 @@ def test_id_property_wrong_type():
assert str(excinfo.value) == "must start with 'my-type--'."
@pytest.mark.parametrize("value", [
'my-type--foo',
# Not a v4 UUID
'my-type--00000000-0000-0000-0000-000000000000',
'my-type--' + str(uuid.uuid1()),
'my-type--' + str(uuid.uuid3(uuid.NAMESPACE_DNS, "example.org")),
'my-type--' + str(uuid.uuid5(uuid.NAMESPACE_DNS, "example.org")),
])
@pytest.mark.parametrize(
"value", [
'my-type--foo',
# Not a v4 UUID
'my-type--00000000-0000-0000-0000-000000000000',
'my-type--' + str(uuid.uuid1()),
'my-type--' + str(uuid.uuid3(uuid.NAMESPACE_DNS, "example.org")),
'my-type--' + str(uuid.uuid5(uuid.NAMESPACE_DNS, "example.org")),
],
)
def test_id_property_not_a_valid_hex_uuid(value):
with pytest.raises(ValueError) as excinfo:
ID_PROP.clean(value)
@ -153,77 +156,89 @@ def test_id_property_default():
assert ID_PROP.clean(default) == default
@pytest.mark.parametrize("value", [
2,
-1,
3.14,
False,
])
@pytest.mark.parametrize(
"value", [
2,
-1,
3.14,
False,
],
)
def test_integer_property_valid(value):
int_prop = IntegerProperty()
assert int_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
"something",
StringProperty(),
])
@pytest.mark.parametrize(
"value", [
"something",
StringProperty(),
],
)
def test_integer_property_invalid(value):
int_prop = IntegerProperty()
with pytest.raises(ValueError):
int_prop.clean(value)
@pytest.mark.parametrize("value", [
2,
-1,
3.14,
False,
])
@pytest.mark.parametrize(
"value", [
2,
-1,
3.14,
False,
],
)
def test_float_property_valid(value):
int_prop = FloatProperty()
assert int_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
"something",
StringProperty(),
])
@pytest.mark.parametrize(
"value", [
"something",
StringProperty(),
],
)
def test_float_property_invalid(value):
int_prop = FloatProperty()
with pytest.raises(ValueError):
int_prop.clean(value)
@pytest.mark.parametrize("value", [
True,
False,
'True',
'False',
'true',
'false',
'TRUE',
'FALSE',
'T',
'F',
't',
'f',
1,
0,
])
@pytest.mark.parametrize(
"value", [
True,
False,
'True',
'False',
'true',
'false',
'TRUE',
'FALSE',
'T',
'F',
't',
'f',
1,
0,
],
)
def test_boolean_property_valid(value):
bool_prop = BooleanProperty()
assert bool_prop.clean(value) is not None
@pytest.mark.parametrize("value", [
'abc',
['false'],
{'true': 'true'},
2,
-1,
])
@pytest.mark.parametrize(
"value", [
'abc',
['false'],
{'true': 'true'},
2,
-1,
],
)
def test_boolean_property_invalid(value):
bool_prop = BooleanProperty()
with pytest.raises(ValueError):
@ -242,11 +257,13 @@ def test_reference_property():
ref_prop.clean("my-type--00000000-0000-0000-0000-000000000000")
@pytest.mark.parametrize("value", [
'2017-01-01T12:34:56Z',
'2017-01-01 12:34:56',
'Jan 1 2017 12:34:56',
])
@pytest.mark.parametrize(
"value", [
'2017-01-01T12:34:56Z',
'2017-01-01 12:34:56',
'Jan 1 2017 12:34:56',
],
)
def test_timestamp_property_valid(value):
ts_prop = TimestampProperty()
assert ts_prop.clean(value) == constants.FAKE_TIME
@ -276,18 +293,22 @@ def test_hex_property():
hex_prop.clean("foobar")
@pytest.mark.parametrize("d", [
{'description': 'something'},
[('abc', 1), ('bcd', 2), ('cde', 3)],
])
@pytest.mark.parametrize(
"d", [
{'description': 'something'},
[('abc', 1), ('bcd', 2), ('cde', 3)],
],
)
def test_dictionary_property_valid(d):
dict_prop = DictionaryProperty(spec_version='2.1')
assert dict_prop.clean(d)
@pytest.mark.parametrize("d", [
[{'a': 'something'}, "Invalid dictionary key a: (shorter than 3 characters)."],
])
@pytest.mark.parametrize(
"d", [
[{'a': 'something'}, "Invalid dictionary key a: (shorter than 3 characters)."],
],
)
def test_dictionary_no_longer_raises(d):
dict_prop = DictionaryProperty(spec_version='2.1')
@ -297,15 +318,21 @@ def test_dictionary_no_longer_raises(d):
pytest.fail("Unexpected DictionaryKeyError...")
@pytest.mark.parametrize("d", [
[{'a'*300: 'something'}, "Invalid dictionary key aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaa: (longer than 250 characters)."],
[{'Hey!': 'something'}, "Invalid dictionary key Hey!: (contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or underscore (_))."],
])
@pytest.mark.parametrize(
"d", [
[
{'a'*300: 'something'}, "Invalid dictionary key aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaaa: (longer than 250 characters).",
],
[
{'Hey!': 'something'}, "Invalid dictionary key Hey!: (contains characters other than lowercase a-z, "
"uppercase A-Z, numerals 0-9, hyphen (-), or underscore (_)).",
],
],
)
def test_dictionary_property_invalid_key(d):
dict_prop = DictionaryProperty(spec_version='2.1')
@ -315,18 +342,20 @@ def test_dictionary_property_invalid_key(d):
assert str(excinfo.value) == d[1]
@pytest.mark.parametrize("d", [
({}, "The dictionary property must contain a non-empty dictionary"),
# TODO: This error message could be made more helpful. The error is caused
# because `json.loads()` doesn't like the *single* quotes around the key
# name, even though they are valid in a Python dictionary. While technically
# accurate (a string is not a dictionary), if we want to be able to load
# string-encoded "dictionaries" that are, we need a better error message
# or an alternative to `json.loads()` ... and preferably *not* `eval()`. :-)
# Changing the following to `'{"description": "something"}'` does not cause
# any ValueError to be raised.
("{'description': 'something'}", "The dictionary property must contain a dictionary"),
])
@pytest.mark.parametrize(
"d", [
({}, "The dictionary property must contain a non-empty dictionary"),
# TODO: This error message could be made more helpful. The error is caused
# because `json.loads()` doesn't like the *single* quotes around the key
# name, even though they are valid in a Python dictionary. While technically
# accurate (a string is not a dictionary), if we want to be able to load
# string-encoded "dictionaries" that are, we need a better error message
# or an alternative to `json.loads()` ... and preferably *not* `eval()`. :-)
# Changing the following to `'{"description": "something"}'` does not cause
# any ValueError to be raised.
("{'description': 'something'}", "The dictionary property must contain a dictionary"),
],
)
def test_dictionary_property_invalid(d):
dict_prop = DictionaryProperty(spec_version='2.1')
@ -336,9 +365,11 @@ def test_dictionary_property_invalid(d):
def test_property_list_of_dictionary():
@stix2.v21.CustomObject('x-new-obj', [
('property1', ListProperty(DictionaryProperty(spec_version='2.1'), required=True)),
])
@stix2.v21.CustomObject(
'x-new-obj', [
('property1', ListProperty(DictionaryProperty(spec_version='2.1'), required=True)),
],
)
class NewObj():
pass
@ -346,19 +377,23 @@ def test_property_list_of_dictionary():
assert test_obj.property1[0]['foo'] == 'bar'
@pytest.mark.parametrize("value", [
{"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"},
[('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')],
])
@pytest.mark.parametrize(
"value", [
{"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"},
[('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')],
],
)
def test_hashes_property_valid(value):
hash_prop = HashesProperty()
assert hash_prop.clean(value)
@pytest.mark.parametrize("value", [
{"MD5": "a"},
{"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"},
])
@pytest.mark.parametrize(
"value", [
{"MD5": "a"},
{"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"},
],
)
def test_hashes_property_invalid(value):
hash_prop = HashesProperty()
@ -371,7 +406,7 @@ def test_embedded_property():
mime = stix2.v21.EmailMIMEComponent(
content_type="text/plain; charset=utf-8",
content_disposition="inline",
body="Cats are funny!"
body="Cats are funny!",
)
assert emb_prop.clean(mime)
@ -379,11 +414,13 @@ def test_embedded_property():
emb_prop.clean("string")
@pytest.mark.parametrize("value", [
['a', 'b', 'c'],
('a', 'b', 'c'),
'b',
])
@pytest.mark.parametrize(
"value", [
['a', 'b', 'c'],
('a', 'b', 'c'),
'b',
],
)
def test_enum_property_valid(value):
enum_prop = EnumProperty(value)
assert enum_prop.clean('b')
@ -399,17 +436,19 @@ def test_extension_property_valid():
ext_prop = ExtensionsProperty(spec_version='2.1', enclosing_type='file')
assert ext_prop({
'windows-pebinary-ext': {
'pe_type': 'exe'
'pe_type': 'exe',
},
})
@pytest.mark.parametrize("data", [
1,
{'foobar-ext': {
'pe_type': 'exe'
}},
])
@pytest.mark.parametrize(
"data", [
1,
{'foobar-ext': {
'pe_type': 'exe',
}},
],
)
def test_extension_property_invalid(data):
ext_prop = ExtensionsProperty(spec_version='2.1', enclosing_type='file')
with pytest.raises(ValueError):
@ -419,10 +458,12 @@ def test_extension_property_invalid(data):
def test_extension_property_invalid_type():
ext_prop = ExtensionsProperty(spec_version='2.1', enclosing_type='indicator')
with pytest.raises(ValueError) as excinfo:
ext_prop.clean({
'windows-pebinary-ext': {
'pe_type': 'exe'
}}
ext_prop.clean(
{
'windows-pebinary-ext': {
'pe_type': 'exe',
},
},
)
assert 'no extensions defined' in str(excinfo.value)

View File

@ -5,8 +5,9 @@ import pytz
import stix2
from .constants import (FAKE_TIME, INDICATOR_ID, MALWARE_ID, RELATIONSHIP_ID,
RELATIONSHIP_KWARGS)
from .constants import (
FAKE_TIME, INDICATOR_ID, MALWARE_ID, RELATIONSHIP_ID, RELATIONSHIP_KWARGS,
)
EXPECTED_RELATIONSHIP = """{
"type": "relationship",
@ -94,7 +95,7 @@ def test_relationship_required_properties_target_ref():
with pytest.raises(stix2.exceptions.MissingPropertiesError) as excinfo:
stix2.v21.Relationship(
relationship_type='indicates',
source_ref=INDICATOR_ID
source_ref=INDICATOR_ID,
)
assert excinfo.value.cls == stix2.v21.Relationship
@ -139,19 +140,21 @@ def test_create_relationship_with_positional_args(indicator, malware):
assert rel.id == 'relationship--00000000-0000-4000-8000-000000000005'
@pytest.mark.parametrize("data", [
EXPECTED_RELATIONSHIP,
{
"created": "2016-04-06T20:06:37Z",
"id": "relationship--df7c87eb-75d2-4948-af81-9d49d246f301",
"modified": "2016-04-06T20:06:37Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"spec_version": "2.1",
"type": "relationship"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_RELATIONSHIP,
{
"created": "2016-04-06T20:06:37Z",
"id": "relationship--df7c87eb-75d2-4948-af81-9d49d246f301",
"modified": "2016-04-06T20:06:37Z",
"relationship_type": "indicates",
"source_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"target_ref": "malware--9c4638ec-f1de-4ddb-abf4-1b760417654e",
"spec_version": "2.1",
"type": "relationship",
},
],
)
def test_parse_relationship(data):
rel = stix2.parse(data, version="2.1")

View File

@ -41,7 +41,7 @@ def test_report_example():
object_refs=[
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -61,7 +61,7 @@ def test_report_example_objects_in_object_refs():
object_refs=[
stix2.v21.Indicator(id="indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2", **INDICATOR_KWARGS),
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -82,7 +82,7 @@ def test_report_example_objects_in_object_refs_with_bad_id():
object_refs=[
stix2.v21.Indicator(id="indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2", **INDICATOR_KWARGS),
"campaign-83422c77-904c-4dc1-aff5-5c38f3a2c55c", # the "bad" id, missing a "-"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
)
@ -92,28 +92,30 @@ def test_report_example_objects_in_object_refs_with_bad_id():
assert str(excinfo.value) == "Invalid value for Report 'object_refs': " + stix2.properties.ERROR_INVALID_ID
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"created_by_ref": "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
"description": "A simple report with an indicator and campaign",
"id": "report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
"report_types": [
"campaign"
],
"modified": "2015-12-21T19:59:11.000Z",
"name": "The Black Vine Cyberespionage Group",
"object_refs": [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"
],
"published": "2016-01-20T17:00:00Z",
"spec_version": "2.1",
"type": "report"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2015-12-21T19:59:11.000Z",
"created_by_ref": "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283",
"description": "A simple report with an indicator and campaign",
"id": "report--84e4d88f-44ea-4bcd-bbf3-b2c1c320bcb3",
"report_types": [
"campaign",
],
"modified": "2015-12-21T19:59:11.000Z",
"name": "The Black Vine Cyberespionage Group",
"object_refs": [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
],
"published": "2016-01-20T17:00:00Z",
"spec_version": "2.1",
"type": "report",
},
],
)
def test_parse_report(data):
rept = stix2.parse(data, version="2.1")
@ -123,9 +125,11 @@ def test_parse_report(data):
assert rept.created == dt.datetime(2015, 12, 21, 19, 59, 11, tzinfo=pytz.utc)
assert rept.modified == dt.datetime(2015, 12, 21, 19, 59, 11, tzinfo=pytz.utc)
assert rept.created_by_ref == "identity--a463ffb3-1bd9-4d94-b02d-74e4f1658283"
assert rept.object_refs == ["indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a"]
assert rept.object_refs == [
"indicator--26ffb872-1dd9-446e-b6f5-d58527e5b5d2",
"campaign--83422c77-904c-4dc1-aff5-5c38f3a2c55c",
"relationship--f82356ae-fe6c-437c-9c24-6b64314ae68a",
]
assert rept.description == "A simple report with an indicator and campaign"
assert rept.report_types == ["campaign"]
assert rept.name == "The Black Vine Cyberespionage Group"

View File

@ -41,7 +41,7 @@ def test_sighting_all_required_properties():
created=now,
modified=now,
sighting_of_ref=INDICATOR_ID,
where_sighted_refs=["identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
where_sighted_refs=["identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"],
)
assert str(s) == EXPECTED_SIGHTING
@ -56,7 +56,7 @@ def test_sighting_bad_where_sighted_refs():
created=now,
modified=now,
sighting_of_ref=INDICATOR_ID,
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"]
where_sighted_refs=["malware--8cc7afd6-5455-4d2b-a736-e614ee631d99"],
)
assert excinfo.value.cls == stix2.v21.Sighting
@ -91,20 +91,22 @@ def test_create_sighting_from_objects_rather_than_ids(malware): # noqa: F811
assert rel.id == 'sighting--00000000-0000-4000-8000-000000000003'
@pytest.mark.parametrize("data", [
EXPECTED_SIGHTING,
{
"created": "2016-04-06T20:06:37Z",
"id": "sighting--bfbc19db-ec35-4e45-beed-f8bde2a772fb",
"modified": "2016-04-06T20:06:37Z",
"sighting_of_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"spec_version": "2.1",
"type": "sighting",
"where_sighted_refs": [
"identity--8cc7afd6-5455-4d2b-a736-e614ee631d99"
]
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED_SIGHTING,
{
"created": "2016-04-06T20:06:37Z",
"id": "sighting--bfbc19db-ec35-4e45-beed-f8bde2a772fb",
"modified": "2016-04-06T20:06:37Z",
"sighting_of_ref": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"spec_version": "2.1",
"type": "sighting",
"where_sighted_refs": [
"identity--8cc7afd6-5455-4d2b-a736-e614ee631d99",
],
},
],
)
def test_parse_sighting(data):
sighting = stix2.parse(data, version="2.1")

View File

@ -36,22 +36,24 @@ def test_threat_actor_example():
assert str(threat_actor) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "The Evil Org threat actor group",
"id": "threat-actor--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"threat_actor_types": [
"crime-syndicate"
],
"modified": "2016-04-06T20:03:48.000Z",
"name": "Evil Org",
"spec_version": "2.1",
"type": "threat-actor"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48.000Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"description": "The Evil Org threat actor group",
"id": "threat-actor--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"threat_actor_types": [
"crime-syndicate",
],
"modified": "2016-04-06T20:03:48.000Z",
"name": "Evil Org",
"spec_version": "2.1",
"type": "threat-actor",
},
],
)
def test_parse_threat_actor(data):
actor = stix2.parse(data, version="2.1")

View File

@ -48,21 +48,23 @@ def test_tool_example():
assert str(tool) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"id": "tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"tool_types": [
"remote-access"
],
"modified": "2016-04-06T20:03:48Z",
"name": "VNC",
"spec_version": "2.1",
"type": "tool"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-04-06T20:03:48Z",
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
"id": "tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
"tool_types": [
"remote-access",
],
"modified": "2016-04-06T20:03:48Z",
"name": "VNC",
"spec_version": "2.1",
"type": "tool",
},
],
)
def test_parse_tool(data):
tool = stix2.parse(data, version="2.1")

View File

@ -12,76 +12,90 @@ amsterdam = pytz.timezone('Europe/Amsterdam')
eastern = pytz.timezone('US/Eastern')
@pytest.mark.parametrize('dttm, timestamp', [
(dt.datetime(2017, 1, 1, tzinfo=pytz.utc), '2017-01-01T00:00:00Z'),
(amsterdam.localize(dt.datetime(2017, 1, 1)), '2016-12-31T23:00:00Z'),
(eastern.localize(dt.datetime(2017, 1, 1, 12, 34, 56)), '2017-01-01T17:34:56Z'),
(eastern.localize(dt.datetime(2017, 7, 1)), '2017-07-01T04:00:00Z'),
(dt.datetime(2017, 7, 1), '2017-07-01T00:00:00Z'),
(dt.datetime(2017, 7, 1, 0, 0, 0, 1), '2017-07-01T00:00:00.000001Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='millisecond'), '2017-07-01T00:00:00.000Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='second'), '2017-07-01T00:00:00Z'),
])
@pytest.mark.parametrize(
'dttm, timestamp', [
(dt.datetime(2017, 1, 1, tzinfo=pytz.utc), '2017-01-01T00:00:00Z'),
(amsterdam.localize(dt.datetime(2017, 1, 1)), '2016-12-31T23:00:00Z'),
(eastern.localize(dt.datetime(2017, 1, 1, 12, 34, 56)), '2017-01-01T17:34:56Z'),
(eastern.localize(dt.datetime(2017, 7, 1)), '2017-07-01T04:00:00Z'),
(dt.datetime(2017, 7, 1), '2017-07-01T00:00:00Z'),
(dt.datetime(2017, 7, 1, 0, 0, 0, 1), '2017-07-01T00:00:00.000001Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='millisecond'), '2017-07-01T00:00:00.000Z'),
(stix2.utils.STIXdatetime(2017, 7, 1, 0, 0, 0, 1, precision='second'), '2017-07-01T00:00:00Z'),
],
)
def test_timestamp_formatting(dttm, timestamp):
assert stix2.utils.format_datetime(dttm) == timestamp
@pytest.mark.parametrize('timestamp, dttm', [
(dt.datetime(2017, 1, 1, 0, tzinfo=pytz.utc), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
(dt.date(2017, 1, 1), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00Z', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T02:00:00+2:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
])
@pytest.mark.parametrize(
'timestamp, dttm', [
(dt.datetime(2017, 1, 1, 0, tzinfo=pytz.utc), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
(dt.date(2017, 1, 1), dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00Z', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T02:00:00+2:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
('2017-01-01T00:00:00', dt.datetime(2017, 1, 1, 0, 0, 0, tzinfo=pytz.utc)),
],
)
def test_parse_datetime(timestamp, dttm):
assert stix2.utils.parse_into_datetime(timestamp) == dttm
@pytest.mark.parametrize('timestamp, dttm, precision', [
('2017-01-01T01:02:03.000001', dt.datetime(2017, 1, 1, 1, 2, 3, 0, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.001', dt.datetime(2017, 1, 1, 1, 2, 3, 1000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.1', dt.datetime(2017, 1, 1, 1, 2, 3, 100000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, 450000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, tzinfo=pytz.utc), 'second'),
])
@pytest.mark.parametrize(
'timestamp, dttm, precision', [
('2017-01-01T01:02:03.000001', dt.datetime(2017, 1, 1, 1, 2, 3, 0, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.001', dt.datetime(2017, 1, 1, 1, 2, 3, 1000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.1', dt.datetime(2017, 1, 1, 1, 2, 3, 100000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, 450000, tzinfo=pytz.utc), 'millisecond'),
('2017-01-01T01:02:03.45', dt.datetime(2017, 1, 1, 1, 2, 3, tzinfo=pytz.utc), 'second'),
],
)
def test_parse_datetime_precision(timestamp, dttm, precision):
assert stix2.utils.parse_into_datetime(timestamp, precision) == dttm
@pytest.mark.parametrize('ts', [
'foobar',
1,
])
@pytest.mark.parametrize(
'ts', [
'foobar',
1,
],
)
def test_parse_datetime_invalid(ts):
with pytest.raises(ValueError):
stix2.utils.parse_into_datetime('foobar')
@pytest.mark.parametrize('data', [
{"a": 1},
'{"a": 1}',
StringIO(u'{"a": 1}'),
[("a", 1,)],
])
@pytest.mark.parametrize(
'data', [
{"a": 1},
'{"a": 1}',
StringIO(u'{"a": 1}'),
[("a", 1,)],
],
)
def test_get_dict(data):
assert stix2.utils._get_dict(data)
@pytest.mark.parametrize('data', [
1,
[1],
['a', 1],
"foobar",
])
@pytest.mark.parametrize(
'data', [
1,
[1],
['a', 1],
"foobar",
],
)
def test_get_dict_invalid(data):
with pytest.raises(ValueError):
stix2.utils._get_dict(data)
@pytest.mark.parametrize('stix_id, type', [
('malware--d69c8146-ab35-4d50-8382-6fc80e641d43', 'malware'),
('intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542', 'intrusion-set')
])
@pytest.mark.parametrize(
'stix_id, type', [
('malware--d69c8146-ab35-4d50-8382-6fc80e641d43', 'malware'),
('intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542', 'intrusion-set'),
],
)
def test_get_type_from_id(stix_id, type):
assert stix2.utils.get_type_from_id(stix_id) == type
@ -104,78 +118,86 @@ def test_deduplicate(stix_objs1):
assert "2017-01-27T13:49:53.936Z" in mods
@pytest.mark.parametrize('object, tuple_to_find, expected_index', [
(stix2.v21.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file"
},
"1": {
"type": "ipv4-addr",
"value": "198.51.100.3"
},
"2": {
"type": "network-traffic",
"src_ref": "1",
"protocols": [
"tcp",
"http"
],
"extensions": {
"http-request-ext": {
"request_method": "get",
"request_value": "/download.html",
"request_version": "http/1.1",
"request_header": {
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com"
}
}
}
}
},
), ('1', {"type": "ipv4-addr", "value": "198.51.100.3"}), 1),
({
"type": "x-example",
"id": "x-example--d5413db2-c26c-42e0-b0e0-ec800a310bfb",
"created": "2018-06-11T01:25:22.063Z",
"modified": "2018-06-11T01:25:22.063Z",
"dictionary": {
"key": {
"key_one": "value",
"key_two": "value"
}
}
}, ('key', {'key_one': 'value', 'key_two': 'value'}), 0),
({
"type": "language-content",
"spec_version": "2.1",
"id": "language-content--b86bd89f-98bb-4fa9-8cb2-9ad421da981d",
"created": "2017-02-08T21:31:22.007Z",
"modified": "2017-02-08T21:31:22.007Z",
"object_ref": "campaign--12a111f0-b824-4baf-a224-83b80237a094",
"object_modified": "2017-02-08T21:31:22.007Z",
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall"
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire"
}
}
}, ('fr', {"name": "Attaque Bank 1", "description": "Plus d'informations sur la crise bancaire"}), 1)
])
@pytest.mark.parametrize(
'object, tuple_to_find, expected_index', [
(
stix2.v21.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file",
},
"1": {
"type": "ipv4-addr",
"value": "198.51.100.3",
},
"2": {
"type": "network-traffic",
"src_ref": "1",
"protocols": [
"tcp",
"http",
],
"extensions": {
"http-request-ext": {
"request_method": "get",
"request_value": "/download.html",
"request_version": "http/1.1",
"request_header": {
"Accept-Encoding": "gzip,deflate",
"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113",
"Host": "www.example.com",
},
},
},
},
},
), ('1', {"type": "ipv4-addr", "value": "198.51.100.3"}), 1,
),
(
{
"type": "x-example",
"id": "x-example--d5413db2-c26c-42e0-b0e0-ec800a310bfb",
"created": "2018-06-11T01:25:22.063Z",
"modified": "2018-06-11T01:25:22.063Z",
"dictionary": {
"key": {
"key_one": "value",
"key_two": "value",
},
},
}, ('key', {'key_one': 'value', 'key_two': 'value'}), 0,
),
(
{
"type": "language-content",
"spec_version": "2.1",
"id": "language-content--b86bd89f-98bb-4fa9-8cb2-9ad421da981d",
"created": "2017-02-08T21:31:22.007Z",
"modified": "2017-02-08T21:31:22.007Z",
"object_ref": "campaign--12a111f0-b824-4baf-a224-83b80237a094",
"object_modified": "2017-02-08T21:31:22.007Z",
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall",
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire",
},
},
}, ('fr', {"name": "Attaque Bank 1", "description": "Plus d'informations sur la crise bancaire"}), 1,
),
],
)
def test_find_property_index(object, tuple_to_find, expected_index):
assert stix2.utils.find_property_index(
object,
@ -183,29 +205,35 @@ def test_find_property_index(object, tuple_to_find, expected_index):
) == expected_index
@pytest.mark.parametrize('dict_value, tuple_to_find, expected_index', [
({
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall"
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire"
},
"es": {
"name": "Ataque al Banco",
"description": "Mas informacion sobre el ataque al banco"
}
}
}, ('es', {"name": "Ataque al Banco", "description": "Mas informacion sobre el ataque al banco"}), 1), # Sorted alphabetically
({
'my_list': [
{"key_one": 1},
{"key_two": 2}
]
}, ('key_one', 1), 0)
])
@pytest.mark.parametrize(
'dict_value, tuple_to_find, expected_index', [
(
{
"contents": {
"de": {
"name": "Bank Angriff 1",
"description": "Weitere Informationen über Banküberfall",
},
"fr": {
"name": "Attaque Bank 1",
"description": "Plus d'informations sur la crise bancaire",
},
"es": {
"name": "Ataque al Banco",
"description": "Mas informacion sobre el ataque al banco",
},
},
}, ('es', {"name": "Ataque al Banco", "description": "Mas informacion sobre el ataque al banco"}), 1,
), # Sorted alphabetically
(
{
'my_list': [
{"key_one": 1},
{"key_two": 2},
],
}, ('key_one', 1), 0,
),
],
)
def test_iterate_over_values(dict_value, tuple_to_find, expected_index):
assert stix2.utils._find_property_in_seq(dict_value.values(), *tuple_to_find) == expected_index

View File

@ -39,15 +39,15 @@ def test_making_new_version_with_embedded_object():
campaign_v1 = stix2.v21.Campaign(
external_references=[{
"source_name": "capec",
"external_id": "CAPEC-163"
"external_id": "CAPEC-163",
}],
**CAMPAIGN_MORE_KWARGS
)
campaign_v2 = campaign_v1.new_version(external_references=[{
"source_name": "capec",
"external_id": "CAPEC-164"
}])
"external_id": "CAPEC-164",
}])
assert campaign_v1.id == campaign_v2.id
assert campaign_v1.spec_version == campaign_v2.spec_version
@ -92,15 +92,19 @@ def test_versioning_error_bad_modified_value():
assert excinfo.value.cls == stix2.v21.Campaign
assert excinfo.value.prop_name == "modified"
assert excinfo.value.reason == ("The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.")
assert excinfo.value.reason == (
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior."
)
msg = "Invalid value for {0} '{1}': {2}"
msg = msg.format(stix2.v21.Campaign.__name__, "modified",
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.")
msg = msg.format(
stix2.v21.Campaign.__name__, "modified",
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.",
)
assert str(excinfo.value) == msg
@ -221,11 +225,13 @@ def test_revoke_invalid_cls():
def test_remove_custom_stix_property():
mal = stix2.v21.Malware(name="ColePowers",
malware_types=["rootkit"],
is_family=False,
x_custom="armada",
allow_custom=True)
mal = stix2.v21.Malware(
name="ColePowers",
malware_types=["rootkit"],
is_family=False,
x_custom="armada",
allow_custom=True,
)
mal_nc = stix2.utils.remove_custom_stix(mal)
@ -235,10 +241,12 @@ def test_remove_custom_stix_property():
def test_remove_custom_stix_object():
@stix2.v21.CustomObject("x-animal", [
("species", stix2.properties.StringProperty(required=True)),
("animal_class", stix2.properties.StringProperty()),
])
@stix2.v21.CustomObject(
"x-animal", [
("species", stix2.properties.StringProperty(required=True)),
("animal_class", stix2.properties.StringProperty()),
],
)
class Animal(object):
pass

View File

@ -30,31 +30,35 @@ def test_vulnerability_example():
modified="2016-05-12T08:17:27.000Z",
name="CVE-2016-1234",
external_references=[
stix2.ExternalReference(source_name='cve',
external_id="CVE-2016-1234"),
stix2.ExternalReference(
source_name='cve',
external_id="CVE-2016-1234",
),
],
)
assert str(vulnerability) == EXPECTED
@pytest.mark.parametrize("data", [
EXPECTED,
{
"created": "2016-05-12T08:17:27Z",
"external_references": [
{
"external_id": "CVE-2016-1234",
"source_name": "cve"
}
],
"id": "vulnerability--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"modified": "2016-05-12T08:17:27Z",
"name": "CVE-2016-1234",
"spec_version": "2.1",
"type": "vulnerability"
},
])
@pytest.mark.parametrize(
"data", [
EXPECTED,
{
"created": "2016-05-12T08:17:27Z",
"external_references": [
{
"external_id": "CVE-2016-1234",
"source_name": "cve",
},
],
"id": "vulnerability--0c7b5b88-8ff7-4a4d-aa9d-feb398cd0061",
"modified": "2016-05-12T08:17:27Z",
"name": "CVE-2016-1234",
"spec_version": "2.1",
"type": "vulnerability",
},
],
)
def test_parse_vulnerability(data):
vuln = stix2.parse(data, version="2.1")

View File

@ -1,29 +1,25 @@
import os
import stix2
from stix2.workbench import (AttackPattern, Campaign, CourseOfAction,
ExternalReference, FileSystemSource, Filter,
Identity, Indicator, IntrusionSet, Malware,
MarkingDefinition, ObservedData, Relationship,
Report, StatementMarking, ThreatActor, Tool,
Vulnerability, add_data_source, all_versions,
attack_patterns, campaigns, courses_of_action,
create, get, identities, indicators,
intrusion_sets, malware, observed_data, query,
reports, save, set_default_created,
set_default_creator, set_default_external_refs,
set_default_object_marking_refs, threat_actors,
tools, vulnerabilities)
from stix2.workbench import (
AttackPattern, Campaign, CourseOfAction, ExternalReference,
FileSystemSource, Filter, Identity, Indicator, IntrusionSet, Malware,
MarkingDefinition, ObservedData, Relationship, Report, StatementMarking,
ThreatActor, Tool, Vulnerability, add_data_source, all_versions,
attack_patterns, campaigns, courses_of_action, create, get, identities,
indicators, intrusion_sets, malware, observed_data, query, reports, save,
set_default_created, set_default_creator, set_default_external_refs,
set_default_object_marking_refs, threat_actors, tools, vulnerabilities,
)
from .constants import (ATTACK_PATTERN_ID, ATTACK_PATTERN_KWARGS, CAMPAIGN_ID,
CAMPAIGN_KWARGS, COURSE_OF_ACTION_ID,
COURSE_OF_ACTION_KWARGS, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, INTRUSION_SET_ID,
INTRUSION_SET_KWARGS, MALWARE_ID, MALWARE_KWARGS,
OBSERVED_DATA_ID, OBSERVED_DATA_KWARGS, REPORT_ID,
REPORT_KWARGS, THREAT_ACTOR_ID, THREAT_ACTOR_KWARGS,
TOOL_ID, TOOL_KWARGS, VULNERABILITY_ID,
VULNERABILITY_KWARGS)
from .constants import (
ATTACK_PATTERN_ID, ATTACK_PATTERN_KWARGS, CAMPAIGN_ID, CAMPAIGN_KWARGS,
COURSE_OF_ACTION_ID, COURSE_OF_ACTION_KWARGS, IDENTITY_ID, IDENTITY_KWARGS,
INDICATOR_ID, INDICATOR_KWARGS, INTRUSION_SET_ID, INTRUSION_SET_KWARGS,
MALWARE_ID, MALWARE_KWARGS, OBSERVED_DATA_ID, OBSERVED_DATA_KWARGS,
REPORT_ID, REPORT_KWARGS, THREAT_ACTOR_ID, THREAT_ACTOR_KWARGS, TOOL_ID,
TOOL_KWARGS, VULNERABILITY_ID, VULNERABILITY_KWARGS,
)
def test_workbench_environment():
@ -190,8 +186,10 @@ def test_workbench_related():
def test_workbench_related_with_filters():
malware = Malware(malware_types=["ransomware"], name="CryptorBit",
created_by_ref=IDENTITY_ID, is_family=False)
malware = Malware(
malware_types=["ransomware"], name="CryptorBit",
created_by_ref=IDENTITY_ID, is_family=False,
)
rel = Relationship(malware.id, 'variant-of', MALWARE_ID)
save([malware, rel])
@ -226,8 +224,10 @@ def test_additional_filter():
def test_additional_filters_list():
resp = tools([Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'),
Filter('name', '=', 'Windows Credential Editor')])
resp = tools([
Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'),
Filter('name', '=', 'Windows Credential Editor'),
])
assert len(resp) == 1
@ -250,8 +250,10 @@ def test_default_created_timestamp():
def test_default_external_refs():
ext_ref = ExternalReference(source_name="ACME Threat Intel",
description="Threat report")
ext_ref = ExternalReference(
source_name="ACME Threat Intel",
description="Threat report",
)
set_default_external_refs(ext_ref)
campaign = Campaign(**CAMPAIGN_KWARGS)
@ -261,8 +263,10 @@ def test_default_external_refs():
def test_default_object_marking_refs():
stmt_marking = StatementMarking("Copyright 2016, Example Corp")
mark_def = MarkingDefinition(definition_type="statement",
definition=stmt_marking)
mark_def = MarkingDefinition(
definition_type="statement",
definition=stmt_marking,
)
set_default_object_marking_refs(mark_def)
campaign = Campaign(**CAMPAIGN_KWARGS)
@ -300,7 +304,7 @@ def test_workbench_custom_property_dict_in_observable_extension():
'allow_custom': True,
'sid': 1,
'x_foo': 'bar',
}
},
},
)
observed_data = ObservedData(

View File

@ -7,8 +7,9 @@ import json
from dateutil import parser
import pytz
from .exceptions import (InvalidValueError, RevokeError,
UnmodifiablePropertyError)
from .exceptions import (
InvalidValueError, RevokeError, UnmodifiablePropertyError,
)
# Sentinel value for properties that should be set to the current time.
# We can't use the standard 'default' approach, since if there are multiple
@ -26,8 +27,10 @@ class STIXdatetime(dt.datetime):
precision = kwargs.pop('precision', None)
if isinstance(args[0], dt.datetime): # Allow passing in a datetime object
dttm = args[0]
args = (dttm.year, dttm.month, dttm.day, dttm.hour, dttm.minute,
dttm.second, dttm.microsecond, dttm.tzinfo)
args = (
dttm.year, dttm.month, dttm.day, dttm.hour, dttm.minute,
dttm.second, dttm.microsecond, dttm.tzinfo,
)
# self will be an instance of STIXdatetime, not dt.datetime
self = dt.datetime.__new__(cls, *args, **kwargs)
self.precision = precision
@ -117,8 +120,10 @@ def parse_into_datetime(value, precision=None):
parsed = parser.parse(value)
except (TypeError, ValueError):
# Unknown format
raise ValueError("must be a datetime object, date object, or "
"timestamp string in a recognizable format.")
raise ValueError(
"must be a datetime object, date object, or "
"timestamp string in a recognizable format.",
)
if parsed.tzinfo:
ts = parsed.astimezone(pytz.utc)
else:
@ -250,8 +255,10 @@ def new_version(data, **kwargs):
"""
if not isinstance(data, Mapping):
raise ValueError("cannot create new version of object of this type! "
"Try a dictionary or instance of an SDO or SRO class.")
raise ValueError(
"cannot create new version of object of this type! "
"Try a dictionary or instance of an SDO or SRO class.",
)
unchangable_properties = []
if data.get('revoked'):
@ -276,10 +283,12 @@ def new_version(data, **kwargs):
old_modified_property = parse_into_datetime(data.get('modified'), precision='millisecond')
new_modified_property = parse_into_datetime(kwargs['modified'], precision='millisecond')
if new_modified_property <= old_modified_property:
raise InvalidValueError(cls, 'modified',
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.")
raise InvalidValueError(
cls, 'modified',
"The new modified datetime cannot be before than or equal to the current modified datetime."
"It cannot be equal, as according to STIX 2 specification, objects that are different "
"but have the same id and modified timestamp do not have defined consumer behavior.",
)
new_obj_inner.update(kwargs)
# Exclude properties with a value of 'None' in case data is not an instance of a _STIXBase subclass
return cls(**{k: v for k, v in new_obj_inner.items() if v is not None})
@ -292,8 +301,10 @@ def revoke(data):
A new version of the object with ``revoked`` set to ``True``.
"""
if not isinstance(data, Mapping):
raise ValueError("cannot revoke object of this type! Try a dictionary "
"or instance of an SDO or SRO class.")
raise ValueError(
"cannot revoke object of this type! Try a dictionary "
"or instance of an SDO or SRO class.",
)
if data.get('revoked'):
raise RevokeError("revoke")

View File

@ -2,24 +2,27 @@
# flake8: noqa
from .bundle import Bundle
from .common import (TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking,
ExternalReference, GranularMarking, KillChainPhase,
MarkingDefinition, StatementMarking, TLPMarking)
from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact,
AutonomousSystem, CustomExtension, CustomObservable,
Directory, DomainName, EmailAddress, EmailMessage,
EmailMIMEComponent, File, HTTPRequestExt, ICMPExt,
IPv4Address, IPv6Address, MACAddress, Mutex,
NetworkTraffic, NTFSExt, PDFExt, Process,
RasterImageExt, SocketExt, Software, TCPExt,
UNIXAccountExt, UserAccount, WindowsPEBinaryExt,
WindowsPEOptionalHeaderType, WindowsPESection,
WindowsProcessExt, WindowsRegistryKey,
WindowsRegistryValueType, WindowsServiceExt,
X509Certificate, X509V3ExtenstionsType)
from .sdo import (AttackPattern, Campaign, CourseOfAction, CustomObject,
Identity, Indicator, IntrusionSet, Malware, ObservedData,
Report, ThreatActor, Tool, Vulnerability)
from .common import (
TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, ExternalReference,
GranularMarking, KillChainPhase, MarkingDefinition, StatementMarking,
TLPMarking,
)
from .observables import (
URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
CustomExtension, CustomObservable, Directory, DomainName, EmailAddress,
EmailMessage, EmailMIMEComponent, File, HTTPRequestExt, ICMPExt,
IPv4Address, IPv6Address, MACAddress, Mutex, NetworkTraffic, NTFSExt,
PDFExt, Process, RasterImageExt, SocketExt, Software, TCPExt,
UNIXAccountExt, UserAccount, WindowsPEBinaryExt,
WindowsPEOptionalHeaderType, WindowsPESection, WindowsProcessExt,
WindowsRegistryKey, WindowsRegistryValueType, WindowsServiceExt,
X509Certificate, X509V3ExtenstionsType,
)
from .sdo import (
AttackPattern, Campaign, CourseOfAction, CustomObject, Identity, Indicator,
IntrusionSet, Malware, ObservedData, Report, ThreatActor, Tool,
Vulnerability,
)
from .sro import Relationship, Sighting
OBJ_MAP = {
@ -68,7 +71,7 @@ EXT_MAP = {
'ntfs-ext': NTFSExt,
'pdf-ext': PDFExt,
'raster-image-ext': RasterImageExt,
'windows-pebinary-ext': WindowsPEBinaryExt
'windows-pebinary-ext': WindowsPEBinaryExt,
},
'network-traffic': {
'http-request-ext': HTTPRequestExt,

View File

@ -1,8 +1,9 @@
from collections import OrderedDict
from ..base import _STIXBase
from ..properties import (IDProperty, ListProperty, STIXObjectProperty,
StringProperty, TypeProperty)
from ..properties import (
IDProperty, ListProperty, STIXObjectProperty, StringProperty, TypeProperty,
)
class Bundle(_STIXBase):

View File

@ -5,9 +5,10 @@ from collections import OrderedDict
from ..base import _STIXBase
from ..custom import _custom_marking_builder
from ..markings import _MarkingsMixin
from ..properties import (HashesProperty, IDProperty, ListProperty, Property,
ReferenceProperty, SelectorProperty, StringProperty,
TimestampProperty, TypeProperty)
from ..properties import (
HashesProperty, IDProperty, ListProperty, Property, ReferenceProperty,
SelectorProperty, StringProperty, TimestampProperty, TypeProperty,
)
from ..utils import NOW, _get_dict
@ -59,7 +60,7 @@ class TLPMarking(_STIXBase):
# TODO: don't allow the creation of any other TLPMarkings than the ones below
_type = 'tlp'
_properties = OrderedDict([
('tlp', StringProperty(required=True))
('tlp', StringProperty(required=True)),
])
@ -70,7 +71,7 @@ class StatementMarking(_STIXBase):
_type = 'statement'
_properties = OrderedDict([
('statement', StringProperty(required=True))
('statement', StringProperty(required=True)),
])
def __init__(self, statement=None, **kwargs):
@ -157,26 +158,26 @@ TLP_WHITE = MarkingDefinition(
id='marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9',
created='2017-01-20T00:00:00.000Z',
definition_type='tlp',
definition=TLPMarking(tlp='white')
definition=TLPMarking(tlp='white'),
)
TLP_GREEN = MarkingDefinition(
id='marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da',
created='2017-01-20T00:00:00.000Z',
definition_type='tlp',
definition=TLPMarking(tlp='green')
definition=TLPMarking(tlp='green'),
)
TLP_AMBER = MarkingDefinition(
id='marking-definition--f88d31f6-486f-44da-b317-01333bde0b82',
created='2017-01-20T00:00:00.000Z',
definition_type='tlp',
definition=TLPMarking(tlp='amber')
definition=TLPMarking(tlp='amber'),
)
TLP_RED = MarkingDefinition(
id='marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed',
created='2017-01-20T00:00:00.000Z',
definition_type='tlp',
definition=TLPMarking(tlp='red')
definition=TLPMarking(tlp='red'),
)

View File

@ -11,12 +11,12 @@ import itertools
from ..base import _Extension, _Observable, _STIXBase
from ..custom import _custom_extension_builder, _custom_observable_builder
from ..exceptions import AtLeastOnePropertyError, DependentPropertiesError
from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty,
ExtensionsProperty, FloatProperty, HashesProperty,
HexProperty, IntegerProperty, ListProperty,
ObjectReferenceProperty, StringProperty,
TimestampProperty, TypeProperty)
from ..properties import (
BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty,
HashesProperty, HexProperty, IntegerProperty, ListProperty,
ObjectReferenceProperty, StringProperty, TimestampProperty, TypeProperty,
)
class Artifact(_Observable):
@ -423,34 +423,42 @@ class SocketExt(_Extension):
_type = 'socket-ext'
_properties = OrderedDict([
('address_family', EnumProperty(allowed=[
"AF_UNSPEC",
"AF_INET",
"AF_IPX",
"AF_APPLETALK",
"AF_NETBIOS",
"AF_INET6",
"AF_IRDA",
"AF_BTH",
], required=True)),
(
'address_family', EnumProperty(
allowed=[
"AF_UNSPEC",
"AF_INET",
"AF_IPX",
"AF_APPLETALK",
"AF_NETBIOS",
"AF_INET6",
"AF_IRDA",
"AF_BTH",
], required=True,
),
),
('is_blocking', BooleanProperty()),
('is_listening', BooleanProperty()),
('protocol_family', EnumProperty(allowed=[
"PF_INET",
"PF_IPX",
"PF_APPLETALK",
"PF_INET6",
"PF_AX25",
"PF_NETROM"
])),
(
'protocol_family', EnumProperty(allowed=[
"PF_INET",
"PF_IPX",
"PF_APPLETALK",
"PF_INET6",
"PF_AX25",
"PF_NETROM",
]),
),
('options', DictionaryProperty()),
('socket_type', EnumProperty(allowed=[
"SOCK_STREAM",
"SOCK_DGRAM",
"SOCK_RAW",
"SOCK_RDM",
"SOCK_SEQPACKET",
])),
(
'socket_type', EnumProperty(allowed=[
"SOCK_STREAM",
"SOCK_DGRAM",
"SOCK_RAW",
"SOCK_RDM",
"SOCK_SEQPACKET",
]),
),
('socket_descriptor', IntegerProperty()),
('socket_handle', IntegerProperty()),
])
@ -528,29 +536,35 @@ class WindowsServiceExt(_Extension):
('descriptions', ListProperty(StringProperty)),
('display_name', StringProperty()),
('group_name', StringProperty()),
('start_type', EnumProperty(allowed=[
"SERVICE_AUTO_START",
"SERVICE_BOOT_START",
"SERVICE_DEMAND_START",
"SERVICE_DISABLED",
"SERVICE_SYSTEM_ALERT",
])),
(
'start_type', EnumProperty(allowed=[
"SERVICE_AUTO_START",
"SERVICE_BOOT_START",
"SERVICE_DEMAND_START",
"SERVICE_DISABLED",
"SERVICE_SYSTEM_ALERT",
]),
),
('service_dll_refs', ListProperty(ObjectReferenceProperty(valid_types='file'))),
('service_type', EnumProperty(allowed=[
"SERVICE_KERNEL_DRIVER",
"SERVICE_FILE_SYSTEM_DRIVER",
"SERVICE_WIN32_OWN_PROCESS",
"SERVICE_WIN32_SHARE_PROCESS",
])),
('service_status', EnumProperty(allowed=[
"SERVICE_CONTINUE_PENDING",
"SERVICE_PAUSE_PENDING",
"SERVICE_PAUSED",
"SERVICE_RUNNING",
"SERVICE_START_PENDING",
"SERVICE_STOP_PENDING",
"SERVICE_STOPPED",
])),
(
'service_type', EnumProperty(allowed=[
"SERVICE_KERNEL_DRIVER",
"SERVICE_FILE_SYSTEM_DRIVER",
"SERVICE_WIN32_OWN_PROCESS",
"SERVICE_WIN32_SHARE_PROCESS",
]),
),
(
'service_status', EnumProperty(allowed=[
"SERVICE_CONTINUE_PENDING",
"SERVICE_PAUSE_PENDING",
"SERVICE_PAUSED",
"SERVICE_RUNNING",
"SERVICE_START_PENDING",
"SERVICE_STOP_PENDING",
"SERVICE_STOPPED",
]),
),
])
@ -672,21 +686,23 @@ class WindowsRegistryValueType(_STIXBase):
_properties = OrderedDict([
('name', StringProperty(required=True)),
('data', StringProperty()),
('data_type', EnumProperty(allowed=[
"REG_NONE",
"REG_SZ",
"REG_EXPAND_SZ",
"REG_BINARY",
"REG_DWORD",
"REG_DWORD_BIG_ENDIAN",
"REG_LINK",
"REG_MULTI_SZ",
"REG_RESOURCE_LIST",
"REG_FULL_RESOURCE_DESCRIPTION",
"REG_RESOURCE_REQUIREMENTS_LIST",
"REG_QWORD",
"REG_INVALID_TYPE",
])),
(
'data_type', EnumProperty(allowed=[
"REG_NONE",
"REG_SZ",
"REG_EXPAND_SZ",
"REG_BINARY",
"REG_DWORD",
"REG_DWORD_BIG_ENDIAN",
"REG_LINK",
"REG_MULTI_SZ",
"REG_RESOURCE_LIST",
"REG_FULL_RESOURCE_DESCRIPTION",
"REG_RESOURCE_REQUIREMENTS_LIST",
"REG_QWORD",
"REG_INVALID_TYPE",
]),
),
])
@ -782,7 +798,7 @@ def CustomObservable(type='x-custom-observable', properties=None):
_properties = list(itertools.chain.from_iterable([
[('type', TypeProperty(type))],
properties,
[('extensions', ExtensionsProperty(enclosing_type=type))]
[('extensions', ExtensionsProperty(enclosing_type=type))],
]))
return _custom_observable_builder(cls, type, _properties, '2.0')
return wrapper

View File

@ -6,10 +6,11 @@ import itertools
from ..core import STIXDomainObject
from ..custom import _custom_object_builder
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, ObservableProperty, PatternProperty,
ReferenceProperty, StringProperty, TimestampProperty,
TypeProperty)
from ..properties import (
BooleanProperty, IDProperty, IntegerProperty, ListProperty,
ObservableProperty, PatternProperty, ReferenceProperty, StringProperty,
TimestampProperty, TypeProperty,
)
from ..utils import NOW
from .common import ExternalReference, GranularMarking, KillChainPhase
@ -354,7 +355,7 @@ def CustomObject(type='x-custom-type', properties=None):
('id', IDProperty(type)),
('created_by_ref', ReferenceProperty(type='identity')),
('created', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond'))
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
],
[x for x in properties if not x[0].startswith('x_')],
[
@ -364,7 +365,7 @@ def CustomObject(type='x-custom-type', properties=None):
('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])
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
]))
return _custom_object_builder(cls, type, _properties, '2.0')

View File

@ -3,9 +3,10 @@
from collections import OrderedDict
from ..core import STIXRelationshipObject
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, ReferenceProperty, StringProperty,
TimestampProperty, TypeProperty)
from ..properties import (
BooleanProperty, IDProperty, IntegerProperty, ListProperty,
ReferenceProperty, StringProperty, TimestampProperty, TypeProperty,
)
from ..utils import NOW
from .common import ExternalReference, GranularMarking
@ -34,8 +35,10 @@ class Relationship(STIXRelationshipObject):
])
# Explicitly define the first three kwargs to make readable Relationship declarations.
def __init__(self, source_ref=None, relationship_type=None,
target_ref=None, **kwargs):
def __init__(
self, source_ref=None, relationship_type=None,
target_ref=None, **kwargs
):
# Allow (source_ref, relationship_type, target_ref) as positional args.
if source_ref and not kwargs.get('source_ref'):
kwargs['source_ref'] = source_ref

View File

@ -2,26 +2,27 @@
# flake8: noqa
from .bundle import Bundle
from .common import (TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking,
ExternalReference, GranularMarking, KillChainPhase,
LanguageContent, MarkingDefinition, StatementMarking,
TLPMarking)
from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact,
AutonomousSystem, CustomExtension, CustomObservable,
Directory, DomainName, EmailAddress, EmailMessage,
EmailMIMEComponent, File, HTTPRequestExt, ICMPExt,
IPv4Address, IPv6Address, MACAddress, Mutex,
NetworkTraffic, NTFSExt, PDFExt, Process,
RasterImageExt, SocketExt, Software, TCPExt,
UNIXAccountExt, UserAccount, WindowsPEBinaryExt,
WindowsPEOptionalHeaderType, WindowsPESection,
WindowsProcessExt, WindowsRegistryKey,
WindowsRegistryValueType, WindowsServiceExt,
X509Certificate, X509V3ExtenstionsType)
from .sdo import (AttackPattern, Campaign, CourseOfAction, CustomObject,
Identity, Indicator, IntrusionSet, Location, Malware, Note,
ObservedData, Opinion, Report, ThreatActor, Tool,
Vulnerability)
from .common import (
TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, ExternalReference,
GranularMarking, KillChainPhase, LanguageContent, MarkingDefinition,
StatementMarking, TLPMarking,
)
from .observables import (
URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
CustomExtension, CustomObservable, Directory, DomainName, EmailAddress,
EmailMessage, EmailMIMEComponent, File, HTTPRequestExt, ICMPExt,
IPv4Address, IPv6Address, MACAddress, Mutex, NetworkTraffic, NTFSExt,
PDFExt, Process, RasterImageExt, SocketExt, Software, TCPExt,
UNIXAccountExt, UserAccount, WindowsPEBinaryExt,
WindowsPEOptionalHeaderType, WindowsPESection, WindowsProcessExt,
WindowsRegistryKey, WindowsRegistryValueType, WindowsServiceExt,
X509Certificate, X509V3ExtenstionsType,
)
from .sdo import (
AttackPattern, Campaign, CourseOfAction, CustomObject, Identity, Indicator,
IntrusionSet, Location, Malware, Note, ObservedData, Opinion, Report,
ThreatActor, Tool, Vulnerability,
)
from .sro import Relationship, Sighting
OBJ_MAP = {
@ -74,7 +75,7 @@ EXT_MAP = {
'ntfs-ext': NTFSExt,
'pdf-ext': PDFExt,
'raster-image-ext': RasterImageExt,
'windows-pebinary-ext': WindowsPEBinaryExt
'windows-pebinary-ext': WindowsPEBinaryExt,
},
'network-traffic': {
'http-request-ext': HTTPRequestExt,

Some files were not shown because too many files have changed in this diff Show More