Merge remote-tracking branch 'emmanvg/marking-support' into markings

stix2.1
clenk 2017-08-17 12:26:46 -04:00
commit 14b922ba92
9 changed files with 2266 additions and 3 deletions

View File

@ -11,6 +11,7 @@ from .exceptions import (AtLeastOnePropertyError, DependentPropertiesError,
MissingPropertiesError, MissingPropertiesError,
MutuallyExclusivePropertiesError, RevokeError, MutuallyExclusivePropertiesError, RevokeError,
UnmodifiablePropertyError) UnmodifiablePropertyError)
from .markings.utils import validate
from .utils import NOW, format_datetime, get_timestamp, parse_into_datetime from .utils import NOW, format_datetime, get_timestamp, parse_into_datetime
__all__ = ['STIXJSONEncoder', '_STIXBase'] __all__ = ['STIXJSONEncoder', '_STIXBase']
@ -80,8 +81,7 @@ class _STIXBase(collections.Mapping):
def _check_object_constraints(self): def _check_object_constraints(self):
for m in self.get("granular_markings", []): for m in self.get("granular_markings", []):
# TODO: check selectors validate(self, m.get("selectors"), m.get("marking_ref"))
pass
def __init__(self, allow_custom=False, **kwargs): def __init__(self, allow_custom=False, **kwargs):
cls = self.__class__ cls = self.__class__

View File

@ -157,3 +157,29 @@ class ParseError(STIXError, ValueError):
def __init__(self, msg): def __init__(self, msg):
super(ParseError, self).__init__(msg) super(ParseError, self).__init__(msg)
class InvalidSelectorError(STIXError, ValueError):
"""Granular Marking selector violation. The selector must resolve into an existing STIX object property."""
def __init__(self, cls, key):
super(InvalidSelectorError, self).__init__()
self.cls = cls
self.key = key
def __str__(self):
msg = "Selector '{0}' in '{1}' is not valid!"
return msg.format(self.key, self.__class__.__name__)
class DuplicateMarkingError(STIXError, ValueError):
"""Marking violation. The marking reference must be a valid identifier."""
def __init__(self, cls, key):
super(DuplicateMarkingError, self).__init__()
self.cls = cls
self.key = key
def __str__(self):
msg = "Marking '{0}' in '{1}' is not a valid marking reference."
return msg.format(self.key, self.__class__.__name__)

197
stix2/markings/__init__.py Normal file
View File

@ -0,0 +1,197 @@
"""
Python STIX 2.0 Data Markings API.
These high level functions will operate on both object level markings and
granular markings unless otherwise noted in each of the functions.
"""
from stix2.markings import utils
from stix2.markings import granular_markings
from stix2.markings import object_markings
def get_markings(obj, selectors, inherited=False, descendants=False):
"""
Get all markings associated to the field(s).
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
inherited: If True, include object level markings and granular markings
inherited relative to the field(s).
descendants: If True, include granular markings applied to any children
relative to the field(s).
Returns:
list: Marking IDs that matched the selectors expression.
Note:
If ``selectors`` is None, operation will be performed only on object
level markings.
"""
if selectors is None:
return object_markings.get_markings(obj)
results = granular_markings.get_markings(
obj,
selectors,
inherited,
descendants
)
if inherited:
results.extend(object_markings.get_markings(obj))
return list(set(results))
def set_markings(obj, selectors, marking):
"""
Removes all markings associated with selectors and appends a new granular
marking. Refer to `clear_markings` and `add_markings` for details.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
Note:
If ``selectors`` is None, operations will be performed on object level
markings. Otherwise on granular markings.
"""
if selectors is None:
object_markings.set_markings(obj, marking)
else:
granular_markings.set_markings(obj, selectors, marking)
def remove_markings(obj, selectors, marking):
"""
Removes granular_marking from the granular_markings collection.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
Raises:
AssertionError: If `selectors` or `marking` fail data validation. Also
if markings to remove are not found on the provided TLO.
Note:
If ``selectors`` is None, operations will be performed on object level
markings. Otherwise on granular markings.
"""
if selectors is None:
object_markings.remove_markings(obj, marking)
else:
granular_markings.remove_markings(obj, selectors, marking)
def add_markings(obj, selectors, marking):
"""
Appends a granular_marking to the granular_markings collection.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
Raises:
AssertionError: If `selectors` or `marking` fail data validation.
Note:
If ``selectors`` is None, operations will be performed on object level
markings. Otherwise on granular markings.
"""
if selectors is None:
return object_markings.add_markings(obj, marking)
else:
return granular_markings.add_markings(obj, selectors, marking)
def clear_markings(obj, selectors):
"""
Removes all granular_marking associated with the selectors.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
Note:
If ``selectors`` is None, operations will be performed on object level
markings. Otherwise on granular markings.
"""
if selectors is None:
object_markings.clear_markings(obj)
else:
granular_markings.clear_markings(obj, selectors)
def is_marked(obj, selectors, marking=None, inherited=False, descendants=False):
"""
Checks if field(s) is marked by any marking or by specific marking(s).
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
inherited: If True, include object level markings and granular markings
inherited to determine if the field(s) is/are marked.
descendants: If True, include granular markings applied to any children
of the given selector to determine if the field(s) is/are marked.
Returns:
bool: True if ``selectors`` is found on internal TLO collection.
False otherwise.
Note:
When a list of marking IDs is provided, if ANY of the provided marking
IDs matches, True is returned.
If ``selectors`` is None, operation will be performed only on object
level markings.
"""
if selectors is None:
return object_markings.is_marked(obj, marking)
result = granular_markings.is_marked(
obj,
selectors,
marking,
inherited,
descendants
)
if inherited:
granular_marks = granular_markings.get_markings(obj, selectors)
object_marks = object_markings.get_markings(obj)
if granular_marks:
result = granular_markings.is_marked(
obj,
selectors,
granular_marks,
inherited,
descendants
)
result = result or object_markings.is_marked(obj, object_marks)
return result

View File

