diff --git a/stix2/core.py b/stix2/core.py index a82c149..9165a2a 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -97,12 +97,8 @@ def dict_to_stix2(stix_dict, allow_custom=False, version=None): v = 'v' + stix_dict['spec_version'].replace('.', '') elif stix_dict['type'] == 'bundle': # bundles without spec_version are ambiguous. - if version: - v = 'v' + version.replace('.', '') - elif 'spec_version' in stix_dict: - v = 'v' + stix_dict['spec_version'].replace('.', '') - elif any('spec_version' in x for x in stix_dict['objects']): - # Only on 2.1 we are allowed multiple version of SDOs/SROs. + if any('spec_version' in x for x in stix_dict['objects']): + # Only on 2.1 we are allowed to have 'spec_version' in SDOs/SROs. v = 'v21' else: v = 'v' + stix2.DEFAULT_VERSION.replace('.', '') diff --git a/stix2/test/v20/test_bundle.py b/stix2/test/v20/test_bundle.py index fee0eff..907f632 100644 --- a/stix2/test/v20/test_bundle.py +++ b/stix2/test/v20/test_bundle.py @@ -200,3 +200,37 @@ def test_stix_object_property(): identity = stix2.v20.Identity(name="test", identity_class="individual") assert prop.clean(identity) is identity + + +def test_bundle_with_different_spec_objects(): + # This is a 2.0 case only... + + data = [ + { + "spec_version": "2.1", + "type": "indicator", + "id": "indicator--00000000-0000-4000-8000-000000000001", + "created": "2017-01-01T12:34:56.000Z", + "modified": "2017-01-01T12:34:56.000Z", + "pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']", + "valid_from": "2017-01-01T12:34:56Z", + "labels": [ + "malicious-activity", + ], + }, + { + "type": "malware", + "id": "malware--00000000-0000-4000-8000-000000000003", + "created": "2017-01-01T12:34:56.000Z", + "modified": "2017-01-01T12:34:56.000Z", + "name": "Cryptolocker", + "labels": [ + "ransomware", + ], + }, + ] + + with pytest.raises(ValueError) as excinfo: + stix2.v20.Bundle(objects=data) + + assert "Spec version 2.0 bundles don't yet support containing objects of a different spec version." in str(excinfo.value) diff --git a/stix2/test/v20/test_core.py b/stix2/test/v20/test_core.py index 4e4b50e..017344f 100644 --- a/stix2/test/v20/test_core.py +++ b/stix2/test/v20/test_core.py @@ -57,6 +57,15 @@ def test_parse_observable_with_version(): assert v in str(obs_obj.__class__) +@pytest.mark.xfail(reason="The default version is no longer 2.0", condition=stix2.DEFAULT_VERSION != "2.0") +def test_parse_observable_with_no_version(): + observable = {"type": "file", "name": "foo.exe"} + obs_obj = core.parse_observable(observable) + v = 'v20' + + 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') @@ -74,6 +83,16 @@ def test_register_marking_with_version(): 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", diff --git a/stix2/test/v20/test_datastore_memory.py b/stix2/test/v20/test_datastore_memory.py index a5c951f..495652b 100644 --- a/stix2/test/v20/test_datastore_memory.py +++ b/stix2/test/v20/test_datastore_memory.py @@ -299,7 +299,6 @@ def test_memory_store_object_creator_of_missing(mem_store): camp = Campaign( name="Scipio Africanus", objective="Defeat the Carthaginians", - created_by_ref="identity--e4196283-7420-4277-a7a3-d57f61ef1389", x_empire="Roman", allow_custom=True, ) diff --git a/stix2/test/v21/test_core.py b/stix2/test/v21/test_core.py index 6214f4c..19aa275 100644 --- a/stix2/test/v21/test_core.py +++ b/stix2/test/v21/test_core.py @@ -60,6 +60,15 @@ def test_parse_observable_with_version(): assert v in str(obs_obj.__class__) +@pytest.mark.xfail(reason="The default version is not 2.1", condition=stix2.DEFAULT_VERSION != "2.1") +def test_parse_observable_with_no_version(): + observable = {"type": "file", "name": "foo.exe"} + obs_obj = core.parse_observable(observable) + v = 'v21' + + assert v in str(obs_obj.__class__) + + def test_register_object_with_version(): bundle = core.dict_to_stix2(BUNDLE, version='2.1') core._register_object(bundle.objects[0].__class__) @@ -77,6 +86,16 @@ def test_register_marking_with_version(): assert v in str(stix2.v21.TLP_WHITE.__class__) +@pytest.mark.xfail(reason="The default version is not 2.1", condition=stix2.DEFAULT_VERSION != "2.1") +def test_register_marking_with_no_version(): + # Uses default version (2.0 in this case) + core._register_marking(stix2.v21.TLP_WHITE.__class__) + v = 'v21' + + assert stix2.v21.TLP_WHITE.definition._type in core.STIX2_OBJ_MAPS[v]['markings'] + assert v in str(stix2.v21.TLP_WHITE.__class__) + + def test_register_observable_with_default_version(): observed_data = stix2.v21.ObservedData( id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf", diff --git a/stix2/test/v21/test_datastore_memory.py b/stix2/test/v21/test_datastore_memory.py index 52ff239..eb30f07 100644 --- a/stix2/test/v21/test_datastore_memory.py +++ b/stix2/test/v21/test_datastore_memory.py @@ -306,7 +306,6 @@ def test_memory_store_object_creator_of_missing(mem_store): camp = Campaign( name="Scipio Africanus", objective="Defeat the Carthaginians", - created_by_ref="identity--e4196283-7420-4277-a7a3-d57f61ef1389", x_empire="Roman", allow_custom=True, )