From 806c6c52d9f00e70a1e78f892ace7b89b31b3fc2 Mon Sep 17 00:00:00 2001 From: Zach Rush Date: Mon, 25 Nov 2019 15:52:50 -0500 Subject: [PATCH] Added tests for other changes, and moved attribute defaults to an init function --- stix2/test/v21/test_observed_data.py | 25 ++++++++++++++++++++++++- stix2/test/v21/test_properties.py | 10 ++++++++++ stix2/v21/observables.py | 27 +++++++++------------------ stix2/v21/sdo.py | 12 +++++++----- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py index 43d1ff7..2910ba1 100644 --- a/stix2/test/v21/test_observed_data.py +++ b/stix2/test/v21/test_observed_data.py @@ -1117,6 +1117,28 @@ def test_network_traffic_socket_example(): assert nt.extensions['socket-ext'].socket_type == "SOCK_STREAM" +def test_incorrect_socket_options(): + with pytest.raises(ValueError) as excinfo: + stix2.v21.SocketExt( + is_listening=True, + address_family="AF_INET", + protocol_family="PF_INET", + socket_type="SOCK_STREAM", + options={"RCVTIMEO": 100}, + ) + assert "Incorrect options key" == str(excinfo.value) + + with pytest.raises(ValueError) as excinfo: + stix2.v21.SocketExt( + is_listening=True, + address_family="AF_INET", + protocol_family="PF_INET", + socket_type="SOCK_STREAM", + options={"SO_RCVTIMEO": '100'}, + ) + assert "Options value must be an integer" == str(excinfo.value) + + def test_network_traffic_tcp_example(): h = stix2.v21.TCPExt(src_flags_hex="00000002") nt = stix2.v21.NetworkTraffic( @@ -1374,7 +1396,8 @@ def test_x509_certificate_error(): ) assert excinfo.value.cls == stix2.v21.X509Certificate - assert "X.509 Certificate objects must contain at least one object specific property" in str(excinfo.value) + assert "At least one of the" in str(excinfo.value) + assert "properties for X509Certificate must be populated." in str(excinfo.value) def test_new_version_with_related_objects(): diff --git a/stix2/test/v21/test_properties.py b/stix2/test/v21/test_properties.py index 1fb3cc4..50bce17 100644 --- a/stix2/test/v21/test_properties.py +++ b/stix2/test/v21/test_properties.py @@ -72,6 +72,14 @@ def test_list_property(): p.clean([]) +def test_dictionary_property(): + p = DictionaryProperty(StringProperty) + + assert p.clean({'spec_version': '2.1'}) + with pytest.raises(ValueError): + p.clean({}) + + def test_string_property(): prop = StringProperty() @@ -411,6 +419,7 @@ def test_property_list_of_dictionary(): "value", [ {"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"}, [('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')], + [('TLSH', '6FF02BEF718027B0160B4391212923ED7F1A463D563B1549B86CF62973B197AD2731F8')], ], ) def test_hashes_property_valid(value): @@ -422,6 +431,7 @@ def test_hashes_property_valid(value): "value", [ {"MD5": "a"}, {"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"}, + {"TLSH": "6FF02BEF718027B0160B4391212923ED7F1A463D563B1549B86CF62973B197AD2731F"}, ], ) def test_hashes_property_invalid(value): diff --git a/stix2/v21/observables.py b/stix2/v21/observables.py index 12f0165..fdb61f4 100644 --- a/stix2/v21/observables.py +++ b/stix2/v21/observables.py @@ -12,8 +12,7 @@ import warnings from ..base import _Extension, _Observable, _STIXBase from ..custom import _custom_extension_builder, _custom_observable_builder from ..exceptions import ( - AtLeastOnePropertyError, DependentPropertiesError, PropertyPresenceError, - STIXDeprecationWarning, + AtLeastOnePropertyError, DependentPropertiesError, STIXDeprecationWarning, ) from ..properties import ( BinaryProperty, BooleanProperty, CallableValues, DictionaryProperty, @@ -1002,22 +1001,14 @@ class X509Certificate(_Observable): def _check_object_constraints(self): super(X509Certificate, self)._check_object_constraints() - if ( - self.get('is_self_signed') is None and - self.get('hashes') is None and - self.get('version') is None and - self.get('serial_number') is None and - self.get('signature_algorithm') is None and - self.get('issuer') is None and - self.get('validity_not_before') is None and - self.get('validity_not_after') is None and - self.get('subject') is None and - self.get('subject_public_key_algorithm') is None and - self.get('subject_public_key_modulus') is None and - self.get('subject_public_key_exponent') is None and - self.get('x509_v3_extensions') is None - ): - raise PropertyPresenceError("X.509 Certificate objects must contain at least one object specific property", X509Certificate) + att_list = [ + 'is_self_signed', 'hashes', 'version', 'serial_number', + 'signature_algorithm', 'issuer', 'validity_not_before', + 'validity_not_after', 'subject', 'subject_public_key_algorithm', + 'subject_public_key_modulus', 'subject_public_key_exponent', + 'x509_v3_extensions', + ] + self._check_at_least_one_property(att_list) def CustomObservable(type='x-custom-observable', properties=None): diff --git a/stix2/v21/sdo.py b/stix2/v21/sdo.py index e43ed84..6f7b52d 100644 --- a/stix2/v21/sdo.py +++ b/stix2/v21/sdo.py @@ -215,21 +215,23 @@ class Indicator(STIXDomainObject): ('granular_markings', ListProperty(GranularMarking)), ]) + def __init__(self, *args, **kwargs): + + if kwargs.get('pattern') and kwargs.get('pattern_type') == 'stix' and not kwargs.get('pattern_version'): + kwargs['pattern_version'] = '2.1' + + super(STIXDomainObject, self).__init__(*args, **kwargs) + def _check_object_constraints(self): super(Indicator, self)._check_object_constraints() valid_from = self.get('valid_from') valid_until = self.get('valid_until') - pattern_type = self.get('pattern_type') - pattern_version = self.get('pattern_version') if valid_from and valid_until and valid_until <= valid_from: msg = "{0.id} 'valid_until' must be greater than 'valid_from'" raise ValueError(msg.format(self)) - if not pattern_version and pattern_type == 'stix': - self._inner['pattern_version'] = self.get('spec_version') - class Infrastructure(STIXDomainObject): # TODO: Add link