@ -0,0 +1,237 @@
from stix2.markings import utils
def get_markings(obj, selectors, inherited=False, descendants=False):
"""
Get all markings associated to the field(s).
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
inherited: If True, include markings inherited relative to the field(s).
descendants: If True, include granular markings applied to any children
relative to the field(s).
Returns:
list: Marking IDs that matched the selectors expression.
"""
selectors = utils.fix_value(selectors)
utils.validate(obj, selectors)
granular_markings = obj.get("granular_markings", [])
if not granular_markings:
return []
results = set()
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
refs = marking.get("marking_ref", [])
results.update([refs])
return list(results)
def set_markings(obj, selectors, marking):
"""
Removes all markings associated with selectors and appends a new granular
marking. Refer to `clear_markings` and `add_markings` for details.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
"""
clear_markings(obj, selectors)
add_markings(obj, selectors, marking)
def remove_markings(obj, selectors, marking):
"""
Removes granular_marking from the granular_markings collection.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
Raises:
AssertionError: If `selectors` or `marking` fail data validation. Also
if markings to remove are not found on the provided TLO.
"""
selectors = utils.fix_value(selectors)
utils.validate(obj, selectors, marking)
utils.expand_markings(obj)
granular_markings = obj.get("granular_markings")
if not granular_markings:
return
tlo = utils.build_granular_marking(
{"selectors": selectors, "marking_ref": marking}
)
remove = tlo.get("granular_markings", [])
if not any(marking in granular_markings for marking in remove):
raise AssertionError("Unable to remove Granular Marking(s) from"
" internal collection. Marking(s) not found...")
obj["granular_markings"] = [
m for m in granular_markings if m not in remove
]
utils.compress_markings(obj)
if not obj.get("granular_markings"):
obj.pop("granular_markings")
def add_markings(obj, selectors, marking):
"""
Appends a granular_marking to the granular_markings collection.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
Raises:
AssertionError: If `selectors` or `marking` fail data validation.
"""
selectors = utils.fix_value(selectors)
utils.validate(obj, selectors, marking)
granular_marking = {"selectors": sorted(selectors), "marking_ref": marking}
if not obj.get("granular_markings"):
obj["granular_markings"] = list()
obj["granular_markings"].append(granular_marking)
utils.expand_markings(obj)
utils.compress_markings(obj)
def clear_markings(obj, selectors):
"""
Removes all granular_marking associated with the selectors.
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
Raises:
AssertionError: If `selectors` or `marking` fail data validation. Also
if markings to remove are not found on the provided TLO.
"""
selectors = utils.fix_value(selectors)
utils.validate(obj, selectors)
utils.expand_markings(obj)
granular_markings = obj.get("granular_markings")
if not granular_markings:
return
tlo = utils.build_granular_marking(
{"selectors": selectors, "marking_ref": ["N/A"]}
)
clear = tlo.get("granular_markings", [])
if not any(clear_selector in tlo_selectors.get("selectors", [])
for tlo_selectors in granular_markings
for clear_marking in clear
for clear_selector in clear_marking.get("selectors", [])
):
raise AssertionError("Unable to clear Granular Marking(s) from"
" internal collection. Selector(s) not found...")
for granular_marking in granular_markings:
for s in selectors:
if s in granular_marking.get("selectors", []):
marking_refs = granular_marking.get("marking_ref")
if marking_refs:
granular_marking["marking_ref"] = list()
utils.compress_markings(obj)
if not obj.get("granular_markings"):
obj.pop("granular_markings")
def is_marked(obj, selectors, marking=None, inherited=False, descendants=False):
"""
Checks if field is marked by any marking or by specific marking(s).
Args:
obj: A TLO object.
selectors: string or list of selectors strings relative to the TLO in
which the field(s) appear(s).
marking: identifier or list of marking identifiers that apply to the
field(s) selected by `selectors`.
inherited: If True, return markings inherited from the given selector.
descendants: If True, return granular markings applied to any children
of the given selector.
Returns:
bool: True if ``selectors`` is found on internal TLO collection.
False otherwise.
Note:
When a list of marking IDs is provided, if ANY of the provided marking
IDs matches, True is returned.
"""
selectors = utils.fix_value(selectors)
marking = utils.fix_value(marking)
utils.validate(obj, selectors, marking)
granular_markings = obj.get("granular_markings", [])
marked = False
markings = set()
for granular_marking in granular_markings:
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
marking_ref = granular_marking.get("marking_ref", "")
if marking and any(x == marking_ref for x in marking):
markings.update([marking_ref])
marked = True
if marking:
# All user-provided markings must be found.
return markings.issuperset(set(marking))
return marked

View File

@ -0,0 +1,118 @@
from stix2.markings import utils
def get_markings(obj):
"""
Get all object level markings from the given SDO or SRO object.
Args:
obj: A SDO or SRO object.
Returns:
list: Marking IDs contained in the SDO or SRO. Empty list if no
markings are present in `object_marking_refs`.
"""
return obj.get("object_marking_refs", [])
def add_markings(obj, marking):
"""
Appends an object level marking to the object_marking_refs collection.
Args:
obj: A SDO or SRO object.
marking: identifier or list of identifiers to apply SDO or SRO object.
Raises:
AssertionError: If `marking` fail data validation.
"""
marking = utils.convert_to_list(marking)
# TODO: Remove set for comparison and raise DuplicateMarkingException.
object_markings = set(obj.get("object_marking_refs", []) + marking)
return obj.new_version(object_marking_refs=list(object_markings))
def remove_markings(obj, marking):
"""
Removes object level marking from the object_marking_refs collection.
Args:
obj: A SDO or SRO object.
marking: identifier or list of identifiers that apply to the
SDO or SRO object.
Raises:
AssertionError: If markings to remove are not found on the provided
SDO or SRO.
"""
marking = utils.convert_to_list(marking)
utils.validate(obj, marking=marking)
object_markings = obj.get("object_marking_refs", [])
if not object_markings:
return obj
if any(x not in obj["object_marking_refs"] for x in marking):
raise AssertionError("Unable to remove Object Level Marking(s) from "
"internal collection. Marking(s) not found...")
return obj.new_version(object_marking_refs=[x for x in object_markings
if x not in marking])
def set_markings(obj, marking):
"""
Removes all object level markings and appends new object level markings to
the collection. Refer to `clear_markings` and `add_markings` for details.
Args:
obj: A SDO or SRO object.
marking: identifier or list of identifiers to apply in the
SDO or SRO object.
"""
return add_markings(clear_markings(obj), marking)
def clear_markings(obj):
"""
Removes all object level markings from the object_marking_refs collection.
Args:
obj: A SDO or SRO object.
"""
return obj.new_version(object_marking_refs=None)
def is_marked(obj, marking=None):
"""
Checks if SDO or SRO is marked by any marking or by specific marking(s).
Args:
obj: A SDO or SRO object.
marking: identifier or list of marking identifiers that apply to the
SDO or SRO object.
Returns:
bool: True if SDO or SRO has object level markings. False otherwise.
Note:
When an identifier or list of identifiers is provided, if ANY of the
provided marking refs match, True is returned.
"""
marking = utils.convert_to_list(marking)
object_markings = obj.get("object_marking_refs", [])
if marking:
return any(x in object_markings for x in marking)
else:
return bool(object_markings)

228
stix2/markings/utils.py Normal file
View File

