Merge pull request #7 from rpiazza/cyber-observables

Cyber observables
stix2.1
Chris Lenk 2017-05-10 09:18:17 -04:00 committed by GitHub
commit aed8e2cdef
4 changed files with 51 additions and 18 deletions

View File

@ -47,6 +47,12 @@ class _STIXBase(collections.Mapping):
except ValueError as 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):
cls = self.__class__
@ -75,10 +81,7 @@ class _STIXBase(collections.Mapping):
self._inner = setting_kwargs
if self.granular_markings:
for m in self.granular_markings:
# TODO: check selectors
pass
self._check_object_constaints()
def __getitem__(self, key):
return self._inner[key]
@ -114,6 +117,9 @@ class _STIXBase(collections.Mapping):
cls = type(self)
return cls(**new_inner)
def properties_populated(self):
return list(self._inner.keys())
# Versioning API
def new_version(self, **kwargs):

View File

@ -60,7 +60,7 @@ class DictionaryKeyError(STIXError, ValueError):
self.reason = reason
def __str__(self):
msg = "Invliad dictionary key {0.key}: ({0.reason})."
msg = "Invalid dictionary key {0.key}: ({0.reason})."
return msg.format(self)
@ -90,6 +90,20 @@ class UnmodifiablePropertyError(STIXError, ValueError):
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):
"""Attempted to an operation on a revoked object"""

View File

@ -6,6 +6,7 @@ and do not have a '_type' attribute.
"""
from .base import Observable, _STIXBase
from .exceptions import ObjectConstraintError
from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
EmbeddedObjectProperty, HashesProperty, HexProperty,
IntegerProperty, ListProperty,
@ -114,12 +115,24 @@ class File(Observable):
'accessed': TimestampProperty(),
'parent_directory_ref': ObjectReferenceProperty(),
'is_encrypted': BooleanProperty(),
'encyption_algorithm': StringProperty(),
'encryption_algorithm': StringProperty(),
'decryption_key': StringProperty(),
'contains_refs': ListProperty(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):
_type = 'ipv4-addr'
@ -259,7 +272,7 @@ class WindowsRegistryKey(Observable):
_properties = {
'type': TypeProperty(_type),
'key': StringProperty(required=True),
'values': ListProperty(WindowsRegistryValueType),
'values': ListProperty(EmbeddedObjectProperty(type=WindowsRegistryValueType)),
# this is not the modified timestamps of the object itself
'modified': TimestampProperty(),
'creator_user_ref': ObjectReferenceProperty(),

View File

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