2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2018-07-05 21:23:25 +02:00
|
|
|
from stix2 import exceptions, markings
|
|
|
|
from stix2.v20 import TLP_AMBER, Malware
|
2017-08-21 19:57:01 +02:00
|
|
|
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
from ...exceptions import MarkingNotFoundError
|
2018-02-21 18:02:08 +01:00
|
|
|
from .constants import FAKE_TIME, MALWARE_ID
|
2017-08-21 19:57:01 +02:00
|
|
|
from .constants import MALWARE_KWARGS as MALWARE_KWARGS_CONST
|
2018-02-21 18:02:08 +01:00
|
|
|
from .constants import MARKING_IDS
|
2017-08-18 18:36:34 +02:00
|
|
|
|
2017-06-09 20:22:56 +02:00
|
|
|
"""Tests for the Data Markings API."""
|
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
MALWARE_KWARGS = MALWARE_KWARGS_CONST.copy()
|
|
|
|
MALWARE_KWARGS.update({
|
|
|
|
'id': MALWARE_ID,
|
|
|
|
'created': FAKE_TIME,
|
|
|
|
'modified': FAKE_TIME,
|
|
|
|
})
|
|
|
|
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
(
|
|
|
|
Malware(**MALWARE_KWARGS),
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
MARKING_IDS[0],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
MALWARE_KWARGS,
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
MARKING_IDS[0],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
Malware(**MALWARE_KWARGS),
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[TLP_AMBER.id],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
TLP_AMBER,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2017-09-01 22:37:49 +02:00
|
|
|
def test_add_markings_one_marking(data):
|
|
|
|
before = data[0]
|
|
|
|
after = data[1]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-10-02 18:28:47 +02:00
|
|
|
before = markings.add_markings(before, data[2], None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-23 19:07:22 +02:00
|
|
|
for m in before["object_marking_refs"]:
|
|
|
|
assert m in after["object_marking_refs"]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_add_markings_multiple_marking():
|
2017-08-23 19:07:22 +02:00
|
|
|
before = Malware(
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
|
|
|
|
after = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1]],
|
2017-08-23 19:12:40 +02:00
|
|
|
**MALWARE_KWARGS
|
2017-08-23 19:07:22 +02:00
|
|
|
)
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.add_markings(before, [MARKING_IDS[0], MARKING_IDS[1]], None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
for m in before["object_marking_refs"]:
|
|
|
|
assert m in after["object_marking_refs"]
|
|
|
|
|
|
|
|
|
|
|
|
def test_add_markings_combination():
|
2017-08-21 19:57:01 +02:00
|
|
|
before = Malware(
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
after = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1]],
|
|
|
|
granular_markings=[
|
2017-06-09 20:22:56 +02:00
|
|
|
{
|
2017-08-21 19:57:01 +02:00
|
|
|
"selectors": ["labels"],
|
2018-07-13 17:10:05 +02:00
|
|
|
"marking_ref": MARKING_IDS[2],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
2017-08-21 19:57:01 +02:00
|
|
|
"selectors": ["name"],
|
2018-07-13 17:10:05 +02:00
|
|
|
"marking_ref": MARKING_IDS[3],
|
|
|
|
},
|
2017-08-21 19:57:01 +02:00
|
|
|
],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.add_markings(before, MARKING_IDS[0], None)
|
|
|
|
before = markings.add_markings(before, MARKING_IDS[1], None)
|
|
|
|
before = markings.add_markings(before, MARKING_IDS[2], "labels")
|
|
|
|
before = markings.add_markings(before, MARKING_IDS[3], "name")
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
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"]
|
|
|
|
|
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
([""]),
|
|
|
|
(""),
|
|
|
|
([MARKING_IDS[0], 456]),
|
|
|
|
],
|
|
|
|
)
|
2017-06-09 20:22:56 +02:00
|
|
|
def test_add_markings_bad_markings(data):
|
2017-08-21 19:57:01 +02:00
|
|
|
before = Malware(
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
with pytest.raises(exceptions.InvalidValueError):
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.add_markings(before, data, None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
assert "object_marking_refs" not in before
|
|
|
|
|
|
|
|
|
|
|
|
GET_MARKINGS_TEST_DATA = \
|
|
|
|
{
|
|
|
|
"a": 333,
|
|
|
|
"b": "value",
|
|
|
|
"c": [
|
|
|
|
17,
|
|
|
|
"list value",
|
|
|
|
{
|
|
|
|
"g": "nested",
|
2018-07-13 17:10:05 +02:00
|
|
|
"h": 45,
|
|
|
|
},
|
2017-06-09 20:22:56 +02:00
|
|
|
],
|
|
|
|
"x": {
|
|
|
|
"y": [
|
|
|
|
"hello",
|
2018-07-13 17:10:05 +02:00
|
|
|
88,
|
2017-06-09 20:22:56 +02:00
|
|
|
],
|
|
|
|
"z": {
|
|
|
|
"foo1": "bar",
|
2018-07-13 17:10:05 +02:00
|
|
|
"foo2": 65,
|
|
|
|
},
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
"object_marking_refs": ["11"],
|
|
|
|
"granular_markings": [
|
|
|
|
{
|
|
|
|
"marking_ref": "1",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["a"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "2",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "3",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[1]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "4",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[2]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "5",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[2].g"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "6",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "7",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.y"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "8",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.y.[1]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "9",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.z"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "10",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.z.foo2"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
2018-07-13 17:10:05 +02:00
|
|
|
],
|
2017-06-09 20:22:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@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"])
|
|
|
|
|
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
(
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
Malware(**MALWARE_KWARGS),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
MALWARE_KWARGS,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2017-09-01 22:37:49 +02:00
|
|
|
def test_remove_markings_object_level(data):
|
|
|
|
before = data[0]
|
|
|
|
after = data[1]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.remove_markings(before, MARKING_IDS[0], None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
assert 'object_marking_refs' not in before
|
|
|
|
assert 'object_marking_refs' not in after
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-09-01 22:37:49 +02:00
|
|
|
modified = after['modified']
|
2017-09-01 16:50:01 +02:00
|
|
|
after = markings.remove_markings(after, MARKING_IDS[0], None)
|
2017-09-01 22:37:49 +02:00
|
|
|
modified == after['modified']
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
(
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[1]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
[MARKING_IDS[0], MARKING_IDS[2]],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[1]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
[MARKING_IDS[0], MARKING_IDS[2]],
|
|
|
|
),
|
|
|
|
(
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[1]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
[MARKING_IDS[0], TLP_AMBER],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2017-09-01 22:37:49 +02:00
|
|
|
def test_remove_markings_multiple(data):
|
|
|
|
before = data[0]
|
|
|
|
after = data[1]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-10-02 18:28:47 +02:00
|
|
|
before = markings.remove_markings(before, data[2], None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
assert before['object_marking_refs'] == after['object_marking_refs']
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_remove_markings_bad_markings():
|
2017-08-25 21:56:39 +02:00
|
|
|
before = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
Improved the exception class hierarchy:
- Removed all plain python base classes (e.g. ValueError, TypeError)
- Renamed InvalidPropertyConfigurationError -> PropertyPresenceError,
since incorrect values could be considered a property config error, and
I really just wanted this class to apply to presence (co-)constraint
violations.
- Added ObjectConfigurationError as a superclass of InvalidValueError,
PropertyPresenceError, and any other exception that could be raised
during _STIXBase object init, which is when the spec compliance
checks happen. This class is intended to represent general spec
violations.
- Did some class reordering in exceptions.py, so all the
ObjectConfigurationError subclasses were together.
Changed how property "cleaning" errors were handled:
- Previous docs said they should all be ValueErrors, but that would require
extra exception check-and-replace complexity in the property
implementations, so that requirement is removed. Doc is changed to just
say that cleaning problems should cause exceptions to be raised.
_STIXBase._check_property() now handles most exception types, not just
ValueError.
- Decided to try chaining the original clean error to the InvalidValueError,
in case the extra diagnostics would be helpful in the future. This is
done via 'six' adapter function and only works on python3.
- A small amount of testing was removed, since it was looking at custom
exception properties which became unavailable once the exception was
replaced with InvalidValueError.
Did another pass through unit tests to fix breakage caused by the changed
exception class hierarchy.
Removed unnecessary observable extension handling code from
parse_observable(), since it was all duplicated in ExtensionsProperty.
The redundant code in parse_observable() had different exception behavior
than ExtensionsProperty, which makes the API inconsistent and unit tests
more complicated. (Problems in ExtensionsProperty get replaced with
InvalidValueError, but extensions problems handled directly in
parse_observable() don't get the same replacement, and so the exception
type is different.)
Redid the workbench monkeypatching. The old way was impossible to make
work, and had caused ugly ripple effect hackage in other parts of the
codebase. Now, it replaces the global object maps with factory functions
which behave the same way when called, as real classes. Had to fix up a
few unit tests to get them all passing with this monkeypatching in place.
Also remove all the xfail markings in the workbench test suite, since all
tests now pass.
Since workbench monkeypatching isn't currently affecting any unit tests,
tox.ini was simplified to remove the special-casing for running the
workbench tests.
Removed the v20 workbench test suite, since the workbench currently only
works with the latest stix object version.
2019-07-19 20:50:11 +02:00
|
|
|
with pytest.raises(MarkingNotFoundError) as excinfo:
|
2017-09-01 16:50:01 +02:00
|
|
|
markings.remove_markings(before, [MARKING_IDS[4]], None)
|
2017-08-25 21:56:39 +02:00
|
|
|
assert str(excinfo.value) == "Marking ['%s'] was not found in Malware!" % MARKING_IDS[4]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
(
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
Malware(**MALWARE_KWARGS),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
MALWARE_KWARGS,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2017-09-01 22:37:49 +02:00
|
|
|
def test_clear_markings(data):
|
|
|
|
before = data[0]
|
|
|
|
after = data[1]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
before = markings.clear_markings(before, None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
assert 'object_marking_refs' not in before
|
|
|
|
assert 'object_marking_refs' not in after
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_is_marked_object_and_granular_combinations():
|
|
|
|
"""Test multiple combinations for inherited and descendant markings."""
|
2017-08-25 21:56:39 +02:00
|
|
|
test_sdo = \
|
2017-06-09 20:22:56 +02:00
|
|
|
{
|
|
|
|
"a": 333,
|
|
|
|
"b": "value",
|
|
|
|
"c": [
|
|
|
|
17,
|
|
|
|
"list value",
|
|
|
|
{
|
|
|
|
"g": "nested",
|
2018-07-13 17:10:05 +02:00
|
|
|
"h": 45,
|
|
|
|
},
|
2017-06-09 20:22:56 +02:00
|
|
|
],
|
|
|
|
"x": {
|
|
|
|
"y": [
|
|
|
|
"hello",
|
2018-07-13 17:10:05 +02:00
|
|
|
88,
|
2017-06-09 20:22:56 +02:00
|
|
|
],
|
|
|
|
"z": {
|
|
|
|
"foo1": "bar",
|
2018-07-13 17:10:05 +02:00
|
|
|
"foo2": 65,
|
|
|
|
},
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
"object_marking_refs": "11",
|
|
|
|
"granular_markings": [
|
|
|
|
{
|
|
|
|
"marking_ref": "1",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["a"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "2",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "3",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[1]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "4",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[2]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "5",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["c.[2].g"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "6",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "7",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.y"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "8",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.y.[1]"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "9",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.z"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"marking_ref": "10",
|
2018-07-13 17:10:05 +02:00
|
|
|
"selectors": ["x.z.foo2"],
|
2017-06-09 20:22:56 +02:00
|
|
|
},
|
2018-07-13 17:10:05 +02:00
|
|
|
],
|
2017-06-09 20:22:56 +02:00
|
|
|
}
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["1"], "a", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["1", "11"], "a", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["1", "11"], "a", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["1"], "a", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
|
|
|
assert markings.is_marked(test_sdo, "b", inherited=False, descendants=False) is False
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["11"], "b", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["11"], "b", True, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
assert markings.is_marked(test_sdo, "b", inherited=False, descendants=True) is False
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["2"], "c", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "11"], "c", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "3", "4", "5", "11"], "c", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "3", "4", "5"], "c", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
|
|
|
assert markings.is_marked(test_sdo, "c.[0]", inherited=False, descendants=False) is False
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["2", "11"], "c.[0]", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "11"], "c.[0]", True, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
assert markings.is_marked(test_sdo, "c.[0]", inherited=False, descendants=True) is False
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["3"], "c.[1]", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "3", "11"], "c.[1]", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "3", "11"], "c.[1]", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["3"], "c.[1]", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["4"], "c.[2]", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "4", "11"], "c.[2]", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "4", "5", "11"], "c.[2]", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["4", "5"], "c.[2]", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["5"], "c.[2].g", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "4", "5", "11"], "c.[2].g", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["2", "4", "5", "11"], "c.[2].g", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["5"], "c.[2].g", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["6"], "x", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "11"], "x", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "8", "9", "10", "11"], "x", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "8", "9", "10"], "x", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["7"], "x.y", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "11"], "x.y", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "8", "11"], "x.y", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["7", "8"], "x.y", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
|
|
|
assert markings.is_marked(test_sdo, "x.y.[0]", inherited=False, descendants=False) is False
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "11"], "x.y.[0]", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "11"], "x.y.[0]", True, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
assert markings.is_marked(test_sdo, "x.y.[0]", inherited=False, descendants=True) is False
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["8"], "x.y.[1]", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "8", "11"], "x.y.[1]", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "7", "8", "11"], "x.y.[1]", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["8"], "x.y.[1]", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["9"], "x.z", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "11"], "x.z", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "10", "11"], "x.z", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["9", "10"], "x.z", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
|
|
|
assert markings.is_marked(test_sdo, "x.z.foo1", inherited=False, descendants=False) is False
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "11"], "x.z.foo1", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "11"], "x.z.foo1", True, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
assert markings.is_marked(test_sdo, "x.z.foo1", inherited=False, descendants=True) is False
|
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["10"], "x.z.foo2", False, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "10", "11"], "x.z.foo2", True, False)
|
|
|
|
assert markings.is_marked(test_sdo, ["6", "9", "10", "11"], "x.z.foo2", True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["10"], "x.z.foo2", False, True)
|
2017-08-25 21:56:39 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
assert markings.is_marked(test_sdo, ["11"], None, True, True)
|
|
|
|
assert markings.is_marked(test_sdo, ["2"], None, True, True) is False
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
(
|
|
|
|
Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
Malware(**MALWARE_KWARGS),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
dict(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
),
|
|
|
|
MALWARE_KWARGS,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2017-09-01 22:37:49 +02:00
|
|
|
def test_is_marked_no_markings(data):
|
|
|
|
marked = data[0]
|
|
|
|
nonmarked = data[1]
|
|
|
|
|
|
|
|
assert markings.is_marked(marked)
|
|
|
|
assert markings.is_marked(nonmarked) is False
|
|
|
|
|
|
|
|
|
2017-06-09 20:22:56 +02:00
|
|
|
def test_set_marking():
|
2017-08-21 19:57:01 +02:00
|
|
|
before = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
after = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[4], MARKING_IDS[5]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.set_markings(before, [MARKING_IDS[4], MARKING_IDS[5]], None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
for m in before["object_marking_refs"]:
|
2017-08-21 19:57:01 +02:00
|
|
|
assert m in [MARKING_IDS[4], MARKING_IDS[5]]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
2017-08-21 19:57:01 +02:00
|
|
|
assert [MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]] not in before["object_marking_refs"]
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
for x in before["object_marking_refs"]:
|
|
|
|
assert x in after["object_marking_refs"]
|
|
|
|
|
|
|
|
|
2018-07-13 17:10:05 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"data", [
|
|
|
|
([""]),
|
|
|
|
(""),
|
|
|
|
([MARKING_IDS[4], 687]),
|
|
|
|
],
|
|
|
|
)
|
2017-06-09 20:22:56 +02:00
|
|
|
def test_set_marking_bad_input(data):
|
2017-08-21 19:57:01 +02:00
|
|
|
before = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
after = Malware(
|
|
|
|
object_marking_refs=[MARKING_IDS[0]],
|
|
|
|
**MALWARE_KWARGS
|
|
|
|
)
|
|
|
|
with pytest.raises(exceptions.InvalidValueError):
|
2017-09-01 16:50:01 +02:00
|
|
|
before = markings.set_markings(before, data, None)
|
2017-06-09 20:22:56 +02:00
|
|
|
|
|
|
|
assert before == after
|