@ -0,0 +1,228 @@
import collections
import six
def evaluate_expression(obj, selector):
for items, value in iterpath(obj):
path = ".".join(items)
if path == selector and value:
return [value]
return []
def validate_selector(obj, selector):
results = list(evaluate_expression(obj, selector))
if len(results) >= 1:
return True
def validate_markings(marking):
if isinstance(marking, six.string_types):
if not marking:
return False
else:
return True
elif isinstance(marking, list) and len(marking) >= 1:
for m in marking:
if not m:
return False
elif not isinstance(m, six.string_types):
return False
return True
else:
return False
def validate(obj, selectors=None, marking=None):
if selectors is not None:
assert selectors
for s in selectors:
assert validate_selector(obj, s)
if marking is not None:
assert validate_markings(marking)
def convert_to_list(data):
if data is not None:
if isinstance(data, list):
return data
else:
return [data]
def fix_value(data):
data = convert_to_list(data)
return data
def _fix_markings(markings):
for granular_marking in markings:
refs = granular_marking.get("marking_ref", [])
selectors = granular_marking.get("selectors", [])
if not isinstance(refs, list):
granular_marking["marking_ref"] = [refs]
if not isinstance(selectors, list):
granular_marking["selectors"] = [selectors]
def _group_by(markings):
key = "marking_ref"
retrieve = "selectors"
map_ = collections.defaultdict(set)
for granular_marking in markings:
for data in granular_marking.get(key, []):
map_[data].update(granular_marking.get(retrieve))
granular_markings = \
[
{"selectors": sorted(selectors), "marking_ref": ref}
for ref, selectors in six.iteritems(map_)
]
return granular_markings
def compress_markings(tlo):
if not tlo.get("granular_markings"):
return
granular_markings = tlo.get("granular_markings")
_fix_markings(granular_markings)
tlo["granular_markings"] = _group_by(granular_markings)
def expand_markings(tlo):
if not tlo.get("granular_markings"):
return
granular_markings = tlo.get("granular_markings")
_fix_markings(granular_markings)
expanded = list()
for marking in granular_markings:
selectors = marking.get("selectors", [])
marking_ref = marking.get("marking_ref", [])
expanded.extend(
[
{"selectors": [sel], "marking_ref": ref}
for sel in selectors
for ref in marking_ref
]
)
tlo["granular_markings"] = expanded
def build_granular_marking(granular_marking):
tlo = {"granular_markings": [granular_marking]}
expand_markings(tlo)
return tlo
def iterpath(obj, path=None):
"""
Generator which walks the input ``obj`` model. Each iteration yields a
tuple containing a list of ancestors and the property value.
Args:
obj: A TLO object.
path: None, used recursively to store ancestors.
Example:
>>> for item in iterpath(tlo):
>>> print(item)
(['type'], 'campaign')
...
(['cybox', 'objects', '[0]', 'hashes', 'sha1'], 'cac35ec206d868b7d7cb0b55f31d9425b075082b')
Returns:
tuple: Containing two items: a list of ancestors and the property value.
"""
if path is None:
path = []
for varname, varobj in iter(sorted(six.iteritems(obj))):
path.append(varname)
yield (path, varobj)
if isinstance(varobj, dict):
for item in iterpath(varobj, path):
yield item
elif isinstance(varobj, list):
for item in varobj:
index = "[{0}]".format(varobj.index(item))
path.append(index)
yield (path, item)
if isinstance(item, dict):
for descendant in iterpath(item, path):
yield descendant
path.pop()
path.pop()
def get_selector(obj, prop):
"""
Function that creates a selector based on ``prop``.
Args:
obj: A TLO object.
prop: A property of the TLO object.
Note:
Must supply the actual value inside the structure. Since some
limitations exist with Python interning methods, checking for object
location is for now the option to assert the data.
Example:
>>> selector = get_selector(tlo, tlo["cybox"]["objects"][0]["file_name"])
>>> print(selector)
["cybox.objects.[0].file_name"]
Returns:
list: A list with one selector that asserts the supplied property.
Empty list if it was unable to find the property.
"""
selector = []
for ancestors, value in iterpath(obj):
if value is prop:
path = ".".join(ancestors)
selector.append(path)
return selector

View File

