`stix-extension` to `extension-definition`

pull/1/head
Emmanuelle Vargas-Gonzalez 2020-12-22 21:59:18 -05:00
parent 4127ea9afd
commit ef2ef95c3a
6 changed files with 61 additions and 55 deletions

View File

@ -134,7 +134,7 @@ class _STIXBase(Mapping):
if extra_kwargs and not self._allow_custom: if extra_kwargs and not self._allow_custom:
ext_found = False ext_found = False
for key_id, ext_def in kwargs.get('extensions', {}).items(): for key_id, ext_def in kwargs.get('extensions', {}).items():
if key_id.startswith('stix-extension--'): if key_id.startswith('extension-definition--'):
ext_found = True ext_found = True
break break
if ext_found is False: if ext_found is False:

View File

@ -144,7 +144,7 @@ def dict_to_stix2(stix_dict, allow_custom=False, version=None):
# be parsed into STIX object, returned as is # be parsed into STIX object, returned as is
return stix_dict return stix_dict
for key_id, ext_def in stix_dict.get('extensions', {}).items(): for key_id, ext_def in stix_dict.get('extensions', {}).items():
if key_id.startswith('stix-extension--') and ext_def.get('extension_type', None): if key_id.startswith('extension-definition--') and ext_def.get('extension_type', None):
# prevents ParseError for unregistered objects when # prevents ParseError for unregistered objects when
# 'is_new_object' or 'is_extension_so' are set to True and allow_custom=False # 'is_new_object' or 'is_extension_so' are set to True and allow_custom=False
return stix_dict return stix_dict
@ -352,9 +352,9 @@ def _register_extension(
) )
if version == "2.1": if version == "2.1":
if not (ext_type.endswith('-ext') or ext_type.startswith('stix-extension--')): if not (ext_type.endswith('-ext') or ext_type.startswith('extension-definition--')):
raise ValueError( raise ValueError(
"Invalid extension type name '%s': must end with '-ext' or start with 'stix-extension--<UUID>'." % "Invalid extension type name '%s': must end with '-ext' or start with 'extension-definition--<UUID>'." %
ext_type, ext_type,
) )

View File

@ -672,8 +672,8 @@ class ExtensionsProperty(DictionaryProperty):
else: else:
if self.allow_custom: if self.allow_custom:
dictified[key] = subvalue dictified[key] = subvalue
elif key.startswith('stix-extension--'): elif key.startswith('extension-definition--'):
_validate_id(key, '2.1', 'stix-extension') _validate_id(key, '2.1', 'extension-definition')
dictified[key] = subvalue dictified[key] = subvalue
else: else:
raise CustomContentError("Can't parse unknown extension type: {}".format(key)) raise CustomContentError("Can't parse unknown extension type: {}".format(key))

View File

