Merge pull request #45 from oasis-open/pattern-validation

Validate patterns when creating Indicators
stix2.1
Greg Back 2017-08-21 22:24:59 +00:00 committed by GitHub
commit 1e1f13740b
4 changed files with 40 additions and 3 deletions

View File

@ -50,5 +50,6 @@ setup(
'six', 'six',
'python-dateutil', 'python-dateutil',
'requests', 'requests',
'stix2-patterns',
], ],
) )

View File

@ -7,6 +7,8 @@ import uuid
from six import string_types, text_type from six import string_types, text_type
from stix2patterns.validator import run_validator
from .base import _STIXBase from .base import _STIXBase
from .exceptions import DictionaryKeyError from .exceptions import DictionaryKeyError
from .utils import get_dict, parse_into_datetime from .utils import get_dict, parse_into_datetime
@ -370,3 +372,17 @@ class EnumProperty(StringProperty):
if value not in self.allowed: if value not in self.allowed:
raise ValueError("value '%s' is not valid for this enumeration." % value) raise ValueError("value '%s' is not valid for this enumeration." % value)
return self.string_type(value) return self.string_type(value)
class PatternProperty(StringProperty):
def __init__(self, **kwargs):
super(PatternProperty, self).__init__(**kwargs)
def clean(self, value):
str_value = super(PatternProperty, self).clean(value)
errors = run_validator(str_value)
if errors:
raise ValueError(str(errors[0]))
return self.string_type(value)

View File

@ -6,8 +6,8 @@ from .base import _STIXBase
from .common import COMMON_PROPERTIES, KillChainPhase from .common import COMMON_PROPERTIES, KillChainPhase
from .observables import ObservableProperty from .observables import ObservableProperty
from .properties import (IDProperty, IntegerProperty, ListProperty, from .properties import (IDProperty, IntegerProperty, ListProperty,
ReferenceProperty, StringProperty, TimestampProperty, PatternProperty, ReferenceProperty, StringProperty,
TypeProperty) TimestampProperty, TypeProperty)
from .utils import NOW from .utils import NOW
@ -77,7 +77,7 @@ class Indicator(_STIXBase):
'labels': ListProperty(StringProperty, required=True), 'labels': ListProperty(StringProperty, required=True),
'name': StringProperty(), 'name': StringProperty(),
'description': StringProperty(), 'description': StringProperty(),
'pattern': StringProperty(required=True), 'pattern': PatternProperty(required=True),
'valid_from': TimestampProperty(default=lambda: NOW), 'valid_from': TimestampProperty(default=lambda: NOW),
'valid_until': TimestampProperty(), 'valid_until': TimestampProperty(),
'kill_chain_phases': ListProperty(KillChainPhase), 'kill_chain_phases': ListProperty(KillChainPhase),

View File

@ -174,3 +174,23 @@ def test_parse_indicator(data):
assert idctr.valid_from == dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=pytz.utc) assert idctr.valid_from == dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=pytz.utc)
assert idctr.labels[0] == "malicious-activity" assert idctr.labels[0] == "malicious-activity"
assert idctr.pattern == "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']" assert idctr.pattern == "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']"
def test_invalid_indicator_pattern():
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
stix2.Indicator(
labels=['malicious-activity'],
pattern="file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e'",
)
assert excinfo.value.cls == stix2.Indicator
assert excinfo.value.prop_name == 'pattern'
assert 'input is missing square brackets' in excinfo.value.reason
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
stix2.Indicator(
labels=['malicious-activity'],
pattern='[file:hashes.MD5 = "d41d8cd98f00b204e9800998ecf8427e"]',
)
assert excinfo.value.cls == stix2.Indicator
assert excinfo.value.prop_name == 'pattern'
assert 'mismatched input' in excinfo.value.reason