Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix existing tests and add new tests. Fixes #363 #376

Merged
merged 7 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sudo: false
os: linux
language: python
cache: pip
dist: xenial
Expand Down
10 changes: 9 additions & 1 deletion stix2/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import stix2

from .base import _Observable, _STIXBase
from .exceptions import ParseError
from .exceptions import DuplicateRegistrationError, ParseError
from .markings import _MarkingsMixin
from .utils import SCO21_EXT_REGEX, TYPE_REGEX, _get_dict

Expand Down Expand Up @@ -217,6 +217,8 @@ def _register_object(new_type, version=None):
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')

OBJ_MAP = STIX2_OBJ_MAPS[v]['objects']
if new_type._type in OBJ_MAP.keys():
raise DuplicateRegistrationError("STIX Object", new_type._type)
OBJ_MAP[new_type._type] = new_type


Expand All @@ -236,6 +238,8 @@ def _register_marking(new_marking, version=None):
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')

OBJ_MAP_MARKING = STIX2_OBJ_MAPS[v]['markings']
if new_marking._type in OBJ_MAP_MARKING.keys():
raise DuplicateRegistrationError("STIX Marking", new_marking._type)
OBJ_MAP_MARKING[new_marking._type] = new_marking


Expand All @@ -255,6 +259,8 @@ def _register_observable(new_observable, version=None):
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')

OBJ_MAP_OBSERVABLE = STIX2_OBJ_MAPS[v]['observables']
if new_observable._type in OBJ_MAP_OBSERVABLE.keys():
raise DuplicateRegistrationError("Cyber Observable", new_observable._type)
OBJ_MAP_OBSERVABLE[new_observable._type] = new_observable


