added tests for process and file extensions

if no properties are passed to _check_at_least_one_property assume its all properties
when extensions are involved always check them in _check_at_least_one_property (caused by raising the exception on the enclosing type)
added _check_object_constaints to extensions, where appropriate
stix2.1
Richard Piazza 2017-05-17 15:33:28 -04:00
parent 7c71b9e577
commit f56ea8e951
3 changed files with 141 additions and 15 deletions

View File

@ -56,9 +56,14 @@ class _STIXBase(collections.Mapping):
if count > 1 or (at_least_one and count == 0): if count > 1 or (at_least_one and count == 0):
raise MutuallyExclusivePropertiesError(self.__class__, list_of_properties) raise MutuallyExclusivePropertiesError(self.__class__, list_of_properties)
def _check_at_least_one_property(self, list_of_properties): def _check_at_least_one_property(self, list_of_properties=None):
if not list_of_properties:
list_of_properties = sorted(list(self.__class__._properties.keys()))
if "type" in list_of_properties:
list_of_properties.remove("type")
current_properties = self.properties_populated() current_properties = self.properties_populated()
if not set(list_of_properties).intersection(current_properties): list_of_properties_populated = set(list_of_properties).intersection(current_properties)
if list_of_properties and (not list_of_properties_populated or list_of_properties_populated == {"extensions"}):
raise AtLeastOnePropertyError(self.__class__, list_of_properties) raise AtLeastOnePropertyError(self.__class__, list_of_properties)
def _check_properties_dependency(self, list_of_properties, list_of_dependent_properties, values=[]): def _check_properties_dependency(self, list_of_properties, list_of_dependent_properties, values=[]):

View File

@ -6,9 +6,11 @@ and do not have a '_type' attribute.
""" """
from .base import _Observable, _STIXBase from .base import _Observable, _STIXBase
from .exceptions import AtLeastOnePropertyError
from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty, from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty, ExtensionsProperty, FloatProperty, EmbeddedObjectProperty, EnumProperty,
HashesProperty, HexProperty, IntegerProperty, ListProperty, ExtensionsProperty, FloatProperty, HashesProperty,
HexProperty, IntegerProperty, ListProperty,
ObjectReferenceProperty, StringProperty, ObjectReferenceProperty, StringProperty,
TimestampProperty, TypeProperty) TimestampProperty, TypeProperty)
@ -133,6 +135,10 @@ class NTFSExt(_STIXBase):
'alternate_data_streams': ListProperty(EmbeddedObjectProperty(type=AlternateDataStream)), 'alternate_data_streams': ListProperty(EmbeddedObjectProperty(type=AlternateDataStream)),
} }
def _check_object_constaints(self):
super(NTFSExt, self)._check_object_constaints()
self._check_at_least_one_property()
class PDFExt(_STIXBase): class PDFExt(_STIXBase):
_properties = { _properties = {
@ -143,6 +149,10 @@ class PDFExt(_STIXBase):
'pdfid1': StringProperty(), 'pdfid1': StringProperty(),
} }
def _check_object_constaints(self):
super(PDFExt, self)._check_object_constaints()
self._check_at_least_one_property()
class RasterImageExt(_STIXBase): class RasterImageExt(_STIXBase):
_properties = { _properties = {
@ -153,6 +163,10 @@ class RasterImageExt(_STIXBase):
'exif_tags': DictionaryProperty(), 'exif_tags': DictionaryProperty(),
} }
def _check_object_constaints(self):
super(RasterImageExt, self)._check_object_constaints()
self._check_at_least_one_property()
class WindowsPEOptionalHeaderType(_STIXBase): class WindowsPEOptionalHeaderType(_STIXBase):
_properties = { _properties = {
@ -189,6 +203,10 @@ class WindowsPEOptionalHeaderType(_STIXBase):
'hashes': HashesProperty(), 'hashes': HashesProperty(),
} }
def _check_object_constaints(self):
super(WindowsPEOptionalHeaderType, self)._check_object_constaints()
self._check_at_least_one_property()
class WindowsPESection(_STIXBase): class WindowsPESection(_STIXBase):
_properties = { _properties = {
@ -338,6 +356,10 @@ class TCPExt(_STIXBase):
'dst_flags_hex': HexProperty(), 'dst_flags_hex': HexProperty(),
} }
def _check_object_constaints(self):
super(TCPExt, self)._check_object_constaints()
self._check_at_least_one_property()
class NetworkTraffic(_Observable): class NetworkTraffic(_Observable):
_type = 'network-traffic' _type = 'network-traffic'
@ -432,6 +454,19 @@ class Process(_Observable):
'child_refs': ListProperty(ObjectReferenceProperty), 'child_refs': ListProperty(ObjectReferenceProperty),
} }
def _check_object_constaints(self):
super(Process, self)._check_object_constaints()
try:
self._check_at_least_one_property()
if self.extensions and "windows-process-ext" in self.extensions:
self.extensions["windows-process-ext"]._check_at_least_one_property()
except AtLeastOnePropertyError as enclosing_exc:
if not self.extensions:
raise enclosing_exc
else:
if "windows-process-ext" in self.extensions:
self.extensions["windows-process-ext"]._check_at_least_one_property()
class Software(_Observable): class Software(_Observable):
_type = 'software' _type = 'software'

