Merge 'master' and fix imports for consistency
commit
a0d535336e
|
@ -0,0 +1,33 @@
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: cti-python-stix2 test harness
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||||
|
|
||||||
|
name: Python ${{ matrix.python-version }} Build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install and update essential dependencies
|
||||||
|
run: |
|
||||||
|
pip install -U pip setuptools
|
||||||
|
pip install tox-gh-actions
|
||||||
|
pip install codecov
|
||||||
|
- name: Test with Tox
|
||||||
|
run: |
|
||||||
|
tox
|
||||||
|
- name: Upload coverage information to Codecov
|
||||||
|
uses: codecov/codecov-action@v1
|
||||||
|
with:
|
||||||
|
fail_ci_if_error: true # optional (default = false)
|
||||||
|
verbose: true # optional (default = false)
|
|
@ -1,17 +1,25 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v1.3.0
|
rev: v3.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: flake8
|
|
||||||
args:
|
|
||||||
- --max-line-length=160
|
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- repo: https://github.com/asottile/add-trailing-comma
|
- repo: https://github.com/asottile/add-trailing-comma
|
||||||
rev: v0.6.4
|
rev: v2.0.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: add-trailing-comma
|
- id: add-trailing-comma
|
||||||
- repo: https://github.com/FalconSocial/pre-commit-python-sorter
|
- repo: https://github.com/PyCQA/flake8
|
||||||
sha: b57843b0b874df1d16eb0bef00b868792cb245c2
|
rev: 3.8.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-import-sorter
|
- id: flake8
|
||||||
|
name: Check project styling
|
||||||
|
args:
|
||||||
|
- --max-line-length=160
|
||||||
|
- repo: https://github.com/PyCQA/isort
|
||||||
|
rev: 5.7.0
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
name: Sort python imports (shows diff)
|
||||||
|
args: ["-c", "--diff"]
|
||||||
|
- id: isort
|
||||||
|
name: Sort python imports (fixes files)
|
||||||
|
|
19
.travis.yml
19
.travis.yml
|
@ -1,19 +0,0 @@
|
||||||
os: linux
|
|
||||||
language: python
|
|
||||||
cache: pip
|
|
||||||
dist: bionic
|
|
||||||
python:
|
|
||||||
- "3.5"
|
|
||||||
- "3.6"
|
|
||||||
- "3.7"
|
|
||||||
- "3.8"
|
|
||||||
install:
|
|
||||||
- pip install -U pip setuptools
|
|
||||||
- pip install tox-travis
|
|
||||||
- pip install codecov
|
|
||||||
- pip install pre-commit
|
|
||||||
script:
|
|
||||||
- tox
|
|
||||||
- pre-commit run --all-files
|
|
||||||
after_success:
|
|
||||||
- codecov
|
|
|
@ -163,8 +163,8 @@ questions about TC Open Repository participation to OASIS Staff at
|
||||||
repository-admin@oasis-open.org and any specific CLA-related questions
|
repository-admin@oasis-open.org and any specific CLA-related questions
|
||||||
to repository-cla@oasis-open.org.
|
to repository-cla@oasis-open.org.
|
||||||
|
|
||||||
.. |Build_Status| image:: https://travis-ci.org/oasis-open/cti-python-stix2.svg?branch=master
|
.. |Build_Status| image:: https://github.com/oasis-open/cti-python-stix2/workflows/cti-python-stix2%20test%20harness/badge.svg
|
||||||
:target: https://travis-ci.org/oasis-open/cti-python-stix2
|
:target: https://github.com/oasis-open/cti-python-stix2/actions?query=workflow%3A%22cti-python-stix2+test+harness%22
|
||||||
:alt: Build Status
|
:alt: Build Status
|
||||||
.. |Coverage| image:: https://codecov.io/gh/oasis-open/cti-python-stix2/branch/master/graph/badge.svg
|
.. |Coverage| image:: https://codecov.io/gh/oasis-open/cti-python-stix2/branch/master/graph/badge.svg
|
||||||
:target: https://codecov.io/gh/oasis-open/cti-python-stix2
|
:target: https://codecov.io/gh/oasis-open/cti-python-stix2
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -40,10 +40,10 @@ setup(
|
||||||
'Topic :: Security',
|
'Topic :: Security',
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.5',
|
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
|
'Programming Language :: Python :: 3.9',
|
||||||
],
|
],
|
||||||
keywords='stix stix2 json cti cyber threat intelligence',
|
keywords='stix stix2 json cti cyber threat intelligence',
|
||||||
packages=find_packages(exclude=['*.test', '*.test.*']),
|
packages=find_packages(exclude=['*.test', '*.test.*']),
|
||||||
|
|
|
@ -164,8 +164,10 @@ class _STIXBase(Mapping):
|
||||||
defaulted = []
|
defaulted = []
|
||||||
for name, prop in self._properties.items():
|
for name, prop in self._properties.items():
|
||||||
try:
|
try:
|
||||||
if (not prop.required and not hasattr(prop, '_fixed_value') and
|
if (
|
||||||
prop.default() == setting_kwargs[name]):
|
not prop.required and not hasattr(prop, '_fixed_value') and
|
||||||
|
prop.default() == setting_kwargs[name]
|
||||||
|
):
|
||||||
defaulted.append(name)
|
defaulted.append(name)
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
continue
|
continue
|
||||||
|
@ -194,8 +196,10 @@ class _STIXBase(Mapping):
|
||||||
unpickling = '_inner' not in self.__dict__
|
unpickling = '_inner' not in self.__dict__
|
||||||
if not unpickling and name in self:
|
if not unpickling and name in self:
|
||||||
return self.__getitem__(name)
|
return self.__getitem__(name)
|
||||||
raise AttributeError("'%s' object has no attribute '%s'" %
|
raise AttributeError(
|
||||||
(self.__class__.__name__, name))
|
"'%s' object has no attribute '%s'" %
|
||||||
|
(self.__class__.__name__, name),
|
||||||
|
)
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if not name.startswith("_"):
|
if not name.startswith("_"):
|
||||||
|
|
|
@ -75,8 +75,10 @@ class _ObjectFamily(object):
|
||||||
|
|
||||||
def add(self, obj):
|
def add(self, obj):
|
||||||
self.all_versions[obj["modified"]] = obj
|
self.all_versions[obj["modified"]] = obj
|
||||||
if (self.latest_version is None or
|
if (
|
||||||
obj["modified"] > self.latest_version["modified"]):
|
self.latest_version is None or
|
||||||
|
obj["modified"] > self.latest_version["modified"]
|
||||||
|
):
|
||||||
self.latest_version = obj
|
self.latest_version = obj
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -188,11 +190,13 @@ class MemorySink(DataSink):
|
||||||
def save_to_file(self, path, encoding="utf-8"):
|
def save_to_file(self, path, encoding="utf-8"):
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
|
|
||||||
all_objs = list(itertools.chain.from_iterable(
|
all_objs = list(
|
||||||
|
itertools.chain.from_iterable(
|
||||||
value.all_versions.values() if isinstance(value, _ObjectFamily)
|
value.all_versions.values() if isinstance(value, _ObjectFamily)
|
||||||
else [value]
|
else [value]
|
||||||
for value in self._data.values()
|
for value in self._data.values()
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
if any("spec_version" in x for x in all_objs):
|
if any("spec_version" in x for x in all_objs):
|
||||||
bundle = v21.Bundle(all_objs, allow_custom=self.allow_custom)
|
bundle = v21.Bundle(all_objs, allow_custom=self.allow_custom)
|
||||||
|
|
|
@ -9,18 +9,14 @@
|
||||||
|
|
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import stix2
|
from ... import pattern_visitor
|
||||||
from stix2.equivalence.pattern.compare.observation import (
|
from ...version import DEFAULT_VERSION
|
||||||
observation_expression_cmp,
|
from .compare.observation import observation_expression_cmp
|
||||||
)
|
from .transform import ChainTransformer, SettleTransformer
|
||||||
from stix2.equivalence.pattern.transform import (
|
from .transform.observation import (
|
||||||
ChainTransformer, SettleTransformer,
|
|
||||||
)
|
|
||||||
from stix2.equivalence.pattern.transform.observation import (
|
|
||||||
AbsorptionTransformer, CanonicalizeComparisonExpressionsTransformer,
|
AbsorptionTransformer, CanonicalizeComparisonExpressionsTransformer,
|
||||||
DNFTransformer, FlattenTransformer, OrderDedupeTransformer,
|
DNFTransformer, FlattenTransformer, OrderDedupeTransformer,
|
||||||
)
|
)
|
||||||
import stix2.pattern_visitor
|
|
||||||
|
|
||||||
# Lazy-initialize
|
# Lazy-initialize
|
||||||
_pattern_canonicalizer = None
|
_pattern_canonicalizer = None
|
||||||
|
@ -61,7 +57,7 @@ def _get_pattern_canonicalizer():
|
||||||
return _pattern_canonicalizer
|
return _pattern_canonicalizer
|
||||||
|
|
||||||
|
|
||||||
def equivalent_patterns(pattern1, pattern2, stix_version=stix2.DEFAULT_VERSION):
|
def equivalent_patterns(pattern1, pattern2, stix_version=DEFAULT_VERSION):
|
||||||
"""
|
"""
|
||||||
Determine whether two STIX patterns are semantically equivalent.
|
Determine whether two STIX patterns are semantically equivalent.
|
||||||
|
|
||||||
|
@ -74,10 +70,10 @@ def equivalent_patterns(pattern1, pattern2, stix_version=stix2.DEFAULT_VERSION):
|
||||||
Returns:
|
Returns:
|
||||||
True if the patterns are semantically equivalent; False if not
|
True if the patterns are semantically equivalent; False if not
|
||||||
"""
|
"""
|
||||||
patt_ast1 = stix2.pattern_visitor.create_pattern_object(
|
patt_ast1 = pattern_visitor.create_pattern_object(
|
||||||
pattern1, version=stix_version,
|
pattern1, version=stix_version,
|
||||||
)
|
)
|
||||||
patt_ast2 = stix2.pattern_visitor.create_pattern_object(
|
patt_ast2 = pattern_visitor.create_pattern_object(
|
||||||
pattern2, version=stix_version,
|
pattern2, version=stix_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,7 +87,7 @@ def equivalent_patterns(pattern1, pattern2, stix_version=stix2.DEFAULT_VERSION):
|
||||||
|
|
||||||
|
|
||||||
def find_equivalent_patterns(
|
def find_equivalent_patterns(
|
||||||
search_pattern, patterns, stix_version=stix2.DEFAULT_VERSION,
|
search_pattern, patterns, stix_version=DEFAULT_VERSION,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Find patterns from a sequence which are equivalent to a given pattern.
|
Find patterns from a sequence which are equivalent to a given pattern.
|
||||||
|
@ -109,7 +105,7 @@ def find_equivalent_patterns(
|
||||||
Returns:
|
Returns:
|
||||||
A generator iterator producing the semantically equivalent patterns
|
A generator iterator producing the semantically equivalent patterns
|
||||||
"""
|
"""
|
||||||
search_pattern_ast = stix2.pattern_visitor.create_pattern_object(
|
search_pattern_ast = pattern_visitor.create_pattern_object(
|
||||||
search_pattern, version=stix_version,
|
search_pattern, version=stix_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,7 +115,7 @@ def find_equivalent_patterns(
|
||||||
)
|
)
|
||||||
|
|
||||||
for pattern in patterns:
|
for pattern in patterns:
|
||||||
pattern_ast = stix2.pattern_visitor.create_pattern_object(
|
pattern_ast = pattern_visitor.create_pattern_object(
|
||||||
pattern, version=stix_version,
|
pattern, version=stix_version,
|
||||||
)
|
)
|
||||||
canon_pattern_ast, _ = pattern_canonicalizer.transform(pattern_ast)
|
canon_pattern_ast, _ = pattern_canonicalizer.transform(pattern_ast)
|
||||||
|
|
|
@ -144,7 +144,7 @@ class ComparisonExpressionTransformer(Transformer):
|
||||||
|
|
||||||
|
|
||||||
class OrderDedupeTransformer(
|
class OrderDedupeTransformer(
|
||||||
ComparisonExpressionTransformer
|
ComparisonExpressionTransformer,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Canonically order the children of all nodes in the AST. Because the
|
Canonically order the children of all nodes in the AST. Because the
|
||||||
|
@ -247,7 +247,7 @@ class FlattenTransformer(ComparisonExpressionTransformer):
|
||||||
|
|
||||||
|
|
||||||
class AbsorptionTransformer(
|
class AbsorptionTransformer(
|
||||||
ComparisonExpressionTransformer
|
ComparisonExpressionTransformer,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Applies boolean "absorption" rules for AST simplification. E.g.:
|
Applies boolean "absorption" rules for AST simplification. E.g.:
|
||||||
|
|
|
@ -152,9 +152,11 @@ class ObservationExpressionTransformer(Transformer):
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("Not an observation expression: {}: {}".format(
|
raise TypeError(
|
||||||
|
"Not an observation expression: {}: {}".format(
|
||||||
type(ast).__name__, str(ast),
|
type(ast).__name__, str(ast),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return result, changed
|
return result, changed
|
||||||
|
|
||||||
|
@ -229,7 +231,7 @@ class FlattenTransformer(ObservationExpressionTransformer):
|
||||||
|
|
||||||
|
|
||||||
class OrderDedupeTransformer(
|
class OrderDedupeTransformer(
|
||||||
ObservationExpressionTransformer
|
ObservationExpressionTransformer,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Canonically order AND/OR expressions, and dedupe ORs. E.g.:
|
Canonically order AND/OR expressions, and dedupe ORs. E.g.:
|
||||||
|
@ -272,7 +274,7 @@ class OrderDedupeTransformer(
|
||||||
|
|
||||||
|
|
||||||
class AbsorptionTransformer(
|
class AbsorptionTransformer(
|
||||||
ObservationExpressionTransformer
|
ObservationExpressionTransformer,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Applies boolean "absorption" rules for observation expressions, for AST
|
Applies boolean "absorption" rules for observation expressions, for AST
|
||||||
|
@ -479,7 +481,7 @@ class DNFTransformer(ObservationExpressionTransformer):
|
||||||
|
|
||||||
|
|
||||||
class CanonicalizeComparisonExpressionsTransformer(
|
class CanonicalizeComparisonExpressionsTransformer(
|
||||||
ObservationExpressionTransformer
|
ObservationExpressionTransformer,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Canonicalize all comparison expressions.
|
Canonicalize all comparison expressions.
|
||||||
|
|
|
@ -182,7 +182,9 @@ def parse_observable(data, _valid_refs=None, allow_custom=False, version=None):
|
||||||
# flag allows for unknown custom objects too, but will not
|
# flag allows for unknown custom objects too, but will not
|
||||||
# be parsed into STIX observable object, just returned as is
|
# be parsed into STIX observable object, just returned as is
|
||||||
return obj
|
return obj
|
||||||
raise ParseError("Can't parse unknown observable type '%s'! For custom observables, "
|
raise ParseError(
|
||||||
"use the CustomObservable decorator." % obj['type'])
|
"Can't parse unknown observable type '%s'! For custom observables, "
|
||||||
|
"use the CustomObservable decorator." % obj['type'],
|
||||||
|
)
|
||||||
|
|
||||||
return obj_class(allow_custom=allow_custom, **obj)
|
return obj_class(allow_custom=allow_custom, **obj)
|
||||||
|
|
|
@ -17,10 +17,9 @@ from stix2patterns.v21.grammars.STIXPatternVisitor import \
|
||||||
STIXPatternVisitor as STIXPatternVisitor21
|
STIXPatternVisitor as STIXPatternVisitor21
|
||||||
from stix2patterns.v21.pattern import Pattern as Pattern21
|
from stix2patterns.v21.pattern import Pattern as Pattern21
|
||||||
|
|
||||||
import stix2
|
|
||||||
|
|
||||||
from .patterns import *
|
from .patterns import *
|
||||||
from .patterns import _BooleanExpression
|
from .patterns import _BooleanExpression
|
||||||
|
from .version import DEFAULT_VERSION
|
||||||
|
|
||||||
# flake8: noqa F405
|
# flake8: noqa F405
|
||||||
|
|
||||||
|
@ -261,11 +260,13 @@ class STIXPatternVisitorForSTIX2():
|
||||||
property_path.append(self.instantiate("ListObjectPathComponent", current.property_name, next.getText()))
|
property_path.append(self.instantiate("ListObjectPathComponent", current.property_name, next.getText()))
|
||||||
i += 2
|
i += 2
|
||||||
elif isinstance(next, IntegerConstant):
|
elif isinstance(next, IntegerConstant):
|
||||||
property_path.append(self.instantiate(
|
property_path.append(
|
||||||
|
self.instantiate(
|
||||||
"ListObjectPathComponent",
|
"ListObjectPathComponent",
|
||||||
current.property_name if isinstance(current, BasicObjectPathComponent) else text_type(current),
|
current.property_name if isinstance(current, BasicObjectPathComponent) else text_type(current),
|
||||||
next.value,
|
next.value,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
i += 2
|
i += 2
|
||||||
else:
|
else:
|
||||||
property_path.append(current)
|
property_path.append(current)
|
||||||
|
@ -389,7 +390,7 @@ class STIXPatternVisitorForSTIX20(STIXPatternVisitorForSTIX2, STIXPatternVisitor
|
||||||
super(STIXPatternVisitor20, self).__init__()
|
super(STIXPatternVisitor20, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
def create_pattern_object(pattern, module_suffix="", module_name="", version=stix2.DEFAULT_VERSION):
|
def create_pattern_object(pattern, module_suffix="", module_name="", version=DEFAULT_VERSION):
|
||||||
"""
|
"""
|
||||||
Create a STIX pattern AST from a pattern string.
|
Create a STIX pattern AST from a pattern string.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,8 +9,6 @@ import uuid
|
||||||
|
|
||||||
from six import string_types, text_type
|
from six import string_types, text_type
|
||||||
|
|
||||||
import stix2
|
|
||||||
|
|
||||||
from .base import _STIXBase
|
from .base import _STIXBase
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
CustomContentError, DictionaryKeyError, MissingPropertiesError,
|
CustomContentError, DictionaryKeyError, MissingPropertiesError,
|
||||||
|
@ -19,6 +17,7 @@ from .exceptions import (
|
||||||
from .parsing import parse, parse_observable
|
from .parsing import parse, parse_observable
|
||||||
from .registry import STIX2_OBJ_MAPS
|
from .registry import STIX2_OBJ_MAPS
|
||||||
from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
|
from .utils import _get_dict, get_class_hierarchy_names, parse_into_datetime
|
||||||
|
from .version import DEFAULT_VERSION
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
@ -248,9 +247,11 @@ class ListProperty(Property):
|
||||||
valid = self.contained(**item)
|
valid = self.contained(**item)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Can't create a {} out of {}".format(
|
raise ValueError(
|
||||||
|
"Can't create a {} out of {}".format(
|
||||||
self.contained._type, str(item),
|
self.contained._type, str(item),
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
result.append(valid)
|
result.append(valid)
|
||||||
|
|
||||||
|
@ -274,7 +275,7 @@ class StringProperty(Property):
|
||||||
|
|
||||||
class TypeProperty(Property):
|
class TypeProperty(Property):
|
||||||
|
|
||||||
def __init__(self, type, spec_version=stix2.DEFAULT_VERSION):
|
def __init__(self, type, spec_version=DEFAULT_VERSION):
|
||||||
_validate_type(type, spec_version)
|
_validate_type(type, spec_version)
|
||||||
self.spec_version = spec_version
|
self.spec_version = spec_version
|
||||||
super(TypeProperty, self).__init__(fixed=type)
|
super(TypeProperty, self).__init__(fixed=type)
|
||||||
|
@ -282,7 +283,7 @@ class TypeProperty(Property):
|
||||||
|
|
||||||
class IDProperty(Property):
|
class IDProperty(Property):
|
||||||
|
|
||||||
def __init__(self, type, spec_version=stix2.DEFAULT_VERSION):
|
def __init__(self, type, spec_version=DEFAULT_VERSION):
|
||||||
self.required_prefix = type + "--"
|
self.required_prefix = type + "--"
|
||||||
self.spec_version = spec_version
|
self.spec_version = spec_version
|
||||||
super(IDProperty, self).__init__()
|
super(IDProperty, self).__init__()
|
||||||
|
@ -381,7 +382,7 @@ class TimestampProperty(Property):
|
||||||
|
|
||||||
class DictionaryProperty(Property):
|
class DictionaryProperty(Property):
|
||||||
|
|
||||||
def __init__(self, spec_version=stix2.DEFAULT_VERSION, **kwargs):
|
def __init__(self, spec_version=DEFAULT_VERSION, **kwargs):
|
||||||
self.spec_version = spec_version
|
self.spec_version = spec_version
|
||||||
super(DictionaryProperty, self).__init__(**kwargs)
|
super(DictionaryProperty, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
@ -470,7 +471,7 @@ class HexProperty(Property):
|
||||||
|
|
||||||
class ReferenceProperty(Property):
|
class ReferenceProperty(Property):
|
||||||
|
|
||||||
def __init__(self, valid_types=None, invalid_types=None, spec_version=stix2.DEFAULT_VERSION, **kwargs):
|
def __init__(self, valid_types=None, invalid_types=None, spec_version=DEFAULT_VERSION, **kwargs):
|
||||||
"""
|
"""
|
||||||
references sometimes must be to a specific object type
|
references sometimes must be to a specific object type
|
||||||
"""
|
"""
|
||||||
|
@ -604,7 +605,7 @@ class ObservableProperty(Property):
|
||||||
"""Property for holding Cyber Observable Objects.
|
"""Property for holding Cyber Observable Objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
|
def __init__(self, spec_version=DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
|
||||||
self.allow_custom = allow_custom
|
self.allow_custom = allow_custom
|
||||||
self.spec_version = spec_version
|
self.spec_version = spec_version
|
||||||
super(ObservableProperty, self).__init__(*args, **kwargs)
|
super(ObservableProperty, self).__init__(*args, **kwargs)
|
||||||
|
@ -639,7 +640,7 @@ class ExtensionsProperty(DictionaryProperty):
|
||||||
"""Property for representing extensions on Observable objects.
|
"""Property for representing extensions on Observable objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, enclosing_type=None, required=False):
|
def __init__(self, spec_version=DEFAULT_VERSION, allow_custom=False, enclosing_type=None, required=False):
|
||||||
self.allow_custom = allow_custom
|
self.allow_custom = allow_custom
|
||||||
self.enclosing_type = enclosing_type
|
self.enclosing_type = enclosing_type
|
||||||
super(ExtensionsProperty, self).__init__(spec_version=spec_version, required=required)
|
super(ExtensionsProperty, self).__init__(spec_version=spec_version, required=required)
|
||||||
|
@ -681,7 +682,7 @@ class ExtensionsProperty(DictionaryProperty):
|
||||||
|
|
||||||
class STIXObjectProperty(Property):
|
class STIXObjectProperty(Property):
|
||||||
|
|
||||||
def __init__(self, spec_version=stix2.DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
|
def __init__(self, spec_version=DEFAULT_VERSION, allow_custom=False, *args, **kwargs):
|
||||||
self.allow_custom = allow_custom
|
self.allow_custom = allow_custom
|
||||||
self.spec_version = spec_version
|
self.spec_version = spec_version
|
||||||
super(STIXObjectProperty, self).__init__(*args, **kwargs)
|
super(STIXObjectProperty, self).__init__(*args, **kwargs)
|
||||||
|
@ -689,8 +690,10 @@ class STIXObjectProperty(Property):
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
# Any STIX Object (SDO, SRO, or Marking Definition) can be added to
|
# Any STIX Object (SDO, SRO, or Marking Definition) can be added to
|
||||||
# a bundle with no further checks.
|
# a bundle with no further checks.
|
||||||
if any(x in ('_DomainObject', '_RelationshipObject', 'MarkingDefinition')
|
if any(
|
||||||
for x in get_class_hierarchy_names(value)):
|
x in ('_DomainObject', '_RelationshipObject', 'MarkingDefinition')
|
||||||
|
for x in get_class_hierarchy_names(value)
|
||||||
|
):
|
||||||
# A simple "is this a spec version 2.1+ object" test. For now,
|
# A simple "is this a spec version 2.1+ object" test. For now,
|
||||||
# limit 2.0 bundles to 2.0 objects. It's not possible yet to
|
# limit 2.0 bundles to 2.0 objects. It's not possible yet to
|
||||||
# have validation co-constraints among properties, e.g. have
|
# have validation co-constraints among properties, e.g. have
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import stix2
|
from . import registry
|
||||||
import stix2.registry
|
|
||||||
|
|
||||||
from .base import _DomainObject, _Observable
|
from .base import _DomainObject, _Observable
|
||||||
from .exceptions import DuplicateRegistrationError
|
from .exceptions import DuplicateRegistrationError
|
||||||
|
from .properties import _validate_type
|
||||||
from .utils import PREFIX_21_REGEX, get_class_hierarchy_names
|
from .utils import PREFIX_21_REGEX, get_class_hierarchy_names
|
||||||
|
from .version import DEFAULT_VERSION
|
||||||
|
|
||||||
|
|
||||||
def _register_object(new_type, version=stix2.DEFAULT_VERSION):
|
def _register_object(new_type, version=DEFAULT_VERSION):
|
||||||
"""Register a custom STIX Object type.
|
"""Register a custom STIX Object type.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -40,15 +40,15 @@ def _register_object(new_type, version=stix2.DEFAULT_VERSION):
|
||||||
v = 'v' + version.replace('.', '')
|
v = 'v' + version.replace('.', '')
|
||||||
else:
|
else:
|
||||||
# Use default version (latest) if no version was provided.
|
# Use default version (latest) if no version was provided.
|
||||||
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')
|
v = 'v' + DEFAULT_VERSION.replace('.', '')
|
||||||
|
|
||||||
OBJ_MAP = stix2.registry.STIX2_OBJ_MAPS[v]['objects']
|
OBJ_MAP = registry.STIX2_OBJ_MAPS[v]['objects']
|
||||||
if new_type._type in OBJ_MAP.keys():
|
if new_type._type in OBJ_MAP.keys():
|
||||||
raise DuplicateRegistrationError("STIX Object", new_type._type)
|
raise DuplicateRegistrationError("STIX Object", new_type._type)
|
||||||
OBJ_MAP[new_type._type] = new_type
|
OBJ_MAP[new_type._type] = new_type
|
||||||
|
|
||||||
|
|
||||||
def _register_marking(new_marking, version=stix2.DEFAULT_VERSION):
|
def _register_marking(new_marking, version=DEFAULT_VERSION):
|
||||||
"""Register a custom STIX Marking Definition type.
|
"""Register a custom STIX Marking Definition type.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -61,7 +61,7 @@ def _register_marking(new_marking, version=stix2.DEFAULT_VERSION):
|
||||||
mark_type = new_marking._type
|
mark_type = new_marking._type
|
||||||
properties = new_marking._properties
|
properties = new_marking._properties
|
||||||
|
|
||||||
stix2.properties._validate_type(mark_type, version)
|
_validate_type(mark_type, version)
|
||||||
|
|
||||||
if version == "2.1":
|
if version == "2.1":
|
||||||
for prop_name, prop_value in properties.items():
|
for prop_name, prop_value in properties.items():
|
||||||
|
@ -72,15 +72,15 @@ def _register_marking(new_marking, version=stix2.DEFAULT_VERSION):
|
||||||
v = 'v' + version.replace('.', '')
|
v = 'v' + version.replace('.', '')
|
||||||
else:
|
else:
|
||||||
# Use default version (latest) if no version was provided.
|
# Use default version (latest) if no version was provided.
|
||||||
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')
|
v = 'v' + DEFAULT_VERSION.replace('.', '')
|
||||||
|
|
||||||
OBJ_MAP_MARKING = stix2.registry.STIX2_OBJ_MAPS[v]['markings']
|
OBJ_MAP_MARKING = registry.STIX2_OBJ_MAPS[v]['markings']
|
||||||
if mark_type in OBJ_MAP_MARKING.keys():
|
if mark_type in OBJ_MAP_MARKING.keys():
|
||||||
raise DuplicateRegistrationError("STIX Marking", mark_type)
|
raise DuplicateRegistrationError("STIX Marking", mark_type)
|
||||||
OBJ_MAP_MARKING[mark_type] = new_marking
|
OBJ_MAP_MARKING[mark_type] = new_marking
|
||||||
|
|
||||||
|
|
||||||
def _register_observable(new_observable, version=stix2.DEFAULT_VERSION):
|
def _register_observable(new_observable, version=DEFAULT_VERSION):
|
||||||
"""Register a custom STIX Cyber Observable type.
|
"""Register a custom STIX Cyber Observable type.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -99,8 +99,12 @@ def _register_observable(new_observable, version=stix2.DEFAULT_VERSION):
|
||||||
"'%s' is named like an object reference property but "
|
"'%s' is named like an object reference property but "
|
||||||
"is not an ObjectReferenceProperty." % prop_name,
|
"is not an ObjectReferenceProperty." % prop_name,
|
||||||
)
|
)
|
||||||
elif (prop_name.endswith('_refs') and ('ListProperty' not in get_class_hierarchy_names(prop) or
|
elif (
|
||||||
'ObjectReferenceProperty' not in get_class_hierarchy_names(prop.contained))):
|
prop_name.endswith('_refs') and (
|
||||||
|
'ListProperty' not in get_class_hierarchy_names(prop) or
|
||||||
|
'ObjectReferenceProperty' not in get_class_hierarchy_names(prop.contained)
|
||||||
|
)
|
||||||
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'%s' is named like an object reference list property but "
|
"'%s' is named like an object reference list property but "
|
||||||
"is not a ListProperty containing ObjectReferenceProperty." % prop_name,
|
"is not a ListProperty containing ObjectReferenceProperty." % prop_name,
|
||||||
|
@ -115,8 +119,12 @@ def _register_observable(new_observable, version=stix2.DEFAULT_VERSION):
|
||||||
"'%s' is named like a reference property but "
|
"'%s' is named like a reference property but "
|
||||||
"is not a ReferenceProperty." % prop_name,
|
"is not a ReferenceProperty." % prop_name,
|
||||||
)
|
)
|
||||||
elif (prop_name.endswith('_refs') and ('ListProperty' not in get_class_hierarchy_names(prop) or
|
elif (
|
||||||
'ReferenceProperty' not in get_class_hierarchy_names(prop.contained))):
|
prop_name.endswith('_refs') and (
|
||||||
|
'ListProperty' not in get_class_hierarchy_names(prop) or
|
||||||
|
'ReferenceProperty' not in get_class_hierarchy_names(prop.contained)
|
||||||
|
)
|
||||||
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"'%s' is named like a reference list property but "
|
"'%s' is named like a reference list property but "
|
||||||
"is not a ListProperty containing ReferenceProperty." % prop_name,
|
"is not a ListProperty containing ReferenceProperty." % prop_name,
|
||||||
|
@ -126,16 +134,16 @@ def _register_observable(new_observable, version=stix2.DEFAULT_VERSION):
|
||||||
v = 'v' + version.replace('.', '')
|
v = 'v' + version.replace('.', '')
|
||||||
else:
|
else:
|
||||||
# Use default version (latest) if no version was provided.
|
# Use default version (latest) if no version was provided.
|
||||||
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '')
|
v = 'v' + DEFAULT_VERSION.replace('.', '')
|
||||||
|
|
||||||
OBJ_MAP_OBSERVABLE = stix2.registry.STIX2_OBJ_MAPS[v]['observables']
|
OBJ_MAP_OBSERVABLE = registry.STIX2_OBJ_MAPS[v]['observables']
|
||||||
if new_observable._type in OBJ_MAP_OBSERVABLE.keys():
|
if new_observable._type in OBJ_MAP_OBSERVABLE.keys():
|
||||||
raise DuplicateRegistrationError("Cyber Observable", new_observable._type)
|
raise DuplicateRegistrationError("Cyber Observable", new_observable._type)
|
||||||
OBJ_MAP_OBSERVABLE[new_observable._type] = new_observable
|
OBJ_MAP_OBSERVABLE[new_observable._type] = new_observable
|
||||||
|
|
||||||
|
|
||||||
def _register_observable_extension(
|
def _register_observable_extension(
|
||||||
observable, new_extension, version=stix2.DEFAULT_VERSION,
|
observable, new_extension, version=DEFAULT_VERSION,
|
||||||
):
|
):
|
||||||
"""Register a custom extension to a STIX Cyber Observable type.
|
"""Register a custom extension to a STIX Cyber Observable type.
|
||||||
|
|
||||||
|
@ -155,7 +163,7 @@ def _register_observable_extension(
|
||||||
if not issubclass(obs_class, _Observable):
|
if not issubclass(obs_class, _Observable):
|
||||||
raise ValueError("'observable' must be a valid Observable class!")
|
raise ValueError("'observable' must be a valid Observable class!")
|
||||||
|
|
||||||
stix2.properties._validate_type(ext_type, version)
|
_validate_type(ext_type, version)
|
||||||
|
|
||||||
if not new_extension._properties:
|
if not new_extension._properties:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -184,8 +192,8 @@ def _register_observable_extension(
|
||||||
"created with the @CustomObservable decorator.",
|
"created with the @CustomObservable decorator.",
|
||||||
)
|
)
|
||||||
|
|
||||||
OBJ_MAP_OBSERVABLE = stix2.registry.STIX2_OBJ_MAPS[v]['observables']
|
OBJ_MAP_OBSERVABLE = registry.STIX2_OBJ_MAPS[v]['observables']
|
||||||
EXT_MAP = stix2.registry.STIX2_OBJ_MAPS[v]['observable-extensions']
|
EXT_MAP = registry.STIX2_OBJ_MAPS[v]['observable-extensions']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if ext_type in EXT_MAP[observable_type].keys():
|
if ext_type in EXT_MAP[observable_type].keys():
|
||||||
|
|
|
@ -175,12 +175,14 @@ def test_memory_source_get_nonexistant_object(mem_source):
|
||||||
|
|
||||||
def test_memory_store_all_versions(mem_store):
|
def test_memory_store_all_versions(mem_store):
|
||||||
# Add bundle of items to sink
|
# Add bundle of items to sink
|
||||||
mem_store.add(dict(
|
mem_store.add(
|
||||||
|
dict(
|
||||||
id="bundle--%s" % make_id(),
|
id="bundle--%s" % make_id(),
|
||||||
objects=STIX_OBJS2,
|
objects=STIX_OBJS2,
|
||||||
spec_version="2.0",
|
spec_version="2.0",
|
||||||
type="bundle",
|
type="bundle",
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
|
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
|
||||||
assert len(resp) == 3
|
assert len(resp) == 3
|
||||||
|
|
|
@ -39,15 +39,19 @@ def ds2():
|
||||||
cam = stix2.v20.Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS)
|
cam = stix2.v20.Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS)
|
||||||
idy = stix2.v20.Identity(id=IDENTITY_ID, **IDENTITY_KWARGS)
|
idy = stix2.v20.Identity(id=IDENTITY_ID, **IDENTITY_KWARGS)
|
||||||
ind = stix2.v20.Indicator(id=INDICATOR_ID, created_by_ref=idy.id, **INDICATOR_KWARGS)
|
ind = stix2.v20.Indicator(id=INDICATOR_ID, created_by_ref=idy.id, **INDICATOR_KWARGS)
|
||||||
indv2 = ind.new_version(external_references=[{
|
indv2 = ind.new_version(
|
||||||
|
external_references=[{
|
||||||
"source_name": "unknown",
|
"source_name": "unknown",
|
||||||
"url": "https://examplewebsite.com/",
|
"url": "https://examplewebsite.com/",
|
||||||
}])
|
}],
|
||||||
|
)
|
||||||
mal = stix2.v20.Malware(id=MALWARE_ID, created_by_ref=idy.id, **MALWARE_KWARGS)
|
mal = stix2.v20.Malware(id=MALWARE_ID, created_by_ref=idy.id, **MALWARE_KWARGS)
|
||||||
malv2 = mal.new_version(external_references=[{
|
malv2 = mal.new_version(
|
||||||
|
external_references=[{
|
||||||
"source_name": "unknown",
|
"source_name": "unknown",
|
||||||
"url": "https://examplewebsite2.com/",
|
"url": "https://examplewebsite2.com/",
|
||||||
}])
|
}],
|
||||||
|
)
|
||||||
rel1 = stix2.v20.Relationship(ind, 'indicates', mal, id=RELATIONSHIP_IDS[0])
|
rel1 = stix2.v20.Relationship(ind, 'indicates', mal, id=RELATIONSHIP_IDS[0])
|
||||||
rel2 = stix2.v20.Relationship(mal, 'targets', idy, id=RELATIONSHIP_IDS[1])
|
rel2 = stix2.v20.Relationship(mal, 'targets', idy, id=RELATIONSHIP_IDS[1])
|
||||||
rel3 = stix2.v20.Relationship(cam, 'uses', mal, id=RELATIONSHIP_IDS[2])
|
rel3 = stix2.v20.Relationship(cam, 'uses', mal, id=RELATIONSHIP_IDS[2])
|
||||||
|
|
|
@ -20,7 +20,8 @@ EXPECTED_INDICATOR = """{
|
||||||
]
|
]
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join("""
|
EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join(
|
||||||
|
"""
|
||||||
type='indicator',
|
type='indicator',
|
||||||
id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7',
|
id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7',
|
||||||
created='2017-01-01T00:00:01.000Z',
|
created='2017-01-01T00:00:01.000Z',
|
||||||
|
@ -28,7 +29,8 @@ EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join("""
|
||||||
pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
|
pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
|
||||||
valid_from='1970-01-01T00:00:01Z',
|
valid_from='1970-01-01T00:00:01Z',
|
||||||
labels=['malicious-activity']
|
labels=['malicious-activity']
|
||||||
""".split()) + ")"
|
""".split(),
|
||||||
|
) + ")"
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_with_all_required_properties():
|
def test_indicator_with_all_required_properties():
|
||||||
|
|
|
@ -1180,21 +1180,24 @@ def test_process_example_extensions_empty():
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsProcessExt_Object():
|
def test_process_example_with_WindowsProcessExt_Object():
|
||||||
p = stix2.v20.Process(extensions={
|
p = stix2.v20.Process(
|
||||||
|
extensions={
|
||||||
"windows-process-ext": stix2.v20.WindowsProcessExt(
|
"windows-process-ext": stix2.v20.WindowsProcessExt(
|
||||||
aslr_enabled=True,
|
aslr_enabled=True,
|
||||||
dep_enabled=True,
|
dep_enabled=True,
|
||||||
priority="HIGH_PRIORITY_CLASS",
|
priority="HIGH_PRIORITY_CLASS",
|
||||||
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
|
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
|
||||||
), # noqa
|
), # noqa
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-process-ext"].dep_enabled
|
assert p.extensions["windows-process-ext"].dep_enabled
|
||||||
assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
|
assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsServiceExt():
|
def test_process_example_with_WindowsServiceExt():
|
||||||
p = stix2.v20.Process(extensions={
|
p = stix2.v20.Process(
|
||||||
|
extensions={
|
||||||
"windows-service-ext": {
|
"windows-service-ext": {
|
||||||
"service_name": "sirvizio",
|
"service_name": "sirvizio",
|
||||||
"display_name": "Sirvizio",
|
"display_name": "Sirvizio",
|
||||||
|
@ -1202,14 +1205,16 @@ def test_process_example_with_WindowsServiceExt():
|
||||||
"service_type": "SERVICE_WIN32_OWN_PROCESS",
|
"service_type": "SERVICE_WIN32_OWN_PROCESS",
|
||||||
"service_status": "SERVICE_RUNNING",
|
"service_status": "SERVICE_RUNNING",
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
||||||
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsProcessServiceExt():
|
def test_process_example_with_WindowsProcessServiceExt():
|
||||||
p = stix2.v20.Process(extensions={
|
p = stix2.v20.Process(
|
||||||
|
extensions={
|
||||||
"windows-service-ext": {
|
"windows-service-ext": {
|
||||||
"service_name": "sirvizio",
|
"service_name": "sirvizio",
|
||||||
"display_name": "Sirvizio",
|
"display_name": "Sirvizio",
|
||||||
|
@ -1223,7 +1228,8 @@ def test_process_example_with_WindowsProcessServiceExt():
|
||||||
"priority": "HIGH_PRIORITY_CLASS",
|
"priority": "HIGH_PRIORITY_CLASS",
|
||||||
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
|
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
||||||
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
||||||
|
|
|
@ -2,8 +2,7 @@ from collections import OrderedDict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import stix2
|
from stix2 import DEFAULT_VERSION, exceptions, parsing, registration, registry
|
||||||
from stix2 import exceptions, parsing, registration, registry
|
|
||||||
|
|
||||||
BUNDLE = {
|
BUNDLE = {
|
||||||
"type": "bundle",
|
"type": "bundle",
|
||||||
|
@ -59,7 +58,7 @@ def test_parse_observable_with_version():
|
||||||
assert v in str(obs_obj.__class__)
|
assert v in str(obs_obj.__class__)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="The default version is no longer 2.0", condition=stix2.DEFAULT_VERSION != "2.0")
|
@pytest.mark.xfail(reason="The default version is no longer 2.0", condition=DEFAULT_VERSION != "2.0")
|
||||||
def test_parse_observable_with_no_version():
|
def test_parse_observable_with_no_version():
|
||||||
observable = {"type": "file", "name": "foo.exe"}
|
observable = {"type": "file", "name": "foo.exe"}
|
||||||
obs_obj = parsing.parse_observable(observable)
|
obs_obj = parsing.parse_observable(observable)
|
||||||
|
|
|
@ -306,10 +306,12 @@ def test_multiple_qualifiers():
|
||||||
|
|
||||||
|
|
||||||
def test_set_op():
|
def test_set_op():
|
||||||
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression(
|
exp = stix2.ObservationExpression(
|
||||||
|
stix2.IsSubsetComparisonExpression(
|
||||||
"network-traffic:dst_ref.value",
|
"network-traffic:dst_ref.value",
|
||||||
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
|
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
|
||||||
))
|
),
|
||||||
|
)
|
||||||
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
|
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ def test_parse_datetime_invalid(ts):
|
||||||
{"a": 1},
|
{"a": 1},
|
||||||
'{"a": 1}',
|
'{"a": 1}',
|
||||||
StringIO(u'{"a": 1}'),
|
StringIO(u'{"a": 1}'),
|
||||||
[("a", 1,)],
|
[("a", 1)],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_get_dict(data):
|
def test_get_dict(data):
|
||||||
|
|
|
@ -46,10 +46,12 @@ def test_making_new_version_with_embedded_object():
|
||||||
**CAMPAIGN_MORE_KWARGS
|
**CAMPAIGN_MORE_KWARGS
|
||||||
)
|
)
|
||||||
|
|
||||||
campaign_v2 = campaign_v1.new_version(external_references=[{
|
campaign_v2 = campaign_v1.new_version(
|
||||||
|
external_references=[{
|
||||||
"source_name": "capec",
|
"source_name": "capec",
|
||||||
"external_id": "CAPEC-164",
|
"external_id": "CAPEC-164",
|
||||||
}])
|
}],
|
||||||
|
)
|
||||||
|
|
||||||
assert campaign_v1.id == campaign_v2.id
|
assert campaign_v1.id == campaign_v2.id
|
||||||
assert campaign_v1.created_by_ref == campaign_v2.created_by_ref
|
assert campaign_v1.created_by_ref == campaign_v2.created_by_ref
|
||||||
|
@ -237,8 +239,10 @@ def test_remove_custom_stix_property():
|
||||||
mal_nc = stix2.versioning.remove_custom_stix(mal)
|
mal_nc = stix2.versioning.remove_custom_stix(mal)
|
||||||
|
|
||||||
assert "x_custom" not in mal_nc
|
assert "x_custom" not in mal_nc
|
||||||
assert (stix2.utils.parse_into_datetime(mal["modified"], precision="millisecond") <
|
assert (
|
||||||
stix2.utils.parse_into_datetime(mal_nc["modified"], precision="millisecond"))
|
stix2.utils.parse_into_datetime(mal["modified"], precision="millisecond") <
|
||||||
|
stix2.utils.parse_into_datetime(mal_nc["modified"], precision="millisecond")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_remove_custom_stix_object():
|
def test_remove_custom_stix_object():
|
||||||
|
|
|
@ -191,11 +191,13 @@ def test_memory_source_get_nonexistant_object(mem_source):
|
||||||
|
|
||||||
def test_memory_store_all_versions(mem_store):
|
def test_memory_store_all_versions(mem_store):
|
||||||
# Add bundle of items to sink
|
# Add bundle of items to sink
|
||||||
mem_store.add(dict(
|
mem_store.add(
|
||||||
|
dict(
|
||||||
id="bundle--%s" % make_id(),
|
id="bundle--%s" % make_id(),
|
||||||
objects=STIX_OBJS2,
|
objects=STIX_OBJS2,
|
||||||
type="bundle",
|
type="bundle",
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
|
resp = mem_store.all_versions("indicator--00000000-0000-4000-8000-000000000001")
|
||||||
assert len(resp) == 3
|
assert len(resp) == 3
|
||||||
|
|
|
@ -20,7 +20,8 @@ EXPECTED_INDICATOR = """{
|
||||||
"valid_from": "1970-01-01T00:00:01Z"
|
"valid_from": "1970-01-01T00:00:01Z"
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join("""
|
EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join(
|
||||||
|
"""
|
||||||
type='indicator',
|
type='indicator',
|
||||||
spec_version='2.1',
|
spec_version='2.1',
|
||||||
id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7',
|
id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7',
|
||||||
|
@ -30,7 +31,8 @@ EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join("""
|
||||||
pattern_type='stix',
|
pattern_type='stix',
|
||||||
pattern_version='2.1',
|
pattern_version='2.1',
|
||||||
valid_from='1970-01-01T00:00:01Z'
|
valid_from='1970-01-01T00:00:01Z'
|
||||||
""".split()) + ")"
|
""".split(),
|
||||||
|
) + ")"
|
||||||
|
|
||||||
|
|
||||||
def test_indicator_with_all_required_properties():
|
def test_indicator_with_all_required_properties():
|
||||||
|
|
|
@ -19,14 +19,16 @@ EXPECTED_LOCATION_1 = """{
|
||||||
"longitude": 2.3522
|
"longitude": 2.3522
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
EXPECTED_LOCATION_1_REPR = "Location(" + " ".join("""
|
EXPECTED_LOCATION_1_REPR = "Location(" + " ".join(
|
||||||
|
"""
|
||||||
type='location',
|
type='location',
|
||||||
spec_version='2.1',
|
spec_version='2.1',
|
||||||
id='location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64',
|
id='location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64',
|
||||||
created='2016-04-06T20:03:00.000Z',
|
created='2016-04-06T20:03:00.000Z',
|
||||||
modified='2016-04-06T20:03:00.000Z',
|
modified='2016-04-06T20:03:00.000Z',
|
||||||
latitude=48.8566,
|
latitude=48.8566,
|
||||||
longitude=2.3522""".split()) + ")"
|
longitude=2.3522""".split(),
|
||||||
|
) + ")"
|
||||||
|
|
||||||
EXPECTED_LOCATION_2 = """{
|
EXPECTED_LOCATION_2 = """{
|
||||||
"type": "location",
|
"type": "location",
|
||||||
|
@ -38,13 +40,15 @@ EXPECTED_LOCATION_2 = """{
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXPECTED_LOCATION_2_REPR = "Location(" + " ".join("""
|
EXPECTED_LOCATION_2_REPR = "Location(" + " ".join(
|
||||||
|
"""
|
||||||
type='location',
|
type='location',
|
||||||
spec_version='2.1',
|
spec_version='2.1',
|
||||||
id='location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64',
|
id='location--a6e9345f-5a15-4c29-8bb3-7dcc5d168d64',
|
||||||
created='2016-04-06T20:03:00.000Z',
|
created='2016-04-06T20:03:00.000Z',
|
||||||
modified='2016-04-06T20:03:00.000Z',
|
modified='2016-04-06T20:03:00.000Z',
|
||||||
region='north-america'""".split()) + ")"
|
region='north-america'""".split(),
|
||||||
|
) + ")"
|
||||||
|
|
||||||
|
|
||||||
def test_location_with_some_required_properties():
|
def test_location_with_some_required_properties():
|
||||||
|
|
|
@ -496,12 +496,14 @@ def test_parse_email_message_not_multipart(data):
|
||||||
def test_parse_file_archive(data):
|
def test_parse_file_archive(data):
|
||||||
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
||||||
odata = stix2.parse(odata_str, version="2.1")
|
odata = stix2.parse(odata_str, version="2.1")
|
||||||
assert all(x in odata.objects["3"].extensions['archive-ext'].contains_refs
|
assert all(
|
||||||
|
x in odata.objects["3"].extensions['archive-ext'].contains_refs
|
||||||
for x in [
|
for x in [
|
||||||
"file--ecd47d73-15e4-5250-afda-ef8897b22340",
|
"file--ecd47d73-15e4-5250-afda-ef8897b22340",
|
||||||
"file--65f2873d-38c2-56b4-bfa5-e3ef21e8a3c3",
|
"file--65f2873d-38c2-56b4-bfa5-e3ef21e8a3c3",
|
||||||
"file--ef2d6dca-ec7d-5ab7-8dd9-ec9c0dee0eac",
|
"file--ef2d6dca-ec7d-5ab7-8dd9-ec9c0dee0eac",
|
||||||
])
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -904,14 +906,14 @@ def test_file_with_archive_ext_object():
|
||||||
f_obj = stix2.v21.File(
|
f_obj = stix2.v21.File(
|
||||||
name="foo", extensions={
|
name="foo", extensions={
|
||||||
"archive-ext": {
|
"archive-ext": {
|
||||||
"contains_refs": [ad, ],
|
"contains_refs": [ad],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
f_ref = stix2.v21.File(
|
f_ref = stix2.v21.File(
|
||||||
name="foo", extensions={
|
name="foo", extensions={
|
||||||
"archive-ext": {
|
"archive-ext": {
|
||||||
"contains_refs": [ad.id, ],
|
"contains_refs": [ad.id],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1229,9 +1231,11 @@ def test_process_example_empty_error():
|
||||||
|
|
||||||
def test_process_example_empty_with_extensions():
|
def test_process_example_empty_with_extensions():
|
||||||
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
stix2.v21.Process(extensions={
|
stix2.v21.Process(
|
||||||
|
extensions={
|
||||||
"windows-process-ext": {},
|
"windows-process-ext": {},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v21.Process
|
assert excinfo.value.cls == stix2.v21.Process
|
||||||
|
|
||||||
|
@ -1276,21 +1280,24 @@ def test_process_example_extensions_empty():
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsProcessExt_Object():
|
def test_process_example_with_WindowsProcessExt_Object():
|
||||||
p = stix2.v21.Process(extensions={
|
p = stix2.v21.Process(
|
||||||
|
extensions={
|
||||||
"windows-process-ext": stix2.v21.WindowsProcessExt(
|
"windows-process-ext": stix2.v21.WindowsProcessExt(
|
||||||
aslr_enabled=True,
|
aslr_enabled=True,
|
||||||
dep_enabled=True,
|
dep_enabled=True,
|
||||||
priority="HIGH_PRIORITY_CLASS",
|
priority="HIGH_PRIORITY_CLASS",
|
||||||
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
|
owner_sid="S-1-5-21-186985262-1144665072-74031268-1309",
|
||||||
), # noqa
|
), # noqa
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-process-ext"].dep_enabled
|
assert p.extensions["windows-process-ext"].dep_enabled
|
||||||
assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
|
assert p.extensions["windows-process-ext"].owner_sid == "S-1-5-21-186985262-1144665072-74031268-1309"
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsServiceExt():
|
def test_process_example_with_WindowsServiceExt():
|
||||||
p = stix2.v21.Process(extensions={
|
p = stix2.v21.Process(
|
||||||
|
extensions={
|
||||||
"windows-service-ext": {
|
"windows-service-ext": {
|
||||||
"service_name": "sirvizio",
|
"service_name": "sirvizio",
|
||||||
"display_name": "Sirvizio",
|
"display_name": "Sirvizio",
|
||||||
|
@ -1298,14 +1305,16 @@ def test_process_example_with_WindowsServiceExt():
|
||||||
"service_type": "SERVICE_WIN32_OWN_PROCESS",
|
"service_type": "SERVICE_WIN32_OWN_PROCESS",
|
||||||
"service_status": "SERVICE_RUNNING",
|
"service_status": "SERVICE_RUNNING",
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
||||||
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
||||||
|
|
||||||
|
|
||||||
def test_process_example_with_WindowsProcessServiceExt():
|
def test_process_example_with_WindowsProcessServiceExt():
|
||||||
p = stix2.v21.Process(extensions={
|
p = stix2.v21.Process(
|
||||||
|
extensions={
|
||||||
"windows-service-ext": {
|
"windows-service-ext": {
|
||||||
"service_name": "sirvizio",
|
"service_name": "sirvizio",
|
||||||
"display_name": "Sirvizio",
|
"display_name": "Sirvizio",
|
||||||
|
@ -1319,7 +1328,8 @@ def test_process_example_with_WindowsProcessServiceExt():
|
||||||
"priority": "HIGH_PRIORITY_CLASS",
|
"priority": "HIGH_PRIORITY_CLASS",
|
||||||
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
|
"owner_sid": "S-1-5-21-186985262-1144665072-74031268-1309",
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
assert p.extensions["windows-service-ext"].service_name == "sirvizio"
|
||||||
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
assert p.extensions["windows-service-ext"].service_type == "SERVICE_WIN32_OWN_PROCESS"
|
||||||
|
|
|
@ -2,8 +2,7 @@ from collections import OrderedDict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import stix2
|
from stix2 import DEFAULT_VERSION, exceptions, parsing, registration, registry
|
||||||
from stix2 import exceptions, parsing, registration, registry
|
|
||||||
|
|
||||||
BUNDLE = {
|
BUNDLE = {
|
||||||
"type": "bundle",
|
"type": "bundle",
|
||||||
|
@ -64,7 +63,7 @@ def test_parse_observable_with_version():
|
||||||
assert v in str(obs_obj.__class__)
|
assert v in str(obs_obj.__class__)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="The default version is not 2.1", condition=stix2.DEFAULT_VERSION != "2.1")
|
@pytest.mark.xfail(reason="The default version is not 2.1", condition=DEFAULT_VERSION != "2.1")
|
||||||
def test_parse_observable_with_no_version():
|
def test_parse_observable_with_no_version():
|
||||||
observable = {"type": "file", "name": "foo.exe", "spec_version": "2.1"}
|
observable = {"type": "file", "name": "foo.exe", "spec_version": "2.1"}
|
||||||
obs_obj = parsing.parse_observable(observable)
|
obs_obj = parsing.parse_observable(observable)
|
||||||
|
@ -85,7 +84,7 @@ def test_register_marking_with_version():
|
||||||
assert v in str(registry.STIX2_OBJ_MAPS[v]['markings'][NewMarking1._type])
|
assert v in str(registry.STIX2_OBJ_MAPS[v]['markings'][NewMarking1._type])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="The default version is not 2.1", condition=stix2.DEFAULT_VERSION != "2.1")
|
@pytest.mark.xfail(reason="The default version is not 2.1", condition=DEFAULT_VERSION != "2.1")
|
||||||
def test_register_marking_with_no_version():
|
def test_register_marking_with_no_version():
|
||||||
# Uses default version (2.1 in this case)
|
# Uses default version (2.1 in this case)
|
||||||
class NewMarking2:
|
class NewMarking2:
|
||||||
|
|
|
@ -444,10 +444,12 @@ def test_multiple_qualifiers():
|
||||||
|
|
||||||
|
|
||||||
def test_set_op():
|
def test_set_op():
|
||||||
exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression(
|
exp = stix2.ObservationExpression(
|
||||||
|
stix2.IsSubsetComparisonExpression(
|
||||||
"network-traffic:dst_ref.value",
|
"network-traffic:dst_ref.value",
|
||||||
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
|
"2001:0db8:dead:beef:0000:0000:0000:0000/64",
|
||||||
))
|
),
|
||||||
|
)
|
||||||
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
|
assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
|
||||||
|
|
||||||
|
|
||||||
|
@ -712,12 +714,12 @@ def test_parsing_boolean():
|
||||||
|
|
||||||
|
|
||||||
def test_parsing_mixed_boolean_expression_1():
|
def test_parsing_mixed_boolean_expression_1():
|
||||||
patt_obj = create_pattern_object("[a:b = 1 AND a:b = 2 OR a:b = 3]",)
|
patt_obj = create_pattern_object("[a:b = 1 AND a:b = 2 OR a:b = 3]")
|
||||||
assert str(patt_obj) == "[a:b = 1 AND a:b = 2 OR a:b = 3]"
|
assert str(patt_obj) == "[a:b = 1 AND a:b = 2 OR a:b = 3]"
|
||||||
|
|
||||||
|
|
||||||
def test_parsing_mixed_boolean_expression_2():
|
def test_parsing_mixed_boolean_expression_2():
|
||||||
patt_obj = create_pattern_object("[a:b = 1 OR a:b = 2 AND a:b = 3]",)
|
patt_obj = create_pattern_object("[a:b = 1 OR a:b = 2 AND a:b = 3]")
|
||||||
assert str(patt_obj) == "[a:b = 1 OR a:b = 2 AND a:b = 3]"
|
assert str(patt_obj) == "[a:b = 1 OR a:b = 2 AND a:b = 3]"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ def test_parse_datetime_invalid(ts):
|
||||||
{"a": 1},
|
{"a": 1},
|
||||||
'{"a": 1}',
|
'{"a": 1}',
|
||||||
StringIO(u'{"a": 1}'),
|
StringIO(u'{"a": 1}'),
|
||||||
[("a", 1,)],
|
[("a", 1)],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_get_dict(data):
|
def test_get_dict(data):
|
||||||
|
|
|
@ -50,10 +50,12 @@ def test_making_new_version_with_embedded_object():
|
||||||
**CAMPAIGN_MORE_KWARGS
|
**CAMPAIGN_MORE_KWARGS
|
||||||
)
|
)
|
||||||
|
|
||||||
campaign_v2 = campaign_v1.new_version(external_references=[{
|
campaign_v2 = campaign_v1.new_version(
|
||||||
|
external_references=[{
|
||||||
"source_name": "capec",
|
"source_name": "capec",
|
||||||
"external_id": "CAPEC-164",
|
"external_id": "CAPEC-164",
|
||||||
}])
|
}],
|
||||||
|
)
|
||||||
|
|
||||||
assert campaign_v1.id == campaign_v2.id
|
assert campaign_v1.id == campaign_v2.id
|
||||||
assert campaign_v1.spec_version == campaign_v2.spec_version
|
assert campaign_v1.spec_version == campaign_v2.spec_version
|
||||||
|
|
|
@ -71,9 +71,11 @@ def _to_enum(value, enum_type, enum_default=None):
|
||||||
elif isinstance(value, six.string_types):
|
elif isinstance(value, six.string_types):
|
||||||
value = enum_type[value.upper()]
|
value = enum_type[value.upper()]
|
||||||
else:
|
else:
|
||||||
raise TypeError("Not a valid {}: {}".format(
|
raise TypeError(
|
||||||
|
"Not a valid {}: {}".format(
|
||||||
enum_type.__name__, value,
|
enum_type.__name__, value,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -440,24 +440,28 @@ class SocketExt(_Extension):
|
||||||
('is_blocking', BooleanProperty()),
|
('is_blocking', BooleanProperty()),
|
||||||
('is_listening', BooleanProperty()),
|
('is_listening', BooleanProperty()),
|
||||||
(
|
(
|
||||||
'protocol_family', EnumProperty(allowed=[
|
'protocol_family', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"PF_INET",
|
"PF_INET",
|
||||||
"PF_IPX",
|
"PF_IPX",
|
||||||
"PF_APPLETALK",
|
"PF_APPLETALK",
|
||||||
"PF_INET6",
|
"PF_INET6",
|
||||||
"PF_AX25",
|
"PF_AX25",
|
||||||
"PF_NETROM",
|
"PF_NETROM",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
('options', DictionaryProperty(spec_version="2.0")),
|
('options', DictionaryProperty(spec_version="2.0")),
|
||||||
(
|
(
|
||||||
'socket_type', EnumProperty(allowed=[
|
'socket_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SOCK_STREAM",
|
"SOCK_STREAM",
|
||||||
"SOCK_DGRAM",
|
"SOCK_DGRAM",
|
||||||
"SOCK_RAW",
|
"SOCK_RAW",
|
||||||
"SOCK_RDM",
|
"SOCK_RDM",
|
||||||
"SOCK_SEQPACKET",
|
"SOCK_SEQPACKET",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
('socket_descriptor', IntegerProperty()),
|
('socket_descriptor', IntegerProperty()),
|
||||||
('socket_handle', IntegerProperty()),
|
('socket_handle', IntegerProperty()),
|
||||||
|
@ -537,25 +541,30 @@ class WindowsServiceExt(_Extension):
|
||||||
('display_name', StringProperty()),
|
('display_name', StringProperty()),
|
||||||
('group_name', StringProperty()),
|
('group_name', StringProperty()),
|
||||||
(
|
(
|
||||||
'start_type', EnumProperty(allowed=[
|
'start_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_AUTO_START",
|
"SERVICE_AUTO_START",
|
||||||
"SERVICE_BOOT_START",
|
"SERVICE_BOOT_START",
|
||||||
"SERVICE_DEMAND_START",
|
"SERVICE_DEMAND_START",
|
||||||
"SERVICE_DISABLED",
|
"SERVICE_DISABLED",
|
||||||
"SERVICE_SYSTEM_ALERT",
|
"SERVICE_SYSTEM_ALERT",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
('service_dll_refs', ListProperty(ObjectReferenceProperty(valid_types='file'))),
|
('service_dll_refs', ListProperty(ObjectReferenceProperty(valid_types='file'))),
|
||||||
(
|
(
|
||||||
'service_type', EnumProperty(allowed=[
|
'service_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_KERNEL_DRIVER",
|
"SERVICE_KERNEL_DRIVER",
|
||||||
"SERVICE_FILE_SYSTEM_DRIVER",
|
"SERVICE_FILE_SYSTEM_DRIVER",
|
||||||
"SERVICE_WIN32_OWN_PROCESS",
|
"SERVICE_WIN32_OWN_PROCESS",
|
||||||
"SERVICE_WIN32_SHARE_PROCESS",
|
"SERVICE_WIN32_SHARE_PROCESS",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'service_status', EnumProperty(allowed=[
|
'service_status', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_CONTINUE_PENDING",
|
"SERVICE_CONTINUE_PENDING",
|
||||||
"SERVICE_PAUSE_PENDING",
|
"SERVICE_PAUSE_PENDING",
|
||||||
"SERVICE_PAUSED",
|
"SERVICE_PAUSED",
|
||||||
|
@ -563,7 +572,8 @@ class WindowsServiceExt(_Extension):
|
||||||
"SERVICE_START_PENDING",
|
"SERVICE_START_PENDING",
|
||||||
"SERVICE_STOP_PENDING",
|
"SERVICE_STOP_PENDING",
|
||||||
"SERVICE_STOPPED",
|
"SERVICE_STOPPED",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -687,7 +697,8 @@ class WindowsRegistryValueType(_STIXBase20):
|
||||||
('name', StringProperty(required=True)),
|
('name', StringProperty(required=True)),
|
||||||
('data', StringProperty()),
|
('data', StringProperty()),
|
||||||
(
|
(
|
||||||
'data_type', EnumProperty(allowed=[
|
'data_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"REG_NONE",
|
"REG_NONE",
|
||||||
"REG_SZ",
|
"REG_SZ",
|
||||||
"REG_EXPAND_SZ",
|
"REG_EXPAND_SZ",
|
||||||
|
@ -701,7 +712,8 @@ class WindowsRegistryValueType(_STIXBase20):
|
||||||
"REG_RESOURCE_REQUIREMENTS_LIST",
|
"REG_RESOURCE_REQUIREMENTS_LIST",
|
||||||
"REG_QWORD",
|
"REG_QWORD",
|
||||||
"REG_INVALID_TYPE",
|
"REG_INVALID_TYPE",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -790,11 +802,13 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def wrapper(cls):
|
def wrapper(cls):
|
||||||
_properties = list(itertools.chain.from_iterable([
|
_properties = list(
|
||||||
|
itertools.chain.from_iterable([
|
||||||
[('type', TypeProperty(type, spec_version='2.0'))],
|
[('type', TypeProperty(type, spec_version='2.0'))],
|
||||||
properties,
|
properties,
|
||||||
[('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=type))],
|
[('extensions', ExtensionsProperty(spec_version="2.0", enclosing_type=type))],
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
return _custom_observable_builder(cls, type, _properties, '2.0', _Observable)
|
return _custom_observable_builder(cls, type, _properties, '2.0', _Observable)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
|
@ -356,7 +356,8 @@ def CustomObject(type='x-custom-type', properties=None):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def wrapper(cls):
|
def wrapper(cls):
|
||||||
_properties = list(itertools.chain.from_iterable([
|
_properties = list(
|
||||||
|
itertools.chain.from_iterable([
|
||||||
[
|
[
|
||||||
('type', TypeProperty(type, spec_version='2.0')),
|
('type', TypeProperty(type, spec_version='2.0')),
|
||||||
('id', IDProperty(type, spec_version='2.0')),
|
('id', IDProperty(type, spec_version='2.0')),
|
||||||
|
@ -373,6 +374,7 @@ def CustomObject(type='x-custom-type', properties=None):
|
||||||
('granular_markings', ListProperty(GranularMarking)),
|
('granular_markings', ListProperty(GranularMarking)),
|
||||||
],
|
],
|
||||||
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
|
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
return _custom_object_builder(cls, type, _properties, '2.0', _DomainObject)
|
return _custom_object_builder(cls, type, _properties, '2.0', _DomainObject)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
|
@ -505,13 +505,15 @@ class SocketExt(_Extension):
|
||||||
('is_listening', BooleanProperty()),
|
('is_listening', BooleanProperty()),
|
||||||
('options', DictionaryProperty(spec_version='2.1')),
|
('options', DictionaryProperty(spec_version='2.1')),
|
||||||
(
|
(
|
||||||
'socket_type', EnumProperty(allowed=[
|
'socket_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SOCK_STREAM",
|
"SOCK_STREAM",
|
||||||
"SOCK_DGRAM",
|
"SOCK_DGRAM",
|
||||||
"SOCK_RAW",
|
"SOCK_RAW",
|
||||||
"SOCK_RDM",
|
"SOCK_RDM",
|
||||||
"SOCK_SEQPACKET",
|
"SOCK_SEQPACKET",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
('socket_descriptor', IntegerProperty(min=0)),
|
('socket_descriptor', IntegerProperty(min=0)),
|
||||||
('socket_handle', IntegerProperty()),
|
('socket_handle', IntegerProperty()),
|
||||||
|
@ -612,12 +614,14 @@ class WindowsProcessExt(_Extension):
|
||||||
('window_title', StringProperty()),
|
('window_title', StringProperty()),
|
||||||
('startup_info', DictionaryProperty(spec_version='2.1')),
|
('startup_info', DictionaryProperty(spec_version='2.1')),
|
||||||
(
|
(
|
||||||
'integrity_level', EnumProperty(allowed=[
|
'integrity_level', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"low",
|
"low",
|
||||||
"medium",
|
"medium",
|
||||||
"high",
|
"high",
|
||||||
"system",
|
"system",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -634,25 +638,30 @@ class WindowsServiceExt(_Extension):
|
||||||
('display_name', StringProperty()),
|
('display_name', StringProperty()),
|
||||||
('group_name', StringProperty()),
|
('group_name', StringProperty()),
|
||||||
(
|
(
|
||||||
'start_type', EnumProperty(allowed=[
|
'start_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_AUTO_START",
|
"SERVICE_AUTO_START",
|
||||||
"SERVICE_BOOT_START",
|
"SERVICE_BOOT_START",
|
||||||
"SERVICE_DEMAND_START",
|
"SERVICE_DEMAND_START",
|
||||||
"SERVICE_DISABLED",
|
"SERVICE_DISABLED",
|
||||||
"SERVICE_SYSTEM_ALERT",
|
"SERVICE_SYSTEM_ALERT",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
('service_dll_refs', ListProperty(ReferenceProperty(valid_types='file', spec_version="2.1"))),
|
('service_dll_refs', ListProperty(ReferenceProperty(valid_types='file', spec_version="2.1"))),
|
||||||
(
|
(
|
||||||
'service_type', EnumProperty(allowed=[
|
'service_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_KERNEL_DRIVER",
|
"SERVICE_KERNEL_DRIVER",
|
||||||
"SERVICE_FILE_SYSTEM_DRIVER",
|
"SERVICE_FILE_SYSTEM_DRIVER",
|
||||||
"SERVICE_WIN32_OWN_PROCESS",
|
"SERVICE_WIN32_OWN_PROCESS",
|
||||||
"SERVICE_WIN32_SHARE_PROCESS",
|
"SERVICE_WIN32_SHARE_PROCESS",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'service_status', EnumProperty(allowed=[
|
'service_status', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"SERVICE_CONTINUE_PENDING",
|
"SERVICE_CONTINUE_PENDING",
|
||||||
"SERVICE_PAUSE_PENDING",
|
"SERVICE_PAUSE_PENDING",
|
||||||
"SERVICE_PAUSED",
|
"SERVICE_PAUSED",
|
||||||
|
@ -660,7 +669,8 @@ class WindowsServiceExt(_Extension):
|
||||||
"SERVICE_START_PENDING",
|
"SERVICE_START_PENDING",
|
||||||
"SERVICE_STOP_PENDING",
|
"SERVICE_STOP_PENDING",
|
||||||
"SERVICE_STOPPED",
|
"SERVICE_STOPPED",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -808,7 +818,8 @@ class WindowsRegistryValueType(_STIXBase21):
|
||||||
('name', StringProperty()),
|
('name', StringProperty()),
|
||||||
('data', StringProperty()),
|
('data', StringProperty()),
|
||||||
(
|
(
|
||||||
'data_type', EnumProperty(allowed=[
|
'data_type', EnumProperty(
|
||||||
|
allowed=[
|
||||||
"REG_NONE",
|
"REG_NONE",
|
||||||
"REG_SZ",
|
"REG_SZ",
|
||||||
"REG_EXPAND_SZ",
|
"REG_EXPAND_SZ",
|
||||||
|
@ -822,7 +833,8 @@ class WindowsRegistryValueType(_STIXBase21):
|
||||||
"REG_RESOURCE_REQUIREMENTS_LIST",
|
"REG_RESOURCE_REQUIREMENTS_LIST",
|
||||||
"REG_QWORD",
|
"REG_QWORD",
|
||||||
"REG_INVALID_TYPE",
|
"REG_INVALID_TYPE",
|
||||||
]),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -935,13 +947,15 @@ def CustomObservable(type='x-custom-observable', properties=None, id_contrib_pro
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def wrapper(cls):
|
def wrapper(cls):
|
||||||
_properties = list(itertools.chain.from_iterable([
|
_properties = list(
|
||||||
|
itertools.chain.from_iterable([
|
||||||
[('type', TypeProperty(type, spec_version='2.1'))],
|
[('type', TypeProperty(type, spec_version='2.1'))],
|
||||||
[('spec_version', StringProperty(fixed='2.1'))],
|
[('spec_version', StringProperty(fixed='2.1'))],
|
||||||
[('id', IDProperty(type, spec_version='2.1'))],
|
[('id', IDProperty(type, spec_version='2.1'))],
|
||||||
properties,
|
properties,
|
||||||
[('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))],
|
[('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))],
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
return _custom_observable_builder(cls, type, _properties, '2.1', _Observable, id_contrib_props)
|
return _custom_observable_builder(cls, type, _properties, '2.1', _Observable, id_contrib_props)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
|
@ -789,7 +789,8 @@ def CustomObject(type='x-custom-type', properties=None):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def wrapper(cls):
|
def wrapper(cls):
|
||||||
_properties = list(itertools.chain.from_iterable([
|
_properties = list(
|
||||||
|
itertools.chain.from_iterable([
|
||||||
[
|
[
|
||||||
('type', TypeProperty(type, spec_version='2.1')),
|
('type', TypeProperty(type, spec_version='2.1')),
|
||||||
('spec_version', StringProperty(fixed='2.1')),
|
('spec_version', StringProperty(fixed='2.1')),
|
||||||
|
@ -809,7 +810,8 @@ def CustomObject(type='x-custom-type', properties=None):
|
||||||
('granular_markings', ListProperty(GranularMarking)),
|
('granular_markings', ListProperty(GranularMarking)),
|
||||||
],
|
],
|
||||||
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
|
sorted([x for x in properties if x[0].startswith('x_')], key=lambda x: x[0]),
|
||||||
]))
|
]),
|
||||||
|
)
|
||||||
return _custom_object_builder(cls, type, _properties, '2.1', _DomainObject)
|
return _custom_object_builder(cls, type, _properties, '2.1', _DomainObject)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import stix2
|
|
||||||
from . import AttackPattern as _AttackPattern
|
from . import AttackPattern as _AttackPattern
|
||||||
from . import Campaign as _Campaign
|
from . import Campaign as _Campaign
|
||||||
from . import CourseOfAction as _CourseOfAction
|
from . import CourseOfAction as _CourseOfAction
|
||||||
|
@ -34,34 +34,37 @@ from . import Location as _Location
|
||||||
from . import Malware as _Malware
|
from . import Malware as _Malware
|
||||||
from . import MalwareAnalysis as _MalwareAnalysis
|
from . import MalwareAnalysis as _MalwareAnalysis
|
||||||
from . import Note as _Note
|
from . import Note as _Note
|
||||||
|
from . import OBJ_MAP
|
||||||
from . import ObservedData as _ObservedData
|
from . import ObservedData as _ObservedData
|
||||||
from . import Opinion as _Opinion
|
from . import Opinion as _Opinion
|
||||||
from . import Report as _Report
|
from . import Report as _Report
|
||||||
from . import ThreatActor as _ThreatActor
|
from . import ThreatActor as _ThreatActor
|
||||||
from . import Tool as _Tool
|
from . import Tool as _Tool
|
||||||
from . import Vulnerability as _Vulnerability
|
from . import Vulnerability as _Vulnerability
|
||||||
from . import ( # noqa: F401
|
from .version import DEFAULT_VERSION
|
||||||
|
|
||||||
|
from . import ( # noqa: F401 isort:skip
|
||||||
AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
|
AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem,
|
||||||
Bundle, CustomExtension, CustomMarking, CustomObservable,
|
Bundle, CustomExtension, CustomMarking, CustomObservable,
|
||||||
Directory, DomainName, EmailAddress, EmailMessage,
|
Directory, DomainName, EmailAddress, EmailMessage,
|
||||||
EmailMIMEComponent, Environment, ExternalReference, File,
|
EmailMIMEComponent, Environment, ExternalReference, File,
|
||||||
FileSystemSource, Filter, GranularMarking, HTTPRequestExt,
|
FileSystemSource, Filter, GranularMarking, HTTPRequestExt,
|
||||||
ICMPExt, IPv4Address, IPv6Address, KillChainPhase, LanguageContent, MACAddress,
|
ICMPExt, IPv4Address, IPv6Address, KillChainPhase, LanguageContent,
|
||||||
MarkingDefinition, MemoryStore, Mutex, NetworkTraffic, NTFSExt,
|
MACAddress, MarkingDefinition, MemoryStore, Mutex, NetworkTraffic,
|
||||||
parse_observable, PDFExt, Process, RasterImageExt, Relationship,
|
NTFSExt, parse_observable, PDFExt, Process, RasterImageExt, Relationship,
|
||||||
Sighting, SocketExt, Software, StatementMarking,
|
Sighting, SocketExt, Software, StatementMarking,
|
||||||
TAXIICollectionSource, TCPExt, TLP_AMBER, TLP_GREEN, TLP_RED,
|
TAXIICollectionSource, TCPExt, TLP_AMBER, TLP_GREEN, TLP_RED,
|
||||||
TLP_WHITE, TLPMarking, UNIXAccountExt, URL, UserAccount,
|
TLP_WHITE, TLPMarking, UNIXAccountExt, URL, UserAccount,
|
||||||
WindowsPEBinaryExt, WindowsPEOptionalHeaderType,
|
WindowsPEBinaryExt, WindowsPEOptionalHeaderType,
|
||||||
WindowsPESection, WindowsProcessExt, WindowsRegistryKey,
|
WindowsPESection, WindowsProcessExt, WindowsRegistryKey,
|
||||||
WindowsRegistryValueType, WindowsServiceExt, X509Certificate,
|
WindowsRegistryValueType, WindowsServiceExt, X509Certificate,
|
||||||
X509V3ExtensionsType
|
X509V3ExtensionsType,
|
||||||
)
|
)
|
||||||
from .datastore.filters import FilterSet
|
from .datastore.filters import FilterSet # isort:skip
|
||||||
|
|
||||||
|
|
||||||
# Enable some adaptation to the current default supported STIX version.
|
# Enable some adaptation to the current default supported STIX version.
|
||||||
_STIX_VID = "v" + stix2.DEFAULT_VERSION.replace(".", "")
|
_STIX_VID = "v" + DEFAULT_VERSION.replace(".", "")
|
||||||
|
|
||||||
|
|
||||||
# Use an implicit MemoryStore
|
# Use an implicit MemoryStore
|
||||||
|
@ -161,7 +164,7 @@ def _setup_workbench():
|
||||||
# Add our new "class" to this module's globals and to the library-wide
|
# Add our new "class" to this module's globals and to the library-wide
|
||||||
# mapping. This allows parse() to use the wrapped classes.
|
# mapping. This allows parse() to use the wrapped classes.
|
||||||
globals()[obj_type.__name__] = factory_func
|
globals()[obj_type.__name__] = factory_func
|
||||||
stix2.OBJ_MAP[obj_type._type] = factory_func
|
OBJ_MAP[obj_type._type] = factory_func
|
||||||
|
|
||||||
|
|
||||||
_setup_workbench()
|
_setup_workbench()
|
||||||
|
|
33
tox.ini
33
tox.ini
|
@ -1,5 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py35,py36,py37,py38,style,isort-check,packaging
|
envlist = py36,py37,py38,py39,packaging,pre-commit-check
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
|
@ -15,33 +15,24 @@ deps =
|
||||||
commands =
|
commands =
|
||||||
python -m pytest --cov=stix2 stix2/test/ --cov-report term-missing -W ignore::stix2.exceptions.STIXDeprecationWarning
|
python -m pytest --cov=stix2 stix2/test/ --cov-report term-missing -W ignore::stix2.exceptions.STIXDeprecationWarning
|
||||||
|
|
||||||
passenv = CI TRAVIS TRAVIS_*
|
passenv = GITHUB_*
|
||||||
|
|
||||||
[testenv:style]
|
|
||||||
deps =
|
|
||||||
flake8
|
|
||||||
commands =
|
|
||||||
flake8
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 160
|
|
||||||
|
|
||||||
[testenv:isort-check]
|
|
||||||
deps = isort
|
|
||||||
commands =
|
|
||||||
isort stix2 examples --df
|
|
||||||
isort stix2 examples -c
|
|
||||||
|
|
||||||
[testenv:packaging]
|
[testenv:packaging]
|
||||||
deps =
|
deps =
|
||||||
twine
|
twine
|
||||||
commands =
|
commands =
|
||||||
python setup.py bdist_wheel --universal
|
python setup.py sdist bdist_wheel --universal
|
||||||
twine check dist/*
|
twine check dist/*
|
||||||
|
|
||||||
[travis]
|
[testenv:pre-commit-check]
|
||||||
|
deps =
|
||||||
|
pre-commit
|
||||||
|
commands =
|
||||||
|
pre-commit run --all-files
|
||||||
|
|
||||||
|
[gh-actions]
|
||||||
python =
|
python =
|
||||||
3.5: py35
|
|
||||||
3.6: py36
|
3.6: py36
|
||||||
3.7: py37
|
3.7: py37
|
||||||
3.8: py38, style, packaging
|
3.8: py38
|
||||||
|
3.9: py39, packaging, pre-commit-check
|
||||||
|
|
Loading…
Reference in New Issue