@ -1314,15 +1314,16 @@ def test_unregistered_top_level_extension_passes_with_allow_custom_false():
pattern_type='stix', pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z', valid_from='2014-02-20T09:00:00.000000Z',
extensions={ extensions={
'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': { 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': {
'extends_stix_object_definition': True, 'extension_type': 'toplevel-property-extension',
}, },
}, },
allow_custom=False, allow_custom=False,
) )
assert indicator.rank == 5 assert indicator.rank == 5
assert indicator.toxicity == 8 assert indicator.toxicity == 8
assert isinstance(indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], dict) assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['extension_type'] == 'toplevel-property-extension'
assert isinstance(indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], dict)
def test_unregistered_embedded_extension_passes_with_allow_custom_false(): def test_unregistered_embedded_extension_passes_with_allow_custom_false():
@ -1339,27 +1340,29 @@ def test_unregistered_embedded_extension_passes_with_allow_custom_false():
pattern_type='stix', pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z', valid_from='2014-02-20T09:00:00.000000Z',
extensions={ extensions={
'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': { 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': {
'extension_type': 'property-extension',
'rank': 5, 'rank': 5,
'toxicity': 8, 'toxicity': 8,
}, },
}, },
allow_custom=False, allow_custom=False,
) )
assert indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['rank'] == 5 assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['rank'] == 5
assert indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['toxicity'] == 8 assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['toxicity'] == 8
assert isinstance(indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], dict) assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['extension_type'] == 'property-extension'
assert isinstance(indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], dict)
def test_registered_top_level_extension_passes_with_allow_custom_false(): def test_registered_top_level_extension_passes_with_allow_custom_false():
@stix2.v21.CustomExtension( @stix2.v21.CustomExtension(
'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e', [ 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e', [
('rank', stix2.properties.IntegerProperty(required=True)), ('rank', stix2.properties.IntegerProperty(required=True)),
('toxicity', stix2.properties.IntegerProperty(required=True)), ('toxicity', stix2.properties.IntegerProperty(required=True)),
], ],
) )
class ExtensionFoo1: class ExtensionFoo1:
extends_stix_object_definition = True extension_type = 'toplevel-property-extension'
indicator = stix2.v21.Indicator( indicator = stix2.v21.Indicator(
id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c', id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
@ -1376,22 +1379,23 @@ def test_registered_top_level_extension_passes_with_allow_custom_false():
pattern_type='stix', pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z', valid_from='2014-02-20T09:00:00.000000Z',
extensions={ extensions={
'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': { 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e': {
'extends_stix_object_definition': True, 'extension_type': 'toplevel-property-extension',
}, },
}, },
allow_custom=False, allow_custom=False,
) )
assert indicator.rank == 5 assert indicator.rank == 5
assert indicator.toxicity == 8 assert indicator.toxicity == 8
assert isinstance(indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], ExtensionFoo1) assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e']['extension_type'] == 'toplevel-property-extension'
assert isinstance(indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e'], ExtensionFoo1)
def test_registered_embedded_extension_passes_with_allow_custom_false(): def test_registered_embedded_extension_passes_with_allow_custom_false():
@stix2.v21.CustomExtension( @stix2.v21.CustomExtension(
'stix-extension--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e', [ 'extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e', [
('rank', stix2.properties.IntegerProperty(required=True)), ('rank', stix2.properties.IntegerProperty(required=True)),
('toxicity', stix2.properties.IntegerProperty(required=True)), ('toxicity', stix2.properties.IntegerProperty(required=True)),
], ],
) )
class ExtensionFoo1: class ExtensionFoo1:
@ -1410,16 +1414,18 @@ def test_registered_embedded_extension_passes_with_allow_custom_false():
pattern_type='stix', pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z', valid_from='2014-02-20T09:00:00.000000Z',
extensions={ extensions={
'stix-extension--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e': { 'extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e': {
'extension_type': 'property-extension',
'rank': 5, 'rank': 5,
'toxicity': 8, 'toxicity': 8,
}, },
}, },
allow_custom=False, allow_custom=False,
) )
assert indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e']['rank'] == 5 assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e']['rank'] == 5
assert indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e']['toxicity'] == 8 assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e']['toxicity'] == 8
assert isinstance(indicator.extensions['stix-extension--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e'], ExtensionFoo1) assert indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e']['extension_type'] == 'property-extension'
assert isinstance(indicator.extensions['extension-definition--d83fce45-ef58-4c6c-a3ff-1fbc32e98c6e'], ExtensionFoo1)
def test_registered_new_extension_sdo_allow_custom_false(): def test_registered_new_extension_sdo_allow_custom_false():
@ -1428,7 +1434,7 @@ def test_registered_new_extension_sdo_allow_custom_false():
('name', stix2.properties.StringProperty(required=True)), ('name', stix2.properties.StringProperty(required=True)),
('some_property_name1', stix2.properties.StringProperty(required=True)), ('some_property_name1', stix2.properties.StringProperty(required=True)),
('some_property_name2', stix2.properties.StringProperty()), ('some_property_name2', stix2.properties.StringProperty()),
], 'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e9999', ], 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e9999',
) )
class MyFavSDO: class MyFavSDO:
pass pass
@ -1443,18 +1449,18 @@ def test_registered_new_extension_sdo_allow_custom_false():
'some_property_name1': 'value1', 'some_property_name1': 'value1',
'some_property_name2': 'value2', 'some_property_name2': 'value2',
# 'extensions': { # 'extensions': {
# 'stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e9999': STIXExtensiond83fce45ef584c6ca3f41fbc32e98c6e() # 'extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e9999': STIXExtensiond83fce45ef584c6ca3f41fbc32e98c6e()
# } # }
} }
sdo_object = stix2.parse(my_favorite_sdo) sdo_object = stix2.parse(my_favorite_sdo)
assert isinstance(sdo_object, MyFavSDO) assert isinstance(sdo_object, MyFavSDO)
assert isinstance( assert isinstance(
sdo_object.extensions['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e9999'], sdo_object.extensions['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e9999'],
stix2.v21.EXT_MAP['stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e9999'], stix2.v21.EXT_MAP['extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e9999'],
) )
sdo_serialized = sdo_object.serialize() sdo_serialized = sdo_object.serialize()
assert '"extensions": {"stix-extension--d83fce45-ef58-4c6c-a3f4-1fbc32e9999": {"is_new_object": true}}' in sdo_serialized assert '"extensions": {"extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e9999": {"extension_type": "new-sdo"}}' in sdo_serialized
def test_registered_new_extension_sco_allow_custom_false(): def test_registered_new_extension_sco_allow_custom_false():
@ -1462,7 +1468,7 @@ def test_registered_new_extension_sco_allow_custom_false():
'my-favorite-sco', [ 'my-favorite-sco', [
('name', stix2.properties.StringProperty(required=True)), ('name', stix2.properties.StringProperty(required=True)),
('some_network_protocol_field', stix2.properties.StringProperty(required=True)), ('some_network_protocol_field', stix2.properties.StringProperty(required=True)),
], ['name', 'some_network_protocol_field'], 'stix-extension--a932fcc6-e032-177c-126f-cb970a5a1fff', ], ['name', 'some_network_protocol_field'], 'extension-definition--a932fcc6-e032-177c-126f-cb970a5a1fff',
) )
class MyFavSCO: class MyFavSCO:
pass pass
@ -1474,7 +1480,7 @@ def test_registered_new_extension_sco_allow_custom_false():
'name': 'This is the name of my favorite SCO', 'name': 'This is the name of my favorite SCO',
'some_network_protocol_field': 'value', 'some_network_protocol_field': 'value',
# 'extensions': { # 'extensions': {
# 'stix-extension--a932fcc6-e032-177c-126f-cb970a5a1fff': { # 'extension-definition--a932fcc6-e032-177c-126f-cb970a5a1fff': {
# 'is_extension_so': true # 'is_extension_so': true
# } # }
# } # }
@ -1483,20 +1489,19 @@ def test_registered_new_extension_sco_allow_custom_false():
sco_object = stix2.parse(my_favorite_sco) sco_object = stix2.parse(my_favorite_sco)
assert isinstance(sco_object, MyFavSCO) assert isinstance(sco_object, MyFavSCO)
assert isinstance( assert isinstance(
sco_object.extensions['stix-extension--a932fcc6-e032-177c-126f-cb970a5a1fff'], sco_object.extensions['extension-definition--a932fcc6-e032-177c-126f-cb970a5a1fff'],
stix2.v21.EXT_MAP['stix-extension--a932fcc6-e032-177c-126f-cb970a5a1fff'], stix2.v21.EXT_MAP['extension-definition--a932fcc6-e032-177c-126f-cb970a5a1fff'],
) )
sco_serialized = sco_object.serialize() sco_serialized = sco_object.serialize()
assert '"extensions": {"stix-extension--a932fcc6-e032-177c-126f-cb970a5a1fff": {"is_extension_so": true}}' in sco_serialized assert '"extensions": {"extension-definition--a932fcc6-e032-177c-126f-cb970a5a1fff": {"extension_type": "new-sco"}}' in sco_serialized
def test_registered_new_extension_marking_allow_custom_false(): def test_registered_new_extension_marking_allow_custom_false():
@stix2.v21.CustomMarking( @stix2.v21.CustomMarking(
'my-favorite-marking', [ 'my-favorite-marking', [
('name', stix2.properties.StringProperty(required=True)),
('some_marking_field', stix2.properties.StringProperty(required=True)), ('some_marking_field', stix2.properties.StringProperty(required=True)),
], 'stix-extension--a932fcc6-e032-176c-126f-cb970a5a1fff', ], 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff',
) )
class MyFavMarking: class MyFavMarking:
pass pass
@ -1506,10 +1511,10 @@ def test_registered_new_extension_marking_allow_custom_false():
'spec_version': '2.1', 'spec_version': '2.1',
'id': 'marking-definition--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874', 'id': 'marking-definition--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874',
'name': 'This is the name of my favorite Marking', 'name': 'This is the name of my favorite Marking',
'some_marking_field': 'value',
'extensions': { 'extensions': {
'stix-extension--a932fcc6-e032-176c-126f-cb970a5a1fff': { 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff': {
'extends_stix_object_definition': True, 'extension_type': 'property-extension',
'some_marking_field': 'value',
}, },
}, },
} }
@ -1517,9 +1522,10 @@ def test_registered_new_extension_marking_allow_custom_false():
marking_object = stix2.parse(my_favorite_marking) marking_object = stix2.parse(my_favorite_marking)
assert isinstance(marking_object, stix2.v21.MarkingDefinition) assert isinstance(marking_object, stix2.v21.MarkingDefinition)
assert isinstance( assert isinstance(
marking_object.extensions['stix-extension--a932fcc6-e032-176c-126f-cb970a5a1fff'], marking_object.extensions['extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'],
stix2.v21.EXT_MAP['stix-extension--a932fcc6-e032-176c-126f-cb970a5a1fff'], stix2.v21.EXT_MAP['extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'],
) )
marking_serialized = marking_object.serialize() marking_serialized = marking_object.serialize(sort_keys=True)
assert '"extensions": {"stix-extension--a932fcc6-e032-176c-126f-cb970a5a1fff": {"extends_stix_object_definition": true}}' in marking_serialized assert '"extensions": {"extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff": ' \
'{"extension_type": "property-extension", "some_marking_field": "value"}}' in marking_serialized