Expand Down Expand Up @@ -319,6 +325,8 @@ def _register_observable_extension(
EXT_MAP = STIX2_OBJ_MAPS[v]['observable-extensions']

try:
if ext_type in EXT_MAP[observable_type].keys():
raise DuplicateRegistrationError("Observable Extension", ext_type)
EXT_MAP[observable_type][ext_type] = new_extension
except KeyError:
if observable_type not in OBJ_MAP_OBSERVABLE:
Expand Down
13 changes: 13 additions & 0 deletions stix2/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,16 @@ class STIXDeprecationWarning(DeprecationWarning):
Represents usage of a deprecated component of a STIX specification.
"""
pass


class DuplicateRegistrationError(STIXError):
"""A STIX object with the same type as an existing object is being registered"""

def __init__(self, obj_type, reg_obj_type):
super(DuplicateRegistrationError, self).__init__()
self.obj_type = obj_type
self.reg_obj_type = reg_obj_type

def __str__(self):
msg = "A(n) {0} with type '{1}' already exists and cannot be registered again"
return msg.format(self.obj_type, self.reg_obj_type)
102 changes: 0 additions & 102 deletions stix2/test/v20/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import stix2
from stix2 import core, exceptions

from .constants import IDENTITY_ID

BUNDLE = {
"type": "bundle",
"spec_version": "2.0",
Expand Down Expand Up @@ -68,109 +66,9 @@ def test_parse_observable_with_no_version():
assert v in str(obs_obj.__class__)


def test_register_object_with_version():
bundle = core.dict_to_stix2(BUNDLE, version='2.0')
core._register_object(bundle.objects[0].__class__, version='2.0')
v = 'v20'

assert bundle.objects[0].type in core.STIX2_OBJ_MAPS[v]['objects']
# spec_version is not in STIX 2.0, and is required in 2.1, so this
# suffices as a test for a STIX 2.0 object.
assert "spec_version" not in bundle.objects[0]


def test_register_marking_with_version():
core._register_marking(stix2.v20.TLP_WHITE.__class__, version='2.0')
v = 'v20'

assert stix2.v20.TLP_WHITE.definition._type in core.STIX2_OBJ_MAPS[v]['markings']
assert v in str(stix2.v20.TLP_WHITE.__class__)


@pytest.mark.xfail(reason="The default version is no longer 2.0", condition=stix2.DEFAULT_VERSION != "2.0")
def test_register_marking_with_no_version():
# Uses default version (2.0 in this case)
core._register_marking(stix2.v20.TLP_WHITE.__class__)
v = 'v20'

assert stix2.v20.TLP_WHITE.definition._type in core.STIX2_OBJ_MAPS[v]['markings']
assert v in str(stix2.v20.TLP_WHITE.__class__)


def test_register_observable_with_version():
observed_data = stix2.v20.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref=IDENTITY_ID,
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file",
"extensions": {
"ntfs-ext": {
"alternate_data_streams": [
{
"name": "second.stream",
"size": 25536,
},
],
},
},
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["0"],
},
},
)
core._register_observable(observed_data.objects['0'].__class__, version='2.0')
v = 'v20'

assert observed_data.objects['0'].type in core.STIX2_OBJ_MAPS[v]['observables']
assert v in str(observed_data.objects['0'].__class__)


def test_register_observable_extension_with_version():
observed_data = stix2.v20.ObservedData(
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
created_by_ref=IDENTITY_ID,
created="2016-04-06T19:58:16.000Z",
modified="2016-04-06T19:58:16.000Z",
first_observed="2015-12-21T19:00:00Z",
last_observed="2015-12-21T19:00:00Z",
number_observed=50,
objects={
"0": {
"name": "foo.exe",
"type": "file",
"extensions": {
"ntfs-ext": {
"alternate_data_streams": [
{
"name": "second.stream",
"size": 25536,
},
],
},
},
},
"1": {
"type": "directory",
"path": "/usr/home",
"contains_refs": ["0"],
},
},
)
core._register_observable_extension(observed_data.objects['0'], observed_data.objects['0'].extensions['ntfs-ext'].__class__, version='2.0')
v = 'v20'

assert observed_data.objects['0'].type in core.STIX2_OBJ_MAPS[v]['observables']
assert v in str(observed_data.objects['0'].__class__)

assert observed_data.objects['0'].extensions['ntfs-ext']._type in core.STIX2_OBJ_MAPS[v]['observable-extensions']['file']
assert v in str(observed_data.objects['0'].extensions['ntfs-ext'].__class__)
125 changes: 123 additions & 2 deletions stix2/test/v20/test_custom.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import pytest

import stix2
from stix2 import core
import stix2.v20

from ...exceptions import InvalidValueError
from ...exceptions import DuplicateRegistrationError, InvalidValueError
from .constants import FAKE_TIME, IDENTITY_ID, MARKING_DEFINITION_ID

IDENTITY_CUSTOM_PROP = stix2.v20.Identity(
Expand Down Expand Up @@ -449,7 +450,7 @@ def test_custom_observable_raises_exception():

def test_custom_observable_object_no_init_1():
@stix2.v20.CustomObservable(
'x-new-observable', [
'x-new-observable-1', [
('property1', stix2.properties.StringProperty()),
],
)
Expand Down Expand Up @@ -1011,3 +1012,123 @@ def __init__(self, **kwargs):
)

assert data == str(example)


@stix2.v20.CustomObject(
'x-new-type-2', [
('property1', stix2.properties.StringProperty()),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewType2(object):
pass


def test_register_custom_object_with_version():
custom_obj_1 = {
"type": "x-new-type-2",
"id": "x-new-type-2--00000000-0000-4000-8000-000000000007",
}

cust_obj_1 = core.dict_to_stix2(custom_obj_1, version='2.0')
v = 'v20'

assert cust_obj_1.type in core.STIX2_OBJ_MAPS[v]['objects']
# spec_version is not in STIX 2.0, and is required in 2.1, so this
# suffices as a test for a STIX 2.0 object.
assert "spec_version" not in cust_obj_1


def test_register_duplicate_object_with_version():
with pytest.raises(DuplicateRegistrationError) as excinfo:
@stix2.v20.CustomObject(
'x-new-type-2', [
('property1', stix2.properties.StringProperty()),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewType2(object):
pass
assert "cannot be registered again" in str(excinfo.value)


@stix2.v20.CustomObservable(
'x-new-observable-2', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObservable2(object):
pass


def test_register_observable_with_version():
custom_obs = NewObservable2(property1="Test Observable")
v = 'v20'

assert custom_obs.type in core.STIX2_OBJ_MAPS[v]['observables']


def test_register_duplicate_observable_with_version():
with pytest.raises(DuplicateRegistrationError) as excinfo:
@stix2.v20.CustomObservable(
'x-new-observable-2', [
('property1', stix2.properties.StringProperty()),
],
)
class NewObservable2(object):
pass
assert "cannot be registered again" in str(excinfo.value)


def test_register_marking_with_version():
@stix2.v20.CustomMarking(
'x-new-obj-2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2():
pass
v = 'v20'

no = NewObj2(property1='something')
assert no._type in core.STIX2_OBJ_MAPS[v]['markings']


def test_register_observable_extension_with_version():
@stix2.v20.CustomExtension(
stix2.v20.UserAccount, 'some-extension-2', [
('keys', stix2.properties.StringProperty(required=True)),
],
)
class SomeCustomExtension2:
pass

v = 'v20'
example = SomeCustomExtension2(keys='test123')

assert example._type in core.STIX2_OBJ_MAPS[v]['observable-extensions']['user-account']


def test_register_duplicate_observable_extension():
with pytest.raises(DuplicateRegistrationError) as excinfo:
@stix2.v20.CustomExtension(
stix2.v20.UserAccount, 'some-extension-2', [
('property1', stix2.properties.StringProperty(required=True)),
('property2', stix2.properties.IntegerProperty()),
],
)
class NewExtension2():
pass
assert "cannot be registered again" in str(excinfo.value)


def test_register_duplicate_marking():
with pytest.raises(DuplicateRegistrationError) as excinfo:
@stix2.v20.CustomMarking(
'x-new-obj-2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
class NewObj2():
pass
assert "cannot be registered again" in str(excinfo.value)
4 changes: 2 additions & 2 deletions stix2/test/v20/test_datastore_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ def test_filesystem_object_with_custom_property_in_bundle(fs_store):

def test_filesystem_custom_object(fs_store):
@stix2.v20.CustomObject(
'x-new-obj', [
'x-new-obj-2', [
('property1', stix2.properties.StringProperty(required=True)),
],
)
Expand All @@ -650,7 +650,7 @@ class NewObj():
assert newobj_r["property1"] == 'something'

# remove dir
shutil.rmtree(os.path.join(FS_PATH, "x-new-obj"), True)
shutil.rmtree(os.path.join(FS_PATH, "x-new-obj-2"), True)


def test_relationships(rel_fs_store):
Expand Down
2 changes: 1 addition & 1 deletion stix2/test/v20/test_datastore_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def test_memory_store_object_with_custom_property_in_bundle(mem_store):

def test_memory_store_custom_object(mem_store):
@CustomObject(
'x-new-obj', [
'x-new-obj-3', [
('property1', properties.StringProperty(required=True)),
],
)
Expand Down
2 changes: 1 addition & 1 deletion stix2/test/v20/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def test_dictionary_property_invalid(d):

def test_property_list_of_dictionary():
@stix2.v20.CustomObject(
'x-new-obj', [
'x-new-obj-4', [
('property1', ListProperty(DictionaryProperty(spec_version="2.0"), required=True)),
],
)
Expand Down
Loading