@ -0,0 +1,968 @@
from stix2 import markings
import pytest
"""Tests for the Data Markings API."""
def test_add_marking_mark_one_selector_multiple_refs():
before = {
"description": "test description",
"title": "foo",
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description"],
"marking_ref": "marking-definition--2"
},
]
}
markings.add_markings(before, ["description"], ["marking-definition--1", "marking-definition--2"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
def test_add_marking_mark_multiple_selector_one_refs():
before = {
"description": "test description",
"title": "foo",
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
]
}
markings.add_markings(before, ["description", "title"], ["marking-definition--1"])
assert before == after
def test_add_marking_mark_multiple_selector_multiple_refs():
before = {
"description": "test description",
"title": "foo",
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--2"
},
]
}
markings.add_markings(before, ["description", "title"], ["marking-definition--1", "marking-definition--2"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
def test_add_marking_mark_another_property_same_marking():
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
]
}
markings.add_markings(before, ["title"], ["marking-definition--1"])
assert before == after
def test_add_marking_mark_same_property_same_marking():
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
markings.add_markings(before, ["description"], ["marking-definition--1"])
assert before == after
@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])
GET_MARKINGS_TEST_DATA = \
{
"a": 333,
"b": "value",
"c": [
17,
"list value",
{
"g": "nested",
"h": 45
}
],
"x": {
"y": [
"hello",
88
],
"z": {
"foo1": "bar",
"foo2": 65
}
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
},
{
"marking_ref": "2",
"selectors": ["c"]
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
},
{
"marking_ref": "6",
"selectors": ["x"]
},
{
"marking_ref": "7",
"selectors": ["x.y"]
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
},
{
"marking_ref": "9",
"selectors": ["x.z"]
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
},
]
}
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_smoke(data):
"""Test get_markings does not fail."""
assert len(markings.get_markings(data, "a")) >= 1
assert markings.get_markings(data, "a") == ["1"]
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_not_marked(data):
"""Test selector that is not marked returns empty list."""
results = markings.get_markings(data, "b")
assert len(results) == 0
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_multiple_selectors(data):
"""Test multiple selectors return combination of markings."""
total = markings.get_markings(data, ["x.y", "x.z"])
xy_markings = markings.get_markings(data, ["x.y"])
xz_markings = markings.get_markings(data, ["x.z"])
assert set(xy_markings).issubset(total)
assert set(xz_markings).issubset(total)
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")
])
def test_get_markings_bad_selector(data, selector):
"""Test bad selectors raise exception"""
with pytest.raises(AssertionError):
markings.get_markings(data, selector)
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_positional_arguments_combinations(data):
"""Test multiple combinations for inherited and descendant markings."""
assert set(markings.get_markings(data, "a", False, False)) == set(["1"])
assert set(markings.get_markings(data, "a", True, False)) == set(["1"])
assert set(markings.get_markings(data, "a", True, True)) == set(["1"])
assert set(markings.get_markings(data, "a", False, True)) == set(["1"])
assert set(markings.get_markings(data, "b", False, False)) == set([])
assert set(markings.get_markings(data, "b", True, False)) == set([])
assert set(markings.get_markings(data, "b", True, True)) == set([])
assert set(markings.get_markings(data, "b", False, True)) == set([])
assert set(markings.get_markings(data, "c", False, False)) == set(["2"])
assert set(markings.get_markings(data, "c", True, False)) == set(["2"])
assert set(markings.get_markings(data, "c", True, True)) == set(["2", "3", "4", "5"])
assert set(markings.get_markings(data, "c", False, True)) == set(["2", "3", "4", "5"])
assert set(markings.get_markings(data, "c.[0]", False, False)) == set([])
assert set(markings.get_markings(data, "c.[0]", True, False)) == set(["2"])
assert set(markings.get_markings(data, "c.[0]", True, True)) == set(["2"])
assert set(markings.get_markings(data, "c.[0]", False, True)) == set([])
assert set(markings.get_markings(data, "c.[1]", False, False)) == set(["3"])
assert set(markings.get_markings(data, "c.[1]", True, False)) == set(["2", "3"])
assert set(markings.get_markings(data, "c.[1]", True, True)) == set(["2", "3"])
assert set(markings.get_markings(data, "c.[1]", False, True)) == set(["3"])
assert set(markings.get_markings(data, "c.[2]", False, False)) == set(["4"])
assert set(markings.get_markings(data, "c.[2]", True, False)) == set(["2", "4"])
assert set(markings.get_markings(data, "c.[2]", True, True)) == set(["2", "4", "5"])
assert set(markings.get_markings(data, "c.[2]", False, True)) == set(["4", "5"])
assert set(markings.get_markings(data, "c.[2].g", False, False)) == set(["5"])
assert set(markings.get_markings(data, "c.[2].g", True, False)) == set(["2", "4", "5"])
assert set(markings.get_markings(data, "c.[2].g", True, True)) == set(["2", "4", "5"])
assert set(markings.get_markings(data, "c.[2].g", False, True)) == set(["5"])
assert set(markings.get_markings(data, "x", False, False)) == set(["6"])
assert set(markings.get_markings(data, "x", True, False)) == set(["6"])
assert set(markings.get_markings(data, "x", True, True)) == set(["6", "7", "8", "9", "10"])
assert set(markings.get_markings(data, "x", False, True)) == set(["6", "7", "8", "9", "10"])
assert set(markings.get_markings(data, "x.y", False, False)) == set(["7"])
assert set(markings.get_markings(data, "x.y", True, False)) == set(["6", "7"])
assert set(markings.get_markings(data, "x.y", True, True)) == set(["6", "7", "8"])
assert set(markings.get_markings(data, "x.y", False, True)) == set(["7", "8"])
assert set(markings.get_markings(data, "x.y.[0]", False, False)) == set([])
assert set(markings.get_markings(data, "x.y.[0]", True, False)) == set(["6", "7"])
assert set(markings.get_markings(data, "x.y.[0]", True, True)) == set(["6", "7"])
assert set(markings.get_markings(data, "x.y.[0]", False, True)) == set([])
assert set(markings.get_markings(data, "x.y.[1]", False, False)) == set(["8"])
assert set(markings.get_markings(data, "x.y.[1]", True, False)) == set(["6", "7", "8"])
assert set(markings.get_markings(data, "x.y.[1]", True, True)) == set(["6", "7", "8"])
assert set(markings.get_markings(data, "x.y.[1]", False, True)) == set(["8"])
assert set(markings.get_markings(data, "x.z", False, False)) == set(["9"])
assert set(markings.get_markings(data, "x.z", True, False)) == set(["6", "9"])
assert set(markings.get_markings(data, "x.z", True, True)) == set(["6", "9", "10"])
assert set(markings.get_markings(data, "x.z", False, True)) == set(["9", "10"])
assert set(markings.get_markings(data, "x.z.foo1", False, False)) == set([])
assert set(markings.get_markings(data, "x.z.foo1", True, False)) == set(["6", "9"])
assert set(markings.get_markings(data, "x.z.foo1", True, True)) == set(["6", "9"])
assert set(markings.get_markings(data, "x.z.foo1", False, True)) == set([])
assert set(markings.get_markings(data, "x.z.foo2", False, False)) == set(["10"])
assert set(markings.get_markings(data, "x.z.foo2", True, False)) == set(["6", "9", "10"])
assert set(markings.get_markings(data, "x.z.foo2", True, True)) == set(["6", "9", "10"])
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
def test_remove_marking_remove_one_selector_with_multiple_refs():
after = {
"description": "test description",
"title": "foo",
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description"],
"marking_ref": "marking-definition--2"
},
]
}
markings.remove_markings(before, ["description"], ["marking-definition--1", "marking-definition--2"])
assert before == after
def test_remove_marking_remove_multiple_selector_one_ref():
after = {
"description": "test description",
"title": "foo",
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
]
}
markings.remove_markings(before, ["description", "title"], ["marking-definition--1"])
assert before == after
def test_remove_marking_mark_one_selector_from_multiple_ones():
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
]
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
]
}
markings.remove_markings(before, ["title"], ["marking-definition--1"])
assert before == after
def test_remove_marking_mark_one_selector_markings_from_multiple_ones():
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--2"
},
]
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--2"
},
]
}
markings.remove_markings(before, ["title"], ["marking-definition--1"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
def test_remove_marking_mark_mutilple_selector_multiple_refs():
after = {
"description": "test description",
"title": "foo",
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--2"
},
]
}
markings.remove_markings(before, ["description", "title"], ["marking-definition--1", "marking-definition--2"])
assert before == after
def test_remove_marking_mark_another_property_same_marking():
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
]
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["title"],
"marking_ref": "marking-definition--1"
}
]
}
markings.remove_markings(before, ["title"], ["marking-definition--1"])
assert before == after
def test_remove_marking_mark_same_property_same_marking():
after = {
"description": "test description",
"title": "foo",
}
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
markings.remove_markings(before, ["description"], ["marking-definition--1"])
assert before == after
def test_remove_marking_bad_selector():
before = {
"description": "test description",
}
with pytest.raises(AssertionError):
markings.remove_markings(before, ["title"], ["marking-definition--1", "marking-definition--2"])
IS_MARKED_TEST_DATA = \
{
"title": "test title",
"description": "test description",
"revision": 2,
"type": "test",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["revision", "description"],
"marking_ref": "marking-definition--2"
},
{
"selectors": ["revision", "description"],
"marking_ref": "marking-definition--3"
},
]
}
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_smoke(data):
"""Smoke test is_marked call does not fail."""
assert markings.is_marked(data, ["description"])
assert markings.is_marked(data, ["title"]) is False
@pytest.mark.parametrize("data,selector", [
(IS_MARKED_TEST_DATA, "foo"),
(IS_MARKED_TEST_DATA, ""),
(IS_MARKED_TEST_DATA, []),
(IS_MARKED_TEST_DATA, [""]),
(IS_MARKED_TEST_DATA, "x.z.[-2]"),
(IS_MARKED_TEST_DATA, "c.f"),
(IS_MARKED_TEST_DATA, "c.[2].i"),
(IS_MARKED_TEST_DATA, "c.[3]"),
(IS_MARKED_TEST_DATA, "d"),
(IS_MARKED_TEST_DATA, "x.[0]"),
(IS_MARKED_TEST_DATA, "z.y.w"),
(IS_MARKED_TEST_DATA, "x.z.[1]"),
(IS_MARKED_TEST_DATA, "x.z.foo3")
])
def test_is_marked_invalid_selector(data, selector):
"""Test invalid selector raises an error."""
with pytest.raises(AssertionError):
markings.is_marked(data, selector)
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_mix_selector(data):
"""Test valid selector, one marked and one not marked returns True."""
assert markings.is_marked(data, ["description", "revision"])
assert markings.is_marked(data, ["description"])
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_valid_selector_no_refs(data):
"""Test that a valid selector return True when it has marking refs and False when not."""
assert markings.is_marked(data, ["description"])
assert markings.is_marked(data, ["description"], ["marking-definition--2", "marking-definition--3"])
assert markings.is_marked(data, ["description"], ["marking-definition--2"])
assert markings.is_marked(data, ["description"], ["marking-definition--2", "marking-definition--8"]) is False
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_valid_selector_and_refs(data):
"""Test that a valid selector returns True when marking_refs match."""
assert markings.is_marked(data, ["description"], ["marking-definition--1"])
assert markings.is_marked(data, ["title"], ["marking-definition--1"]) is False
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_valid_selector_multiple_refs(data):
"""Test that a valid selector returns True if aall marking_refs match.
Otherwise False."""
assert markings.is_marked(data, ["revision"], ["marking-definition--2", "marking-definition--3"])
assert markings.is_marked(data, ["revision"], ["marking-definition--2", "marking-definition--1"]) is False
assert markings.is_marked(data, ["revision"], "marking-definition--2")
assert markings.is_marked(data, ["revision"], ["marking-definition--1234"]) is False
@pytest.mark.parametrize("data", [IS_MARKED_TEST_DATA])
def test_is_marked_no_marking_refs(data):
"""Test that a valid content selector with no marking_refs returns True
if there is a granular_marking that asserts that field, False
otherwise."""
assert markings.is_marked(data, ["type"]) is False
assert markings.is_marked(data, ["revision"])
def test_is_marked_positional_arguments_combinations():
"""Test multiple combinations for inherited and descendant markings."""
test_tlo = \
{
"a": 333,
"b": "value",
"c": [
17,
"list value",
{
"g": "nested",
"h": 45
}
],
"x": {
"y": [
"hello",
88
],
"z": {
"foo1": "bar",
"foo2": 65
}
},
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
},
{
"marking_ref": "2",
"selectors": ["c"]
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
},
{
"marking_ref": "6",
"selectors": ["x"]
},
{
"marking_ref": "7",
"selectors": ["x.y"]
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
},
{
"marking_ref": "9",
"selectors": ["x.z"]
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
},
]
}
assert markings.is_marked(test_tlo, "a", ["1"], False, False)
assert markings.is_marked(test_tlo, "a", ["1"], True, False)
assert markings.is_marked(test_tlo, "a", ["1"], True, True)
assert markings.is_marked(test_tlo, "a", ["1"], False, True)
assert markings.is_marked(test_tlo, "b", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "b", inherited=True, descendants=False) is False
assert markings.is_marked(test_tlo, "b", inherited=True, descendants=True) is False
assert markings.is_marked(test_tlo, "b", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "c", ["2"], False, False)
assert markings.is_marked(test_tlo, "c", ["2"], True, False)
assert markings.is_marked(test_tlo, "c", ["2", "3", "4", "5"], True, True)
assert markings.is_marked(test_tlo, "c", ["2", "3", "4", "5"], False, True)
assert markings.is_marked(test_tlo, "c.[0]", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "c.[0]", ["2"], True, False)
assert markings.is_marked(test_tlo, "c.[0]", ["2"], True, True)
assert markings.is_marked(test_tlo, "c.[0]", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "c.[1]", ["3"], False, False)
assert markings.is_marked(test_tlo, "c.[1]", ["2", "3"], True, False)
assert markings.is_marked(test_tlo, "c.[1]", ["2", "3"], True, True)
assert markings.is_marked(test_tlo, "c.[1]", ["3"], False, True)
assert markings.is_marked(test_tlo, "c.[2]", ["4"], False, False)
assert markings.is_marked(test_tlo, "c.[2]", ["2", "4"], True, False)
assert markings.is_marked(test_tlo, "c.[2]", ["2", "4", "5"], True, True)
assert markings.is_marked(test_tlo, "c.[2]", ["4", "5"], False, True)
assert markings.is_marked(test_tlo, "c.[2].g", ["5"], False, False)
assert markings.is_marked(test_tlo, "c.[2].g", ["2", "4", "5"], True, False)
assert markings.is_marked(test_tlo, "c.[2].g", ["2", "4", "5"], True, True)
assert markings.is_marked(test_tlo, "c.[2].g", ["5"], False, True)
assert markings.is_marked(test_tlo, "x", ["6"], False, False)
assert markings.is_marked(test_tlo, "x", ["6"], True, False)
assert markings.is_marked(test_tlo, "x", ["6", "7", "8", "9", "10"], True, True)
assert markings.is_marked(test_tlo, "x", ["6", "7", "8", "9", "10"], False, True)
assert markings.is_marked(test_tlo, "x.y", ["7"], False, False)
assert markings.is_marked(test_tlo, "x.y", ["6", "7"], True, False)
assert markings.is_marked(test_tlo, "x.y", ["6", "7", "8"], True, True)
assert markings.is_marked(test_tlo, "x.y", ["7", "8"], False, True)
assert markings.is_marked(test_tlo, "x.y.[0]", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "x.y.[0]", ["6", "7"], True, False)
assert markings.is_marked(test_tlo, "x.y.[0]", ["6", "7"], True, True)
assert markings.is_marked(test_tlo, "x.y.[0]", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "x.y.[1]", ["8"], False, False)
assert markings.is_marked(test_tlo, "x.y.[1]", ["6", "7", "8"], True, False)
assert markings.is_marked(test_tlo, "x.y.[1]", ["6", "7", "8"], True, True)
assert markings.is_marked(test_tlo, "x.y.[1]", ["8"], False, True)
assert markings.is_marked(test_tlo, "x.z", ["9"], False, False)
assert markings.is_marked(test_tlo, "x.z", ["6", "9"], True, False)
assert markings.is_marked(test_tlo, "x.z", ["6", "9", "10"], True, True)
assert markings.is_marked(test_tlo, "x.z", ["9", "10"], False, True)
assert markings.is_marked(test_tlo, "x.z.foo1", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "x.z.foo1", ["6", "9"], True, False)
assert markings.is_marked(test_tlo, "x.z.foo1", ["6", "9"], True, True)
assert markings.is_marked(test_tlo, "x.z.foo1", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "x.z.foo2", ["10"], False, False)
assert markings.is_marked(test_tlo, "x.z.foo2", ["6", "9", "10"], True, False)
assert markings.is_marked(test_tlo, "x.z.foo2", ["6", "9", "10"], True, True)
assert markings.is_marked(test_tlo, "x.z.foo2", ["10"], False, True)
def test_set_marking_mark_one_selector_multiple_refs():
before = {
"description": "test description",
"title": "foo",
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description"],
"marking_ref": "marking-definition--2"
},
]
}
markings.set_markings(before, ["description"], ["marking-definition--1", "marking-definition--2"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
def test_set_marking_mark_multiple_selector_one_refs():
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--3"
},
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
]
}
markings.set_markings(before, ["description", "title"], ["marking-definition--1"])
assert before == after
def test_set_marking_mark_multiple_selector_multiple_refs_from_none():
before = {
"description": "test description",
"title": "foo",
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["description", "title"],
"marking_ref": "marking-definition--2"
},
]
}
markings.set_markings(before, ["description", "title"], ["marking-definition--1", "marking-definition--2"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
def test_set_marking_mark_another_property_same_marking():
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--7"
},
{
"selectors": ["description"],
"marking_ref": "marking-definition--8"
},
]
}
markings.set_markings(before, ["description"], ["marking-definition--7", "marking-definition--8"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
@pytest.mark.parametrize("marking", [
(["foo"], ["marking-definition--7", "marking-definition--8"]),
("", ["marking-definition--7", "marking-definition--8"]),
([], ["marking-definition--7", "marking-definition--8"]),
([""], ["marking-definition--7", "marking-definition--8"])
])
def test_set_marking_bad_selector(marking):
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
]
}
with pytest.raises(AssertionError):
markings.set_markings(before, marking[0], marking[1])
assert before == after
def test_set_marking_mark_same_property_same_marking():
before = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
after = {
"description": "test description",
"title": "foo",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
}
]
}
markings.set_markings(before, ["description"], ["marking-definition--1"])
assert before == after
CLEAR_MARKINGS_TEST_DATA = \
{
"title": "test title",
"description": "test description",
"revision": 2,
"type": "test",
"granular_markings": [
{
"selectors": ["description"],
"marking_ref": "marking-definition--1"
},
{
"selectors": ["revision", "description"],
"marking_ref": "marking-definition--2"
},
{
"selectors": ["revision", "description", "type"],
"marking_ref": "marking-definition--3"
},
]
}
@pytest.mark.parametrize("data", [CLEAR_MARKINGS_TEST_DATA])
def test_clear_marking_smoke(data):
"""Test clear_marking call does not fail."""
markings.clear_markings(data, "revision")
assert markings.is_marked(data, "revision") is False
@pytest.mark.parametrize("data", [CLEAR_MARKINGS_TEST_DATA])
def test_clear_marking_multiple_selectors(data):
"""Test clearing markings for multiple selectors effectively removes associated markings."""
markings.clear_markings(data, ["type", "description"])
assert markings.is_marked(data, ["type", "description"]) is False
@pytest.mark.parametrize("data", [CLEAR_MARKINGS_TEST_DATA])
def test_clear_marking_one_selector(data):
"""Test markings associated with one selector were removed."""
markings.clear_markings(data, "description")
assert markings.is_marked(data, "description") is False
@pytest.mark.parametrize("data", [CLEAR_MARKINGS_TEST_DATA])
def test_clear_marking_all_selectors(data):
markings.clear_markings(data, ["description", "type", "revision"])
assert markings.is_marked(data, "description") is False
assert "granular_markings" not in data
@pytest.mark.parametrize("data,selector", [
(CLEAR_MARKINGS_TEST_DATA, "foo"),
(CLEAR_MARKINGS_TEST_DATA, ""),
(CLEAR_MARKINGS_TEST_DATA, []),
(CLEAR_MARKINGS_TEST_DATA, [""]),
])
def test_clear_marking_bad_selector(data, selector):
"""Test bad selector raises exception."""
with pytest.raises(AssertionError):
markings.clear_markings(data, selector)

