Merge pull request #21 from emmanvg/master

Minor Code Changes.
stix2.1
Greg Back 2017-06-08 10:04:09 -05:00 committed by GitHub
commit 41481139bf
3 changed files with 55 additions and 14 deletions

View File

@ -73,8 +73,7 @@ class _STIXBase(collections.Mapping):
failed_dependency_pairs = [] failed_dependency_pairs = []
for p in list_of_properties: for p in list_of_properties:
for dp in list_of_dependent_properties: for dp in list_of_dependent_properties:
if ((not hasattr(self, p) or (hasattr(self, p) and not self.__getattr__(p))) and if not self.get(p) and self.get(dp):
hasattr(self, dp) and self.__getattr__(dp)):
failed_dependency_pairs.append((p, dp)) failed_dependency_pairs.append((p, dp))
if failed_dependency_pairs: if failed_dependency_pairs:
raise DependentPropertiesError(self.__class__, failed_dependency_pairs) raise DependentPropertiesError(self.__class__, failed_dependency_pairs)
@ -125,12 +124,10 @@ class _STIXBase(collections.Mapping):
# Handle attribute access just like key access # Handle attribute access just like key access
def __getattr__(self, name): def __getattr__(self, name):
try: if name in self:
# Return attribute value.
return self.__getitem__(name) return self.__getitem__(name)
except KeyError: raise AttributeError("'%s' object has no attribute '%s'" %
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
(self.__class__.__name__, name))
def __setattr__(self, name, value): def __setattr__(self, name, value):
if name != '_inner' and not name.startswith("_STIXBase__"): if name != '_inner' and not name.startswith("_STIXBase__"):
@ -160,7 +157,7 @@ class _STIXBase(collections.Mapping):
def new_version(self, **kwargs): def new_version(self, **kwargs):
unchangable_properties = [] unchangable_properties = []
if hasattr(self, 'revoked') and self.revoked: if self.get("revoked"):
raise RevokeError("new_version") raise RevokeError("new_version")
new_obj_inner = copy.deepcopy(self._inner) new_obj_inner = copy.deepcopy(self._inner)
properties_to_change = kwargs.keys() properties_to_change = kwargs.keys()
@ -180,7 +177,7 @@ class _STIXBase(collections.Mapping):
return cls(**new_obj_inner) return cls(**new_obj_inner)
def revoke(self): def revoke(self):
if hasattr(self, 'revoked') and self.revoked: if self.get("revoked"):
raise RevokeError("revoke") raise RevokeError("revoke")
return self.new_version(revoked=True) return self.new_version(revoked=True)

View File

@ -6,7 +6,7 @@ and do not have a '_type' attribute.
""" """
from .base import _Extension, _Observable, _STIXBase from .base import _Extension, _Observable, _STIXBase
from .exceptions import AtLeastOnePropertyError from .exceptions import AtLeastOnePropertyError, DependentPropertiesError
from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty, from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, EnumProperty, EmbeddedObjectProperty, EnumProperty,
ExtensionsProperty, FloatProperty, HashesProperty, ExtensionsProperty, FloatProperty, HashesProperty,
@ -110,7 +110,9 @@ class EmailMessage(_Observable):
def _check_object_constraints(self): def _check_object_constraints(self):
super(EmailMessage, self)._check_object_constraints() super(EmailMessage, self)._check_object_constraints()
self._check_properties_dependency(["is_multipart"], ["body_multipart"]) self._check_properties_dependency(["is_multipart"], ["body_multipart"])
# self._dependency(["is_multipart"], ["body"], [False]) if self.get("is_multipart") is True and self.get("body"):
# 'body' MAY only be used if is_multipart is false.
raise DependentPropertiesError(self.__class__, [("is_multipart", "body")])
class ArchiveExt(_Extension): class ArchiveExt(_Extension):
@ -443,13 +445,13 @@ class Process(_Observable):
super(Process, self)._check_object_constraints() super(Process, self)._check_object_constraints()
try: try:
self._check_at_least_one_property() self._check_at_least_one_property()
if hasattr(self, 'extensions') and "windows-process-ext" in self.extensions: if "windows-process-ext" in self.get('extensions', {}):
self.extensions["windows-process-ext"]._check_at_least_one_property() self.extensions["windows-process-ext"]._check_at_least_one_property()
except AtLeastOnePropertyError as enclosing_exc: except AtLeastOnePropertyError as enclosing_exc:
if not hasattr(self, 'extensions'): if 'extensions' not in self:
raise enclosing_exc raise enclosing_exc
else: else:
if "windows-process-ext" in self.extensions: if "windows-process-ext" in self.get('extensions', {}):
self.extensions["windows-process-ext"]._check_at_least_one_property() self.extensions["windows-process-ext"]._check_at_least_one_property()

View File

@ -294,6 +294,31 @@ def test_parse_email_message(data):
assert odata.body_multipart[0].content_disposition == "inline" assert odata.body_multipart[0].content_disposition == "inline"
@pytest.mark.parametrize("data", [
"""
{
"type": "email-message",
"from_ref": "0",
"to_refs": ["1"],
"is_multipart": true,
"date": "1997-11-21T15:55:06.000Z",
"subject": "Saying Hello",
"body": "Cats are funny!"
}
"""
])
def test_parse_email_message_not_multipart(data):
valid_refs = {
"0": "email-addr",
"1": "email-addr",
}
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
stix2.parse_observable(data, valid_refs)
assert excinfo.value.cls == stix2.EmailMessage
assert excinfo.value.dependencies == [("is_multipart", "body")]
@pytest.mark.parametrize("data", [ @pytest.mark.parametrize("data", [
""""0": { """"0": {
"type": "file", "type": "file",
@ -913,6 +938,23 @@ def test_process_example_empty_with_extensions():
assert excinfo.value.properties == sorted(properties_of_extension) assert excinfo.value.properties == sorted(properties_of_extension)
def test_process_example_windows_process_ext():
proc = stix2.Process(pid=314,
name="foobar.exe",
extensions={
"windows-process-ext": {
"aslr_enabled": True,
"dep_enabled": True,
"priority": "HIGH_PRIORITY_CLASS",
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309"
}
})
assert proc.extensions["windows-process-ext"].aslr_enabled
assert proc.extensions["windows-process-ext"].dep_enabled
assert proc.extensions["windows-process-ext"].priority == "HIGH_PRIORITY_CLASS"
assert proc.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
def test_process_example_windows_process_ext_empty(): def test_process_example_windows_process_ext_empty():
with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo: with pytest.raises(stix2.exceptions.AtLeastOnePropertyError) as excinfo:
stix2.Process(pid=1221, stix2.Process(pid=1221,