View File

@ -19,9 +19,9 @@ from .base import (
) )
from .bundle import Bundle from .bundle import Bundle
from .common import ( from .common import (
TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, ExternalReference, TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking,
GranularMarking, KillChainPhase, LanguageContent, MarkingDefinition, ExtensionDefinition, ExternalReference, GranularMarking, KillChainPhase,
StatementMarking, STIXExtension, TLPMarking, LanguageContent, MarkingDefinition, StatementMarking, TLPMarking,
) )
from .observables import ( from .observables import (
URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem, URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
@ -66,7 +66,7 @@ OBJ_MAP = {
'threat-actor': ThreatActor, 'threat-actor': ThreatActor,
'tool': Tool, 'tool': Tool,
'sighting': Sighting, 'sighting': Sighting,
'stix-extension': STIXExtension, 'extension-definition': ExtensionDefinition,
'vulnerability': Vulnerability, 'vulnerability': Vulnerability,
} }
@ -112,9 +112,9 @@ EXT_MAP = {
__all__ = """ __all__ = """
Bundle, Bundle,
TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, ExternalReference, TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking, ExtensionDefinition,
GranularMarking, KillChainPhase, LanguageContent, MarkingDefinition, ExternalReference, GranularMarking, KillChainPhase, LanguageContent,
StatementMarking, STIXExtension, TLPMarking, MarkingDefinition, StatementMarking, TLPMarking,
URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem, URL, AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
CustomExtension, CustomObservable, Directory, DomainName, EmailAddress, CustomExtension, CustomObservable, Directory, DomainName, EmailAddress,

View File

@ -105,12 +105,12 @@ class LanguageContent(_STIXBase21):
]) ])
class STIXExtension(_STIXBase21): class ExtensionDefinition(_STIXBase21):
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <link here>`__.
""" """
_type = 'stix-extension' _type = 'extension-definition'
_properties = OrderedDict([ _properties = OrderedDict([
('type', TypeProperty(_type, spec_version='2.1')), ('type', TypeProperty(_type, spec_version='2.1')),
('spec_version', StringProperty(fixed='2.1')), ('spec_version', StringProperty(fixed='2.1')),