Rework kill chain phases

stix2.1
clenk 2017-04-07 17:34:06 -04:00
parent 93b8076ae3
commit bab8d187c9
5 changed files with 24 additions and 6 deletions

View File

@ -58,6 +58,7 @@ class _STIXBase(collections.Mapping):
if extra_kwargs:
raise TypeError("unexpected keyword arguments: " + str(extra_kwargs))
# Detect any missing required fields
required_fields = get_required_properties(cls._properties)
missing_kwargs = set(required_fields) - set(kwargs)
if missing_kwargs:

View File

@ -1,7 +1,8 @@
"""STIX 2 Common Data Types and Properties"""
from .base import _STIXBase
from .properties import Property, BooleanProperty, ReferenceProperty
from .properties import (Property, BooleanProperty, ReferenceProperty,
StringProperty)
from .utils import NOW
COMMON_PROPERTIES = {
@ -28,6 +29,6 @@ class ExternalReference(_STIXBase):
class KillChainPhase(_STIXBase):
_properties = {
'kill_chain_name': Property(required=True),
'phase_name': Property(required=True),
'kill_chain_name': StringProperty(required=True),
'phase_name': StringProperty(required=True),
}

View File

@ -110,7 +110,7 @@ class ListProperty(Property):
def clean(self, value):
try:
return [self.contained(x) for x in value]
return [self.contained(**x) if type(x) is dict else self.contained(x) for x in value]
except TypeError:
raise ValueError("must be an iterable over a type whose constructor creates an object from the value.")

View File

@ -1,7 +1,7 @@
"""STIX 2.0 Domain Objects"""
from .base import _STIXBase
from .common import COMMON_PROPERTIES
from .common import COMMON_PROPERTIES, KillChainPhase
from .properties import (StringProperty, IDProperty, ListProperty,
TypeProperty, Property)
from .utils import NOW
@ -109,7 +109,7 @@ class Malware(_STIXBase):
'labels': ListProperty(StringProperty, required=True),
'name': StringProperty(required=True),
'description': StringProperty(),
'kill_chain_phases': Property(),
'kill_chain_phases': ListProperty(KillChainPhase),
})

View File

@ -107,3 +107,19 @@ def test_parse_malware_invalid_labels():
with pytest.raises(ValueError) as excinfo:
stix2.parse(data)
assert "Invalid value for Malware 'labels'" in str(excinfo.value)
def test_parse_malware_kill_chain_phases():
kill_chain = """
"kill_chain_phases": [
{
"kill_chain_name": "lockheed-martin-cyber-kill-chain",
"phase_name": "reconnaissance"
}
]"""
data = EXPECTED_MALWARE.replace('malware"', 'malware",%s' % kill_chain)
mal = stix2.parse(data)
assert mal.kill_chain_phases[0].kill_chain_name == "lockheed-martin-cyber-kill-chain"
assert mal.kill_chain_phases[0].phase_name == "reconnaissance"
assert mal['kill_chain_phases'][0]['kill_chain_name'] == "lockheed-martin-cyber-kill-chain"
assert mal['kill_chain_phases'][0]['phase_name'] == "reconnaissance"