diff --git a/docs/conf.py b/docs/conf.py index 9b1ad5d..51d58f3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,7 +49,7 @@ html_sidebars = { 'navigation.html', 'relations.html', 'searchbox.html', - ] + ], } latex_elements = {} diff --git a/examples/taxii_example.py b/examples/taxii_example.py index 1457770..51ba821 100644 --- a/examples/taxii_example.py +++ b/examples/taxii_example.py @@ -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) diff --git a/setup.py b/setup.py index e911d13..1acf1f5 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,6 @@ setup( 'stix2-patterns', ], extras_require={ - 'taxii': ['taxii2-client'] - } + 'taxii': ['taxii2-client'], + }, ) diff --git a/stix2/__init__.py b/stix2/__init__.py index 5a906fa..e9be3a9 100644 --- a/stix2/__init__.py +++ b/stix2/__init__.py @@ -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__ diff --git a/stix2/base.py b/stix2/base.py index deb5054..fe4c5bd 100644 --- a/stix2/base.py +++ b/stix2/base.py @@ -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. diff --git a/stix2/core.py b/stix2/core.py index 663b3e6..20888a8 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -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} diff --git a/stix2/custom.py b/stix2/custom.py index 87903f7..1c5d017 100644 --- a/stix2/custom.py +++ b/stix2/custom.py @@ -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 diff --git a/stix2/datastore/filesystem.py b/stix2/datastore/filesystem.py index abad2ea..1f8ff13 100644 --- a/stix2/datastore/filesystem.py +++ b/stix2/datastore/filesystem.py @@ -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): diff --git a/stix2/datastore/memory.py b/stix2/datastore/memory.py index 2434530..b18ebb5 100644 --- a/stix2/datastore/memory.py +++ b/stix2/datastore/memory.py @@ -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): diff --git a/stix2/datastore/taxii.py b/stix2/datastore/taxii.py index 7547bd7..dde53dc 100644 --- a/stix2/datastore/taxii.py +++ b/stix2/datastore/taxii.py @@ -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] diff --git a/stix2/environment.py b/stix2/environment.py index 0b861ee..78c1492 100644 --- a/stix2/environment.py +++ b/stix2/environment.py @@ -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: diff --git a/stix2/exceptions.py b/stix2/exceptions.py index 79c5a81..172cc69 100644 --- a/stix2/exceptions.py +++ b/stix2/exceptions.py @@ -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): diff --git a/stix2/markings/__init__.py b/stix2/markings/__init__.py index c8dbdbc..b8f2c6e 100644 --- a/stix2/markings/__init__.py +++ b/stix2/markings/__init__.py @@ -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) diff --git a/stix2/markings/granular_markings.py b/stix2/markings/granular_markings.py index 5f47f41..c8f9fe0 100644 --- a/stix2/markings/granular_markings.py +++ b/stix2/markings/granular_markings.py @@ -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): diff --git a/stix2/markings/utils.py b/stix2/markings/utils.py index 4b0b64d..77f57bb 100644 --- a/stix2/markings/utils.py +++ b/stix2/markings/utils.py @@ -180,7 +180,7 @@ def expand_markings(granular_markings): [ {'marking_ref': marking_ref, 'selectors': [selector]} for selector in selectors - ] + ], ) return expanded diff --git a/stix2/patterns.py b/stix2/patterns.py index 9599a53..9668c2a 100644 --- a/stix2/patterns.py +++ b/stix2/patterns.py @@ -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])) diff --git a/stix2/properties.py b/stix2/properties.py index bcd21f9..6048dd3 100644 --- a/stix2/properties.py +++ b/stix2/properties.py @@ -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 --" @@ -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) diff --git a/stix2/test/v20/conftest.py b/stix2/test/v20/conftest.py index d5f7321..48e4532 100644 --- a/stix2/test/v20/conftest.py +++ b/stix2/test/v20/conftest.py @@ -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] diff --git a/stix2/test/v20/constants.py b/stix2/test/v20/constants.py index 408ee76..8d439f1 100644 --- a/stix2/test/v20/constants.py +++ b/stix2/test/v20/constants.py @@ -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( diff --git a/stix2/test/v20/test_attack_pattern.py b/stix2/test/v20/test_attack_pattern.py index 835f36b..f071d3a 100644 --- a/stix2/test/v20/test_attack_pattern.py +++ b/stix2/test/v20/test_attack_pattern.py @@ -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 diff --git a/stix2/test/v20/test_bundle.py b/stix2/test/v20/test_bundle.py index f9a8971..fee0eff 100644 --- a/stix2/test/v20/test_bundle.py +++ b/stix2/test/v20/test_bundle.py @@ -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", + }, + ], } diff --git a/stix2/test/v20/test_campaign.py b/stix2/test/v20/test_campaign.py index 96d01a5..57dbfd2 100644 --- a/stix2/test/v20/test_campaign.py +++ b/stix2/test/v20/test_campaign.py @@ -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") diff --git a/stix2/test/v20/test_course_of_action.py b/stix2/test/v20/test_course_of_action.py index 9ba0286..d1c0fb7 100644 --- a/stix2/test/v20/test_course_of_action.py +++ b/stix2/test/v20/test_course_of_action.py @@ -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") diff --git a/stix2/test/v20/test_custom.py b/stix2/test/v20/test_custom.py index 17d0c24..5a29873 100644 --- a/stix2/test/v20/test_custom.py +++ b/stix2/test/v20/test_custom.py @@ -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) diff --git a/stix2/test/v20/test_datastore.py b/stix2/test/v20/test_datastore.py index df7ef52..606e5b0 100644 --- a/stix2/test/v20/test_datastore.py +++ b/stix2/test/v20/test_datastore.py @@ -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) diff --git a/stix2/test/v20/test_datastore_composite.py b/stix2/test/v20/test_datastore_composite.py index 3d69953..bd2eb6f 100644 --- a/stix2/test/v20/test_datastore_composite.py +++ b/stix2/test/v20/test_datastore_composite.py @@ -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 ''") + assert str(excinfo.value) == ( + "DataSource (to be added) is not of type " + "stix2.DataSource. DataSource type is ''" + ) 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) diff --git a/stix2/test/v20/test_datastore_filesystem.py b/stix2/test/v20/test_datastore_filesystem.py index 20747f1..47a4eec 100644 --- a/stix2/test/v20/test_datastore_filesystem.py +++ b/stix2/test/v20/test_datastore_filesystem.py @@ -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 diff --git a/stix2/test/v20/test_datastore_filters.py b/stix2/test/v20/test_datastore_filters.py index 0f7b1ec..159685e 100644 --- a/stix2/test/v20/test_datastore_filters.py +++ b/stix2/test/v20/test_datastore_filters.py @@ -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] diff --git a/stix2/test/v20/test_datastore_memory.py b/stix2/test/v20/test_datastore_memory.py index 6d76459..4472674 100644 --- a/stix2/test/v20/test_datastore_memory.py +++ b/stix2/test/v20/test_datastore_memory.py @@ -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 diff --git a/stix2/test/v20/test_datastore_taxii.py b/stix2/test/v20/test_datastore_taxii.py index ccdef91..c984247 100644 --- a/stix2/test/v20/test_datastore_taxii.py +++ b/stix2/test/v20/test_datastore_taxii.py @@ -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) diff --git a/stix2/test/v20/test_environment.py b/stix2/test/v20/test_environment.py index c8a2906..80fb498 100644 --- a/stix2/test/v20/test_environment.py +++ b/stix2/test/v20/test_environment.py @@ -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) diff --git a/stix2/test/v20/test_external_reference.py b/stix2/test/v20/test_external_reference.py index e7226cb..07cf42d 100644 --- a/stix2/test/v20/test_external_reference.py +++ b/stix2/test/v20/test_external_reference.py @@ -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", ) diff --git a/stix2/test/v20/test_granular_markings.py b/stix2/test/v20/test_granular_markings.py index 797e810..b5f2e3d 100644 --- a/stix2/test/v20/test_granular_markings.py +++ b/stix2/test/v20/test_granular_markings.py @@ -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): diff --git a/stix2/test/v20/test_identity.py b/stix2/test/v20/test_identity.py index 9bdc612..4a88a8a 100644 --- a/stix2/test/v20/test_identity.py +++ b/stix2/test/v20/test_identity.py @@ -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" diff --git a/stix2/test/v20/test_indicator.py b/stix2/test/v20/test_indicator.py index df58ba8..f8c3a91 100644 --- a/stix2/test/v20/test_indicator.py +++ b/stix2/test/v20/test_indicator.py @@ -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") diff --git a/stix2/test/v20/test_intrusion_set.py b/stix2/test/v20/test_intrusion_set.py index 1d58403..bf4a7d5 100644 --- a/stix2/test/v20/test_intrusion_set.py +++ b/stix2/test/v20/test_intrusion_set.py @@ -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") diff --git a/stix2/test/v20/test_malware.py b/stix2/test/v20/test_malware.py index 2a88e38..844c7d9 100644 --- a/stix2/test/v20/test_malware.py +++ b/stix2/test/v20/test_malware.py @@ -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") diff --git a/stix2/test/v20/test_markings.py b/stix2/test/v20/test_markings.py index d3a3a1f..c6bdd0e 100644 --- a/stix2/test/v20/test_markings.py +++ b/stix2/test/v20/test_markings.py @@ -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" diff --git a/stix2/test/v20/test_object_markings.py b/stix2/test/v20/test_object_markings.py index 10741be..495c45a 100644 --- a/stix2/test/v20/test_object_markings.py +++ b/stix2/test/v20/test_object_markings.py @@ -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]], diff --git a/stix2/test/v20/test_observed_data.py b/stix2/test/v20/test_observed_data.py index fac767c..41a80d6 100644 --- a/stix2/test/v20/test_observed_data.py +++ b/stix2/test/v20/test_observed_data.py @@ -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 diff --git a/stix2/test/v20/test_pattern_expressions.py b/stix2/test/v20/test_pattern_expressions.py index 14e3774..fa635fe 100644 --- a/stix2/test/v20/test_pattern_expressions.py +++ b/stix2/test/v20/test_pattern_expressions.py @@ -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) diff --git a/stix2/test/v20/test_pickle.py b/stix2/test/v20/test_pickle.py index 399fc7a..6c65d8f 100644 --- a/stix2/test/v20/test_pickle.py +++ b/stix2/test/v20/test_pickle.py @@ -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)) diff --git a/stix2/test/v20/test_properties.py b/stix2/test/v20/test_properties.py index 70f3f92..55c5147 100644 --- a/stix2/test/v20/test_properties.py +++ b/stix2/test/v20/test_properties.py @@ -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) diff --git a/stix2/test/v20/test_relationship.py b/stix2/test/v20/test_relationship.py index 2ee962b..4dc1de8 100644 --- a/stix2/test/v20/test_relationship.py +++ b/stix2/test/v20/test_relationship.py @@ -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") diff --git a/stix2/test/v20/test_report.py b/stix2/test/v20/test_report.py index 2ad756c..072fc95 100644 --- a/stix2/test/v20/test_report.py +++ b/stix2/test/v20/test_report.py @@ -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" diff --git a/stix2/test/v20/test_sighting.py b/stix2/test/v20/test_sighting.py index 0185201..e93ca7e 100644 --- a/stix2/test/v20/test_sighting.py +++ b/stix2/test/v20/test_sighting.py @@ -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") diff --git a/stix2/test/v20/test_threat_actor.py b/stix2/test/v20/test_threat_actor.py index 85135d3..f7ef843 100644 --- a/stix2/test/v20/test_threat_actor.py +++ b/stix2/test/v20/test_threat_actor.py @@ -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") diff --git a/stix2/test/v20/test_tool.py b/stix2/test/v20/test_tool.py index 6444825..e0c7082 100644 --- a/stix2/test/v20/test_tool.py +++ b/stix2/test/v20/test_tool.py @@ -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") diff --git a/stix2/test/v20/test_utils.py b/stix2/test/v20/test_utils.py index e175cd2..1aa85b1 100644 --- a/stix2/test/v20/test_utils.py +++ b/stix2/test/v20/test_utils.py @@ -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 diff --git a/stix2/test/v20/test_versioning.py b/stix2/test/v20/test_versioning.py index 2c560ed..9974e42 100644 --- a/stix2/test/v20/test_versioning.py +++ b/stix2/test/v20/test_versioning.py @@ -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 diff --git a/stix2/test/v20/test_vulnerability.py b/stix2/test/v20/test_vulnerability.py index 2266bb7..7ce05ef 100644 --- a/stix2/test/v20/test_vulnerability.py +++ b/stix2/test/v20/test_vulnerability.py @@ -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") diff --git a/stix2/test/v20/test_workbench.py b/stix2/test/v20/test_workbench.py index d50a76d..8123e41 100644 --- a/stix2/test/v20/test_workbench.py +++ b/stix2/test/v20/test_workbench.py @@ -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( diff --git a/stix2/test/v21/conftest.py b/stix2/test/v21/conftest.py index 491a982..dea29ca 100644 --- a/stix2/test/v21/conftest.py +++ b/stix2/test/v21/conftest.py @@ -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] diff --git a/stix2/test/v21/constants.py b/stix2/test/v21/constants.py index 9b1fd23..d90b25c 100644 --- a/stix2/test/v21/constants.py +++ b/stix2/test/v21/constants.py @@ -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( diff --git a/stix2/test/v21/test_attack_pattern.py b/stix2/test/v21/test_attack_pattern.py index cb73767..9c13a12 100644 --- a/stix2/test/v21/test_attack_pattern.py +++ b/stix2/test/v21/test_attack_pattern.py @@ -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 diff --git a/stix2/test/v21/test_bundle.py b/stix2/test/v21/test_bundle.py index 494dd7f..2657958 100644 --- a/stix2/test/v21/test_bundle.py +++ b/stix2/test/v21/test_bundle.py @@ -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", + }, + ], } diff --git a/stix2/test/v21/test_campaign.py b/stix2/test/v21/test_campaign.py index 32b6c1f..ad7e753 100644 --- a/stix2/test/v21/test_campaign.py +++ b/stix2/test/v21/test_campaign.py @@ -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") diff --git a/stix2/test/v21/test_confidence.py b/stix2/test/v21/test_confidence.py index b4146a5..a3044f3 100644 --- a/stix2/test/v21/test_confidence.py +++ b/stix2/test/v21/test_confidence.py @@ -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) diff --git a/stix2/test/v21/test_course_of_action.py b/stix2/test/v21/test_course_of_action.py index e59273a..73e8eca 100644 --- a/stix2/test/v21/test_course_of_action.py +++ b/stix2/test/v21/test_course_of_action.py @@ -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") diff --git a/stix2/test/v21/test_custom.py b/stix2/test/v21/test_custom.py index c5d8c5f..807e158 100644 --- a/stix2/test/v21/test_custom.py +++ b/stix2/test/v21/test_custom.py @@ -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) diff --git a/stix2/test/v21/test_datastore.py b/stix2/test/v21/test_datastore.py index 0374ac9..8a4bcdb 100644 --- a/stix2/test/v21/test_datastore.py +++ b/stix2/test/v21/test_datastore.py @@ -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) diff --git a/stix2/test/v21/test_datastore_composite.py b/stix2/test/v21/test_datastore_composite.py index c4f39a3..39c7c48 100644 --- a/stix2/test/v21/test_datastore_composite.py +++ b/stix2/test/v21/test_datastore_composite.py @@ -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 ''") + assert str(excinfo.value) == ( + "DataSource (to be added) is not of type " + "stix2.DataSource. DataSource type is ''" + ) 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) diff --git a/stix2/test/v21/test_datastore_filesystem.py b/stix2/test/v21/test_datastore_filesystem.py index af51eed..6954eb1 100644 --- a/stix2/test/v21/test_datastore_filesystem.py +++ b/stix2/test/v21/test_datastore_filesystem.py @@ -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 diff --git a/stix2/test/v21/test_datastore_filters.py b/stix2/test/v21/test_datastore_filters.py index c1fab36..dbd15fb 100644 --- a/stix2/test/v21/test_datastore_filters.py +++ b/stix2/test/v21/test_datastore_filters.py @@ -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] diff --git a/stix2/test/v21/test_datastore_memory.py b/stix2/test/v21/test_datastore_memory.py index 9078b51..5233d69 100644 --- a/stix2/test/v21/test_datastore_memory.py +++ b/stix2/test/v21/test_datastore_memory.py @@ -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 diff --git a/stix2/test/v21/test_datastore_taxii.py b/stix2/test/v21/test_datastore_taxii.py index f3c30cc..0ba27b1 100644 --- a/stix2/test/v21/test_datastore_taxii.py +++ b/stix2/test/v21/test_datastore_taxii.py @@ -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) diff --git a/stix2/test/v21/test_environment.py b/stix2/test/v21/test_environment.py index 0bfed83..e1b3157 100644 --- a/stix2/test/v21/test_environment.py +++ b/stix2/test/v21/test_environment.py @@ -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) diff --git a/stix2/test/v21/test_external_reference.py b/stix2/test/v21/test_external_reference.py index 27929c2..d192a11 100644 --- a/stix2/test/v21/test_external_reference.py +++ b/stix2/test/v21/test_external_reference.py @@ -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", ) diff --git a/stix2/test/v21/test_granular_markings.py b/stix2/test/v21/test_granular_markings.py index 8528157..9f7234e 100644 --- a/stix2/test/v21/test_granular_markings.py +++ b/stix2/test/v21/test_granular_markings.py @@ -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): diff --git a/stix2/test/v21/test_identity.py b/stix2/test/v21/test_identity.py index 0a3399b..da99de4 100644 --- a/stix2/test/v21/test_identity.py +++ b/stix2/test/v21/test_identity.py @@ -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" diff --git a/stix2/test/v21/test_indicator.py b/stix2/test/v21/test_indicator.py index 1effd06..628bdff 100644 --- a/stix2/test/v21/test_indicator.py +++ b/stix2/test/v21/test_indicator.py @@ -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") diff --git a/stix2/test/v21/test_intrusion_set.py b/stix2/test/v21/test_intrusion_set.py index cc650ad..d87780c 100644 --- a/stix2/test/v21/test_intrusion_set.py +++ b/stix2/test/v21/test_intrusion_set.py @@ -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) diff --git a/stix2/test/v21/test_language_content.py b/stix2/test/v21/test_language_content.py index 093b8e4..4f541e0 100644 --- a/stix2/test/v21/test_language_content.py +++ b/stix2/test/v21/test_language_content.py @@ -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') diff --git a/stix2/test/v21/test_location.py b/stix2/test/v21/test_location.py index 0fa61f6..b5e781b 100644 --- a/stix2/test/v21/test_location.py +++ b/stix2/test/v21/test_location.py @@ -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") diff --git a/stix2/test/v21/test_malware.py b/stix2/test/v21/test_malware.py index 8621456..cf113da 100644 --- a/stix2/test/v21/test_malware.py +++ b/stix2/test/v21/test_malware.py @@ -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) diff --git a/stix2/test/v21/test_markings.py b/stix2/test/v21/test_markings.py index 7dbb321..4fb6203 100644 --- a/stix2/test/v21/test_markings.py +++ b/stix2/test/v21/test_markings.py @@ -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" diff --git a/stix2/test/v21/test_note.py b/stix2/test/v21/test_note.py index 86c11ea..a9594cf 100644 --- a/stix2/test/v21/test_note.py +++ b/stix2/test/v21/test_note.py @@ -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") diff --git a/stix2/test/v21/test_object_markings.py b/stix2/test/v21/test_object_markings.py index 0a1abb4..d43aad5 100644 --- a/stix2/test/v21/test_object_markings.py +++ b/stix2/test/v21/test_object_markings.py @@ -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]], diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py index 1faa019..a37bec3 100644 --- a/stix2/test/v21/test_observed_data.py +++ b/stix2/test/v21/test_observed_data.py @@ -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 diff --git a/stix2/test/v21/test_opinion.py b/stix2/test/v21/test_opinion.py index c82e1cf..38001f3 100644 --- a/stix2/test/v21/test_opinion.py +++ b/stix2/test/v21/test_opinion.py @@ -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") diff --git a/stix2/test/v21/test_pattern_expressions.py b/stix2/test/v21/test_pattern_expressions.py index 14e3774..fa635fe 100644 --- a/stix2/test/v21/test_pattern_expressions.py +++ b/stix2/test/v21/test_pattern_expressions.py @@ -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) diff --git a/stix2/test/v21/test_pickle.py b/stix2/test/v21/test_pickle.py index b573d7a..0dc1c4c 100644 --- a/stix2/test/v21/test_pickle.py +++ b/stix2/test/v21/test_pickle.py @@ -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)) diff --git a/stix2/test/v21/test_properties.py b/stix2/test/v21/test_properties.py index 3ad7126..9d53663 100644 --- a/stix2/test/v21/test_properties.py +++ b/stix2/test/v21/test_properties.py @@ -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) diff --git a/stix2/test/v21/test_relationship.py b/stix2/test/v21/test_relationship.py index fe76f17..a822a48 100644 --- a/stix2/test/v21/test_relationship.py +++ b/stix2/test/v21/test_relationship.py @@ -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") diff --git a/stix2/test/v21/test_report.py b/stix2/test/v21/test_report.py index 8b3f222..baf3911 100644 --- a/stix2/test/v21/test_report.py +++ b/stix2/test/v21/test_report.py @@ -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" diff --git a/stix2/test/v21/test_sighting.py b/stix2/test/v21/test_sighting.py index 79f3031..8fcbb6d 100644 --- a/stix2/test/v21/test_sighting.py +++ b/stix2/test/v21/test_sighting.py @@ -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") diff --git a/stix2/test/v21/test_threat_actor.py b/stix2/test/v21/test_threat_actor.py index a89e6cd..8ca31f1 100644 --- a/stix2/test/v21/test_threat_actor.py +++ b/stix2/test/v21/test_threat_actor.py @@ -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") diff --git a/stix2/test/v21/test_tool.py b/stix2/test/v21/test_tool.py index 47a04d7..9258a23 100644 --- a/stix2/test/v21/test_tool.py +++ b/stix2/test/v21/test_tool.py @@ -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") diff --git a/stix2/test/v21/test_utils.py b/stix2/test/v21/test_utils.py index 1f8d8e2..96a06d3 100644 --- a/stix2/test/v21/test_utils.py +++ b/stix2/test/v21/test_utils.py @@ -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 diff --git a/stix2/test/v21/test_versioning.py b/stix2/test/v21/test_versioning.py index dbf0b4f..d11fb4f 100644 --- a/stix2/test/v21/test_versioning.py +++ b/stix2/test/v21/test_versioning.py @@ -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 diff --git a/stix2/test/v21/test_vulnerability.py b/stix2/test/v21/test_vulnerability.py index 1f5b342..9c618e5 100644 --- a/stix2/test/v21/test_vulnerability.py +++ b/stix2/test/v21/test_vulnerability.py @@ -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") diff --git a/stix2/test/v21/test_workbench.py b/stix2/test/v21/test_workbench.py index 25c7f48..6892c84 100644 --- a/stix2/test/v21/test_workbench.py +++ b/stix2/test/v21/test_workbench.py @@ -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( diff --git a/stix2/utils.py b/stix2/utils.py index a5efb47..fab8a2d 100644 --- a/stix2/utils.py +++ b/stix2/utils.py @@ -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") diff --git a/stix2/v20/__init__.py b/stix2/v20/__init__.py index 8fb7182..44c06c4 100644 --- a/stix2/v20/__init__.py +++ b/stix2/v20/__init__.py @@ -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, diff --git a/stix2/v20/bundle.py b/stix2/v20/bundle.py index a945063..f096b2c 100644 --- a/stix2/v20/bundle.py +++ b/stix2/v20/bundle.py @@ -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): diff --git a/stix2/v20/common.py b/stix2/v20/common.py index 1756233..85270d1 100644 --- a/stix2/v20/common.py +++ b/stix2/v20/common.py @@ -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'), ) diff --git a/stix2/v20/observables.py b/stix2/v20/observables.py index 5bae00e..0e7c4a0 100644 --- a/stix2/v20/observables.py +++ b/stix2/v20/observables.py @@ -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 diff --git a/stix2/v20/sdo.py b/stix2/v20/sdo.py index ca96c26..cf4ee50 100644 --- a/stix2/v20/sdo.py +++ b/stix2/v20/sdo.py @@ -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') diff --git a/stix2/v20/sro.py b/stix2/v20/sro.py index ffe81d3..9abb38a 100644 --- a/stix2/v20/sro.py +++ b/stix2/v20/sro.py @@ -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 diff --git a/stix2/v21/__init__.py b/stix2/v21/__init__.py index 83d554a..9101e7e 100644 --- a/stix2/v21/__init__.py +++ b/stix2/v21/__init__.py @@ -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, diff --git a/stix2/v21/bundle.py b/stix2/v21/bundle.py index 766e34a..aba81d5 100644 --- a/stix2/v21/bundle.py +++ b/stix2/v21/bundle.py @@ -1,8 +1,9 @@ from collections import OrderedDict from ..base import _STIXBase -from ..properties import (IDProperty, ListProperty, STIXObjectProperty, - TypeProperty) +from ..properties import ( + IDProperty, ListProperty, STIXObjectProperty, TypeProperty, +) class Bundle(_STIXBase): diff --git a/stix2/v21/common.py b/stix2/v21/common.py index 8c27996..666fea5 100644 --- a/stix2/v21/common.py +++ b/stix2/v21/common.py @@ -5,10 +5,11 @@ from collections import OrderedDict from ..base import _STIXBase from ..custom import _custom_marking_builder from ..markings import _MarkingsMixin -from ..properties import (BooleanProperty, DictionaryProperty, HashesProperty, - IDProperty, ListProperty, Property, - ReferenceProperty, SelectorProperty, StringProperty, - TimestampProperty, TypeProperty) +from ..properties import ( + BooleanProperty, DictionaryProperty, HashesProperty, IDProperty, + ListProperty, Property, ReferenceProperty, SelectorProperty, + StringProperty, TimestampProperty, TypeProperty, +) from ..utils import NOW, _get_dict @@ -95,7 +96,7 @@ class TLPMarking(_STIXBase): _type = 'tlp' _properties = OrderedDict([ - ('tlp', Property(required=True)) + ('tlp', Property(required=True)), ]) @@ -107,7 +108,7 @@ class StatementMarking(_STIXBase): _type = 'statement' _properties = OrderedDict([ - ('statement', StringProperty(required=True)) + ('statement', StringProperty(required=True)), ]) def __init__(self, statement=None, **kwargs): @@ -196,26 +197,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'), ) diff --git a/stix2/v21/observables.py b/stix2/v21/observables.py index 9dc1902..4b863cf 100644 --- a/stix2/v21/observables.py +++ b/stix2/v21/observables.py @@ -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): @@ -444,34 +444,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(spec_version='2.1')), - ('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()), ]) @@ -553,29 +561,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", + ]), + ), ]) @@ -704,21 +718,23 @@ class WindowsRegistryValueType(_STIXBase): _properties = OrderedDict([ ('name', StringProperty()), ('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", + ]), + ), ]) @@ -817,7 +833,7 @@ def CustomObservable(type='x-custom-observable', properties=None): _properties = list(itertools.chain.from_iterable([ [('type', TypeProperty(type))], properties, - [('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))] + [('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))], ])) return _custom_observable_builder(cls, type, _properties, '2.1') return wrapper diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py index 3e6e1a5..24206b8 100644 --- a/stix2/v21/sdo.py +++ b/stix2/v21/sdo.py @@ -6,12 +6,12 @@ import itertools from ..base import _STIXBase from ..core import STIXDomainObject from ..custom import _custom_object_builder -from ..properties import (BooleanProperty, DictionaryProperty, - EmbeddedObjectProperty, EnumProperty, FloatProperty, - IDProperty, IntegerProperty, ListProperty, - ObservableProperty, PatternProperty, - ReferenceProperty, StringProperty, TimestampProperty, - TypeProperty) +from ..properties import ( + BooleanProperty, DictionaryProperty, EmbeddedObjectProperty, EnumProperty, + FloatProperty, IDProperty, IntegerProperty, ListProperty, + ObservableProperty, PatternProperty, ReferenceProperty, StringProperty, + TimestampProperty, TypeProperty, +) from ..utils import NOW from .common import ExternalReference, GranularMarking, KillChainPhase @@ -233,7 +233,7 @@ class AnalysisType(_STIXBase): ('end_time', TimestampProperty()), ('analysis_tools', ObservableProperty(spec_version='2.1')), ('analysis_environment', DictionaryProperty(spec_version='2.1')), - ('results', DictionaryProperty(spec_version='2.1', required=True)) + ('results', DictionaryProperty(spec_version='2.1', required=True)), ]) @@ -246,7 +246,7 @@ class AVResultsType(_STIXBase): ('submitted', TimestampProperty()), ('scanned', TimestampProperty()), ('result', StringProperty()), - ('details', StringProperty()) + ('details', StringProperty()), ]) @@ -285,7 +285,7 @@ class Malware(STIXDomainObject): ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type='marking-definition'))), - ('granular_markings', ListProperty(GranularMarking)) + ('granular_markings', ListProperty(GranularMarking)), ]) @@ -368,13 +368,17 @@ class Opinion(STIXDomainObject): ('description', StringProperty()), ('authors', ListProperty(StringProperty)), ('object_refs', ListProperty(ReferenceProperty, required=True)), - ('opinion', EnumProperty(allowed=[ - 'strongly-disagree', - 'disagree', - 'neutral', - 'agree', - 'strongly-agree' - ], required=True)), + ( + 'opinion', EnumProperty( + allowed=[ + 'strongly-disagree', + 'disagree', + 'neutral', + 'agree', + 'strongly-agree', + ], required=True, + ), + ), ('revoked', BooleanProperty(default=lambda: False)), ('labels', ListProperty(StringProperty)), ('confidence', IntegerProperty()), @@ -553,7 +557,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.1') diff --git a/stix2/v21/sro.py b/stix2/v21/sro.py index 266a222..8373acb 100644 --- a/stix2/v21/sro.py +++ b/stix2/v21/sro.py @@ -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 @@ -38,8 +39,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 diff --git a/stix2/workbench.py b/stix2/workbench.py index 81f8563..4e1ece1 100644 --- a/stix2/workbench.py +++ b/stix2/workbench.py @@ -33,21 +33,23 @@ from . import Report as _Report from . import ThreatActor as _ThreatActor from . import Tool as _Tool from . import Vulnerability as _Vulnerability -from . import (AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem, # noqa: F401 - Bundle, CustomExtension, CustomMarking, CustomObservable, - Directory, DomainName, EmailAddress, EmailMessage, - EmailMIMEComponent, Environment, ExternalReference, File, - FileSystemSource, Filter, GranularMarking, HTTPRequestExt, - ICMPExt, IPv4Address, IPv6Address, KillChainPhase, MACAddress, - MarkingDefinition, MemoryStore, Mutex, NetworkTraffic, NTFSExt, - parse_observable, PDFExt, Process, RasterImageExt, Relationship, - Sighting, SocketExt, Software, StatementMarking, - TAXIICollectionSource, TCPExt, TLP_AMBER, TLP_GREEN, TLP_RED, - TLP_WHITE, TLPMarking, UNIXAccountExt, URL, UserAccount, - WindowsPEBinaryExt, WindowsPEOptionalHeaderType, - WindowsPESection, WindowsProcessExt, WindowsRegistryKey, - WindowsRegistryValueType, WindowsServiceExt, X509Certificate, - X509V3ExtenstionsType) +from . import ( # noqa: F401 + AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem, + Bundle, CustomExtension, CustomMarking, CustomObservable, + Directory, DomainName, EmailAddress, EmailMessage, + EmailMIMEComponent, Environment, ExternalReference, File, + FileSystemSource, Filter, GranularMarking, HTTPRequestExt, + ICMPExt, IPv4Address, IPv6Address, KillChainPhase, MACAddress, + MarkingDefinition, MemoryStore, Mutex, NetworkTraffic, NTFSExt, + parse_observable, PDFExt, Process, RasterImageExt, Relationship, + Sighting, SocketExt, Software, StatementMarking, + TAXIICollectionSource, TCPExt, TLP_AMBER, TLP_GREEN, TLP_RED, + TLP_WHITE, TLPMarking, UNIXAccountExt, URL, UserAccount, + WindowsPEBinaryExt, WindowsPEOptionalHeaderType, + WindowsPESection, WindowsProcessExt, WindowsRegistryKey, + WindowsRegistryValueType, WindowsServiceExt, X509Certificate, + X509V3ExtenstionsType +) from .datastore.filters import FilterSet # Use an implicit MemoryStore @@ -75,9 +77,11 @@ add_data_sources = _environ.source.add_data_sources # Wrap SDOs with helper functions -STIX_OBJS = [_AttackPattern, _Campaign, _CourseOfAction, _Identity, - _Indicator, _IntrusionSet, _Malware, _ObservedData, _Report, - _ThreatActor, _Tool, _Vulnerability] +STIX_OBJS = [ + _AttackPattern, _Campaign, _CourseOfAction, _Identity, + _Indicator, _IntrusionSet, _Malware, _ObservedData, _Report, + _ThreatActor, _Tool, _Vulnerability, +] STIX_OBJ_DOCS = """ @@ -93,9 +97,11 @@ STIX_OBJ_DOCS = """ {} -""".format(_environ.creator_of.__doc__, - _environ.relationships.__doc__, - _environ.related_to.__doc__) +""".format( + _environ.creator_of.__doc__, + _environ.relationships.__doc__, + _environ.related_to.__doc__ +) def _created_by_wrapper(self, *args, **kwargs): @@ -143,7 +149,7 @@ def _setup_workbench(): for obj_type in STIX_OBJS: new_class_dict = { '__new__': _constructor_wrapper(obj_type), - '__doc__': 'Workbench wrapper around the `{0} `__ object. {1}'.format(obj_type.__name__, STIX_OBJ_DOCS) + '__doc__': 'Workbench wrapper around the `{0} `__ object. {1}'.format(obj_type.__name__, STIX_OBJ_DOCS), } new_class = type(obj_type.__name__, (), new_class_dict)