WIP - just at stash point
parent
e92db2417a
commit
27647091a5
|
@ -16,7 +16,7 @@ import uuid
|
||||||
|
|
||||||
from six import with_metaclass
|
from six import with_metaclass
|
||||||
|
|
||||||
from stix2.datastore.filters import Filter
|
from stix2.datastore.filters import Filter, FilterSet
|
||||||
from stix2.utils import deduplicate
|
from stix2.utils import deduplicate
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,13 +220,13 @@ class DataSource(with_metaclass(ABCMeta)):
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
id (str): A unique UUIDv4 to identify this DataSource.
|
id (str): A unique UUIDv4 to identify this DataSource.
|
||||||
filters (set): A collection of filters attached to this DataSource.
|
filters (FilterSet): A collection of filters attached to this DataSource.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(DataSource, self).__init__()
|
super(DataSource, self).__init__()
|
||||||
self.id = make_id()
|
self.id = make_id()
|
||||||
self.filters = set()
|
self.filters = FilterSet()
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get(self, stix_id):
|
def get(self, stix_id):
|
||||||
|
@ -420,7 +420,7 @@ class CompositeDataSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): the id of the STIX object to retrieve.
|
stix_id (str): the id of the STIX object to retrieve.
|
||||||
_composite_filters (list): a list of filters passed from a
|
_composite_filters (FilterSet): a collection of filters passed from a
|
||||||
CompositeDataSource (i.e. if this CompositeDataSource is attached
|
CompositeDataSource (i.e. if this CompositeDataSource is attached
|
||||||
to another parent CompositeDataSource), not user supplied.
|
to another parent CompositeDataSource), not user supplied.
|
||||||
|
|
||||||
|
@ -432,11 +432,12 @@ class CompositeDataSource(DataSource):
|
||||||
raise AttributeError('CompositeDataSource has no data sources')
|
raise AttributeError('CompositeDataSource has no data sources')
|
||||||
|
|
||||||
all_data = []
|
all_data = []
|
||||||
all_filters = set()
|
all_filters = FilterSet()
|
||||||
all_filters.update(self.filters)
|
|
||||||
|
all_filters.add(self.filters)
|
||||||
|
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
all_filters.update(_composite_filters)
|
all_filters.add(_composite_filters)
|
||||||
|
|
||||||
# for every configured Data Source, call its retrieve handler
|
# for every configured Data Source, call its retrieve handler
|
||||||
for ds in self.data_sources:
|
for ds in self.data_sources:
|
||||||
|
@ -466,7 +467,7 @@ class CompositeDataSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): id of the STIX objects to retrieve.
|
stix_id (str): id of the STIX objects to retrieve.
|
||||||
_composite_filters (list): a list of filters passed from a
|
_composite_filters (FilterSet): a collection of filters passed from a
|
||||||
CompositeDataSource (i.e. if this CompositeDataSource is
|
CompositeDataSource (i.e. if this CompositeDataSource is
|
||||||
attached to a parent CompositeDataSource), not user supplied.
|
attached to a parent CompositeDataSource), not user supplied.
|
||||||
|
|
||||||
|
@ -478,12 +479,12 @@ class CompositeDataSource(DataSource):
|
||||||
raise AttributeError('CompositeDataSource has no data sources')
|
raise AttributeError('CompositeDataSource has no data sources')
|
||||||
|
|
||||||
all_data = []
|
all_data = []
|
||||||
all_filters = set()
|
all_filters = FilterSet()
|
||||||
|
|
||||||
all_filters.update(self.filters)
|
all_filters.add(self.filters)
|
||||||
|
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
all_filters.update(_composite_filters)
|
all_filters.add(_composite_filters)
|
||||||
|
|
||||||
# retrieve STIX objects from all configured data sources
|
# retrieve STIX objects from all configured data sources
|
||||||
for ds in self.data_sources:
|
for ds in self.data_sources:
|
||||||
|
@ -505,7 +506,7 @@ class CompositeDataSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query (list): list of filters to search on.
|
query (list): list of filters to search on.
|
||||||
_composite_filters (list): a list of filters passed from a
|
_composite_filters (FilterSet): a collection of filters passed from a
|
||||||
CompositeDataSource (i.e. if this CompositeDataSource is
|
CompositeDataSource (i.e. if this CompositeDataSource is
|
||||||
attached to a parent CompositeDataSource), not user supplied.
|
attached to a parent CompositeDataSource), not user supplied.
|
||||||
|
|
||||||
|
@ -517,17 +518,17 @@ class CompositeDataSource(DataSource):
|
||||||
raise AttributeError('CompositeDataSource has no data sources')
|
raise AttributeError('CompositeDataSource has no data sources')
|
||||||
|
|
||||||
if not query:
|
if not query:
|
||||||
# don't mess with the query (i.e. convert to a set, as that's done
|
# don't mess with the query (i.e. deduplicate, as that's done
|
||||||
# within the specific DataSources that are called)
|
# within the specific DataSources that are called)
|
||||||
query = []
|
query = []
|
||||||
|
|
||||||
all_data = []
|
all_data = []
|
||||||
|
all_filters = FilterSet()
|
||||||
|
|
||||||
all_filters = set()
|
all_filters.add(self.filters)
|
||||||
all_filters.update(self.filters)
|
|
||||||
|
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
all_filters.update(_composite_filters)
|
all_filters.add(_composite_filters)
|
||||||
|
|
||||||
# federate query to all attached data sources,
|
# federate query to all attached data sources,
|
||||||
# pass composite filters to id
|
# pass composite filters to id
|
||||||
|
|
|
@ -8,7 +8,7 @@ import os
|
||||||
|
|
||||||
from stix2.core import Bundle, parse
|
from stix2.core import Bundle, parse
|
||||||
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
||||||
from stix2.datastore.filters import Filter, apply_common_filters
|
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||||
from stix2.utils import deduplicate, get_class_hierarchy_names
|
from stix2.utils import deduplicate, get_class_hierarchy_names
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ class FileSystemSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -195,7 +195,7 @@ class FileSystemSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -217,7 +217,7 @@ class FileSystemSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query (list): list of filters to search on
|
query (list): list of filters to search on
|
||||||
_composite_filters (set): set of filters passed from the
|
_composite_filters (FilterSet): collection of filters passed from the
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -231,20 +231,13 @@ class FileSystemSource(DataSource):
|
||||||
|
|
||||||
all_data = []
|
all_data = []
|
||||||
|
|
||||||
if query is None:
|
query = FilterSet(query)
|
||||||
query = set()
|
|
||||||
else:
|
|
||||||
if not isinstance(query, list):
|
|
||||||
# make sure dont make set from a Filter object,
|
|
||||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
|
||||||
query = [query]
|
|
||||||
query = set(query)
|
|
||||||
|
|
||||||
# combine all query filters
|
# combine all query filters
|
||||||
if self.filters:
|
if self.filters:
|
||||||
query.update(self.filters)
|
query.add(self.filters)
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
query.update(_composite_filters)
|
query.add(_composite_filters)
|
||||||
|
|
||||||
# extract any filters that are for "type" or "id" , as we can then do
|
# extract any filters that are for "type" or "id" , as we can then do
|
||||||
# filtering before reading in the STIX objects. A STIX 'type' filter
|
# filtering before reading in the STIX objects. A STIX 'type' filter
|
||||||
|
@ -343,8 +336,8 @@ class FileSystemSource(DataSource):
|
||||||
search space of a FileSystemStore (or FileSystemSink).
|
search space of a FileSystemStore (or FileSystemSink).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
file_filters = set()
|
file_filters = []
|
||||||
for filter_ in query:
|
for filter_ in query:
|
||||||
if filter_.property == "id" or filter_.property == "type":
|
if filter_.property == "id" or filter_.property == "type":
|
||||||
file_filters.add(filter_)
|
file_filters.append(filter_)
|
||||||
return file_filters
|
return file_filters
|
||||||
|
|
|
@ -17,6 +17,23 @@ except NameError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def deduplicate_filters(filters):
|
||||||
|
"""utility for deduplicating list of filters, this
|
||||||
|
is used when 'set()' cannot be used as one of the
|
||||||
|
filter values is a dict (or non-hashable type)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filters (list): a list of filters
|
||||||
|
|
||||||
|
Returns: list of unique filters
|
||||||
|
"""
|
||||||
|
unique_filters = []
|
||||||
|
for filter_ in filters:
|
||||||
|
if filter_ not in unique_filters:
|
||||||
|
unique_filters.append(filter_)
|
||||||
|
return unique_filters
|
||||||
|
|
||||||
|
|
||||||
def _check_filter_components(prop, op, value):
|
def _check_filter_components(prop, op, value):
|
||||||
"""Check that filter meets minimum validity.
|
"""Check that filter meets minimum validity.
|
||||||
|
|
||||||
|
@ -168,3 +185,39 @@ def _check_filter(filter_, stix_obj):
|
||||||
else:
|
else:
|
||||||
# Check if property matches
|
# Check if property matches
|
||||||
return filter_._check_property(stix_obj[prop])
|
return filter_._check_property(stix_obj[prop])
|
||||||
|
|
||||||
|
|
||||||
|
class FilterSet(object):
|
||||||
|
""" """
|
||||||
|
|
||||||
|
def __init__(self, filters=None):
|
||||||
|
""" """
|
||||||
|
self._filters = []
|
||||||
|
if filters:
|
||||||
|
self.add(filters)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
""" """
|
||||||
|
for f in self._filters:
|
||||||
|
yield f
|
||||||
|
|
||||||
|
def add(self, filters):
|
||||||
|
""" """
|
||||||
|
if not isinstance(filters, FilterSet) and not isinstance(filters, list):
|
||||||
|
filters = [filters]
|
||||||
|
|
||||||
|
for f in filters:
|
||||||
|
if f not in self._filters:
|
||||||
|
self._filters.append(f)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def remove(self, filters):
|
||||||
|
""" """
|
||||||
|
if not isinstance(filters, FilterSet) and not isinstance(filters, list):
|
||||||
|
filters = [filters]
|
||||||
|
|
||||||
|
for f in filters:
|
||||||
|
self._filters.remove(f)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
|
@ -18,7 +18,7 @@ import os
|
||||||
from stix2.base import _STIXBase
|
from stix2.base import _STIXBase
|
||||||
from stix2.core import Bundle, parse
|
from stix2.core import Bundle, parse
|
||||||
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
||||||
from stix2.datastore.filters import Filter, apply_common_filters
|
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||||
|
|
||||||
|
|
||||||
def _add(store, stix_data=None, version=None):
|
def _add(store, stix_data=None, version=None):
|
||||||
|
@ -197,7 +197,7 @@ class MemorySource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -236,7 +236,7 @@ class MemorySource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX 2 object to retrieve.
|
stix_id (str): The STIX ID of the STIX 2 object to retrieve.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -258,7 +258,7 @@ class MemorySource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query (list): list of filters to search on
|
query (list): list of filters to search on
|
||||||
_composite_filters (set): set of filters passed from the
|
_composite_filters (FilterSet): collection of filters passed from the
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -269,19 +269,15 @@ class MemorySource(DataSource):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if query is None:
|
if query is None:
|
||||||
query = set()
|
query = FilterSet()
|
||||||
else:
|
else:
|
||||||
if not isinstance(query, list):
|
query = FilterSet(query)
|
||||||
# make sure don't make set from a Filter object,
|
|
||||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
|
||||||
query = [query]
|
|
||||||
query = set(query)
|
|
||||||
|
|
||||||
# combine all query filters
|
# combine all query filters
|
||||||
if self.filters:
|
if self.filters:
|
||||||
query.update(self.filters)
|
query.add(self.filters)
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
query.update(_composite_filters)
|
query.add(_composite_filters)
|
||||||
|
|
||||||
# Apply STIX common property filters.
|
# Apply STIX common property filters.
|
||||||
all_data = list(apply_common_filters(self._data.values(), query))
|
all_data = list(apply_common_filters(self._data.values(), query))
|
||||||
|
|
|
@ -6,7 +6,7 @@ from requests.exceptions import HTTPError
|
||||||
from stix2.base import _STIXBase
|
from stix2.base import _STIXBase
|
||||||
from stix2.core import Bundle, parse
|
from stix2.core import Bundle, parse
|
||||||
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
||||||
from stix2.datastore.filters import Filter, apply_common_filters
|
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||||
from stix2.utils import deduplicate
|
from stix2.utils import deduplicate
|
||||||
|
|
||||||
TAXII_FILTERS = ['added_after', 'id', 'type', 'version']
|
TAXII_FILTERS = ['added_after', 'id', 'type', 'version']
|
||||||
|
@ -120,7 +120,7 @@ class TAXIICollectionSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -132,11 +132,12 @@ class TAXIICollectionSource(DataSource):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# combine all query filters
|
# combine all query filters
|
||||||
query = set()
|
query = FilterSet()
|
||||||
|
|
||||||
if self.filters:
|
if self.filters:
|
||||||
query.update(self.filters)
|
query.add(self.filters)
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
query.update(_composite_filters)
|
query.add(_composite_filters)
|
||||||
|
|
||||||
# dont extract TAXII filters from query (to send to TAXII endpoint)
|
# dont extract TAXII filters from query (to send to TAXII endpoint)
|
||||||
# as directly retrieveing a STIX object by ID
|
# as directly retrieveing a STIX object by ID
|
||||||
|
@ -164,7 +165,7 @@ class TAXIICollectionSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||||
_composite_filters (set): set of filters passed from the parent
|
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -198,7 +199,7 @@ class TAXIICollectionSource(DataSource):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query (list): list of filters to search on
|
query (list): list of filters to search on
|
||||||
_composite_filters (set): set of filters passed from the
|
_composite_filters (FilterSet): collection of filters passed from the
|
||||||
CompositeDataSource, not user supplied
|
CompositeDataSource, not user supplied
|
||||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||||
None, use latest version.
|
None, use latest version.
|
||||||
|
@ -209,20 +210,13 @@ class TAXIICollectionSource(DataSource):
|
||||||
parsed into python STIX objects and then returned.
|
parsed into python STIX objects and then returned.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if query is None:
|
query = FilterSet(query)
|
||||||
query = set()
|
|
||||||
else:
|
|
||||||
if not isinstance(query, list):
|
|
||||||
# make sure dont make set from a Filter object,
|
|
||||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
|
||||||
query = [query]
|
|
||||||
query = set(query)
|
|
||||||
|
|
||||||
# combine all query filters
|
# combine all query filters
|
||||||
if self.filters:
|
if self.filters:
|
||||||
query.update(self.filters)
|
query.add(self.filters)
|
||||||
if _composite_filters:
|
if _composite_filters:
|
||||||
query.update(_composite_filters)
|
query.add(_composite_filters)
|
||||||
|
|
||||||
# parse taxii query params (that can be applied remotely)
|
# parse taxii query params (that can be applied remotely)
|
||||||
taxii_filters = self._parse_taxii_filters(query)
|
taxii_filters = self._parse_taxii_filters(query)
|
||||||
|
@ -268,17 +262,16 @@ class TAXIICollectionSource(DataSource):
|
||||||
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query (set): set of filters to extract which ones are TAXII
|
query (list): list of filters to extract which ones are TAXII
|
||||||
specific.
|
specific.
|
||||||
|
|
||||||
Returns:
|
Returns: a list of the TAXII filters
|
||||||
taxii_filters (set): set of the TAXII filters
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
taxii_filters = set()
|
taxii_filters = []
|
||||||
|
|
||||||
for filter_ in query:
|
for filter_ in query:
|
||||||
if filter_.property in TAXII_FILTERS:
|
if filter_.property in TAXII_FILTERS:
|
||||||
taxii_filters.add(filter_)
|
taxii_filters.append(filter_)
|
||||||
|
|
||||||
return taxii_filters
|
return taxii_filters
|
||||||
|
|
Loading…
Reference in New Issue