View File

@ -4,7 +4,7 @@ import pytest
import pytz import pytz
import stix2 import stix2
from stix2 import TLP_WHITE from stix2 import TLP_WHITE, markings
from .constants import MARKING_DEFINITION_ID from .constants import MARKING_DEFINITION_ID
@ -155,6 +155,8 @@ def test_campaign_with_granular_markings_example():
marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9", marking_ref="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9",
selectors=["description"]) selectors=["description"])
]) ])
print (markings.get_markings(campaign, None))
print (markings.add_markings(campaign, None, "marking-definition--00000000-0000-0000-0000-000000000000"))
assert str(campaign) == EXPECTED_CAMPAIGN_WITH_GRANULAR_MARKINGS assert str(campaign) == EXPECTED_CAMPAIGN_WITH_GRANULAR_MARKINGS

View File

@ -0,0 +1,487 @@
from stix2 import markings
import pytest
"""Tests for the Data Markings API."""
def test_add_markings_one_marking():
before = {
"title": "test title",
"description": "test description"
}
after = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1"]
}
markings.add_markings(before, None, "marking-definition--1")
assert before == after
def test_add_markings_multiple_marking():
before = {
"title": "test title",
"description": "test description"
}
after = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2"]
}
markings.add_markings(before, None, ["marking-definition--1", "marking-definition--2"])
for m in before["object_marking_refs"]:
assert m in after["object_marking_refs"]
def test_add_markings_combination():
before = {
"title": "test title",
"description": "test description"
}
after = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2"],
"granular_markings": [
{
"selectors": ["title"],
"marking_ref": "marking-definition--3"
},
{
"selectors": ["description"],
"marking_ref": "marking-definition--4"
},
]
}
markings.add_markings(before, None, "marking-definition--1")
markings.add_markings(before, None, "marking-definition--2")
markings.add_markings(before, "title", "marking-definition--3")
markings.add_markings(before, "description", "marking-definition--4")
for m in before["granular_markings"]:
assert m in after["granular_markings"]
for m in before["object_marking_refs"]:
assert m in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([""]),
(""),
([]),
(["marking-definition--1", 456])
])
def test_add_markings_bad_markings(data):
before = {
"title": "test title",
"description": "test description"
}
with pytest.raises(AssertionError):
markings.add_markings(before, None, data)
assert "object_marking_refs" not in before
GET_MARKINGS_TEST_DATA = \
{
"a": 333,
"b": "value",
"c": [
17,
"list value",
{
"g": "nested",
"h": 45
}
],
"x": {
"y": [
"hello",
88
],
"z": {
"foo1": "bar",
"foo2": 65
}
},
"object_marking_refs": ["11"],
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
},
{
"marking_ref": "2",
"selectors": ["c"]
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
},
{
"marking_ref": "6",
"selectors": ["x"]
},
{
"marking_ref": "7",
"selectors": ["x.y"]
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
},
{
"marking_ref": "9",
"selectors": ["x.z"]
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
},
]
}
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_object_marking(data):
assert set(markings.get_markings(data, None)) == set(["11"])
@pytest.mark.parametrize("data", [GET_MARKINGS_TEST_DATA])
def test_get_markings_object_and_granular_combinations(data):
"""Test multiple combinations for inherited and descendant markings."""
assert set(markings.get_markings(data, "a", False, False)) == set(["1"])
assert set(markings.get_markings(data, "a", True, False)) == set(["1", "11"])
assert set(markings.get_markings(data, "a", True, True)) == set(["1", "11"])
assert set(markings.get_markings(data, "a", False, True)) == set(["1"])
assert set(markings.get_markings(data, "b", False, False)) == set([])
assert set(markings.get_markings(data, "b", True, False)) == set(["11"])
assert set(markings.get_markings(data, "b", True, True)) == set(["11"])
assert set(markings.get_markings(data, "b", False, True)) == set([])
assert set(markings.get_markings(data, "c", False, False)) == set(["2"])
assert set(markings.get_markings(data, "c", True, False)) == set(["2", "11"])
assert set(markings.get_markings(data, "c", True, True)) == set(["2", "3", "4", "5", "11"])
assert set(markings.get_markings(data, "c", False, True)) == set(["2", "3", "4", "5"])
assert set(markings.get_markings(data, "c.[0]", False, False)) == set([])
assert set(markings.get_markings(data, "c.[0]", True, False)) == set(["2", "11"])
assert set(markings.get_markings(data, "c.[0]", True, True)) == set(["2", "11"])
assert set(markings.get_markings(data, "c.[0]", False, True)) == set([])
assert set(markings.get_markings(data, "c.[1]", False, False)) == set(["3"])
assert set(markings.get_markings(data, "c.[1]", True, False)) == set(["2", "3", "11"])
assert set(markings.get_markings(data, "c.[1]", True, True)) == set(["2", "3", "11"])
assert set(markings.get_markings(data, "c.[1]", False, True)) == set(["3"])
assert set(markings.get_markings(data, "c.[2]", False, False)) == set(["4"])
assert set(markings.get_markings(data, "c.[2]", True, False)) == set(["2", "4", "11"])
assert set(markings.get_markings(data, "c.[2]", True, True)) == set(["2", "4", "5", "11"])
assert set(markings.get_markings(data, "c.[2]", False, True)) == set(["4", "5"])
assert set(markings.get_markings(data, "c.[2].g", False, False)) == set(["5"])
assert set(markings.get_markings(data, "c.[2].g", True, False)) == set(["2", "4", "5", "11"])
assert set(markings.get_markings(data, "c.[2].g", True, True)) == set(["2", "4", "5", "11"])
assert set(markings.get_markings(data, "c.[2].g", False, True)) == set(["5"])
assert set(markings.get_markings(data, "x", False, False)) == set(["6"])
assert set(markings.get_markings(data, "x", True, False)) == set(["6", "11"])
assert set(markings.get_markings(data, "x", True, True)) == set(["6", "7", "8", "9", "10", "11"])
assert set(markings.get_markings(data, "x", False, True)) == set(["6", "7", "8", "9", "10"])
assert set(markings.get_markings(data, "x.y", False, False)) == set(["7"])
assert set(markings.get_markings(data, "x.y", True, False)) == set(["6", "7", "11"])
assert set(markings.get_markings(data, "x.y", True, True)) == set(["6", "7", "8", "11"])
assert set(markings.get_markings(data, "x.y", False, True)) == set(["7", "8"])
assert set(markings.get_markings(data, "x.y.[0]", False, False)) == set([])
assert set(markings.get_markings(data, "x.y.[0]", True, False)) == set(["6", "7", "11"])
assert set(markings.get_markings(data, "x.y.[0]", True, True)) == set(["6", "7", "11"])
assert set(markings.get_markings(data, "x.y.[0]", False, True)) == set([])
assert set(markings.get_markings(data, "x.y.[1]", False, False)) == set(["8"])
assert set(markings.get_markings(data, "x.y.[1]", True, False)) == set(["6", "7", "8", "11"])
assert set(markings.get_markings(data, "x.y.[1]", True, True)) == set(["6", "7", "8", "11"])
assert set(markings.get_markings(data, "x.y.[1]", False, True)) == set(["8"])
assert set(markings.get_markings(data, "x.z", False, False)) == set(["9"])
assert set(markings.get_markings(data, "x.z", True, False)) == set(["6", "9", "11"])
assert set(markings.get_markings(data, "x.z", True, True)) == set(["6", "9", "10", "11"])
assert set(markings.get_markings(data, "x.z", False, True)) == set(["9", "10"])
assert set(markings.get_markings(data, "x.z.foo1", False, False)) == set([])
assert set(markings.get_markings(data, "x.z.foo1", True, False)) == set(["6", "9", "11"])
assert set(markings.get_markings(data, "x.z.foo1", True, True)) == set(["6", "9", "11"])
assert set(markings.get_markings(data, "x.z.foo1", False, True)) == set([])
assert set(markings.get_markings(data, "x.z.foo2", False, False)) == set(["10"])
assert set(markings.get_markings(data, "x.z.foo2", True, False)) == set(["6", "9", "10", "11"])
assert set(markings.get_markings(data, "x.z.foo2", True, True)) == set(["6", "9", "10", "11"])
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
def test_remove_markings_object_level():
after = {
"title": "test title",
"description": "test description"
}
before = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1"]
}
markings.remove_markings(before, None, "marking-definition--1")
assert before == after
def test_remove_markings_multiple():
after = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--2"]
}
before = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2", "marking-definition--3"]
}
markings.remove_markings(before, None, ["marking-definition--1", "marking-definition--3"])
assert before == after
def test_remove_markings_bad_markings():
before = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2", "marking-definition--3"]
}
with pytest.raises(AssertionError):
markings.remove_markings(before, None, ["marking-definition--5"])
def test_clear_markings():
after = {
"title": "test title",
"description": "test description"
}
before = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2", "marking-definition--3"]
}
markings.clear_markings(before, None)
assert before == after
def test_is_marked_object_and_granular_combinations():
"""Test multiple combinations for inherited and descendant markings."""
test_tlo = \
{
"a": 333,
"b": "value",
"c": [
17,
"list value",
{
"g": "nested",
"h": 45
}
],
"x": {
"y": [
"hello",
88
],
"z": {
"foo1": "bar",
"foo2": 65
}
},
"object_marking_refs": "11",
"granular_markings": [
{
"marking_ref": "1",
"selectors": ["a"]
},
{
"marking_ref": "2",
"selectors": ["c"]
},
{
"marking_ref": "3",
"selectors": ["c.[1]"]
},
{
"marking_ref": "4",
"selectors": ["c.[2]"]
},
{
"marking_ref": "5",
"selectors": ["c.[2].g"]
},
{
"marking_ref": "6",
"selectors": ["x"]
},
{
"marking_ref": "7",
"selectors": ["x.y"]
},
{
"marking_ref": "8",
"selectors": ["x.y.[1]"]
},
{
"marking_ref": "9",
"selectors": ["x.z"]
},
{
"marking_ref": "10",
"selectors": ["x.z.foo2"]
},
]
}
assert markings.is_marked(test_tlo, "a", ["1"], False, False)
assert markings.is_marked(test_tlo, "a", ["1", "11"], True, False)
assert markings.is_marked(test_tlo, "a", ["1", "11"], True, True)
assert markings.is_marked(test_tlo, "a", ["1"], False, True)
assert markings.is_marked(test_tlo, "b", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "b", ["11"], True, False)
assert markings.is_marked(test_tlo, "b", ["11"], True, True)
assert markings.is_marked(test_tlo, "b", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "c", ["2"], False, False)
assert markings.is_marked(test_tlo, "c", ["2", "11"], True, False)
assert markings.is_marked(test_tlo, "c", ["2", "3", "4", "5", "11"], True, True)
assert markings.is_marked(test_tlo, "c", ["2", "3", "4", "5"], False, True)
assert markings.is_marked(test_tlo, "c.[0]", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "c.[0]", ["2", "11"], True, False)
assert markings.is_marked(test_tlo, "c.[0]", ["2", "11"], True, True)
assert markings.is_marked(test_tlo, "c.[0]", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "c.[1]", ["3"], False, False)
assert markings.is_marked(test_tlo, "c.[1]", ["2", "3", "11"], True, False)
assert markings.is_marked(test_tlo, "c.[1]", ["2", "3", "11"], True, True)
assert markings.is_marked(test_tlo, "c.[1]", ["3"], False, True)
assert markings.is_marked(test_tlo, "c.[2]", ["4"], False, False)
assert markings.is_marked(test_tlo, "c.[2]", ["2", "4", "11"], True, False)
assert markings.is_marked(test_tlo, "c.[2]", ["2", "4", "5", "11"], True, True)
assert markings.is_marked(test_tlo, "c.[2]", ["4", "5"], False, True)
assert markings.is_marked(test_tlo, "c.[2].g", ["5"], False, False)
assert markings.is_marked(test_tlo, "c.[2].g", ["2", "4", "5", "11"], True, False)
assert markings.is_marked(test_tlo, "c.[2].g", ["2", "4", "5", "11"], True, True)
assert markings.is_marked(test_tlo, "c.[2].g", ["5"], False, True)
assert markings.is_marked(test_tlo, "x", ["6"], False, False)
assert markings.is_marked(test_tlo, "x", ["6", "11"], True, False)
assert markings.is_marked(test_tlo, "x", ["6", "7", "8", "9", "10", "11"], True, True)
assert markings.is_marked(test_tlo, "x", ["6", "7", "8", "9", "10"], False, True)
assert markings.is_marked(test_tlo, "x.y", ["7"], False, False)
assert markings.is_marked(test_tlo, "x.y", ["6", "7", "11"], True, False)
assert markings.is_marked(test_tlo, "x.y", ["6", "7", "8", "11"], True, True)
assert markings.is_marked(test_tlo, "x.y", ["7", "8"], False, True)
assert markings.is_marked(test_tlo, "x.y.[0]", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "x.y.[0]", ["6", "7", "11"], True, False)
assert markings.is_marked(test_tlo, "x.y.[0]", ["6", "7", "11"], True, True)
assert markings.is_marked(test_tlo, "x.y.[0]", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "x.y.[1]", ["8"], False, False)
assert markings.is_marked(test_tlo, "x.y.[1]", ["6", "7", "8", "11"], True, False)
assert markings.is_marked(test_tlo, "x.y.[1]", ["6", "7", "8", "11"], True, True)
assert markings.is_marked(test_tlo, "x.y.[1]", ["8"], False, True)
assert markings.is_marked(test_tlo, "x.z", ["9"], False, False)
assert markings.is_marked(test_tlo, "x.z", ["6", "9", "11"], True, False)
assert markings.is_marked(test_tlo, "x.z", ["6", "9", "10", "11"], True, True)
assert markings.is_marked(test_tlo, "x.z", ["9", "10"], False, True)
assert markings.is_marked(test_tlo, "x.z.foo1", inherited=False, descendants=False) is False
assert markings.is_marked(test_tlo, "x.z.foo1", ["6", "9", "11"], True, False)
assert markings.is_marked(test_tlo, "x.z.foo1", ["6", "9", "11"], True, True)
assert markings.is_marked(test_tlo, "x.z.foo1", inherited=False, descendants=True) is False
assert markings.is_marked(test_tlo, "x.z.foo2", ["10"], False, False)
assert markings.is_marked(test_tlo, "x.z.foo2", ["6", "9", "10", "11"], True, False)
assert markings.is_marked(test_tlo, "x.z.foo2", ["6", "9", "10", "11"], True, True)
assert markings.is_marked(test_tlo, "x.z.foo2", ["10"], False, True)
def test_set_marking():
before = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--1", "marking-definition--2", "marking-definition--3"]
}
after = {
"title": "test title",
"description": "test description",
"object_marking_refs": ["marking-definition--7", "marking-definition--9"]
}
markings.set_markings(before, None, ["marking-definition--7", "marking-definition--9"])
for m in before["object_marking_refs"]:
assert m in ["marking-definition--7", "marking-definition--9"]
assert ["marking-definition--1", "marking-definition--2", "marking-definition--3"] not in before["object_marking_refs"]
for x in before["object_marking_refs"]:
assert x in after["object_marking_refs"]
@pytest.mark.parametrize("data", [
([]),
([""]),
(""),
(["marking-definition--7", 687])
])
def test_set_marking_bad_input(data):
before = {
"description": "test description",
"title": "foo",
"object_marking_refs": ["marking-definition--1"]
}
after = {
"description": "test description",
"title": "foo",
"object_marking_refs": ["marking-definition--1"]
}
with pytest.raises(AssertionError):
markings.set_markings(before, None, data)
assert before == after