Merge pull request #167 from oasis-open/invalid-type-names
Disallow invalid type names in custom classesstix2.0
commit
a1befe6387
|
@ -197,6 +197,24 @@ def test_custom_object_no_init_2():
|
||||||
assert no2.property1 == 'something'
|
assert no2.property1 == 'something'
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_object_invalid_type_name():
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.sdo.CustomObject('x', [
|
||||||
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
])
|
||||||
|
class NewObj(object):
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid type name 'x': " in str(excinfo.value)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.sdo.CustomObject('x_new_object', [
|
||||||
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
])
|
||||||
|
class NewObj2(object):
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid type name 'x_new_object':" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_parse_custom_object_type():
|
def test_parse_custom_object_type():
|
||||||
nt_string = """{
|
nt_string = """{
|
||||||
"type": "x-new-type",
|
"type": "x-new-type",
|
||||||
|
@ -295,6 +313,24 @@ def test_custom_observable_object_no_init_2():
|
||||||
assert no2.property1 == 'something'
|
assert no2.property1 == 'something'
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_invalid_type_name():
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.observables.CustomObservable('x', [
|
||||||
|
('property1', stix2.properties.StringProperty()),
|
||||||
|
])
|
||||||
|
class NewObs(object):
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid observable type name 'x':" in str(excinfo.value)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.observables.CustomObservable('x_new_obs', [
|
||||||
|
('property1', stix2.properties.StringProperty()),
|
||||||
|
])
|
||||||
|
class NewObs2(object):
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_custom_observable_object_invalid_ref_property():
|
def test_custom_observable_object_invalid_ref_property():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError) as excinfo:
|
||||||
@stix2.observables.CustomObservable('x-new-obs', [
|
@stix2.observables.CustomObservable('x-new-obs', [
|
||||||
|
@ -573,6 +609,24 @@ def test_custom_extension_invalid_observable():
|
||||||
assert "Custom observables must be created with the @CustomObservable decorator." in str(excinfo.value)
|
assert "Custom observables must be created with the @CustomObservable decorator." in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_extension_invalid_type_name():
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.observables.CustomExtension(stix2.File, 'x', {
|
||||||
|
'property1': stix2.properties.StringProperty(required=True),
|
||||||
|
})
|
||||||
|
class FooExtension():
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid extension type name 'x':" in str(excinfo.value)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
@stix2.observables.CustomExtension(stix2.File, 'x_new_ext', {
|
||||||
|
'property1': stix2.properties.StringProperty(required=True),
|
||||||
|
})
|
||||||
|
class BlaExtension():
|
||||||
|
pass # pragma: no cover
|
||||||
|
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_custom_extension_no_properties():
|
def test_custom_extension_no_properties():
|
||||||
with pytest.raises(ValueError) as excinfo:
|
with pytest.raises(ValueError) as excinfo:
|
||||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', None)
|
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', None)
|
||||||
|
|
|
@ -18,6 +18,8 @@ NOW = object()
|
||||||
# STIX object properties that cannot be modified
|
# STIX object properties that cannot be modified
|
||||||
STIX_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"]
|
STIX_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"]
|
||||||
|
|
||||||
|
TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$'
|
||||||
|
|
||||||
|
|
||||||
class STIXdatetime(dt.datetime):
|
class STIXdatetime(dt.datetime):
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
|
|
|
@ -7,6 +7,7 @@ Observable and do not have a ``_type`` attribute.
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import copy
|
import copy
|
||||||
|
import re
|
||||||
|
|
||||||
from ..base import _Extension, _Observable, _STIXBase
|
from ..base import _Extension, _Observable, _STIXBase
|
||||||
from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
|
from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
|
||||||
|
@ -16,7 +17,7 @@ from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
|
||||||
HashesProperty, HexProperty, IntegerProperty,
|
HashesProperty, HexProperty, IntegerProperty,
|
||||||
ListProperty, ObjectReferenceProperty, Property,
|
ListProperty, ObjectReferenceProperty, Property,
|
||||||
StringProperty, TimestampProperty, TypeProperty)
|
StringProperty, TimestampProperty, TypeProperty)
|
||||||
from ..utils import _get_dict
|
from ..utils import TYPE_REGEX, _get_dict
|
||||||
|
|
||||||
|
|
||||||
class ObservableProperty(Property):
|
class ObservableProperty(Property):
|
||||||
|
@ -981,6 +982,12 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
||||||
|
|
||||||
class _Custom(cls, _Observable):
|
class _Custom(cls, _Observable):
|
||||||
|
|
||||||
|
if not re.match(TYPE_REGEX, type):
|
||||||
|
raise ValueError("Invalid observable type name '%s': must only contain the "
|
||||||
|
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||||
|
elif len(type) < 3 or len(type) > 250:
|
||||||
|
raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type)
|
||||||
|
|
||||||
_type = type
|
_type = type
|
||||||
_properties = OrderedDict()
|
_properties = OrderedDict()
|
||||||
_properties.update([
|
_properties.update([
|
||||||
|
@ -1054,6 +1061,12 @@ def CustomExtension(observable=None, type='x-custom-observable', properties=None
|
||||||
|
|
||||||
class _Custom(cls, _Extension):
|
class _Custom(cls, _Extension):
|
||||||
|
|
||||||
|
if not re.match(TYPE_REGEX, type):
|
||||||
|
raise ValueError("Invalid extension type name '%s': must only contain the "
|
||||||
|
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||||
|
elif len(type) < 3 or len(type) > 250:
|
||||||
|
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
|
||||||
|
|
||||||
_type = type
|
_type = type
|
||||||
_properties = OrderedDict()
|
_properties = OrderedDict()
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
import re
|
||||||
|
|
||||||
import stix2
|
import stix2
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ from ..markings import _MarkingsMixin
|
||||||
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
|
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
|
||||||
ListProperty, PatternProperty, ReferenceProperty,
|
ListProperty, PatternProperty, ReferenceProperty,
|
||||||
StringProperty, TimestampProperty, TypeProperty)
|
StringProperty, TimestampProperty, TypeProperty)
|
||||||
from ..utils import NOW
|
from ..utils import NOW, TYPE_REGEX
|
||||||
from .common import ExternalReference, GranularMarking, KillChainPhase
|
from .common import ExternalReference, GranularMarking, KillChainPhase
|
||||||
from .observables import ObservableProperty
|
from .observables import ObservableProperty
|
||||||
|
|
||||||
|
@ -357,6 +358,13 @@ def CustomObject(type='x-custom-type', properties=None):
|
||||||
def custom_builder(cls):
|
def custom_builder(cls):
|
||||||
|
|
||||||
class _Custom(cls, STIXDomainObject):
|
class _Custom(cls, STIXDomainObject):
|
||||||
|
|
||||||
|
if not re.match(TYPE_REGEX, type):
|
||||||
|
raise ValueError("Invalid type name '%s': must only contain the "
|
||||||
|
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||||
|
elif len(type) < 3 or len(type) > 250:
|
||||||
|
raise ValueError("Invalid type name '%s': must be between 3 and 250 characters." % type)
|
||||||
|
|
||||||
_type = type
|
_type = type
|
||||||
_properties = OrderedDict()
|
_properties = OrderedDict()
|
||||||
_properties.update([
|
_properties.update([
|
||||||
|
|
Loading…
Reference in New Issue