encryption_algorithm was misspelled

uncomment test_file_example_encryption_error
added _check_object_constrains and properties_populated to base class
added ObjectConstraintError
added _check_object_constrains for File
stix2.1
Richard Piazza 2017-05-09 15:28:32 -04:00
parent 5de2cfe6a8
commit c3477b83bf
4 changed files with 51 additions and 18 deletions

View File

@ -49,6 +49,12 @@ class _STIXBase(collections.Mapping):
except ValueError as exc: except ValueError as exc:
raise InvalidValueError(self.__class__, prop_name, reason=str(exc)) raise InvalidValueError(self.__class__, prop_name, reason=str(exc))
def _check_object_constaints(self):
if self.granular_markings:
for m in self.granular_markings:
# TODO: check selectors
pass
def __init__(self, **kwargs): def __init__(self, **kwargs):
cls = self.__class__ cls = self.__class__
@ -77,10 +83,7 @@ class _STIXBase(collections.Mapping):
self._inner = setting_kwargs self._inner = setting_kwargs
if self.granular_markings: self._check_object_constaints()
for m in self.granular_markings:
# TODO: check selectors
pass
def __getitem__(self, key): def __getitem__(self, key):
return self._inner[key] return self._inner[key]
@ -116,6 +119,9 @@ class _STIXBase(collections.Mapping):
cls = type(self) cls = type(self)
return cls(**new_inner) return cls(**new_inner)
def properties_populated(self):
return list(self._inner.keys())
# Versioning API # Versioning API
def new_version(self, **kwargs): def new_version(self, **kwargs):

View File

@ -60,7 +60,7 @@ class DictionaryKeyError(STIXError, ValueError):
self.reason = reason self.reason = reason
def __str__(self): def __str__(self):
msg = "Invliad dictionary key {0.key}: ({0.reason})." msg = "Invalid dictionary key {0.key}: ({0.reason})."
return msg.format(self) return msg.format(self)
@ -90,6 +90,20 @@ class UnmodifiablePropertyError(STIXError, ValueError):
return msg.format(", ".join(self.unchangable_properties)) return msg.format(", ".join(self.unchangable_properties))
class ObjectConstraintError(STIXError, TypeError):
"""Violating some interproperty constraint of a STIX object type."""
def __init__(self, cls, fields):
super(ObjectConstraintError, self).__init__()
self.cls = cls
self.fields = sorted(list(fields))
def __str__(self):
msg = "The field(s) for {0}: ({1}) are not consistent."
return msg.format(self.cls.__name__,
", ".join(x for x in self.fields))
class RevokeError(STIXError, ValueError): class RevokeError(STIXError, ValueError):
"""Attempted to an operation on a revoked object""" """Attempted to an operation on a revoked object"""

View File

@ -6,6 +6,7 @@ and do not have a '_type' attribute.
""" """
from .base import _STIXBase, Observable from .base import _STIXBase, Observable
from .exceptions import ObjectConstraintError
from .properties import BinaryProperty, BooleanProperty, DictionaryProperty, \ from .properties import BinaryProperty, BooleanProperty, DictionaryProperty, \
EmbeddedObjectProperty, HashesProperty, HexProperty, IntegerProperty, \ EmbeddedObjectProperty, HashesProperty, HexProperty, IntegerProperty, \
ListProperty, ObjectReferenceProperty, Property, StringProperty, \ ListProperty, ObjectReferenceProperty, Property, StringProperty, \
@ -113,12 +114,24 @@ class File(Observable):
'accessed': TimestampProperty(), 'accessed': TimestampProperty(),
'parent_directory_ref': ObjectReferenceProperty(), 'parent_directory_ref': ObjectReferenceProperty(),
'is_encrypted': BooleanProperty(), 'is_encrypted': BooleanProperty(),
'encyption_algorithm': StringProperty(), 'encryption_algorithm': StringProperty(),
'decryption_key': StringProperty(), 'decryption_key': StringProperty(),
'contains_refs': ListProperty(ObjectReferenceProperty), 'contains_refs': ListProperty(ObjectReferenceProperty),
'content_ref': ObjectReferenceProperty(), 'content_ref': ObjectReferenceProperty(),
} }
def _check_object_constaints(self):
super(File, self)._check_object_constaints()
illegal_properties = []
current_properties = self.properties_populated()
if not self.is_encrypted:
for p in ["encryption_algorithm", "decryption_key"]:
if p in current_properties:
illegal_properties.append(p)
if illegal_properties:
illegal_properties.append("is_encrypted")
raise ObjectConstraintError(self.__class__, illegal_properties)
class IPv4Address(Observable): class IPv4Address(Observable):
_type = 'ipv4-addr' _type = 'ipv4-addr'
@ -258,7 +271,7 @@ class WindowsRegistryKey(Observable):
_properties = { _properties = {
'type': TypeProperty(_type), 'type': TypeProperty(_type),
'key': StringProperty(required=True), 'key': StringProperty(required=True),
'values': ListProperty(WindowsRegistryValueType), 'values': ListProperty(EmbeddedObjectProperty(type=WindowsRegistryValueType)),
# this is not the modified timestamps of the object itself # this is not the modified timestamps of the object itself
'modified': TimestampProperty(), 'modified': TimestampProperty(),
'creator_user_ref': ObjectReferenceProperty(), 'creator_user_ref': ObjectReferenceProperty(),

View File

@ -326,7 +326,7 @@ def test_file_example():
modified="2016-12-24T19:00:00Z", modified="2016-12-24T19:00:00Z",
accessed="2016-12-21T20:00:00Z", accessed="2016-12-21T20:00:00Z",
is_encrypted=True, is_encrypted=True,
encyption_algorithm="AES128-CBC", encryption_algorithm="AES128-CBC",
decryption_key="fred" decryption_key="fred"
) )
@ -339,19 +339,19 @@ def test_file_example():
assert f.modified == dt.datetime(2016, 12, 24, 19, 0, 0, tzinfo=pytz.utc) assert f.modified == dt.datetime(2016, 12, 24, 19, 0, 0, tzinfo=pytz.utc)
assert f.accessed == dt.datetime(2016, 12, 21, 20, 0, 0, tzinfo=pytz.utc) assert f.accessed == dt.datetime(2016, 12, 21, 20, 0, 0, tzinfo=pytz.utc)
assert f.is_encrypted assert f.is_encrypted
assert f.encyption_algorithm == "AES128-CBC" assert f.encryption_algorithm == "AES128-CBC"
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_encyption_error(): def test_file_example_encryption_error():
# f = stix2.File(name="qwerty.dll", with pytest.raises(stix2.exceptions.ObjectConstraintError) as excinfo:
# is_encrypted=False, stix2.File(name="qwerty.dll",
# encyption_algorithm="AES128-CBC" is_encrypted=False,
# ) encryption_algorithm="AES128-CBC"
# )
# assert f.name == "qwerty.dll"
# assert f.is_encrypted == False assert excinfo.value.cls == stix2.File
# assert f.encyption_algorithm == "AES128-CBC" assert excinfo.value.fields == ["encryption_algorithm", "is_encrypted"]
def test_ip4_address_example(): def test_ip4_address_example():