2018-11-28 22:51:00 +01:00
|
|
|
"""Python STIX2 Memory Source/Sink"""
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-07-10 21:43:58 +02:00
|
|
|
import io
|
2018-10-15 23:57:57 +02:00
|
|
|
import itertools
|
2017-07-12 16:58:31 +02:00
|
|
|
import json
|
|
|
|
import os
|
|
|
|
|
2018-11-01 12:57:09 +01:00
|
|
|
from stix2 import v20, v21
|
2017-09-22 17:29:17 +02:00
|
|
|
from stix2.base import _STIXBase
|
2018-06-14 02:09:07 +02:00
|
|
|
from stix2.core import parse
|
2018-03-01 17:27:37 +01:00
|
|
|
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
2018-10-15 23:57:57 +02:00
|
|
|
from stix2.datastore.filters import FilterSet, apply_common_filters
|
2017-07-12 16:58:31 +02:00
|
|
|
|
|
|
|
|
2018-11-01 12:57:09 +01:00
|
|
|
def _add(store, stix_data, allow_custom=True, version=None):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Add STIX objects to MemoryStore/Sink.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Adds STIX objects to an in-memory dictionary for fast lookup.
|
|
|
|
Recursive function, breaks down STIX Bundles and lists.
|
|
|
|
|
|
|
|
Args:
|
2018-11-01 13:17:34 +01:00
|
|
|
store: A MemoryStore, MemorySink or MemorySource object.
|
2017-09-22 17:29:17 +02:00
|
|
|
stix_data (list OR dict OR STIX object): STIX objects to be added
|
2018-11-01 13:17:34 +01:00
|
|
|
allow_custom (bool): Whether to allow custom properties as well unknown
|
|
|
|
custom objects. Note that unknown custom objects cannot be parsed
|
|
|
|
into STIX objects, and will be returned as is. Default: False.
|
2018-11-01 12:57:09 +01:00
|
|
|
version (str): Which STIX2 version to lock the parser to. (e.g. "2.0",
|
|
|
|
"2.1"). If None, the library makes the best effort to figure
|
|
|
|
out the spec representation of the object.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
2017-10-24 15:15:09 +02:00
|
|
|
"""
|
2018-10-15 23:57:57 +02:00
|
|
|
if isinstance(stix_data, list):
|
2017-09-22 17:29:17 +02:00
|
|
|
# STIX objects are in a list- recurse on each object
|
2017-09-01 14:15:50 +02:00
|
|
|
for stix_obj in stix_data:
|
2018-10-15 23:57:57 +02:00
|
|
|
_add(store, stix_obj, allow_custom, version)
|
|
|
|
|
|
|
|
elif stix_data["type"] == "bundle":
|
|
|
|
# adding a json bundle - so just grab STIX objects
|
|
|
|
for stix_obj in stix_data.get("objects", []):
|
|
|
|
_add(store, stix_obj, allow_custom, version)
|
2017-09-29 17:24:19 +02:00
|
|
|
|
2017-09-01 14:15:50 +02:00
|
|
|
else:
|
2018-10-15 23:57:57 +02:00
|
|
|
# Adding a single non-bundle object
|
|
|
|
if isinstance(stix_data, _STIXBase):
|
|
|
|
stix_obj = stix_data
|
|
|
|
else:
|
|
|
|
stix_obj = parse(stix_data, allow_custom, version)
|
|
|
|
|
2018-10-18 02:54:53 +02:00
|
|
|
# Map ID directly to the object, if it is a marking. Otherwise,
|
|
|
|
# map to a family, so we can track multiple versions.
|
|
|
|
if _is_marking(stix_obj):
|
2018-11-01 15:54:58 +01:00
|
|
|
store._data[stix_obj["id"]] = stix_obj
|
2018-10-18 02:54:53 +02:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
else:
|
2018-11-01 15:54:58 +01:00
|
|
|
if stix_obj["id"] in store._data:
|
|
|
|
obj_family = store._data[stix_obj["id"]]
|
2018-10-18 02:54:53 +02:00
|
|
|
else:
|
|
|
|
obj_family = _ObjectFamily()
|
2018-11-01 15:54:58 +01:00
|
|
|
store._data[stix_obj["id"]] = obj_family
|
2018-10-18 02:54:53 +02:00
|
|
|
|
|
|
|
obj_family.add(stix_obj)
|
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
|
2018-10-18 02:54:53 +02:00
|
|
|
def _is_marking(obj_or_id):
|
|
|
|
"""Determines whether the given object or object ID is/is for a marking
|
|
|
|
definition.
|
|
|
|
|
|
|
|
:param obj_or_id: A STIX object or object ID as a string.
|
|
|
|
:return: True if a marking definition, False otherwise.
|
|
|
|
"""
|
|
|
|
|
2018-11-01 15:54:58 +01:00
|
|
|
if isinstance(obj_or_id, (_STIXBase, dict)):
|
|
|
|
id_ = obj_or_id["id"]
|
2018-10-18 02:54:53 +02:00
|
|
|
else:
|
|
|
|
id_ = obj_or_id
|
|
|
|
|
|
|
|
return id_.startswith("marking-definition--")
|
2018-10-15 23:57:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
class _ObjectFamily(object):
|
|
|
|
"""
|
|
|
|
An internal implementation detail of memory sources/sinks/stores.
|
|
|
|
Represents a "family" of STIX objects: all objects with a particular
|
|
|
|
ID. (I.e. all versions.) The latest version is also tracked so that it
|
|
|
|
can be obtained quickly.
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
self.all_versions = {}
|
|
|
|
self.latest_version = None
|
|
|
|
|
|
|
|
def add(self, obj):
|
2018-11-01 15:54:58 +01:00
|
|
|
self.all_versions[obj["modified"]] = obj
|
2018-11-28 17:21:27 +01:00
|
|
|
if (self.latest_version is None or
|
|
|
|
obj["modified"] > self.latest_version["modified"]):
|
2018-10-15 23:57:57 +02:00
|
|
|
self.latest_version = obj
|
|
|
|
|
|
|
|
def __str__(self):
|
2018-11-01 13:17:34 +01:00
|
|
|
return "<<{}; latest={}>>".format(
|
|
|
|
self.all_versions,
|
2018-11-01 15:54:58 +01:00
|
|
|
self.latest_version["modified"],
|
2018-11-01 13:17:34 +01:00
|
|
|
)
|
2018-10-15 23:57:57 +02:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return str(self)
|
2017-09-01 14:15:50 +02:00
|
|
|
|
|
|
|
|
2018-03-01 17:27:37 +01:00
|
|
|
class MemoryStore(DataStoreMixin):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Interface to an in-memory dictionary of STIX objects.
|
|
|
|
|
|
|
|
MemoryStore is a wrapper around a paired MemorySink and MemorySource.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Note: It doesn't make sense to create a MemoryStore by passing
|
|
|
|
in existing MemorySource and MemorySink because there could
|
|
|
|
be data concurrency issues. As well, just as easy to create new MemoryStore.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
stix_data (list OR dict OR STIX object): STIX content to be added
|
2017-11-29 18:03:10 +01:00
|
|
|
allow_custom (bool): whether to allow custom STIX content.
|
|
|
|
Only applied when export/input functions called, i.e.
|
|
|
|
load_from_file() and save_to_file(). Defaults to True.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Attributes:
|
|
|
|
_data (dict): the in-memory dict that holds STIX objects
|
|
|
|
source (MemorySource): MemorySource
|
|
|
|
sink (MemorySink): MemorySink
|
|
|
|
|
2017-07-12 16:58:31 +02:00
|
|
|
"""
|
2018-07-10 21:43:58 +02:00
|
|
|
def __init__(self, stix_data=None, allow_custom=True):
|
2017-09-22 17:29:17 +02:00
|
|
|
self._data = {}
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-07-13 00:03:59 +02:00
|
|
|
if stix_data:
|
2018-11-01 12:57:09 +01:00
|
|
|
_add(self, stix_data, allow_custom)
|
2017-07-13 00:03:59 +02:00
|
|
|
|
2017-11-08 19:53:21 +01:00
|
|
|
super(MemoryStore, self).__init__(
|
2018-07-10 21:43:58 +02:00
|
|
|
source=MemorySource(stix_data=self._data, allow_custom=allow_custom, _store=True),
|
2018-07-13 17:10:05 +02:00
|
|
|
sink=MemorySink(stix_data=self._data, allow_custom=allow_custom, _store=True),
|
2017-11-08 19:53:21 +01:00
|
|
|
)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-11-08 20:01:56 +01:00
|
|
|
def save_to_file(self, *args, **kwargs):
|
2018-02-27 22:53:05 +01:00
|
|
|
"""Write SITX objects from in-memory dictionary to JSON file, as a STIX
|
2018-07-10 21:43:58 +02:00
|
|
|
Bundle. If a directory is given, the Bundle 'id' will be used as
|
|
|
|
filename. Otherwise, the provided value will be used.
|
2018-02-27 22:53:05 +01:00
|
|
|
|
|
|
|
Args:
|
2018-07-10 21:43:58 +02:00
|
|
|
path (str): file path to write STIX data to.
|
|
|
|
encoding (str): The file encoding. Default utf-8.
|
2018-02-27 22:53:05 +01:00
|
|
|
|
|
|
|
"""
|
2017-11-08 20:01:56 +01:00
|
|
|
return self.sink.save_to_file(*args, **kwargs)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-11-08 20:01:56 +01:00
|
|
|
def load_from_file(self, *args, **kwargs):
|
2018-02-27 22:53:05 +01:00
|
|
|
"""Load STIX data from JSON file.
|
|
|
|
|
2018-07-10 21:43:58 +02:00
|
|
|
File format is expected to be a single JSON STIX object or JSON STIX
|
|
|
|
bundle.
|
2018-02-27 22:53:05 +01:00
|
|
|
|
|
|
|
Args:
|
2018-07-10 21:43:58 +02:00
|
|
|
path (str): file path to load STIX data from
|
2018-02-27 22:53:05 +01:00
|
|
|
|
|
|
|
"""
|
2017-11-08 20:01:56 +01:00
|
|
|
return self.source.load_from_file(*args, **kwargs)
|
2017-11-03 02:29:25 +01:00
|
|
|
|
2017-07-12 16:58:31 +02:00
|
|
|
|
|
|
|
class MemorySink(DataSink):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Interface for adding/pushing STIX objects to an in-memory dictionary.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Designed to be paired with a MemorySource, together as the two
|
|
|
|
components of a MemoryStore.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
stix_data (dict OR list): valid STIX 2.0 content in
|
|
|
|
bundle or a list.
|
2018-03-01 17:27:37 +01:00
|
|
|
_store (bool): whether the MemorySink is a part of a MemoryStore,
|
2017-09-22 17:29:17 +02:00
|
|
|
in which case "stix_data" is a direct reference to
|
|
|
|
shared memory with DataSource. Not user supplied
|
2017-11-29 18:03:10 +01:00
|
|
|
allow_custom (bool): whether to allow custom objects/properties
|
|
|
|
when exporting STIX content to file.
|
|
|
|
Default: True.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Attributes:
|
|
|
|
_data (dict): the in-memory dict that holds STIX objects.
|
2018-02-26 22:56:24 +01:00
|
|
|
If part of a MemoryStore, the dict is shared with a MemorySource
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-10-24 15:15:09 +02:00
|
|
|
"""
|
2018-07-10 21:43:58 +02:00
|
|
|
def __init__(self, stix_data=None, allow_custom=True, _store=False):
|
2017-09-01 14:15:50 +02:00
|
|
|
super(MemorySink, self).__init__()
|
2017-11-29 18:03:10 +01:00
|
|
|
self.allow_custom = allow_custom
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-07-13 00:03:59 +02:00
|
|
|
if _store:
|
2017-09-22 17:29:17 +02:00
|
|
|
self._data = stix_data
|
2018-10-15 23:57:57 +02:00
|
|
|
else:
|
|
|
|
self._data = {}
|
|
|
|
if stix_data:
|
2018-11-01 12:57:09 +01:00
|
|
|
_add(self, stix_data, allow_custom)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-07-10 21:43:58 +02:00
|
|
|
def add(self, stix_data):
|
2018-11-01 12:57:09 +01:00
|
|
|
_add(self, stix_data, self.allow_custom)
|
2017-10-24 15:15:09 +02:00
|
|
|
add.__doc__ = _add.__doc__
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-11-01 15:54:58 +01:00
|
|
|
def save_to_file(self, path, encoding="utf-8"):
|
2018-07-10 21:43:58 +02:00
|
|
|
path = os.path.abspath(path)
|
2017-11-29 18:03:10 +01:00
|
|
|
|
2018-11-01 12:57:09 +01:00
|
|
|
all_objs = list(itertools.chain.from_iterable(
|
2018-10-18 02:54:53 +02:00
|
|
|
value.all_versions.values() if isinstance(value, _ObjectFamily)
|
|
|
|
else [value]
|
|
|
|
for value in self._data.values()
|
2018-11-01 12:57:09 +01:00
|
|
|
))
|
2018-07-10 21:43:58 +02:00
|
|
|
|
2018-11-01 15:54:58 +01:00
|
|
|
if any("spec_version" in x for x in all_objs):
|
2018-11-01 12:57:09 +01:00
|
|
|
bundle = v21.Bundle(all_objs, allow_custom=self.allow_custom)
|
2018-07-10 21:43:58 +02:00
|
|
|
else:
|
|
|
|
bundle = v20.Bundle(all_objs, allow_custom=self.allow_custom)
|
|
|
|
|
2018-11-29 19:49:06 +01:00
|
|
|
if path.endswith(".json"):
|
|
|
|
if not os.path.exists(os.path.dirname(path)):
|
|
|
|
os.makedirs(os.path.dirname(path))
|
|
|
|
else:
|
|
|
|
if not os.path.exists(path):
|
|
|
|
os.makedirs(path)
|
2018-07-10 21:43:58 +02:00
|
|
|
|
2018-11-29 19:49:06 +01:00
|
|
|
# if the user only provided a directory, use the bundle id for filename
|
2018-11-01 15:54:58 +01:00
|
|
|
path = os.path.join(path, bundle["id"] + ".json")
|
2017-11-29 18:03:10 +01:00
|
|
|
|
2018-11-01 15:54:58 +01:00
|
|
|
with io.open(path, "w", encoding=encoding) as f:
|
2018-07-10 21:43:58 +02:00
|
|
|
bundle = bundle.serialize(pretty=True, encoding=encoding, ensure_ascii=False)
|
|
|
|
f.write(bundle)
|
2018-11-29 19:49:06 +01:00
|
|
|
|
2018-11-29 16:25:15 +01:00
|
|
|
return path
|
2017-10-24 15:15:09 +02:00
|
|
|
save_to_file.__doc__ = MemoryStore.save_to_file.__doc__
|
2017-07-12 16:58:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
class MemorySource(DataSource):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Interface for searching/retrieving STIX objects from an in-memory
|
|
|
|
dictionary.
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-09-22 17:29:17 +02:00
|
|
|
Designed to be paired with a MemorySink, together as the two
|
|
|
|
components of a MemoryStore.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
stix_data (dict OR list OR STIX object): valid STIX 2.0 content in
|
|
|
|
bundle or list.
|
2018-03-01 17:27:37 +01:00
|
|
|
_store (bool): if the MemorySource is a part of a MemoryStore,
|
2017-09-22 17:29:17 +02:00
|
|
|
in which case "stix_data" is a direct reference to shared
|
|
|
|
memory with DataSink. Not user supplied
|
2017-11-29 18:03:10 +01:00
|
|
|
allow_custom (bool): whether to allow custom objects/properties
|
|
|
|
when importing STIX content from file.
|
|
|
|
Default: True.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Attributes:
|
|
|
|
_data (dict): the in-memory dict that holds STIX objects.
|
2018-02-26 22:56:24 +01:00
|
|
|
If part of a MemoryStore, the dict is shared with a MemorySink
|
2017-09-22 17:29:17 +02:00
|
|
|
|
2017-10-24 15:15:09 +02:00
|
|
|
"""
|
2018-07-10 21:43:58 +02:00
|
|
|
def __init__(self, stix_data=None, allow_custom=True, _store=False):
|
2017-09-01 14:15:50 +02:00
|
|
|
super(MemorySource, self).__init__()
|
2017-11-29 18:03:10 +01:00
|
|
|
self.allow_custom = allow_custom
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-07-13 00:03:59 +02:00
|
|
|
if _store:
|
2017-09-22 17:29:17 +02:00
|
|
|
self._data = stix_data
|
2018-10-15 23:57:57 +02:00
|
|
|
else:
|
|
|
|
self._data = {}
|
|
|
|
if stix_data:
|
2018-11-01 12:57:09 +01:00
|
|
|
_add(self, stix_data, allow_custom)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-11-03 02:29:25 +01:00
|
|
|
def get(self, stix_id, _composite_filters=None):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Retrieve STIX object from in-memory dict via STIX ID.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
2018-04-11 19:36:52 +02:00
|
|
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
2017-09-22 17:29:17 +02:00
|
|
|
CompositeDataSource, not user supplied
|
|
|
|
|
|
|
|
Returns:
|
2018-10-23 20:29:56 +02:00
|
|
|
(STIX object): STIX object that has the supplied ID.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
2017-10-19 00:31:46 +02:00
|
|
|
"""
|
2018-10-15 23:57:57 +02:00
|
|
|
stix_obj = None
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-10-18 02:54:53 +02:00
|
|
|
if _is_marking(stix_id):
|
|
|
|
stix_obj = self._data.get(stix_id)
|
|
|
|
else:
|
|
|
|
object_family = self._data.get(stix_id)
|
|
|
|
if object_family:
|
|
|
|
stix_obj = object_family.latest_version
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
if stix_obj:
|
|
|
|
all_filters = list(
|
|
|
|
itertools.chain(
|
|
|
|
_composite_filters or [],
|
2018-11-01 13:17:34 +01:00
|
|
|
self.filters,
|
|
|
|
),
|
2018-10-15 23:57:57 +02:00
|
|
|
)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
stix_obj = next(apply_common_filters([stix_obj], all_filters), None)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
return stix_obj
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-11-03 02:29:25 +01:00
|
|
|
def all_versions(self, stix_id, _composite_filters=None):
|
2018-07-10 21:43:58 +02:00
|
|
|
"""Retrieve STIX objects from in-memory dict via STIX ID, all versions
|
|
|
|
of it.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Note: Since Memory sources/sinks don't handle multiple versions of a
|
|
|
|
STIX object, this operation is unnecessary. Translate call to get().
|
2017-08-11 14:10:20 +02:00
|
|
|
|
2017-09-01 14:15:50 +02:00
|
|
|
Args:
|
2017-09-22 17:29:17 +02:00
|
|
|
stix_id (str): The STIX ID of the STIX 2 object to retrieve.
|
2018-07-10 21:43:58 +02:00
|
|
|
_composite_filters (FilterSet): collection of filters passed from
|
|
|
|
the parent CompositeDataSource, not user supplied
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-09-01 14:15:50 +02:00
|
|
|
Returns:
|
2018-10-23 20:29:56 +02:00
|
|
|
(list): list of STIX objects that have the supplied ID.
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-09-01 14:15:50 +02:00
|
|
|
"""
|
2018-10-15 23:57:57 +02:00
|
|
|
results = []
|
2018-10-18 02:54:53 +02:00
|
|
|
stix_objs_to_filter = None
|
|
|
|
if _is_marking(stix_id):
|
|
|
|
stix_obj = self._data.get(stix_id)
|
|
|
|
if stix_obj:
|
|
|
|
stix_objs_to_filter = [stix_obj]
|
|
|
|
else:
|
|
|
|
object_family = self._data.get(stix_id)
|
|
|
|
if object_family:
|
|
|
|
stix_objs_to_filter = object_family.all_versions.values()
|
2018-10-15 23:57:57 +02:00
|
|
|
|
2018-10-18 02:54:53 +02:00
|
|
|
if stix_objs_to_filter:
|
2018-10-15 23:57:57 +02:00
|
|
|
all_filters = list(
|
|
|
|
itertools.chain(
|
|
|
|
_composite_filters or [],
|
2018-11-01 13:17:34 +01:00
|
|
|
self.filters,
|
|
|
|
),
|
2018-10-15 23:57:57 +02:00
|
|
|
)
|
2017-11-29 18:03:10 +01:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
results.extend(
|
2018-11-01 13:17:34 +01:00
|
|
|
apply_common_filters(stix_objs_to_filter, all_filters),
|
2018-10-15 23:57:57 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
return results
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2017-11-03 02:29:25 +01:00
|
|
|
def query(self, query=None, _composite_filters=None):
|
2017-10-19 00:31:46 +02:00
|
|
|
"""Search and retrieve STIX objects based on the complete query.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
A "complete query" includes the filters from the query, the filters
|
2017-10-27 21:50:43 +02:00
|
|
|
attached to this MemorySource, and any filters passed from a
|
|
|
|
CompositeDataSource (i.e. _composite_filters).
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Args:
|
|
|
|
query (list): list of filters to search on
|
2018-07-10 21:43:58 +02:00
|
|
|
_composite_filters (FilterSet): collection of filters passed from
|
|
|
|
the CompositeDataSource, not user supplied
|
2017-09-22 17:29:17 +02:00
|
|
|
|
|
|
|
Returns:
|
2018-10-23 20:29:56 +02:00
|
|
|
(list): list of STIX objects that match the supplied query.
|
2017-09-22 17:29:17 +02:00
|
|
|
|
2017-07-12 16:58:31 +02:00
|
|
|
"""
|
2018-04-23 20:12:16 +02:00
|
|
|
query = FilterSet(query)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
|
|
|
# combine all query filters
|
2017-09-29 17:24:19 +02:00
|
|
|
if self.filters:
|
2018-04-11 19:36:52 +02:00
|
|
|
query.add(self.filters)
|
2017-07-12 16:58:31 +02:00
|
|
|
if _composite_filters:
|
2018-04-11 19:36:52 +02:00
|
|
|
query.add(_composite_filters)
|
2017-07-12 16:58:31 +02:00
|
|
|
|
2018-10-15 23:57:57 +02:00
|
|
|
all_objs = itertools.chain.from_iterable(
|
2018-10-18 02:54:53 +02:00
|
|
|
value.all_versions.values() if isinstance(value, _ObjectFamily)
|
|
|
|
else [value]
|
|
|
|
for value in self._data.values()
|
2018-10-15 23:57:57 +02:00
|
|
|
)
|
|
|
|
|
2017-09-01 14:15:50 +02:00
|
|
|
# Apply STIX common property filters.
|
2018-10-15 23:57:57 +02:00
|
|
|
all_data = list(apply_common_filters(all_objs, query))
|
2017-07-12 16:58:31 +02:00
|
|
|
|
|
|
|
return all_data
|
2017-07-13 00:03:59 +02:00
|
|
|
|
2018-07-10 21:43:58 +02:00
|
|
|
def load_from_file(self, file_path):
|
2018-10-15 23:57:57 +02:00
|
|
|
with open(os.path.abspath(file_path), "r") as f:
|
|
|
|
stix_data = json.load(f)
|
2017-11-29 18:03:10 +01:00
|
|
|
|
2018-11-01 12:57:09 +01:00
|
|
|
_add(self, stix_data, self.allow_custom)
|
2017-10-24 15:15:09 +02:00
|
|
|
load_from_file.__doc__ = MemoryStore.load_from_file.__doc__
|