View File

@ -576,6 +576,35 @@ def test_file_example():
assert f.decryption_key == "fred" # does the key have a format we can test for? assert f.decryption_key == "fred" # does the key have a format we can test for?
def test_file_example_with_NTFSExt():
f = stix2.File(name="abc.txt",
extensions={
"ntfs-ext": {
"alternate_data_streams": [
{
"name": "second.stream",
"size": 25536
}
]
}
})
assert f.name == "abc.txt"
assert f.extensions["ntfs-ext"].alternate_data_streams[0].size == 25536
def test_file_example_with_empty_NTFSExt():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.File(name="abc.txt",
extensions={
"ntfs-ext": {
}
})
assert excinfo.value.cls == stix2.NTFSExt
assert excinfo.value.fields == sorted(list(stix2.NTFSExt._properties.keys()))
def test_file_example_with_PDFExt(): def test_file_example_with_PDFExt():
f = stix2.File(name="qwerty.dll", f = stix2.File(name="qwerty.dll",
extensions={ extensions={
@ -751,20 +780,77 @@ def test_mutex_example():
assert m.name == "barney" assert m.name == "barney"
def test_process_example():
p = stix2.Process(_valid_refs=["0"],
pid=1221,
name="gedit-bin",
created="2016-01-20T14:11:25.55Z",
arguments=["--new-window"],
binary_ref="0")
assert p.name == "gedit-bin"
assert p.arguments == ["--new-window"]
def test_process_example_empty_error():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.Process()
assert excinfo.value.cls == stix2.Process
properties_of_process = list(stix2.Process._properties.keys())
properties_of_process.remove("type")
assert excinfo.value.fields == sorted(properties_of_process)
def test_process_example_empty_with_extensions():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.Process(extensions={
"windows-process-ext": {}
})
assert excinfo.value.cls == stix2.WindowsProcessExt
properties_of_extension = list(stix2.WindowsProcessExt._properties.keys())
assert excinfo.value.fields == sorted(properties_of_extension)
def test_process_example_windows_process_ext_empty():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.Process(pid=1221,
name="gedit-bin",
extensions={
"windows-process-ext": {}
})
assert excinfo.value.cls == stix2.WindowsProcessExt
properties_of_extension = list(stix2.WindowsProcessExt._properties.keys())
assert excinfo.value.fields == sorted(properties_of_extension)
def test_process_example_extensions_empty():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.Process(extensions={
})
assert excinfo.value.cls == stix2.Process
properties_of_process = list(stix2.Process._properties.keys())
properties_of_process.remove("type")
assert excinfo.value.fields == sorted(properties_of_process)
def test_process_example_with_WindowsProcessExt_Object(): def test_process_example_with_WindowsProcessExt_Object():
f = stix2.Process(extensions={ p = stix2.Process(extensions={
"windows-process-ext": stix2.WindowsProcessExt(aslr_enabled=True, "windows-process-ext": stix2.WindowsProcessExt(aslr_enabled=True,
dep_enabled=True, dep_enabled=True,
priority="HIGH_PRIORITY_CLASS", priority="HIGH_PRIORITY_CLASS",
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309") # noqa owner_sid="S-1-5-21-186985262-1144665072-74031268-1309") # noqa
}) })
assert f.extensions["windows-process-ext"].dep_enabled assert p.extensions["windows-process-ext"].dep_enabled
assert f.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309" assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
def test_process_example_with_WindowsServiceExt(): def test_process_example_with_WindowsServiceExt():
f = stix2.Process(extensions={ p = stix2.Process(extensions={
"windows-service-ext": { "windows-service-ext": {
"service_name": "sirvizio", "service_name": "sirvizio",
"display_name": "Sirvizio", "display_name": "Sirvizio",
@ -774,12 +860,12 @@ def test_process_example_with_WindowsServiceExt():
} }
}) })
assert f.extensions["windows-service-ext"].service_name == "sirvizio" assert p.extensions["windows-service-ext"].service_name == "sirvizio"
assert f.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS" assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
def test_process_example_with_WindowsProcessServiceExt(): def test_process_example_with_WindowsProcessServiceExt():
f = stix2.Process(extensions={ p = stix2.Process(extensions={
"windows-service-ext": { "windows-service-ext": {
"service_name": "sirvizio", "service_name": "sirvizio",
"display_name": "Sirvizio", "display_name": "Sirvizio",
@ -795,10 +881,10 @@ def test_process_example_with_WindowsProcessServiceExt():
} }
}) })
assert f.extensions["windows-service-ext"].service_name == "sirvizio" assert p.extensions["windows-service-ext"].service_name == "sirvizio"
assert f.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS" assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
assert f.extensions["windows-process-ext"].dep_enabled assert p.extensions["windows-process-ext"].dep_enabled
assert f.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309" assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
def test_software_example(): def test_software_example():