diff --git a/.gitignore b/.gitignore
index 267b66db..fda5964e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@
# pycharm
.idea/
.idea
+.pytest_cache/
# python setuptools
build/
diff --git a/.travis.yml b/.travis.yml
index 3a162b37..ab509e99 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,19 +1,19 @@
+os: linux
language: python
-env:
- - TOXENV=py26
- - TOXENV=py27
- - TOXENV=lxml23
-
+cache: pip
+dist: xenial
+python:
+ - "2.7"
+ - "3.4"
+ - "3.5"
+ - "3.6"
+ - "3.7"
+ - "3.8"
install:
- - pip install tox
-
+ - pip install -U pip setuptools
+ - pip install tox-travis
script:
- tox
-
-branches:
- only:
- - master
-
notifications:
email:
- stix-commits-list@lists.mitre.org
diff --git a/CHANGES.txt b/CHANGES.txt
index 1f6d6478..cf2d2bc9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,80 @@
+Version 1.1.1.19
+2020-11-16
+- #327 Fix deprecation warning from collections module
+
+Version 1.1.1.18
+2020-05-01
+- #366 Check add_reference methods to prevent NoneType has no attribute 'append'
+- Changes to STIXPackage to prevent the empty tag from appearing in serialization
+
+Version 1.1.1.17
+2020-04-21
+- #365 AISMarkingStructure not serializing correctly. PY3 compatibility issue
+
+Version 1.1.1.16
+2020-04-16
+- #364 TTPs would fail to serialize XML Kill_Chains if no TTP was set
+- Added Python 3.8 to test harness
+
+Version 1.1.1.15
+2020-03-09
+- #357 Add xnl:Type to the PersonName element (CIQ)
+- Update the allowable values for PersonName and OrganisationName
+- Update tests per recent CybOX release
+
+Version 1.1.1.14
+2019-11-26
+- #361 fix problem with lookup_extension for TestMechanism
+
+Version 1.1.1.13
+2019-09-06
+- Update package requirements
+
+Version 1.1.1.12
+2018-04-25
+- #347 Property targeted_technical_details missing in VictimTargeting class
+
+Version 1.1.1.11
+2018-03-21
+- Fix issue with PyPI.
+
+Version 1.1.1.10
+2018-03-06
+- #343 Create separate test environments for when maec is or is not installed
+- #339 [Python3 not supported - v1.1/1.2] to_json vaguely broken on some files
+- #338 VocabTypes are unhashable in 1.1.1.x on Python 3
+- #325 Bug in Indicator class setter for observables property
+- Change stix.ToolInformation to use AttackerToolType vocab
+- Removed Python 2.6 environment from CI tests
+
+Version 1.1.1.9
+2017-05-25
+- Support Python 3.6
+- #321 Fix CIQ extensions.
+
+Version 1.1.1.8
+2017-01-18
+- Update to support Python 3.
+- Convert to use mixbox.
+
+Version 1.1.1.7
+2016-10-21
+- Improved handling of Industry Sectors in CIQ Identity for AIS Markings
+
+Version 1.1.1.6
+2016-10-14
+- Add support for AIS Markings in STIX 1.1.1
+- Support additional fields in CIQ Identity
+
+Version 1.1.1.5
+2015-04-29
+- #200 Refactored ns_dict behavior in to_xml() to allow custom namespace mappings
+- #254 Added information_source to MarkingSpecification class.
+- #188 Added nationalities to CIQ Identity extension.
+- #246 Added coa_requested to Incident class.
+- #248 Set include_schemalocs to False by default in to_xml()
+- #249 Removed "Work In Progress" label from RTD documentation.
+
Version 1.1.1.4
2015-03-19
- #44 Added StructuredCOA support. This completes the COA structure.
@@ -91,7 +168,7 @@ Version 1.1.0.4
2014-02-31
- Added COAs, Exploit Targets, Campaigns, and Related Packages to STIXPackage class
- Updated behavior of id, idref, and timestamp on core STIX constructs to align with best practices
-- Added MAEC malware extension
+- Added MAEC malware extension
- Improved Identity extension mechanism
- Added Sightings to Indicator
- Updates to OpenIOC test mechanism extension
@@ -101,7 +178,7 @@ Version 1.1.0.4
- Added Handling support to Indicator
- Added several fields to COA and Exploit Target
- Bug fixes
-
+
Version 1.1.0.3
2014-02-24
- Added TTP structure (stix.ttp.TTP)
@@ -131,7 +208,7 @@ Version 1.1.0.1
- Fixed several CIQ Identity extension bugs
- Improved namespace parser performance
- Updated Incident test
-- Added initial code for better support of non-standard id namespaces in input documents
+- Added initial code for better support of non-standard id namespaces in input documents
Version 1.1.0.0
2014-02-20
@@ -191,7 +268,7 @@ Version 1.0.0a5
2013-06-27
- Improved README documentation
- Fixed interface issues between python-stix and python-cybox classes
-- Added support for additional namespaces to be added to STIXPackage.to_xml()
+- Added support for additional namespaces to be added to STIXPackage.to_xml()
- Fixed installation issues with pip and setup.py
Version 1.0.0a4
@@ -215,4 +292,4 @@ Version 1.0.0a2
Version 1.0.0a1
2013-04-22
- First (alpha) release on PyPI
-- Compatible with STIX 1.0 Draft 2
\ No newline at end of file
+- Compatible with STIX 1.0 Draft 2
diff --git a/README.rst b/README.rst
index 97329b69..08211d6f 100644
--- a/README.rst
+++ b/README.rst
@@ -1,40 +1,44 @@
python-stix
===========
-A python library for parsing, manipulating, and generating STIX v1.1.1 content.
+A python library for parsing, manipulating, and generating `Structured Threat Information eXpression (STIX™) `_ v1.1.1 content.
:Source: https://github.com/STIXProject/python-stix
-:Documentation: http://stix.readthedocs.org
-:Information: http://stix.mitre.org
+:Documentation: https://stix.readthedocs.io/
+:Information: https://stixproject.github.io/
+:Download: https://pypi.python.org/pypi/stix/
-|travis badge| |landscape.io badge| |version badge| |downloads badge|
+|travis_badge| |landscape_io_badge| |version_badge|
-.. |travis badge| image:: https://api.travis-ci.org/STIXProject/python-stix.png?branch=master
+.. |travis_badge| image:: https://api.travis-ci.org/STIXProject/python-stix.svg?branch=master
:target: https://travis-ci.org/STIXProject/python-stix
:alt: Build Status
-.. |landscape.io badge| image:: https://landscape.io/github/STIXProject/python-stix/master/landscape.png
+.. |landscape_io_badge| image:: https://landscape.io/github/STIXProject/python-stix/master/landscape.svg
:target: https://landscape.io/github/STIXProject/python-stix/master
:alt: Code Health
-.. |version badge| image:: https://pypip.in/v/stix/badge.png
- :target: https://pypi.python.org/pypi/stix/
-.. |downloads badge| image:: https://pypip.in/d/stix/badge.png
+.. |version_badge| image:: https://img.shields.io/pypi/v/stix.svg?maxAge=3600
:target: https://pypi.python.org/pypi/stix/
+ :alt: Version
Installation
------------
-The python-stix library can be installed via the distutils setup.py script
-included at the root directory:
+The python-stix library is hosted on `PyPI
+`_ and the most recent stable version can be
+installed with `pip `_:
- $ python setup.py install
-
-The python-stix library is also hosted on `PyPI
-`_ and can be installed with `pip
-`_:
+::
$ pip install stix
+The python-stix library can also be installed via the distutils setup.py script
+included at the root directory:
+
+::
+
+ $ python setup.py install
+
Dependencies
------------
@@ -53,6 +57,18 @@ Installation on Ubuntu 14.04 (and older)
$ sudo apt-get install python-dev python-pip libxml2-dev libxslt-dev zlib1g-dev
$ sudo pip install stix
+Installation on Windows
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Download the Lxml wheel for your version of Python from
+http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml, then install it via "pip install
+.whl". For example, to install it on 64-bit Windows running Python 2.7:
+
+::
+
+ $ pip install lxml-3.6.1-cp27-cp27m-win_amd64.whl
+ $ pip install stix
+
Versioning
----------
@@ -67,36 +83,36 @@ Layout
The python-stix package layout is as follows:
-* ``stix/`` : root level package
+* ``stix/`` : root level package.
-* ``examples/`` : example python scripts that leverage the python-stix library
+* ``examples/`` : example python scripts that leverage the python-stix library.
* ``stix/utils/`` : utility classes and modules used internally by the python-stix
- library
+ library.
* ``stix/bindings/`` : generateDS generated xml-to-python bindings (leveraged for
- parsing and output of STIX XML content)
-
-* ``stix/campaign/`` : APIs for STIX Campaign constructs
+ parsing and output of STIX XML content).
+
+* ``stix/campaign/`` : APIs for STIX Campaign constructs.
-* ``stix/coa/`` : APIs for STIX Course Of Action constructs
+* ``stix/coa/`` : APIs for STIX Course Of Action constructs.
-* ``stix/core/`` : APIs for core STIX constructs (e.g., STIX Header, STIX Package)
+* ``stix/core/`` : APIs for core STIX constructs (e.g., STIX Header, STIX Package).
* ``stix/common/`` : APIs for common STIX constructs (e.g., Structured Text,
- Information Source)
+ Information Source).
-* ``stix/exploit_target/`` : APIs for STIX Exploit Target constructs
+* ``stix/exploit_target/`` : APIs for STIX Exploit Target constructs.
-* ``stix/incident/`` : APIs for common Incident constructs
+* ``stix/incident/`` : APIs for common Incident constructs.
-* ``stix/indicator/`` : APIs for STIX Indicator constructs
+* ``stix/indicator/`` : APIs for STIX Indicator constructs.
-* ``stix/extensions/`` : APIs for STIX extensions (e.g., CIQ Identity)
+* ``stix/extensions/`` : APIs for STIX extensions (e.g., CIQ Identity).
-* ``stix/threat_actor/`` : APIs for STIX Threat Actor constructs
+* ``stix/threat_actor/`` : APIs for STIX Threat Actor constructs.
-* ``stix/ttp/`` : APIs for STIX TTP constructs
+* ``stix/ttp/`` : APIs for STIX TTP constructs.
Please refer to examples for concrete examples of how to interact with the
-python-stix library
+python-stix library.
diff --git a/docs/api/common/identity.rst b/docs/api/common/identity.rst
index b1dcb283..d00db56f 100644
--- a/docs/api/common/identity.rst
+++ b/docs/api/common/identity.rst
@@ -13,13 +13,8 @@ Classes
.. autoclass:: RelatedIdentities
:show-inheritance:
:members:
-
+
Functions
---------
.. autofunction:: add_extension
-
-Constants
----------
-
-.. autodata:: _EXTENSION_MAP
diff --git a/docs/api/common/vocabs.rst b/docs/api/common/vocabs.rst
index 3dce840b..6af0120f 100644
--- a/docs/api/common/vocabs.rst
+++ b/docs/api/common/vocabs.rst
@@ -138,8 +138,4 @@ Functions
---------
.. autofunction:: add_vocab
-
-Constants
----------
-
-.. autodata:: _VOCAB_MAP
+.. autofunction:: register_vocab
diff --git a/docs/api/data_marking.rst b/docs/api/data_marking.rst
index 37f96699..a4612d17 100644
--- a/docs/api/data_marking.rst
+++ b/docs/api/data_marking.rst
@@ -22,8 +22,3 @@ Functions
---------
.. autofunction:: add_extension
-
-Constants
----------
-
-.. autodata:: _EXTENSION_MAP
diff --git a/docs/api/extensions/marking/ais.rst b/docs/api/extensions/marking/ais.rst
new file mode 100644
index 00000000..6ebceee6
--- /dev/null
+++ b/docs/api/extensions/marking/ais.rst
@@ -0,0 +1,297 @@
+:mod:`stix.extensions.marking.ais` Module
+====================================================
+
+.. automodule:: stix.extensions.marking.ais
+
+Classes
+-------
+
+.. autoclass:: AISMarkingStructure
+ :show-inheritance:
+ :members:
+
+Functions
+---------
+
+.. autofunction:: add_ais_marking
+
+
+Examples
+--------
+
+Applying AIS Markings
+---------------------
+
+The STIX specification allows data markings to be applied to any combination of
+attributes and elements that can be described by XPath. That being said, the
+Automated Indicator Sharing (AIS) capability requires those markings controlled
+structure to select all nodes and attributes ``//node() | //@*``. All required
+fields to create a valid AIS Markings are provided through the ``add_ais_marking``
+function.
+
+.. code-block:: python
+
+ # python-stix imports
+ import stix
+ from stix.core import STIXPackage
+ from stix.extensions.marking.ais import (add_ais_marking,
+ COMMUNICATIONS_SECTOR,
+ INFORMATION_TECHNOLOGY_SECTOR)
+ from stix.indicator import Indicator
+
+ # Create new STIX Package
+ stix_package = STIXPackage()
+
+ # Create new Indicator
+ indicator = Indicator(title='My Indicator Example',
+ description='Example using AIS')
+
+ # Add indicator to our STIX Package
+ stix_package.add_indicator(indicator)
+
+ # Create AIS Marking with CIQ Identity and attach it to STIX Header.
+ add_ais_marking(stix_package, False, 'EVERYONE', 'GREEN',
+ country_name_code='US',
+ country_name_code_type='ISO 3166-1 alpha-2',
+ admin_area_name_code='US-VA',
+ admin_area_name_code_type='ISO 3166-2',
+ organisation_name='Example Corporation',
+ industry_type=[INFORMATION_TECHNOLOGY_SECTOR, COMMUNICATIONS_SECTOR]
+ )
+
+ # Print the XML.
+ print stix_package.to_xml()
+
+ # Print the JSON.
+ print stix_package.to_json()
+
+This corresponds to the XML result:
+
+.. code-block:: xml
+
+
+
+
+
+ //node() | //@*
+
+
+
+
+
+
+
+
+ \
+
+
+ Example Corporation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ My Indicator Example
+ Example using AIS
+
+
+
+
+The following corresponds to the JSON result:
+
+.. code-block:: json
+
+ {
+ "stix_header": {
+ "handling": [
+ {
+ "controlled_structure": "//node() | //@*",
+ "information_source": {
+ "identity": {
+ "xsi:type": "stix-ciqidentity:CIQIdentity3.0InstanceType",
+ "specification": {
+ "organisation_info": {
+ "industry_type": "Information Technology Sector|Communications Sector"
+ },
+ "party_name": {
+ "organisation_names": [
+ {
+ "name_elements": [
+ {
+ "value": "Example Corporation"
+ }
+ ]
+ }
+ ]
+ },
+ "addresses": [
+ {
+ "country": {
+ "name_elements": [
+ {
+ "name_code_type": "ISO 3166-1 alpha-2",
+ "name_code": "US"
+ }
+ ]
+ },
+ "administrative_area": {
+ "name_elements": [
+ {
+ "name_code_type": "ISO 3166-2",
+ "name_code": "US-VA"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "marking_structures": [
+ {
+ "xsi:type": "AIS:AISMarkingStructure",
+ "not_proprietary": {
+ "tlp_marking": {
+ "color": "GREEN"
+ },
+ "ais_consent": {
+ "consent": "EVERYONE"
+ },
+ "cisa_proprietary": "false"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "version": "1.1.1",
+ "indicators": [
+ {
+ "description": "Example using AIS",
+ "title": "My Indicator Example",
+ "timestamp": "2017-10-02T14:26:57.510000+00:00",
+ "id": "example:indicator-81466b8d-4efb-460f-ba13-b072420b9540"
+ }
+ ],
+ "id": "example:Package-a8c8135d-18d8-4384-903f-71285a02346e"
+ }
+
+Parsing AIS Markings
+--------------------
+
+Using the same example used for Applying AIS Markings. This would be how a
+consumer of AIS would parse the data.
+
+.. code-block:: python
+
+ # python-stix imports
+ import stix
+ from stix.core import STIXPackage
+ import stix.extensions.marking.ais # Register the AIS markings
+
+ # Parse STIX Package
+ stix_package = STIXPackage.from_xml("stix_input.xml")
+ # stix_package = STIXPackage.from_json("stix_input.json")
+
+ # Print all indicators
+ for indicator in stix_package.indicators:
+ print(indicator)
+
+ # Extract markings from STIX Header
+ markings = stix_package.stix_header.handling
+
+ # Print all markings contained in the STIX Header
+ for marking in markings:
+ print(marking)
+ print(marking.marking_structures)
+ print("----------MARKING CONTENT----------")
+ ais_struct = marking.marking_structures[0]
+ print("OBJ: %s" % ais_struct)
+ print("NotProprietary OBJ: %s" % ais_struct.not_proprietary)
+ print("CISA_Proprietary: %s" % ais_struct.not_proprietary.cisa_proprietary)
+ print("Consent: %s" % ais_struct.not_proprietary.ais_consent.consent)
+ print("TLP color: %s" % ais_struct.not_proprietary.tlp_marking.color)
+
+ print("----------INFORMATION SOURCE----------")
+ identity = marking.information_source.identity.specification
+ print("OBJ: %s" % identity)
+ print("Organization Name: %s" % identity.party_name.organisation_names[0].name_elements[0].value)
+ print("Country: %s" % identity.addresses[0].country.name_elements[0].name_code)
+ print("Country code type: %s" % identity.addresses[0].country.name_elements[0].name_code_type)
+ print("Administrative area: %s" % identity.addresses[0].administrative_area.name_elements[0].name_code)
+ print("Administrative area code type: %s" % identity.addresses[0].administrative_area.name_elements[0].name_code_type)
+ print("Industry Type: %s" % identity.organisation_info.industry_type)
+
+
+ >>>
+ >>>
+ >>> [, ...]
+ >>> ----------MARKING CONTENT----------
+ >>> OBJ:
+ >>> NotProprietary OBJ:
+ >>> CISA_Proprietary: False
+ >>> Consent: EVERYONE
+ >>> TLP color: GREEN
+ >>> ----------INFORMATION SOURCE----------
+ >>> OBJ:
+ >>> Organization Name: Example Corporation
+ >>> Country: US
+ >>> Country code type: ISO 3166-1 alpha-2
+ >>> Administrative area: US-VA
+ >>> Administrative area code type: ISO 3166-2
+ >>> Industry Type: Information Technology Sector|Communications Sector
+
+Constants
+---------
+
+The following constants can be used for the ``industry_type`` keyword argument to
+``add_ais_marking``:
+
+.. autodata:: CHEMICAL_SECTOR
+.. autodata:: COMMERCIAL_FACILITIES_SECTOR
+.. autodata:: COMMUNICATIONS_SECTOR
+.. autodata:: CRITICAL_MANUFACTURING_SECTOR
+.. autodata:: DAMS_SECTOR
+.. autodata:: DEFENSE_INDUSTRIAL_BASE_SECTOR
+.. autodata:: EMERGENCY_SERVICES_SECTOR
+.. autodata:: ENERGY_SECTOR
+.. autodata:: FINANCIAL_SERVICES_SECTOR
+.. autodata:: FOOD_AND_AGRICULTURE_SECTOR
+.. autodata:: GOVERNMENT_FACILITIES_SECTOR
+.. autodata:: HEALTH_CARE_AND_PUBLIC_HEALTH_SECTOR
+.. autodata:: INFORMATION_TECHNOLOGY_SECTOR
+.. autodata:: NUCLEAR_REACTORS_MATERIALS_AND_WASTE_SECTOR
+.. autodata:: OTHER
+.. autodata:: TRANSPORTATION_SYSTEMS_SECTOR
+.. autodata:: WATER_AND_WASTEWATER_SYSTEMS_SECTOR
diff --git a/docs/api/index.rst b/docs/api/index.rst
index 71e5c6ab..7537d708 100644
--- a/docs/api/index.rst
+++ b/docs/api/index.rst
@@ -16,6 +16,7 @@ Modules located in the base `stix`_ package
.. toctree::
:titlesonly:
+ stix
base
data_marking
diff --git a/docs/api/indicator/test_mechanism.rst b/docs/api/indicator/test_mechanism.rst
index 9267a96d..239dd25f 100644
--- a/docs/api/indicator/test_mechanism.rst
+++ b/docs/api/indicator/test_mechanism.rst
@@ -14,8 +14,3 @@ Functions
---------
.. autofunction:: add_extension
-
-Constants
----------
-
-.. autodata:: _EXTENSION_MAP
diff --git a/docs/api/stix.rst b/docs/api/stix.rst
new file mode 100644
index 00000000..8249b60b
--- /dev/null
+++ b/docs/api/stix.rst
@@ -0,0 +1,12 @@
+:mod:`stix` Module
+==================================
+
+.. module:: stix
+
+Classes
+-------
+
+.. autofunction:: supported_stix_version
+.. autofunction:: register_extension
+.. autofunction:: lookup_extension
+.. autofunction:: add_extension
diff --git a/docs/api/ttp/malware_instance.rst b/docs/api/ttp/malware_instance.rst
index 19786fe2..669e2d80 100644
--- a/docs/api/ttp/malware_instance.rst
+++ b/docs/api/ttp/malware_instance.rst
@@ -14,8 +14,3 @@ Functions
---------
.. autofunction:: add_extension
-
-Constants
----------
-
-.. autodata:: _EXTENSION_MAP
diff --git a/docs/api/utils/nsparser.rst b/docs/api/utils/nsparser.rst
index a39c808f..00180ed2 100644
--- a/docs/api/utils/nsparser.rst
+++ b/docs/api/utils/nsparser.rst
@@ -1,24 +1,6 @@
:mod:`stix.utils.nsparser` Module
==================================
-.. module:: stix.utils.nsparser
-
-Classes
--------
-
-.. autoclass:: NamespaceParser
- :show-inheritance:
+.. automodule:: stix.utils.nsparser
:members:
-
-Constants
----------
-
-.. autodata:: XML_NAMESPACES
-
-.. autodata:: STIX_NS_TO_SCHEMALOCATION
-
-.. autodata:: EXT_NS_TO_SCHEMALOCATION
-
-.. autodata:: DEFAULT_STIX_NS_TO_PREFIX
-
-.. autodata:: DEFAULT_EXT_TO_PREFIX
+ :undoc-members:
diff --git a/docs/conf.py b/docs/conf.py
index 3ece72c7..c4c7dc0b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,7 +13,7 @@
'sphinx.ext.ifconfig',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
- 'sphinxcontrib.napoleon',
+ 'sphinx.ext.napoleon',
]
intersphinx_mapping = {
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index 833cff93..0449fddb 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -10,7 +10,7 @@ This page gives an introduction to **python-stix** and how to use it.
Prerequisites
-------------
-The python-stix library provides an API for creating or processing STIX content. As such, it is a developer tool that can be leveraged by those who know Python 2.6/2.7 and are familiar with object-oriented programming practices, Python package layouts, and are comfortable with the installation of Python libraries. To contribute code to the python-stix repository, users must be familiar with `git`_ and `GitHub pull request`_ methodologies. Understanding XML, XML Schema, and the STIX language is also incredibly helpful when using python-stix in an application.
+The python-stix library provides an API for creating or processing STIX content. As such, it is a developer tool that can be leveraged by those who know Python 2.7/3.3+ and are familiar with object-oriented programming practices, Python package layouts, and are comfortable with the installation of Python libraries. To contribute code to the python-stix repository, users must be familiar with `git`_ and `GitHub pull request`_ methodologies. Understanding XML, XML Schema, and the STIX language is also incredibly helpful when using python-stix in an application.
.. _git: http://git-scm.com/documentation
.. _GitHub pull request: https://help.github.com/articles/using-pull-requests
diff --git a/docs/index.rst b/docs/index.rst
index ee6a4de1..7a7e5974 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -5,9 +5,9 @@ The **python-stix** library provides an API for developing and consuming *Struct
.. note::
- These docs provide standard reference for this Python library. For documentation on *idiomatic* usage and *common patterns*, as well as various STIX-related information and utilities, please visit the `STIXProject at GitHub`_.
-
- .. _STIXProject at GitHub: http://stixproject.github.io/
+ These docs provide standard reference for this Python library. For documentation on *idiomatic* usage and *common patterns*, as well as various STIX-related information and utilities, please visit the `STIXProject at GitHub`_.
+
+ .. _STIXProject at GitHub: http://stixproject.github.io/
.. _STIX website: http://stix.mitre.org
@@ -22,14 +22,14 @@ version of STIX.
============ ===================
STIX Version python-stix Version
============ ===================
-1.1.1 1.1.1.5 (`PyPI`__) (`GitHub`__)
-1.1.0 1.1.0.6 (`PyPI`__) (`GitHub`__)
-1.0.1 1.0.1.1 (`PyPI`__) (`GitHub`__)
-1.0 1.0.0a7 (`PyPI`__) (`GitHub`__)
+1.1.1 1.1.1.19 (`PyPI`__) (`GitHub`__)
+1.1.0 1.1.0.6 (`PyPI`__) (`GitHub`__)
+1.0.1 1.0.1.1 (`PyPI`__) (`GitHub`__)
+1.0 1.0.0a7 (`PyPI`__) (`GitHub`__)
============ ===================
-__ https://pypi.python.org/pypi/stix/1.1.1.5
-__ https://github.com/STIXProject/python-stix/tree/v1.1.1.5
+__ https://pypi.python.org/pypi/stix/1.1.1.19
+__ https://github.com/STIXProject/python-stix/tree/v1.1.1.19
__ https://pypi.python.org/pypi/stix/1.1.0.6
__ https://github.com/STIXProject/python-stix/tree/v1.1.0.6
__ https://pypi.python.org/pypi/stix/1.0.1.1
@@ -67,6 +67,18 @@ API Reference
api/index
api/coverage
+FAQ
+===
+
+- My RAM consumption rises when processing a large amount of files.
+ This problem is caused by a python-cybox_ caching mechanism that is enabled
+ by default. To prevent this issue from happening use the
+ ``cybox.utils.caches.cache_clear()`` method in your code/script to release
+ the cached resources as appropriate. Refer to the ``cybox`` documentation
+ for more details.
+
+.. _python-cybox: http://cybox.readthedocs.io/
+
Contributing
============
If a bug is found, a feature is missing, or something just isn't behaving the way you'd expect it to, please submit an issue to our `tracker`_. If you'd like to contribute code to our repository, you can do so by issuing a `pull request`_ and we will work with you to try and integrate that code into our repository.
@@ -80,4 +92,3 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
-
diff --git a/requirements.txt b/requirements.txt
index 54d46380..14df8061 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,7 @@
--e .[docs,test]
+maec>=4.1.0.13,<4.1.1.0 # For tests that include MAEC
+nose==1.3.7
+sphinx==1.3.6
+sphinx_rtd_theme==0.2.4
+tox==2.7.0
+
+-e .
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 00000000..1920de95
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,17 @@
+[bumpversion]
+current_version = 1.1.1.19
+parse = (?P\d+)\.(?P\d+)\.(?P\d+).(?P\d+)
+serialize = {major}.{minor}.{patch}.{revision}
+commit = True
+tag = True
+
+[bumpversion:file:stix/version.py]
+
+[bumpversion:file:docs/index.rst]
+
+[metadata]
+license_file = LICENSE.txt
+
+[bdist_wheel]
+universal = True
+
diff --git a/setup.py b/setup.py
index 6ad803b2..1a599e72 100644
--- a/setup.py
+++ b/setup.py
@@ -1,8 +1,9 @@
#!/usr/bin/env python
-# Copyright (c) 2015 - The MITRE Corporation
-# For license information, see the LICENSE.txt file
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+from io import open # Allow `encoding` kwarg on Python 2.7
from os.path import abspath, dirname, join
@@ -11,6 +12,7 @@
BASE_DIR = dirname(abspath(__file__))
VERSION_FILE = join(BASE_DIR, 'stix', 'version.py')
+
def get_version():
with open(VERSION_FILE) as f:
for line in f.readlines():
@@ -20,29 +22,17 @@ def get_version():
raise AttributeError("Package does not have a __version__")
-with open('README.rst') as f:
- readme = f.read()
-
-extras_require = {
- 'docs': [
- 'Sphinx==1.2.1',
- # TODO: remove when updating to Sphinx 1.3, since napoleon will be
- # included as sphinx.ext.napoleon
- 'sphinxcontrib-napoleon==0.2.4',
- 'sphinx_rtd_theme==0.1.7',
- ],
- 'test': [
- 'nose==1.3.0',
- 'tox==1.6.1',
- 'maec>=4.1.0.12,<4.1.1.0'
- ],
-}
+def get_long_description():
+ with open('README.rst', encoding='utf-8') as f:
+ return f.read()
install_requires = [
- 'lxml>=2.3',
+ 'lxml>=2.2.3 ; python_version == "2.7" or python_version >= "3.5"',
+ 'lxml>=2.2.3,<4.4.0 ; python_version > "2.7" and python_version < "3.5"',
+ 'mixbox>=1.0.4',
+ 'cybox>=2.1.0.13,<2.1.1.0',
'python-dateutil',
- 'cybox>=2.1.0.11,<2.1.1.0'
]
@@ -52,16 +42,28 @@ def get_version():
author="STIX Project, MITRE Corporation",
author_email="stix@mitre.org",
description="An API for parsing and generating STIX content.",
- long_description=readme,
- url="http://stix.mitre.org",
+ long_description=get_long_description(),
+ url="https://stixproject.github.io/",
packages=find_packages(),
install_requires=install_requires,
- extras_require=extras_require,
+ license="BSD",
classifiers=[
- "Programming Language :: Python",
- "Development Status :: 4 - Beta",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: BSD License",
- "Operating System :: OS Independent",
- ]
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ ],
+ project_urls={
+ 'Documentation': 'https://stix.readthedocs.io/',
+ 'Source Code': 'https://github.com/STIXProject/python-stix/',
+ 'Bug Tracker': 'https://github.com/STIXProject/python-stix/issues/',
+ },
)
diff --git a/stix/__init__.py b/stix/__init__.py
index 95df5e34..2f289ab3 100644
--- a/stix/__init__.py
+++ b/stix/__init__.py
@@ -1,12 +1,138 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# Make sure base gets imported before common.
-from .base import Entity, EntityList, TypedList, BaseCoreComponent # noqa
-from . import common # noqa
+from .base import (Entity, EntityList, TypedCollection, TypedList, # noqa
+ BaseCoreComponent)
+
+from mixbox.vendor.six import string_types, iteritems
+
+#: Mapping of xsi:types to implementation/extension classes
+_EXTENSION_MAP = {}
+
+
+def _lookup_unprefixed(typename):
+ """Attempts to resolve a class for the input XML type `typename`.
+
+ Args:
+ typename: The name of an STIX XML type (e.g., TLPMarkingStructureType)
+ without a namespace prefix.
+
+ Returns:
+ A stix.Entity implementation class for the `typename`.
+
+ Raises:
+ ValueError: If no class has been registered for the input `typename`.
+
+ """
+ for xsi_type, klass in iteritems(_EXTENSION_MAP):
+ if typename in xsi_type:
+ return klass
+
+ error = "Unregistered extension type: %s" % typename
+ raise ValueError(error)
+
+
+def _lookup_extension(xsi_type):
+ """Returns a Python class for the `xsi_type` value.
+
+ Args:
+ xsi_type: An xsi:type value string.
+
+ Returns:
+ A stix.Entity implementation class for the `xsi_type`.
+
+ Raises:
+ ValueError: If no class has been registered for the `xsi_type`.
+
+ """
+ import stix.extensions.malware.maec_4_1_malware
+
+ if xsi_type in _EXTENSION_MAP:
+ return _EXTENSION_MAP[xsi_type]
+
+ raise ValueError("Unregistered xsi:type %s" % xsi_type)
+
+
+def lookup_extension(typeinfo, default=None):
+ """Returns a stix.Entity class for that has been registered for the
+ `typeinfo` value.
+
+ Note:
+ This is for internal use only.
+
+ Args:
+ typeinfo: An object or string containing type information. This can be
+ either an xsi:type attribute value or a stix.bindings object.
+ default: Return class if typeinfo is None or contains no xml type
+ information.
+ Returns:
+ A stix.Entity implementation class for the `xsi_type`.
+
+ Raises:
+ ValueError: If no class has been registered for the `xsi_type`.
+
+ """
+ if typeinfo is None and default:
+ return default
+
+ # If the `typeinfo` was a string, consider it a full xsi:type value.
+ if isinstance(typeinfo, string_types):
+ return _lookup_extension(typeinfo)
+
+ # Most extension bindings include this attribute.
+ if not hasattr(typeinfo, 'xml_type'):
+ if default:
+ return default
+
+ error = "Input %s is missing xml_type attribute. Cannot lookup class."
+ raise ValueError(error % type(typeinfo))
+
+ # Extension binding classes usually (always?) have an `xmlns_prefix`
+ # class attribute.
+ if hasattr(typeinfo, 'xmlns_prefix'):
+ xsi_type = "%s:%s" % (typeinfo.xmlns_prefix, typeinfo.xml_type)
+ return _lookup_extension(xsi_type)
+
+ # no xmlns_prefix found, try to resolve the class by just the `xml_type`
+ return _lookup_unprefixed(typeinfo.xml_type)
+
+
+def add_extension(cls):
+ """Registers a stix.Entity class as an implementation of an xml type.
+
+ Classes must have an ``_XSI_TYPE`` class attributes to be registered. The
+ value of this attribute must be a valid xsi:type.
+
+ Note:
+ This was designed for internal use.
+
+ """
+ _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+
+
+def register_extension(cls):
+ """Class decorator for registering a stix.Entity class as an implementation
+ of an xml type.
+
+ Classes must have an ``_XSI_TYPE`` class attributes to be registered.
+
+ Note:
+ This was designed for internal use.
+
+ """
+ add_extension(cls)
+ return cls
+
+from . import common # noqa
from .version import __version__ # noqa
+
def supported_stix_version():
- return '.'.join(__version__.split('.')[:3])
+ """Returns a tuple of STIX version strings that this version of python-stix
+ supports (i.e., can parse).
+
+ """
+ return ("1.0", "1.0.1", "1.1", "1.1.1")
diff --git a/stix/base.py b/stix/base.py
index f01dd60a..b232cd3c 100644
--- a/stix/base.py
+++ b/stix/base.py
@@ -1,30 +1,32 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# builtin
-import json
+# stdlib
import collections
import itertools
-import StringIO
+
+# mixbox
+from mixbox import compat
+from mixbox import idgen
+from mixbox import entities
+from mixbox import fields
+from mixbox import binding_utils
+from mixbox import namespaces
+from mixbox.vendor.six import StringIO, iteritems, itervalues, text_type, binary_type
# internal
-from . import bindings, utils
+from . import utils
def _override(*args, **kwargs):
raise NotImplementedError()
-class Entity(object):
+class Entity(entities.Entity):
"""Base class for all classes in the STIX API."""
_namespace = None
_XSI_TYPE = None
- def _collect_ns_info(self, ns_info=None):
- if not ns_info:
- return
- ns_info.collect(self)
-
def _set_var(self, klass, try_cast=True, arg=None, **kwargs):
"""Sets an instance property value.
@@ -47,7 +49,7 @@ def _set_var(self, klass, try_cast=True, arg=None, **kwargs):
and the field value is the value.
"""
- name, item = kwargs.iteritems().next()
+ name, item = next(iteritems(kwargs))
attr = utils.private_name(name) # 'title' => '_title'
if item is None:
@@ -82,36 +84,21 @@ def _set_vocab(self, klass=None, **kwargs):
from stix.common import VocabString
klass = klass or VocabString
- item = kwargs.itervalues().next()
+ item = next(itervalues(kwargs))
if isinstance(item, VocabString):
self._set_var(VocabString, **kwargs)
else:
self._set_var(klass, **kwargs)
- def to_obj(self, return_obj=None, ns_info=None):
- """Converts an `Entity` into a binding object.
-
- Note:
- This needs to be overridden by derived classes.
-
- """
- self._collect_ns_info(ns_info)
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- """Create an object from a binding object"""
- raise NotImplementedError()
-
def to_xml(self, include_namespaces=True, include_schemalocs=False,
ns_dict=None, schemaloc_dict=None, pretty=True,
auto_namespace=True, encoding='utf-8'):
"""Serializes a :class:`Entity` instance to an XML string.
The default character encoding is ``utf-8`` and can be set via the
- `encoding` parameter. If `encoding` is ``None``, a unicode string
- is returned.
+ `encoding` parameter. If `encoding` is ``None``, a string (unicode in
+ Python 2, str in Python 3) is returned.
Args:
auto_namespace: Automatically discover and export XML namespaces
@@ -132,7 +119,8 @@ def to_xml(self, include_namespaces=True, include_schemalocs=False,
only be included if `auto_namespace` is ``False``.
pretty: Pretty-print the XML.
encoding: The output character encoding. Default is ``utf-8``. If
- `encoding` is set to ``None``, a unicode string is returned.
+ `encoding` is set to ``None``, a string (unicode in Python 2,
+ str in Python 3) is returned.
Returns:
An XML string for this
@@ -140,15 +128,7 @@ def to_xml(self, include_namespaces=True, include_schemalocs=False,
"""
- from .utils import nsparser
- parser = nsparser.NamespaceParser()
-
- if auto_namespace:
- ns_info = nsparser.NamespaceInfo()
- else:
- ns_info = None
-
- obj = self.to_obj(ns_info=ns_info)
+ from mixbox.entities import NamespaceCollector
if (not auto_namespace) and (not ns_dict):
raise Exception(
@@ -156,34 +136,33 @@ def to_xml(self, include_namespaces=True, include_schemalocs=False,
"or missing."
)
+ ns_info = NamespaceCollector()
+
+ obj = self.to_obj(ns_info=ns_info if auto_namespace else None)
+
+ ns_info.finalize(ns_dict=ns_dict, schemaloc_dict=schemaloc_dict)
+
if auto_namespace:
- ns_info.finalize(ns_dict=ns_dict, schemaloc_dict=schemaloc_dict)
obj_ns_dict = ns_info.binding_namespaces
else:
- ns_info = nsparser.NamespaceInfo()
- ns_info.finalized_namespaces = ns_dict or {}
- ns_info.finalized_schemalocs = schemaloc_dict or {}
obj_ns_dict = dict(
itertools.chain(
- ns_dict.iteritems(),
- nsparser.DEFAULT_STIX_NAMESPACES.iteritems()
+ iteritems(ns_info.binding_namespaces),
+ iteritems(namespaces.get_full_ns_map())
)
)
namespace_def = ""
if include_namespaces:
- xmlns = parser.get_xmlns_str(ns_info.finalized_namespaces)
- namespace_def += ("\n\t" + xmlns)
-
- if include_schemalocs and include_namespaces:
- schemaloc = parser.get_schemaloc_str(ns_info.finalized_schemalocs)
- namespace_def += ("\n\t" + schemaloc)
-
- if not pretty:
- namespace_def = namespace_def.replace('\n\t', ' ')
-
- with bindings.save_encoding(encoding):
- sio = StringIO.StringIO()
+ delim = "\n\t" if pretty else " "
+ xmlns = ns_info.get_xmlns_string(delim)
+ namespace_def += (delim + xmlns)
+ if include_schemalocs:
+ schemaloc = ns_info.get_schema_location_string(delim)
+ namespace_def += (delim + schemaloc)
+
+ with binding_utils.save_encoding(encoding):
+ sio = StringIO()
obj.export(
sio.write, # output buffer
0, # output level
@@ -193,62 +172,13 @@ def to_xml(self, include_namespaces=True, include_schemalocs=False,
)
# Ensure that the StringIO buffer is unicode
- s = unicode(sio.getvalue())
+ s = text_type(sio.getvalue())
if encoding:
return s.encode(encoding)
return s
- def to_json(self):
- return json.dumps(self.to_dict())
-
- @classmethod
- def from_json(cls, json_doc):
- """Parses the JSON document `json_doc` and returns a STIX
- :class:`Entity` implementation instance.
-
- Arguments:
- json_doc: Input JSON representation of a STIX entity. This can be
- a readable object or a JSON string.
-
- Returns:
- An implementation of :class:`.Entity` (e.g.,
- :class:`.STIXPackage`).
-
- """
- try:
- d = json.load(json_doc)
- except AttributeError: # catch the read() error
- d = json.loads(json_doc)
-
- return cls.from_dict(d)
-
- def to_dict(self):
- """Converts a STIX :class:`Entity` implementation into a Python
- dictionary. This may be overridden by derived classes.
-
- """
- return utils.to_dict(self)
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- """Convert from dict representation to object representation.
- This should be overriden by a subclass
-
- """
- raise NotImplementedError()
-
- @classmethod
- def object_from_dict(cls, entity_dict):
- """Convert from dict representation to object representation."""
- return cls.from_dict(entity_dict).to_obj()
-
- @classmethod
- def dict_from_object(cls, entity_obj):
- """Convert from object representation to dict representation."""
- return cls.from_obj(entity_obj).to_dict()
-
def walk(self):
return utils.walk.iterwalk(self)
@@ -265,54 +195,40 @@ def find(self, id_):
return entity
-class EntityList(collections.MutableSequence, Entity):
- _binding_class = _override
- _binding_var = None
- _contained_type = _override
- _inner_name = None
- _dict_as_list = False
+class EntityList(entities.EntityList, Entity):
+ def to_xml(self, *args, **kwargs):
+ return Entity.to_xml(self, *args, **kwargs)
- def __init__(self, *args):
- super(EntityList, self).__init__()
- self._inner = []
- if not any(args):
- return
+class TypedCollection(object):
+ """Abstract base class for non-STIX collections of entities.
- for arg in args:
- if utils.is_sequence(arg):
- self.extend(arg)
- else:
- self.append(arg)
+ See also:
+ TypedList
- def __nonzero__(self):
- return bool(self._inner)
+ """
+ _contained_type = _override
- def __getitem__(self, key):
- return self._inner.__getitem__(key)
+ def __init__(self, *args):
+ self._inner = []
+ self._initialize_inner(*args)
- def __setitem__(self, key, value):
- if not self._is_valid(value):
- value = self._fix_value(value)
- self._inner.__setitem__(key, value)
+ def _initialize_inner(self, *args):
+ """Must be overridden by subclass.
- def __delitem__(self, key):
- self._inner.__delitem__(key)
+ """
+ raise NotImplementedError()
def __len__(self):
return len(self._inner)
- def insert(self, idx, value):
- if not value:
- return
- if not self._is_valid(value):
- value = self._fix_value(value)
- self._inner.insert(idx, value)
+ def __nonzero__(self):
+ return bool(self._inner)
def _is_valid(self, value):
"""Check if this is a valid object to add to the list."""
- # Subclasses can override this function, but if it becomes common, it's
- # probably better to use self._contained_type.istypeof(value)
+ # Subclasses can override this function, but if it becomes common,
+ # it's probably better to use self._contained_type.istypeof(value)
return isinstance(value, self._contained_type)
def _fix_value(self, value):
@@ -322,7 +238,7 @@ def _fix_value(self, value):
"""
try:
new_value = self._contained_type(value)
- except:
+ except Exception:
error = "Can't put '{0}' ({1}) into a {2}. Expected a {3} object."
error = error.format(
value, # Input value
@@ -334,104 +250,71 @@ def _fix_value(self, value):
return new_value
- # The next four functions can be overridden, but otherwise define the
- # default behavior for EntityList subclasses which define the following
- # class-level members:
- # - _binding_class
- # - _binding_var
- # - _contained_type
- # - _inner_name
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(EntityList, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- objlist = [x.to_obj(ns_info=ns_info) for x in self]
- setattr(return_obj, self._binding_var, objlist)
-
- return return_obj
+ def to_obj(self, ns_info=None):
+ return [x.to_obj(ns_info=ns_info) for x in self]
def to_list(self):
return [h.to_dict() for h in self]
- def to_dict(self):
- if self._dict_as_list:
- return self.to_list()
-
- d = utils.to_dict(self, skip=('inner',))
-
- if self._inner:
- d[self._inner_name] = [h.to_dict() for h in self]
-
- return d
-
@classmethod
- def from_obj(cls, obj, return_obj=None, contained_type=None,
- binding_var=None):
- if not obj:
+ def from_obj(cls, obj_list, contained_type=None):
+ if obj_list is None:
return None
- if return_obj is None:
- return_obj = cls()
if not contained_type:
contained_type = cls._contained_type
- if not binding_var:
- binding_var = cls._binding_var
- for item in getattr(obj, binding_var):
- return_obj.append(contained_type.from_obj(item))
+ if not utils.is_sequence(obj_list):
+ obj_list = [obj_list]
- return return_obj
+ items = (contained_type.from_obj(x) for x in obj_list)
+ return cls(items)
@classmethod
- def from_list(cls, list_repr, return_obj=None, contained_type=None):
+ def from_list(cls, list_repr, contained_type=None):
- if not utils.is_sequence(list_repr):
- return None
+ if not list_repr:
+ return cls()
+
+ if isinstance(list_repr, dict) or not utils.is_sequence(list_repr):
+ list_repr = [list_repr]
- if return_obj is None:
- return_obj = cls()
if not contained_type:
contained_type = cls._contained_type
- return_obj.extend(contained_type.from_dict(x) for x in list_repr)
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None, contained_type=None,
- inner_name=None):
-
- if cls._dict_as_list:
- return cls.from_list(
- dict_repr,
- return_obj=return_obj,
- contained_type=contained_type,
- )
+ items = (contained_type.from_dict(x) for x in list_repr)
+ return cls(items)
- if not isinstance(dict_repr, dict):
- return None
+ from_dict = from_list
+ to_dict = to_list
- if return_obj is None:
- return_obj = cls()
- if not contained_type:
- contained_type = cls._contained_type
- if not inner_name:
- inner_name = cls._inner_name
+ @classmethod
+ def object_from_dict(cls, entity_dict):
+ """Convert from dict representation to object representation."""
+ return cls.from_dict(entity_dict).to_obj()
- for item in dict_repr.get(inner_name, []):
- return_obj.append(contained_type.from_dict(item))
+ @classmethod
+ def dict_from_object(cls, entity_obj):
+ """Convert from object representation to dict representation."""
+ return cls.from_obj(entity_obj).to_dict()
- return return_obj
+ @classmethod
+ def istypeof(cls, obj):
+ """Check if `cls` is the type of `obj`
+ In the normal case, as implemented here, a simple isinstance check is
+ used. However, there are more complex checks possible. For instance,
+ EmailAddress.istypeof(obj) checks if obj is an Address object with
+ a category of Address.CAT_EMAIL
+ """
+ return isinstance(obj, cls)
-class TypedList(collections.MutableSequence):
- _contained_type = _override
+class TypedList(TypedCollection, compat.MutableSequence):
def __init__(self, *args):
- self._inner = []
+ TypedCollection.__init__(self, *args)
+ def _initialize_inner(self, *args):
# Check if it was initialized with args=None
if not any(args):
return
@@ -442,9 +325,6 @@ def __init__(self, *args):
else:
self.append(arg)
- def __nonzero__(self):
- return bool(self._inner)
-
def __getitem__(self, key):
return self._inner.__getitem__(key)
@@ -466,358 +346,36 @@ def insert(self, idx, value):
value = self._fix_value(value)
self._inner.insert(idx, value)
- def _is_valid(self, value):
- """Check if this is a valid object to add to the list."""
- # Subclasses can override this function, but if it becomes common,
- # it's probably better to use self._contained_type.istypeof(value)
- return isinstance(value, self._contained_type)
- def _fix_value(self, value):
- """Attempt to coerce value into the correct type.
-
- Subclasses can override this function.
- """
- try:
- new_value = self._contained_type(value)
- except Exception:
- error = "Can't put '{0}' ({1}) into a {2}. Expected a {3} object."
- error = error.format(
- value, # Input value
- type(value), # Type of input value
- type(self), # Type of collection
- self._contained_type # Expected type of input value
- )
- raise ValueError(error)
-
- return new_value
-
- def to_obj(self, ns_info=None):
- return [x.to_obj(ns_info=ns_info) for x in self]
-
- def to_list(self):
- return [h.to_dict() for h in self]
-
- to_dict = to_list
-
- @classmethod
- def from_obj(cls, obj_list, contained_type=None):
- if not obj_list:
- return None
-
- return_obj = cls()
-
- if not contained_type:
- contained_type = cls._contained_type
-
- if not utils.is_sequence(obj_list):
- obj_list = [obj_list]
-
- return_obj.extend(contained_type.from_obj(x) for x in obj_list)
- return return_obj
-
- @classmethod
- def from_list(cls, list_repr, contained_type=None):
-
- if not utils.is_sequence(list_repr):
- return None
-
- return_obj = cls()
-
- if not contained_type:
- contained_type = cls._contained_type
-
- return_obj.extend(contained_type.from_dict(x) for x in list_repr)
- return return_obj
-
- from_dict = from_list
-
- @classmethod
- def object_from_dict(cls, entity_dict):
- """Convert from dict representation to object representation."""
- return cls.from_dict(entity_dict).to_obj()
-
- @classmethod
- def dict_from_object(cls, entity_obj):
- """Convert from object representation to dict representation."""
- return cls.from_obj(entity_obj).to_dict()
+def _validate_version(instance, value):
+ if value:
+ utils.check_version(instance._ALL_VERSIONS, value)
class BaseCoreComponent(Entity):
_ALL_VERSIONS = ()
_ID_PREFIX = None
+ title = fields.TypedField("Title")
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+ version = fields.TypedField("version", preset_hook=_validate_version)
+ timestamp = fields.DateTimeField("timestamp")
+ handling = fields.TypedField("Handling", type_="stix.data_marking.Marking")
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
+ super(BaseCoreComponent, self).__init__()
- self.id_ = id_ or utils.create_id(self._ID_PREFIX)
+ self.id_ = id_ or idgen.create_id(self._ID_PREFIX)
self.idref = idref
self.title = title
self.description = description
self.short_description = short_description
- self.version = None
- self.information_source = None
if timestamp:
self.timestamp = timestamp
else:
self.timestamp = utils.dates.now() if not idref else None
-
- @property
- def id_(self):
- """The ``id_`` property serves as an identifier. This is
- automatically set during ``__init__()``.
-
- Default Value: ``None``
-
- Note:
- Both the ``id_`` and ``idref`` properties cannot be set at the
- same time. **Setting one will unset the other!**
-
- Returns:
- A string id.
-
- """
- return self._id
-
- @id_.setter
- def id_(self, value):
- if not value:
- self._id = None
- else:
- self._id = value
- self.idref = None
-
- @property
- def idref(self):
- """The ``idref`` property must be set to the ``id_`` value of another
- object instance of the same type. An idref does not need to resolve to
- a local object instance.
-
- Default Value: ``None``.
-
- Note:
- Both the ``id_`` and ``idref`` properties cannot be set at the
- same time. **Setting one will unset the other!**
-
- Returns:
- The value of the ``idref`` property
-
- """
- return self._idref
-
- @idref.setter
- def idref(self, value):
- if not value:
- self._idref = None
- else:
- self._idref = value
- self.id_ = None # unset id_ if idref is present
-
- @property
- def version(self):
- """The schematic version of this component. This property
- will always return ``None`` unless it is set to a value different than
- ``self.__class__._version``.
-
- Note:
- This property refers to the version of the schema component
- type and should not be used for the purpose of content versioning.
-
- Default Value: ``None``
-
- Returns:
- The value of the ``version`` property if set to a value different
- than ``self.__class__._version``
-
- """
- return self._version
-
- @version.setter
- def version(self, value):
- if not value:
- self._version = None
- else:
- utils.check_version(self._ALL_VERSIONS, value)
- self._version = value
-
- @property
- def timestamp(self):
- """The timestam property declares the time of creation and is
- automatically set in ``__init__()``.
-
- This property can accept ``datetime.datetime`` or ``str`` values.
- If an ``str`` value is supplied, a best-effort attempt is made to
- parse it into an instance of ``datetime.datetime``.
-
- Default Value: A ``datetime.dateime`` instance with a value of the
- date/time when ``__init__()`` was called.
-
- Note:
- If an ``idref`` is set during ``__init__()``, the value of
- ``timestamp`` will not automatically generated and instead default
- to the ``timestamp`` parameter, which has a default value of
- ``None``.
-
- Returns:
- An instance of ``datetime.datetime``.
-
- """
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- @property
- def title(self):
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- """A description about the contents or purpose of this object.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`.StructuredText`, an attempt to will be made to convert
- the value into an instance of :class:`.StructuredText`.
-
- Returns:
- An instance of
- :class:`.StructuredText`
-
- """
- return self._description
-
- @description.setter
- def description(self, value):
- from stix.common import StructuredText
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- """A short description about the contents or purpose of this object.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`.StructuredText`, an attempt to will be made to convert
- the value into an instance of :class:`.StructuredText`.
-
- Returns:
- An instance of
- :class:`.StructuredText`
-
- """
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- from stix.common import StructuredText
- self._set_var(StructuredText, short_description=value)
-
- @property
- def information_source(self):
- """Contains information about the source of this object.
-
- Default Value: ``None``
-
- Returns:
- An instance of
- :class:`.InformationSource`
-
- Raises:
- ValueError: If set to a value that is not ``None`` and not an
- instance of
- :class:`.InformationSource`
-
- """
- return self._information_source
-
- @information_source.setter
- def information_source(self, value):
- from stix.common import InformationSource
- self._set_var(InformationSource, try_cast=False, information_source=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- from stix.common import StructuredText, InformationSource
-
- if not return_obj:
- raise ValueError("Must provide a return_obj argument")
-
- if not obj:
- raise ValueError("Must provide an obj argument")
-
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
- return_obj.timestamp = obj.timestamp
-
- # These may not be found on the input obj if it isn't a full
- # type definition (e.g., used as a reference)
- return_obj.version = getattr(obj, 'version', None)
- return_obj.title = getattr(obj, 'Title', None)
- return_obj.description = \
- StructuredText.from_obj(getattr(obj, 'Description', None))
- return_obj.short_description = \
- StructuredText.from_obj(getattr(obj, 'Short_Description', None))
- return_obj.information_source = \
- InformationSource.from_obj(getattr(obj, 'Information_Source', None))
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- raise ValueError("Must provide a return_obj argument")
-
- super(BaseCoreComponent, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
- return_obj.version = self.version
- return_obj.Title = self.title
-
- if self.timestamp:
- return_obj.timestamp = utils.dates.serialize_value(self.timestamp)
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.information_source:
- return_obj.Information_Source = self.information_source.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- from stix.common import StructuredText, InformationSource
-
- if not return_obj:
- raise ValueError("Must provide a return_obj argument")
-
- get = d.get
- return_obj.id_ = get('id')
- return_obj.idref = get('idref')
- return_obj.timestamp = get('timestamp')
- return_obj.version = get('version')
- return_obj.title = get('title')
- return_obj.description = \
- StructuredText.from_dict(get('description'))
- return_obj.short_description = \
- StructuredText.from_dict(get('short_description'))
- return_obj.information_source = \
- InformationSource.from_dict(get('information_source'))
-
- return return_obj
-
- def to_dict(self):
- return super(BaseCoreComponent, self).to_dict()
diff --git a/stix/bindings/__init__.py b/stix/bindings/__init__.py
index c88b876c..c042c61d 100644
--- a/stix/bindings/__init__.py
+++ b/stix/bindings/__init__.py
@@ -1,432 +1,109 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-import re
-import base64
import collections
-import contextlib
-from xml.sax import saxutils
-from datetime import datetime, tzinfo, timedelta
from lxml import etree as etree_
-import cybox.bindings as cybox_bindings
+import mixbox.xml
-from stix import xmlconst
-try:
- import maec.bindings as maec_bindings
- _MAEC_INSTALLED = True
-except ImportError:
- _MAEC_INSTALLED = False
-
-
-CDATA_START = ""
-
-ExternalEncoding = 'utf-8'
-Tag_pattern_ = re.compile(r'({.*})?(.*)')
-
-# These are only used internally
-_tzoff_pattern = re.compile(r'(\+|-)((0\d|1[0-3]):[0-5]\d|14:00)$')
-_Tag_strip_pattern_ = re.compile(r'\{.*\}')
-
-
-@contextlib.contextmanager
-def save_encoding(encoding='utf-8'):
- global ExternalEncoding
-
- try:
- # Save original binding encoding attribute value
- orig_stix_encoding = ExternalEncoding
- orig_cybox_encoding = cybox_bindings.ExternalEncoding
-
- # Set binding encoding attribute value to `encoding`
- ExternalEncoding = encoding
- cybox_bindings.ExternalEncoding = encoding
-
- # Set MAEC binding encoding attribute to `encoding` if python-maec
- # is installed.
- if _MAEC_INSTALLED:
- orig_maec_encoding = maec_bindings.ExternalEncoding
- maec_bindings.ExternalEncoding = encoding
-
- # Return to caller
- yield
-
- finally:
- # Reset the binding encoding attribute values to original values
- ExternalEncoding = orig_stix_encoding
- cybox_bindings.ExternalEncoding = orig_cybox_encoding
-
- if _MAEC_INSTALLED:
- maec_bindings.ExternalEncoding = orig_maec_encoding
-
-
-def parsexml_(*args, **kwargs):
- from stix.utils.parser import get_xml_parser
-
- if 'parser' not in kwargs:
- # Use the lxml ElementTree compatible parser so that, e.g.,
- # we ignore comments.
- kwargs['parser'] = get_xml_parser()
- return etree_.parse(*args, **kwargs)
-
-
-class _FixedOffsetTZ(tzinfo):
+TypeInfo = collections.namedtuple("TypeInfo", ('ns', 'typename'))
- def __init__(self, offset, name):
- self.__offset = timedelta(minutes=offset)
- self.__name = name
- def utcoffset(self, dt):
- return self.__offset
+def get_type_info(node):
+ """Returns a ``TypeInfo`` object for `node`.
- def tzname(self, dt):
- return self.__name
+ This is accomplished by parsing the ``xsi:type`` attribute found on
+ `node`.
- def dst(self, dt):
- return None
+ Args:
+ node: An lxml.etree element object.
- __reduce__ = object.__reduce__
+ Raises:
+ KeyError: If `node` does not have an ``xsi:type`` attribute.
+ """
+ xsi_type = node.attrib[mixbox.xml.TAG_XSI_TYPE]
+ typeinfo = xsi_type.split(":")
-class GeneratedsSuper(object):
+ if len(typeinfo) == 2:
+ prefix, typename = typeinfo
+ else:
+ typename = typeinfo
+ prefix = None
- def gds_format_string(self, input_data, input_name=''):
- return input_data
+ ns = node.nsmap[prefix]
+ return TypeInfo(ns=ns, typename=typename)
- def gds_validate_string(self, input_data, node, input_name=''):
- return input_data
- def gds_format_base64(self, input_data, input_name=''):
- return base64.b64encode(input_data)
+#: A mapping of namespace/type information to binding classes.
+_BINDING_EXTENSION_MAP = {}
- def gds_validate_base64(self, input_data, node, input_name=''):
- return input_data
- def gds_format_integer(self, input_data, input_name=''):
- return '%d' % input_data
+def add_extension(cls):
+ """Adds the binding class `cls` to the ``_EXTENSION_MAP``.
- def gds_validate_integer(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_integer_list(self, input_data, input_name=''):
- return '%s' % input_data
-
- def gds_validate_integer_list(self, input_data, node, input_name=''):
- values = input_data.split()
- for value in values:
- try:
- fvalue = float(value)
- except (TypeError, ValueError), exp:
- raise_parse_error(node, 'Requires sequence of integers')
- return input_data
-
- def gds_format_float(self, input_data, input_name=''):
- return '%f' % input_data
-
- def gds_validate_float(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_float_list(self, input_data, input_name=''):
- return '%s' % input_data
-
- def gds_validate_float_list(self, input_data, node, input_name=''):
- values = input_data.split()
- for value in values:
- try:
- fvalue = float(value)
- except (TypeError, ValueError), exp:
- raise_parse_error(node, 'Requires sequence of floats')
- return input_data
-
- def gds_format_double(self, input_data, input_name=''):
- return '%e' % input_data
-
- def gds_validate_double(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_double_list(self, input_data, input_name=''):
- return '%s' % input_data
-
- def gds_validate_double_list(self, input_data, node, input_name=''):
- values = input_data.split()
- for value in values:
- try:
- fvalue = float(value)
- except (TypeError, ValueError), exp:
- raise_parse_error(node, 'Requires sequence of doubles')
- return input_data
-
- def gds_format_boolean(self, input_data, input_name=''):
- return ('%s' % input_data).lower()
-
- def gds_validate_boolean(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_boolean_list(self, input_data, input_name=''):
- return '%s' % input_data
-
- def gds_validate_boolean_list(self, input_data, node, input_name=''):
- values = input_data.split()
- for value in values:
- if value not in ('true', '1', 'false', '0'):
- msg = ('Requires sequence of booleans '
- '("true", "1", "false", "0")')
- raise_parse_error(node, msg)
- return input_data
-
- def gds_validate_datetime(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_datetime(self, input_data, input_name=''):
- if isinstance(input_data, basestring):
- return input_data
- if input_data.microsecond == 0:
- _svalue = input_data.strftime('%Y-%m-%dT%H:%M:%S')
- else:
- _svalue = input_data.strftime('%Y-%m-%dT%H:%M:%S.%f')
- if input_data.tzinfo is not None:
- tzoff = input_data.tzinfo.utcoffset(input_data)
- if tzoff is not None:
- total_seconds = tzoff.seconds + (86400 * tzoff.days)
- if total_seconds == 0:
- _svalue += 'Z'
- else:
- if total_seconds < 0:
- _svalue += '-'
- total_seconds *= -1
- else:
- _svalue += '+'
- hours = total_seconds // 3600
- minutes = (total_seconds - (hours * 3600)) // 60
- _svalue += '{0:02d}:{1:02d}'.format(hours, minutes)
- return _svalue
-
- def gds_parse_datetime(self, input_data, node, input_name=''):
- tz = None
- if input_data[-1] == 'Z':
- tz = _FixedOffsetTZ(0, 'GMT')
- input_data = input_data[:-1]
- else:
- results = _tzoff_pattern.search(input_data)
- if results is not None:
- tzoff_parts = results.group(2).split(':')
- tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
- if results.group(1) == '-':
- tzoff *= -1
- tz = _FixedOffsetTZ(tzoff, results.group(0))
- input_data = input_data[:-6]
- if len(input_data.split('.')) > 1:
- dt = datetime.strptime(input_data, '%Y-%m-%dT%H:%M:%S.%f')
- else:
- dt = datetime.strptime(input_data, '%Y-%m-%dT%H:%M:%S')
- return dt.replace(tzinfo=tz)
-
- def gds_validate_date(self, input_data, node, input_name=''):
- return input_data
-
- def gds_format_date(self, input_data, input_name=''):
- if isinstance(input_data, basestring):
- return input_data
- _svalue = input_data.strftime('%Y-%m-%d')
- if input_data.tzinfo is not None:
- tzoff = input_data.tzinfo.utcoffset(input_data)
- if tzoff is not None:
- total_seconds = tzoff.seconds + (86400 * tzoff.days)
- if total_seconds == 0:
- _svalue += 'Z'
- else:
- if total_seconds < 0:
- _svalue += '-'
- total_seconds *= -1
- else:
- _svalue += '+'
- hours = total_seconds // 3600
- minutes = (total_seconds - (hours * 3600)) // 60
- _svalue += '{0:02d}:{1:02d}'.format(hours, minutes)
- return _svalue
-
- def gds_parse_date(self, input_data, node, input_name=''):
- tz = None
- if input_data[-1] == 'Z':
- tz = _FixedOffsetTZ(0, 'GMT')
- input_data = input_data[:-1]
- else:
- results = _tzoff_pattern.search(input_data)
- if results is not None:
- tzoff_parts = results.group(2).split(':')
- tzoff = int(tzoff_parts[0]) * 60 + int(tzoff_parts[1])
- if results.group(1) == '-':
- tzoff *= -1
- tz = _FixedOffsetTZ(tzoff, results.group(0))
- input_data = input_data[:-6]
- return datetime.strptime(input_data, '%Y-%m-%d').replace(tzinfo=tz)
-
- def gds_str_lower(self, instring):
- return instring.lower()
-
- def get_path_(self, node):
- path_list = []
- self.get_path_list_(node, path_list)
- path_list.reverse()
- path = '/'.join(path_list)
- return path
-
- def get_path_list_(self, node, path_list):
- if node is None:
- return
- tag = _Tag_strip_pattern_.sub('', node.tag)
- if tag:
- path_list.append(tag)
- self.get_path_list_(node.getparent(), path_list)
-
- def get_class_obj_(self, node, default_class=None):
- class_obj1 = default_class
- if 'xsi' in node.nsmap:
- classname = node.get('{%s}type' % node.nsmap['xsi'])
- if classname is not None:
- names = classname.split(':')
- if len(names) == 2:
- classname = names[1]
- class_obj2 = globals().get(classname)
- if class_obj2 is not None:
- class_obj1 = class_obj2
- return class_obj1
-
- def gds_build_any(self, node, type_name=None):
- return None
-
-
-def showIndent(lwrite, level, pretty_print=True):
- if pretty_print:
- lwrite(' ' * level)
-
-
-def quote_xml(text):
- if text is None:
- return u''
-
- # Convert `text` to unicode string. This is mainly a catch-all for non
- # string/unicode types like bool and int.
- try:
- text = unicode(text)
- except UnicodeDecodeError:
- text = text.decode(ExternalEncoding)
-
- # If it's a CDATA block, return the text as is.
- if text.startswith(CDATA_START):
- return text
-
- # If it's not a CDATA block, escape the XML and return the character
- # encoded string.
- return saxutils.escape(text)
-
-
-def quote_attrib(text):
- if text is None:
- return u'""'
-
- # Convert `text` to unicode string. This is mainly a catch-all for non
- # string/unicode types like bool and int.
- try:
- text = unicode(text)
- except UnicodeDecodeError:
- text = text.decode(ExternalEncoding)
-
- # Return the escaped the value of text.
- # Note: This wraps the escaped text in quotation marks.
- return saxutils.quoteattr(text)
-
-
-def quote_python(inStr):
- s1 = inStr
- if s1.find("'") == -1:
- if s1.find('\n') == -1:
- return "'%s'" % s1
- else:
- return "'''%s'''" % s1
- else:
- if s1.find('"') != -1:
- s1 = s1.replace('"', '\\"')
- if s1.find('\n') == -1:
- return '"%s"' % s1
- else:
- return '"""%s"""' % s1
+ This enables the lookup and instantiation of classes during parse when
+ ``xsi:type`` attributes are encountered.
+ """
+ typeinfo = TypeInfo(ns=cls.xmlns, typename=cls.xml_type)
+ _BINDING_EXTENSION_MAP[typeinfo] = cls
-def get_all_text_(node):
- if node.text is not None:
- text = node.text
- else:
- text = ''
- for child in node:
- if child.tail is not None:
- text += child.tail
- return text
+def register_extension(cls):
+ """Class decorator for registering a binding class as an implementation of
+ an xml type.
-def find_attr_value_(attr_name, node):
- attrs = node.attrib
- attr_parts = attr_name.split(':')
- value = None
- if len(attr_parts) == 1:
- value = attrs.get(attr_name)
- elif len(attr_parts) == 2:
- prefix, name = attr_parts
- namespace = node.nsmap.get(prefix)
- if namespace is not None:
- value = attrs.get('{%s}%s' % (namespace, name, ))
- return value
+ Classes must have ``xmlns`` and ``xml_type`` class attributes to be
+ registered.
+ """
+ add_extension(cls)
+ return cls
-class GDSParseError(Exception):
- pass
-def raise_parse_error(node, msg):
- msg = '%s (element %s/line %d)' % (msg, node.tag, node.sourceline)
- raise GDSParseError(msg)
+def lookup_extension(typeinfo, default=None):
+ """Looks up the binding class for `typeinfo`, which is a namespace/typename
+ pairing.
+ Args:
+ typeinfo: An lxml Element node or a stix.bindings.TypeInfo namedtuple.
+ default: A binding class that will be returned if typeinfo is an
+ Element without an xsi:type attribute.
-def _cast(typ, value):
- if typ is None or value is None:
- return value
- return typ(value)
+ Returns:
+ A binding class that has been registered for the namespace and typename
+ found on `typeinfo`.
+ """
+ if not isinstance(typeinfo, TypeInfo):
+ if has_xsi_type(typeinfo):
+ typeinfo = get_type_info(typeinfo)
+ elif default:
+ return default
-TypeInfo = collections.namedtuple("TypeInfo", ('ns', 'typename'))
+ if typeinfo in _BINDING_EXTENSION_MAP:
+ return _BINDING_EXTENSION_MAP[typeinfo]
+ fmt = "No class implemented or registered for XML type '{%s}%s'"
+ error = fmt % (typeinfo.ns, typeinfo.typename)
+ raise NotImplementedError(error)
-def get_type_info(node):
- xsi_type = node.attrib[xmlconst.TAG_XSI_TYPE]
- typeinfo = xsi_type.split(":")
- if len(typeinfo) == 2:
- prefix, typename = typeinfo
- else:
- typename = typeinfo
- prefix = None
+def has_xsi_type(node):
+ """Returns ``True`` if `node` does not have an xsi:type attribute.
- ns = node.nsmap[prefix]
- return TypeInfo(ns=ns, typename=typename)
+ """
+ return mixbox.xml.TAG_XSI_TYPE in node.attrib
__all__ = [
- '_cast',
+ 'TypeInfo',
+ 'add_extension',
'etree_',
- 'ExternalEncoding',
- 'find_attr_value_',
- 'get_all_text_',
'get_type_info',
- 'parsexml_',
- 'quote_xml',
- 'quote_attrib',
- 'quote_python',
- 'raise_parse_error',
- 'showIndent',
- 'Tag_pattern_',
- 'GeneratedsSuper',
- 'CDATA_START',
- 'CDATA_END',
- 'TypeInfo'
+ 'has_xsi_type',
+ 'lookup_extension',
+ 'register_extension',
]
diff --git a/stix/bindings/campaign.py b/stix/bindings/campaign.py
index bb16e77e..b3725838 100644
--- a/stix/bindings/campaign.py
+++ b/stix/bindings/campaign.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -71,6 +74,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NamesTy
for Name_ in self.Name:
Name_.export(lwrite, level, nsmap, namespace_, name_='Name', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -139,6 +143,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Associa
for Associated_Campaign_ in self.Associated_Campaign:
Associated_Campaign_.export(lwrite, level, nsmap, namespace_, name_='Associated_Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -208,6 +213,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Indicator_ in self.Related_Indicator:
Related_Indicator_.export(lwrite, level, nsmap, namespace_, name_='Related_Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -277,6 +283,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Incident_ in self.Related_Incident:
Related_Incident_.export(lwrite, level, nsmap, namespace_, name_='Related_Incident', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -346,6 +353,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_TTP_ in self.Related_TTP:
Related_TTP_.export(lwrite, level, nsmap, namespace_, name_='Related_TTP', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -417,6 +425,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Attribu
for Attributed_Threat_Actor_ in self.Attributed_Threat_Actor:
Attributed_Threat_Actor_.export(lwrite, level, nsmap, namespace_, name_='Attributed_Threat_Actor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -432,17 +441,22 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(AttributionType, self).buildChildren(child_, node, nodeName_, True)
# end class AttributionType
+
+@register_extension
class CampaignType(stix_common_binding.CampaignBaseType):
"""The CampaignType characterizes a single cyber threat
Campaign.Specifies the relevant STIX-Campaign schema version for
this content."""
subclass = None
superclass = stix_common_binding.CampaignBaseType
+
+ xmlns = "http://stix.mitre.org/Campaign-1"
+ xmlns_prefix = "campaign"
+ xml_type = "CampaignType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, version=None, Title=None, Description=None, Short_Description=None, Names=None, Intended_Effect=None, Status=None, Related_TTPs=None, Related_Incidents=None, Related_Indicators=None, Attribution=None, Associated_Campaigns=None, Confidence=None, Activity=None, Information_Source=None, Handling=None, Related_Packages=None):
super(CampaignType, self).__init__(idref=idref, id=id, timestamp=timestamp)
- self.xmlns = "http://stix.mitre.org/Campaign-1"
- self.xmlns_prefix = "campaign"
- self.xml_type = "CampaignType"
self.version = _cast(None, version)
self.Title = Title
self.Description = Description
@@ -607,6 +621,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Campaig
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -693,7 +708,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -739,7 +754,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/course_of_action.py b/stix/bindings/course_of_action.py
index cfc6770c..e1b3392f 100644
--- a/stix/bindings/course_of_action.py
+++ b/stix/bindings/course_of_action.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,8 +9,11 @@
#
import sys
-from stix.bindings import *
+
import cybox.bindings.cybox_core as cybox_core_binding
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -43,9 +46,6 @@ class StructuredCOAType(GeneratedsSuper):
subclass = None
superclass = None
def __init__(self, idref=None, id=None):
- self.xmlns = "http://stix.mitre.org/CourseOfAction-1"
- self.xmlns_prefix = "coa"
- self.xml_type = "CourseOfActionType"
self.idref = _cast(None, idref)
self.id = _cast(None, id)
pass
@@ -99,6 +99,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='coa:',
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='StructuredCOAType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -176,6 +177,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Objecti
if self.Applicability_Confidence is not None:
self.Applicability_Confidence.export(lwrite, level, nsmap, namespace_, name_='Applicability_Confidence', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -198,6 +200,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
self.set_Applicability_Confidence(obj_)
# end class ObjectiveType
+
+@register_extension
class CourseOfActionType(stix_common_binding.CourseOfActionBaseType):
"""The CourseOfActionType characterizes a Course of Action to be taken
in regards to one of more cyber threats. NOTE: This construct is
@@ -206,11 +210,15 @@ class CourseOfActionType(stix_common_binding.CourseOfActionBaseType):
schema version for this content."""
subclass = None
superclass = stix_common_binding.CourseOfActionBaseType
+
+ xmlns = "http://stix.mitre.org/CourseOfAction-1"
+ xmlns_prefix = "coa"
+ xml_type = "CourseOfActionType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, version=None, Title=None, Stage=None, Type=None, Description=None, Short_Description=None, Objective=None, Parameter_Observables=None, Structured_COA=None, Impact=None, Cost=None, Efficacy=None, Information_Source=None, Handling=None, Related_COAs=None, Related_Packages=None):
super(CourseOfActionType, self).__init__(idref=idref, id=id, timestamp=timestamp)
- self.xmlns = "http://stix.mitre.org/CourseOfAction-1"
- self.xmlns_prefix = "coa"
- self.xml_type = "CourseOfActionType"
+
self.version = _cast(None, version)
self.Title = Title
self.Stage = Stage
@@ -354,6 +362,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CourseO
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -395,24 +404,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
obj_.build(child_)
self.set_Parameter_Observables(obj_)
elif nodeName_ == 'Structured_COA':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "GenericStructuredCOAType":
- from .extensions.structured_coa import generic
- obj_ = generic.GenericStructuredCOAType.factory()
- else:
- raise NotImplementedError('No implementation class for Structured_COA: ' + type_name_)
- else:
- raise NotImplementedError('Structured_COA type not declared: missing xsi_type attribute')
-
+ from .extensions.structured_coa import generic
+ obj_ = lookup_extension(child_).factory()
obj_.build(child_)
self.set_Structured_COA(obj_)
elif nodeName_ == 'Impact':
@@ -501,6 +494,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_COA_ in self.Related_COA:
Related_COA_.export(lwrite, level, nsmap, namespace_, name_='Related_COA', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -523,7 +517,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -569,7 +563,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/data_marking.py b/stix/bindings/data_marking.py
index fda03e89..acdbd848 100644
--- a/stix/bindings/data_marking.py
+++ b/stix/bindings/data_marking.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -7,12 +7,12 @@
#
# Generated Thu Apr 11 15:06:22 2013 by generateDS.py version 2.9a.
#
-# stdlib
+
import sys
-# internal
-from stix.bindings import *
-from stix import xmlconst
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension
from . import stix_common as stix_common_binding
XML_NS = "http://data-marking.mitre.org/Marking-1"
@@ -75,6 +75,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Marking
for Marking_ in self.Marking:
Marking_.export(lwrite, level, nsmap, namespace_, name_='Marking', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -197,6 +198,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='marking
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='MarkingStructureType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -308,6 +310,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Marking
if self.Information_Source is not None:
self.Information_Source.export(lwrite, level, nsmap, namespace_, name_='Information_Source', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -339,20 +342,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
# Look for xsi:type. If not there, build an instance of
# MarkingStructureType
- if xmlconst.TAG_XSI_TYPE not in child_.attrib:
- ref = MarkingStructureType.factory()
- ref.build(child_)
- self.Marking_Structure.append(ref)
- return
-
- # Extract the xsi:type associated type namespace and type name
- typeinfo = get_type_info(child_)
-
- if typeinfo not in _EXTENSION_MAP:
- raise NotImplementedError('Marking structure type not implemented ' + typeinfo.typename)
-
- klass = _EXTENSION_MAP[typeinfo]
- obj_ = klass.factory()
+ obj_ = lookup_extension(child_, MarkingStructureType).factory()
obj_.build(child_)
self.Marking_Structure.append(obj_)
@@ -363,13 +353,6 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
# end class MarkingSpecificationType
-_EXTENSION_MAP = {}
-
-def add_extension(klass):
- typeinfo = TypeInfo(ns=klass.xmlns, typename=klass.xml_type)
- _EXTENSION_MAP[typeinfo] = klass
-
-
GDSClassesMapping = {}
USAGE_TEXT = """
@@ -377,7 +360,7 @@ def add_extension(klass):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -423,7 +406,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/exploit_target.py b/stix/bindings/exploit_target.py
index 146d49dc..e5f1b108 100644
--- a/stix/bindings/exploit_target.py
+++ b/stix/bindings/exploit_target.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -157,6 +160,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Vulnera
if self.References is not None:
self.References.export(lwrite, level, nsmap, namespace_, name_='References', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -202,7 +206,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
sval_ = child_.text
try:
ival_ = int(sval_)
- except (TypeError, ValueError), exp:
+ except (TypeError, ValueError) as exp:
raise_parse_error(child_, 'requires integer: %s' % exp)
if ival_ <= 0:
raise_parse_error(child_, 'requires positiveInteger')
@@ -292,6 +296,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Configu
showIndent(lwrite, level, pretty_print)
lwrite('<%s:CCE_ID>%s%s:CCE_ID>%s' % (nsmap[namespace_], quote_xml(self.CCE_ID), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -368,6 +373,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Affecte
for Affected_Software_ in self.Affected_Software:
Affected_Software_.export(lwrite, level, nsmap, namespace_, name_='Affected_Software', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -437,6 +443,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Exploit_Target_ in self.Related_Exploit_Target:
Related_Exploit_Target_.export(lwrite, level, nsmap, namespace_, name_='Related_Exploit_Target', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -506,6 +513,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Weaknes
showIndent(lwrite, level, pretty_print)
lwrite('<%s:CWE_ID>%s%s:CWE_ID>%s' % (nsmap[namespace_], quote_xml(self.CWE_ID), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -618,6 +626,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CVSSVec
if self.Environmental_Vector is not None:
lwrite('<%s:Environmental_Vector>%s%s:Environmental_Vector>%s' % (nsmap[namespace_], quote_xml(self.Environmental_Vector), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -710,6 +719,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Potenti
for Potential_COA_ in self.Potential_COA:
Potential_COA_.export(lwrite, level, nsmap, namespace_, name_='Potential_COA', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -725,16 +735,22 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(PotentialCOAsType, self).buildChildren(child_, node, nodeName_, True)
# end class PotentialCOAsType
+
+@register_extension
class ExploitTargetType(stix_common_binding.ExploitTargetBaseType):
"""Specifies the relevant STIX-ExploitTarget schema version for this
content."""
subclass = None
superclass = stix_common_binding.ExploitTargetBaseType
+
+ xmlns = "http://stix.mitre.org/ExploitTarget-1"
+ xmlns_prefix = "et"
+ xml_type = "ExploitTargetType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, version=None, Title=None, Description=None, Short_Description=None, Vulnerability=None, Weakness=None, Configuration=None, Potential_COAs=None, Information_Source=None, Handling=None, Related_Exploit_Targets=None, Related_Packages=None):
super(ExploitTargetType, self).__init__(timestamp=timestamp, idref=idref, id=id)
- self.xmlns = "http://stix.mitre.org/ExploitTarget-1"
- self.xmlns_prefix = "et"
- self.xml_type = "ExploitTargetType"
+
self.version = _cast(None, version)
self.Title = Title
self.Description = Description
@@ -869,6 +885,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Exploit
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -951,7 +968,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -997,7 +1014,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/address/ciq_address_3_0.py b/stix/bindings/extensions/address/ciq_address_3_0.py
index 6738143a..50938212 100644
--- a/stix/bindings/extensions/address/ciq_address_3_0.py
+++ b/stix/bindings/extensions/address/ciq_address_3_0.py
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.stix_common as stix_common_binding
XML_NS = "http://stix.mitre.org/extensions/Address#CIQAddress3.0-1"
@@ -18,6 +21,7 @@
# Data representation classes.
#
+@register_extension
class CIQAddress3_0InstanceType(stix_common_binding.AddressAbstractType):
"""The CIQAddress3.0InstanceType provides an extension to the
stix_common_binding.AddressAbstractType which imports and leverages version 3.0 of
@@ -25,12 +29,15 @@ class CIQAddress3_0InstanceType(stix_common_binding.AddressAbstractType):
Addresses."""
subclass = None
superclass = stix_common_binding.AddressAbstractType
+
+ xmlns = XML_NS
+ xmlns_prefix = "stix-ciqaddress"
+ xml_type = "CIQAddress3.0InstanceType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, Location=None):
super(CIQAddress3_0InstanceType, self).__init__()
self.Location = Location
- self.xmlns = XML_NS
- self.xmlns_prefix = "ciqAddress"
- self.xml_type = "CIQAddress3.0InstanceType"
def factory(*args_, **kwargs_):
if CIQAddress3_0InstanceType.subclass:
return CIQAddress3_0InstanceType.subclass(*args_, **kwargs_)
@@ -82,9 +89,10 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CIQAddr
eol_ = ''
if self.Location is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.Location, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.Location, pretty_print=pretty_print).decode())
#self.Location.export(lwrite, level, nsmap, namespace_, name_='Location', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -105,7 +113,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -151,7 +159,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/attack_pattern/capec_2_7.py b/stix/bindings/extensions/attack_pattern/capec_2_7.py
index e7cfbce5..2f8d92fd 100644
--- a/stix/bindings/extensions/attack_pattern/capec_2_7.py
+++ b/stix/bindings/extensions/attack_pattern/capec_2_7.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.ttp as ttp_binding
XML_NS = "http://stix.mitre.org/extensions/AP#CAPEC2.7-1"
@@ -18,18 +21,22 @@
# Data representation classes.
#
+@register_extension
class CAPEC2_7InstanceType(ttp_binding.AttackPatternType):
"""The CAPECInstanceType provides an extension to the
APStructureAbstractType which imports and leverages the CAPEC
schema for structured characterization of Attack Patterns."""
subclass = None
superclass = ttp_binding.AttackPatternType
+
+ xmlns = XML_NS
+ xmlns_prefix = "capecInstance"
+ xml_type = "CAPEC2.7InstanceType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, capec_id=None, Description=None, CAPEC=None):
super(CAPEC2_7InstanceType, self).__init__(capec_id=capec_id, Description=Description)
self.CAPEC = CAPEC
- self.xmlns = XML_NS
- self.xmlns_prefix = "capecInstance"
- self.xml_type = "CAPEC2.7InstanceType"
def factory(*args_, **kwargs_):
if CAPEC2_7InstanceType.subclass:
@@ -81,9 +88,10 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CAPEC2.
eol_ = ''
if self.CAPEC is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.CAPEC, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.CAPEC, pretty_print=pretty_print).decode())
#self.CAPEC.export(lwrite, level, nsmap, namespace_, name_='CAPEC', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -104,7 +112,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -150,7 +158,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/identity/ciq_identity_3_0.py b/stix/bindings/extensions/identity/ciq_identity_3_0.py
index ad8fd953..04795013 100644
--- a/stix/bindings/extensions/identity/ciq_identity_3_0.py
+++ b/stix/bindings/extensions/identity/ciq_identity_3_0.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.stix_common as stix_common_binding
XML_NS = "http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1"
@@ -18,6 +21,8 @@
# Data representation classes.
#
+
+@register_extension
class CIQIdentity3_0InstanceType(stix_common_binding.IdentityType):
"""The CIQIdentity3.0InstanceType provides an extension to the
IdentityStructureAbstractType which imports and leverages
@@ -25,12 +30,14 @@ class CIQIdentity3_0InstanceType(stix_common_binding.IdentityType):
characterization of Identities."""
subclass = None
superclass = stix_common_binding.IdentityType
+
+ xmlns = XML_NS
+ xmlns_prefix = "stix-ciqidentity"
+ xml_type = "CIQIdentity3.0InstanceType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, Name=None, Related_Identities=None, Specification=None, Role=None):
super(CIQIdentity3_0InstanceType, self).__init__(idref=idref, id=id, Name=Name, Related_Identities=Related_Identities)
- self.xmlns = XML_NS
- self.xmlns_prefix = "stix-ciqidentity"
- self.xml_type = "CIQIdentity3.0InstanceType"
- self.xsi_type = None
self.Specification = Specification
if Role is None:
self.Role = []
@@ -93,12 +100,13 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CIQIden
eol_ = ''
if self.Specification is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.Specification, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.Specification, pretty_print=pretty_print).decode())
#self.Specification.export(lwrite, level, nsmap, namespace_, name_='Specification', pretty_print=pretty_print)
for Role_ in self.Role:
showIndent(lwrite, level, pretty_print)
lwrite('<%s:Role>%s%s:Role>%s' % (nsmap[namespace_], quote_xml(Role_), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -123,7 +131,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -169,7 +177,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/malware/maec_4_1.py b/stix/bindings/extensions/malware/maec_4_1.py
index 5294cdc4..04787efd 100644
--- a/stix/bindings/extensions/malware/maec_4_1.py
+++ b/stix/bindings/extensions/malware/maec_4_1.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,13 +9,12 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.ttp as ttp_binding
-try:
- from maec.bindings.maec_package import PackageType
- maec_installed = True
-except ImportError:
- maec_installed = False
+
XML_NS = "http://stix.mitre.org/extensions/Malware#MAEC4.1-1"
@@ -23,17 +22,22 @@
# Data representation classes.
#
+
+@register_extension
class MAEC4_1InstanceType(ttp_binding.MalwareInstanceType):
"""The MAEC4.1InstanceType provides an extension to ttp_binding.MalwareInstanceType
- which imports and leverages the MAEC 4.0.1 schema for structured
+ which imports and leverages the MAEC 4.1 schema for structured
characterization of Malware."""
subclass = None
superclass = ttp_binding.MalwareInstanceType
+
+ xmlns = XML_NS
+ xmlns_prefix = "stix-maec"
+ xml_type = "MAEC4.1InstanceType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, Type=None, Name=None, Description=None, MAEC=None):
super(MAEC4_1InstanceType, self).__init__(Type=Type, Name=Name, Description=Description)
- self.xmlns = XML_NS
- self.xmlns_prefix = "stix-maec"
- self.xml_type = "MAEC4.1InstanceType"
self.MAEC = MAEC
def factory(*args_, **kwargs_):
if MAEC4_1InstanceType.subclass:
@@ -80,12 +84,9 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='MAEC4.1
else:
eol_ = ''
if self.MAEC is not None:
- if maec_installed and isinstance(self.MAEC, PackageType):
- self.MAEC.export(lwrite, level, namespace_='stix-maec:', name_='MAEC', pretty_print=pretty_print)
- else:
- showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.MAEC, pretty_print=pretty_print))
+ self.MAEC.export(lwrite, level, namespace_='stix-maec:', name_='MAEC', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -95,12 +96,11 @@ def buildAttributes(self, node, attrs, already_processed):
super(MAEC4_1InstanceType, self).buildAttributes(node, attrs, already_processed)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'MAEC':
- if maec_installed:
- obj_ = PackageType.factory()
- obj_.build(child_)
- self.set_MAEC(obj_)
- else:
- self.set_MAEC(child_)
+ # Fails hard if maec is not installed in your environment.
+ from maec.bindings.maec_package import PackageType
+ obj_ = PackageType.factory()
+ obj_.build(child_)
+ self.set_MAEC(obj_)
super(MAEC4_1InstanceType, self).buildChildren(child_, node, nodeName_, True)
# end class MAEC4_1InstanceType
@@ -111,7 +111,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -157,7 +157,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
@@ -186,4 +186,4 @@ def main():
__all__ = [
"MAEC4_1InstanceType"
- ]
\ No newline at end of file
+ ]
diff --git a/stix/bindings/extensions/marking/ais.py b/stix/bindings/extensions/marking/ais.py
new file mode 100644
index 00000000..52a79f3f
--- /dev/null
+++ b/stix/bindings/extensions/marking/ais.py
@@ -0,0 +1,573 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+
+from mixbox.binding_utils import *
+import stix.bindings.data_marking as data_marking_binding
+from stix.bindings import register_extension
+
+XML_NS = "http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2"
+
+
+#
+# Data representation classes.
+#
+
+@register_extension
+class AISMarkingStructure(data_marking_binding.MarkingStructureType):
+ """
+ The AISMarkingStructure is an implementation of the data marking schema
+ that allows determining consent to share information source attribution.
+ """
+ subclass = None
+ superclass = data_marking_binding.MarkingStructureType
+
+ xmlns = XML_NS
+ xmlns_prefix = "AIS"
+ xml_type = "AISMarkingStructure"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
+ def __init__(self, idref=None, marking_model_ref=None, marking_model_name=None, id=None, Is_Proprietary=None, Not_Proprietary=None):
+ super(AISMarkingStructure, self).__init__(idref=idref, marking_model_ref=marking_model_ref, marking_model_name=marking_model_name, id=id)
+ self.Is_Proprietary = Is_Proprietary
+ self.Not_Proprietary = Not_Proprietary
+
+ def factory(*args_, **kwargs_):
+ if AISMarkingStructure.subclass:
+ return AISMarkingStructure.subclass(*args_, **kwargs_)
+ else:
+ return AISMarkingStructure(*args_, **kwargs_)
+ factory = staticmethod(factory)
+
+ def get_Is_Proprietary(self):
+ return self.Is_Proprietary
+
+ def set_Is_Proprietary(self, Is_Proprietary):
+ self.Is_Proprietary = Is_Proprietary
+
+ def get_Not_Proprietary(self):
+ return self.Not_Proprietary
+
+ def set_Not_Proprietary(self, Not_Proprietary):
+ self.Not_Proprietary = Not_Proprietary
+
+ def hasContent_(self):
+ if (
+ self.Is_Proprietary is not None or
+ self.Not_Proprietary is not None or
+ super(AISMarkingStructure, self).hasContent_()
+ ):
+ return True
+ else:
+ return False
+
+ def export(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AISMarkingStructure', namespacedef_='', pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ showIndent(lwrite, level, pretty_print)
+ lwrite('<%s:%s%s' % (nsmap[namespace_], name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(lwrite, level, already_processed, namespace_, name_='AISMarkingStructure')
+ if self.hasContent_():
+ lwrite('>%s' % (eol_, ))
+ self.exportChildren(lwrite, level + 1, nsmap, XML_NS, name_, pretty_print=pretty_print)
+ showIndent(lwrite, level, pretty_print)
+ lwrite('%s:%s>%s' % (nsmap[namespace_], name_, eol_))
+ else:
+ lwrite('/>%s' % (eol_, ))
+
+ def exportAttributes(self, lwrite, level, already_processed, namespace_=XML_NS, name_='AISMarkingStructure'):
+ super(AISMarkingStructure, self).exportAttributes(lwrite, level, already_processed, namespace_, name_='AISMarkingStructure')
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
+ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AISMarkingStructure', fromsubclass_=False, pretty_print=True):
+ super(AISMarkingStructure, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.Is_Proprietary is not None:
+ self.Is_Proprietary.export(lwrite, level, nsmap, namespace_, name_='Is_Proprietary', pretty_print=pretty_print)
+ if self.Not_Proprietary is not None:
+ self.Not_Proprietary.export(lwrite, level, nsmap, namespace_, name_='Not_Proprietary', pretty_print=pretty_print)
+
+ def build(self, node):
+ self.__sourcenode__ = node
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+
+ def buildAttributes(self, node, attrs, already_processed):
+ super(AISMarkingStructure, self).buildAttributes(node, attrs, already_processed)
+
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'Is_Proprietary':
+ obj_ = IsProprietary.factory()
+ obj_.build(child_)
+ self.set_Is_Proprietary(obj_)
+ if nodeName_ == 'Not_Proprietary':
+ obj_ = NotProprietary.factory()
+ obj_.build(child_)
+ self.set_Not_Proprietary(obj_)
+ super(AISMarkingStructure, self).buildChildren(child_, node, nodeName_, True)
+# end class AISMarkingStructure
+
+
+class IsProprietary(GeneratedsSuper):
+ subclass = None
+ superclass = None
+
+ def __init__(self, CISA_Proprietary=None, AISConsent=None, TLPMarking=None):
+ self.CISA_Proprietary = _cast(bool, CISA_Proprietary)
+ self.AISConsent = AISConsent
+ self.TLPMarking = TLPMarking
+
+ def factory(*args_, **kwargs_):
+ if IsProprietary.subclass:
+ return IsProprietary.subclass(*args_, **kwargs_)
+ else:
+ return IsProprietary(*args_, **kwargs_)
+ factory = staticmethod(factory)
+
+ def get_AISConsent(self):
+ return self.AISConsent
+
+ def set_AISConsent(self, AISConsent):
+ self.AISConsent = AISConsent
+
+ def get_TLPMarking(self):
+ return self.TLPMarking
+
+ def set_TLPMarking(self, TLPMarking):
+ self.TLPMarking = TLPMarking
+
+ def get_CISA_Proprietary(self):
+ return self.CISA_Proprietary
+
+ def set_CISA_Proprietary(self, CISA_Proprietary):
+ self.CISA_Proprietary = CISA_Proprietary
+
+ def hasContent_(self):
+ if (
+ self.AISConsent is not None or
+ self.TLPMarking is not None
+ ):
+ return True
+ else:
+ return False
+
+ def export(self, lwrite, level, nsmap, namespace_=XML_NS, name_='IsProprietary', namespacedef_='', pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ showIndent(lwrite, level, pretty_print)
+ lwrite('<%s:%s%s' % (nsmap[namespace_], name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(lwrite, level, already_processed, namespace_, name_='IsProprietary')
+ if self.hasContent_():
+ lwrite('>%s' % (eol_, ))
+ self.exportChildren(lwrite, level + 1, nsmap, XML_NS, name_, pretty_print=pretty_print)
+ showIndent(lwrite, level, pretty_print)
+ lwrite('%s:%s>%s' % (nsmap[namespace_], name_, eol_))
+ else:
+ lwrite('/>%s' % (eol_, ))
+
+ def exportAttributes(self, lwrite, level, already_processed, namespace_=XML_NS, name_='IsProprietary'):
+ if self.CISA_Proprietary is not None and 'CISA_Proprietary' not in already_processed:
+ already_processed.add('CISA_Proprietary')
+ lwrite(' CISA_Proprietary="%s"' % self.gds_format_boolean(self.CISA_Proprietary, input_name='CISA_Proprietary'))
+
+ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='IsProprietary', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.AISConsent is not None:
+ self.AISConsent.export(lwrite, level, nsmap, namespace_, name_='AISConsent', pretty_print=pretty_print)
+ if self.TLPMarking is not None:
+ self.TLPMarking.export(lwrite, level, nsmap, namespace_, name_='TLPMarking', pretty_print=pretty_print)
+
+ def build(self, node):
+ self.__sourcenode__ = node
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+
+ def buildAttributes(self, node, attrs, already_processed):
+ value = find_attr_value_('CISA_Proprietary', node)
+ if value is not None and 'CISA_Proprietary' not in already_processed:
+ already_processed.add('CISA_Proprietary')
+ if value in ('true', '1'):
+ self.CISA_Proprietary = True
+ elif value in ('false', '0'):
+ self.CISA_Proprietary = False
+ else:
+ raise_parse_error(node, 'Bad boolean attribute')
+
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'AISConsent':
+ obj_ = AISConsentType.factory()
+ obj_.build(child_)
+ self.set_AISConsent(obj_)
+ elif nodeName_ == 'TLPMarking':
+ obj_ = TLPMarkingType.factory()
+ obj_.build(child_)
+ self.set_TLPMarking(obj_)
+# end class IsProprietary
+
+
+class NotProprietary(GeneratedsSuper):
+ subclass = None
+ superclass = None
+
+ def __init__(self, CISA_Proprietary=None, AISConsent=None, TLPMarking=None):
+ self.CISA_Proprietary = _cast(bool, CISA_Proprietary)
+ self.AISConsent = AISConsent
+ self.TLPMarking = TLPMarking
+
+ def factory(*args_, **kwargs_):
+ if NotProprietary.subclass:
+ return NotProprietary.subclass(*args_, **kwargs_)
+ else:
+ return NotProprietary(*args_, **kwargs_)
+ factory = staticmethod(factory)
+
+ def get_AISConsent(self):
+ return self.AISConsent
+
+ def set_AISConsent(self, AISConsent):
+ self.AISConsent = AISConsent
+
+ def get_TLPMarking(self):
+ return self.TLPMarking
+
+ def set_TLPMarking(self, TLPMarking):
+ self.TLPMarking = TLPMarking
+
+ def get_CISA_Proprietary(self):
+ return self.CISA_Proprietary
+
+ def set_CISA_Proprietary(self, CISA_Proprietary):
+ self.CISA_Proprietary = CISA_Proprietary
+
+ def hasContent_(self):
+ if (
+ self.AISConsent is not None or
+ self.TLPMarking is not None
+ ):
+ return True
+ else:
+ return False
+
+ def export(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NotProprietary', namespacedef_='', pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ showIndent(lwrite, level, pretty_print)
+ lwrite('<%s:%s%s' % (nsmap[namespace_], name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(lwrite, level, already_processed, namespace_, name_='NotProprietary')
+ if self.hasContent_():
+ lwrite('>%s' % (eol_, ))
+ self.exportChildren(lwrite, level + 1, nsmap, XML_NS, name_, pretty_print=pretty_print)
+ showIndent(lwrite, level, pretty_print)
+ lwrite('%s:%s>%s' % (nsmap[namespace_], name_, eol_))
+ else:
+ lwrite('/>%s' % (eol_, ))
+
+ def exportAttributes(self, lwrite, level, already_processed, namespace_=XML_NS, name_='NotProprietary'):
+ if self.CISA_Proprietary is not None and 'CISA_Proprietary' not in already_processed:
+ already_processed.add('CISA_Proprietary')
+ lwrite(' CISA_Proprietary="%s"' % self.gds_format_boolean(self.CISA_Proprietary, input_name='CISA_Proprietary'))
+
+ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NotProprietary', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.AISConsent is not None:
+ self.AISConsent.export(lwrite, level, nsmap, namespace_, name_='AISConsent', pretty_print=pretty_print)
+ if self.TLPMarking is not None:
+ self.TLPMarking.export(lwrite, level, nsmap, namespace_, name_='TLPMarking', pretty_print=pretty_print)
+
+ def build(self, node):
+ self.__sourcenode__ = node
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+
+ def buildAttributes(self, node, attrs, already_processed):
+ value = find_attr_value_('CISA_Proprietary', node)
+ if value is not None and 'CISA_Proprietary' not in already_processed:
+ already_processed.add('CISA_Proprietary')
+ if value in ('true', '1'):
+ self.CISA_Proprietary = True
+ elif value in ('false', '0'):
+ self.CISA_Proprietary = False
+ else:
+ raise_parse_error(node, 'Bad boolean attribute')
+
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'AISConsent':
+ obj_ = AISConsentType.factory()
+ obj_.build(child_)
+ self.set_AISConsent(obj_)
+ elif nodeName_ == 'TLPMarking':
+ obj_ = TLPMarkingType.factory()
+ obj_.build(child_)
+ self.set_TLPMarking(obj_)
+# end class NotProprietary
+
+
+class AISConsentType(GeneratedsSuper):
+ subclass = None
+ superclass = None
+
+ def __init__(self, consent=None):
+ self.consent = _cast(None, consent)
+ pass
+
+ def factory(*args_, **kwargs_):
+ if AISConsentType.subclass:
+ return AISConsentType.subclass(*args_, **kwargs_)
+ else:
+ return AISConsentType(*args_, **kwargs_)
+ factory = staticmethod(factory)
+
+ def get_consent(self):
+ return self.consent
+
+ def set_consent(self, consent):
+ self.consent = consent
+
+ def hasContent_(self):
+ if (
+
+ ):
+ return True
+ else:
+ return False
+
+ def export(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AISConsentType', namespacedef_='', pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ showIndent(lwrite, level, pretty_print)
+ lwrite('<%s:%s%s' % (nsmap[namespace_], name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(lwrite, level, already_processed, namespace_, name_='AISConsentType')
+ if self.hasContent_():
+ lwrite('>%s' % (eol_, ))
+ self.exportChildren(lwrite, level + 1, nsmap, XML_NS, name_, pretty_print=pretty_print)
+ lwrite('%s:%s>%s' % (nsmap[namespace_], name_, eol_))
+ else:
+ lwrite('/>%s' % (eol_, ))
+
+ def exportAttributes(self, lwrite, level, already_processed, namespace_=XML_NS, name_='AISConsentType'):
+ if self.consent is not None and 'consent' not in already_processed:
+ already_processed.add('consent')
+ lwrite(' consent=%s' % (quote_attrib(self.consent), ))
+
+ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AISConsentType', fromsubclass_=False, pretty_print=True):
+ pass
+
+ def build(self, node):
+ self.__sourcenode__ = node
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+
+ def buildAttributes(self, node, attrs, already_processed):
+ value = find_attr_value_('consent', node)
+ if value is not None and 'consent' not in already_processed:
+ already_processed.add('consent')
+ self.consent = value
+
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ pass
+# end class AISConsentType
+
+
+class TLPMarkingType(GeneratedsSuper):
+ subclass = None
+ superclass = None
+
+ def __init__(self, color=None):
+ self.color = _cast(None, color)
+ pass
+
+ def factory(*args_, **kwargs_):
+ if TLPMarkingType.subclass:
+ return TLPMarkingType.subclass(*args_, **kwargs_)
+ else:
+ return TLPMarkingType(*args_, **kwargs_)
+ factory = staticmethod(factory)
+
+ def get_color(self):
+ return self.color
+
+ def set_color(self, color):
+ self.color = color
+
+ def hasContent_(self):
+ if (
+
+ ):
+ return True
+ else:
+ return False
+
+ def export(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TLPMarkingType', namespacedef_='', pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ showIndent(lwrite, level, pretty_print)
+ lwrite('<%s:%s%s' % (nsmap[namespace_], name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(lwrite, level, already_processed, namespace_, name_='TLPMarkingType')
+ if self.hasContent_():
+ lwrite('>%s' % (eol_, ))
+ self.exportChildren(lwrite, level + 1, nsmap, XML_NS, name_, pretty_print=pretty_print)
+ lwrite('%s:%s>%s' % (nsmap[namespace_], name_, eol_))
+ else:
+ lwrite('/>%s' % (eol_, ))
+
+ def exportAttributes(self, lwrite, level, already_processed, namespace_=XML_NS, name_='TLPMarkingType'):
+ if self.color is not None and 'color' not in already_processed:
+ already_processed.add('color')
+ lwrite(' color=%s' % (quote_attrib(self.color), ))
+
+ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TLPMarkingType', fromsubclass_=False, pretty_print=True):
+ pass
+
+ def build(self, node):
+ self.__sourcenode__ = node
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+
+ def buildAttributes(self, node, attrs, already_processed):
+ value = find_attr_value_('color', node)
+ if value is not None and 'color' not in already_processed:
+ already_processed.add('color')
+ self.color = value
+
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ pass
+# end class TLPMarkingType
+
+GDSClassesMapping = {}
+
+USAGE_TEXT = """
+Usage: python .py [ -s ]
+"""
+
+
+def usage():
+ print(USAGE_TEXT)
+ sys.exit(1)
+
+
+def get_root_tag(node):
+ tag = Tag_pattern_.match(node.tag).groups()[-1]
+ rootClass = GDSClassesMapping.get(tag)
+ if rootClass is None:
+ rootClass = globals().get(tag)
+ return tag, rootClass
+
+
+def parse(inFileName):
+ doc = parsexml_(inFileName)
+ rootNode = doc.getroot()
+ rootTag, rootClass = get_root_tag(rootNode)
+ if rootClass is None:
+ rootTag = 'AISMarkingStructure'
+ rootClass = AISMarkingStructure
+ rootObj = rootClass.factory()
+ rootObj.build(rootNode)
+ # Enable Python to collect the space used by the DOM.
+ doc = None
+ # sys.stdout.write('\n')
+ # rootObj.export(sys.stdout, 0, name_=rootTag,
+ # namespacedef_='',
+ # pretty_print=True)
+ return rootObj
+
+
+def parseEtree(inFileName):
+ doc = parsexml_(inFileName)
+ rootNode = doc.getroot()
+ rootTag, rootClass = get_root_tag(rootNode)
+ if rootClass is None:
+ rootTag = 'AISMarkingStructure'
+ rootClass = AISMarkingStructure
+ rootObj = rootClass.factory()
+ rootObj.build(rootNode)
+ # Enable Python to collect the space used by the DOM.
+ doc = None
+ rootElement = rootObj.to_etree(None, name_=rootTag)
+ content = etree_.tostring(rootElement, pretty_print=True,
+ xml_declaration=True, encoding="utf-8")
+ sys.stdout.write(content)
+ sys.stdout.write('\n')
+ return rootObj, rootElement
+
+
+def parseString(inString):
+ from mixbox.vendor.six import StringIO
+ doc = parsexml_(StringIO(inString))
+ rootNode = doc.getroot()
+ rootTag, rootClass = get_root_tag(rootNode)
+ if rootClass is None:
+ rootTag = 'AISMarkingStructure'
+ rootClass = AISMarkingStructure
+ rootObj = rootClass.factory()
+ rootObj.build(rootNode)
+ # Enable Python to collect the space used by the DOM.
+ doc = None
+ # sys.stdout.write('\n')
+ # rootObj.export(sys.stdout, 0, name_="AISHandling",
+ # namespacedef_='')
+ return rootObj
+
+
+def main():
+ args = sys.argv[1:]
+ if len(args) == 1:
+ parse(args[0])
+ else:
+ usage()
+
+if __name__ == '__main__':
+ #import pdb; pdb.set_trace()
+ main()
+
+__all__ = [
+ "NotProprietary",
+ "IsProprietary"
+ "AISConsentType",
+ "AISMarkingStructure"
+ "TLPMarkingType"
+ ]
diff --git a/stix/bindings/extensions/marking/simple_marking.py b/stix/bindings/extensions/marking/simple_marking.py
index 54f43f17..61671ac5 100644
--- a/stix/bindings/extensions/marking/simple_marking.py
+++ b/stix/bindings/extensions/marking/simple_marking.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.data_marking as data_marking_binding
XML_NS = "http://data-marking.mitre.org/extensions/MarkingStructure#Simple-1"
@@ -18,6 +21,8 @@
# Data representation classes.
#
+
+@register_extension
class SimpleMarkingStructureType(data_marking_binding.MarkingStructureType):
"""The SimpleMarkingStructureType is a basic implementation of the data
marking schema that allows for a string statement to be
@@ -28,6 +33,7 @@ class SimpleMarkingStructureType(data_marking_binding.MarkingStructureType):
xmlns = XML_NS
xmlns_prefix = "simpleMarking"
xml_type = "SimpleMarkingStructureType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
subclass = None
superclass = data_marking_binding.MarkingStructureType
@@ -86,6 +92,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='SimpleM
showIndent(lwrite, level, pretty_print)
lwrite('<%s:Statement>%s%s:Statement>%s' % (nsmap[namespace_], quote_xml(self.Statement), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -101,7 +108,6 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(SimpleMarkingStructureType, self).buildChildren(child_, node, nodeName_, True)
# end class SimpleMarkingStructureType
-data_marking_binding.add_extension(SimpleMarkingStructureType)
GDSClassesMapping = {}
@@ -110,7 +116,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -156,7 +162,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/marking/terms_of_use_marking.py b/stix/bindings/extensions/marking/terms_of_use_marking.py
index 46c8d5e6..f3152e78 100644
--- a/stix/bindings/extensions/marking/terms_of_use_marking.py
+++ b/stix/bindings/extensions/marking/terms_of_use_marking.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.data_marking as data_marking_binding
XML_NS = "http://data-marking.mitre.org/extensions/MarkingStructure#Terms_Of_Use-1"
@@ -18,6 +21,7 @@
# Data representation classes.
#
+@register_extension
class TermsOfUseMarkingStructureType(data_marking_binding.MarkingStructureType):
"""The TermsOfUseMarkingStructureType is a basic implementation of the
data marking schema that allows for a string statement
@@ -36,6 +40,7 @@ class TermsOfUseMarkingStructureType(data_marking_binding.MarkingStructureType):
xmlns = XML_NS
xmlns_prefix = "TOUMarking"
xml_type = "TermsOfUseMarkingStructureType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
def __init__(self, idref=None, marking_model_ref=None, marking_model_name=None, id=None, Terms_Of_Use=None):
super(TermsOfUseMarkingStructureType, self).__init__(idref=idref, marking_model_ref=marking_model_ref, marking_model_name=marking_model_name, id=id)
@@ -89,6 +94,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TermsOf
showIndent(lwrite, level, pretty_print)
lwrite('<%s:Terms_Of_Use>%s%s:Terms_Of_Use>%s' % (nsmap[namespace_], quote_xml(self.Terms_Of_Use), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -104,8 +110,6 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(TermsOfUseMarkingStructureType, self).buildChildren(child_, node, nodeName_, True)
# end class TermsOfUseMarkingStructureType
-data_marking_binding.add_extension(TermsOfUseMarkingStructureType)
-
GDSClassesMapping = {}
USAGE_TEXT = """
@@ -113,7 +117,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -159,7 +163,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/marking/tlp.py b/stix/bindings/extensions/marking/tlp.py
index bf71fbba..83a68e1d 100644
--- a/stix/bindings/extensions/marking/tlp.py
+++ b/stix/bindings/extensions/marking/tlp.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.data_marking as data_marking_binding
XML_NS = "http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1"
@@ -18,6 +21,7 @@
# Data representation classes.
#
+@register_extension
class TLPMarkingStructureType(data_marking_binding.MarkingStructureType):
"""The TLPMarkingStructureType is an implementation of the data marking
schema that allows for a TLP Designation to be attached to an
@@ -29,6 +33,7 @@ class TLPMarkingStructureType(data_marking_binding.MarkingStructureType):
xmlns = XML_NS
xmlns_prefix = "tlpMarking"
xml_type = "TLPMarkingStructureType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
subclass = None
superclass = data_marking_binding.MarkingStructureType
@@ -83,6 +88,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TLPMark
super(TLPMarkingStructureType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -99,7 +105,6 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
# end class TLPMarkingStructureType
-data_marking_binding.add_extension(TLPMarkingStructureType)
GDSClassesMapping = {}
@@ -108,7 +113,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -154,7 +159,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/structured_coa/generic.py b/stix/bindings/extensions/structured_coa/generic.py
index a7cd6b87..73991c69 100644
--- a/stix/bindings/extensions/structured_coa/generic.py
+++ b/stix/bindings/extensions/structured_coa/generic.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
from stix.bindings.course_of_action import StructuredCOAType
import stix.bindings.stix_common as stix_common_binding
@@ -19,6 +22,8 @@
# Data representation classes.
#
+
+@register_extension
class GenericStructuredCOAType(StructuredCOAType):
"""The GenericStructuredCOAType specifies an instantial extension from
the abstract course_of_action_binding.StructuredCOAType intended to support the generic
@@ -26,11 +31,14 @@ class GenericStructuredCOAType(StructuredCOAType):
location of the Generic Structured COA."""
subclass = None
superclass = StructuredCOAType
+
+ xmlns = XML_NS
+ xmlns_prefix = "genericStructuredCOA"
+ xml_type = "GenericStructuredCOAType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, reference_location=None, Description=None, Type=None, Specification=None):
super(GenericStructuredCOAType, self).__init__(idref=idref, id=id)
- self.xmlns = XML_NS
- self.xmlns_prefix = "genericStructuredCOA"
- self.xml_type = "GenericStructuredCOAType"
self.reference_location = _cast(None, reference_location)
self.Description = Description
self.Type = Type
@@ -101,6 +109,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Generic
if self.Specification is not None:
self.Specification.export(lwrite, level, nsmap, namespace_, name_='Specification', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -135,7 +144,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -164,7 +173,7 @@ def parse(inFileName):
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/test_mechanism/generic.py b/stix/bindings/extensions/test_mechanism/generic.py
index 8afd5efd..5a40d9a9 100644
--- a/stix/bindings/extensions/test_mechanism/generic.py
+++ b/stix/bindings/extensions/test_mechanism/generic.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.indicator as indicator_binding
import stix.bindings.stix_common as stix_common_binding
@@ -19,6 +22,7 @@
# Data representation classes.
#
+@register_extension
class GenericTestMechanismType(indicator_binding.TestMechanismType):
"""The GenericTestMechanismType specifies an instantial extension from
the abstract indicator_binding.TestMechanismType intended to support the generic
@@ -26,11 +30,15 @@ class GenericTestMechanismType(indicator_binding.TestMechanismType):
URL for the location of the Generic Test Mechanism."""
subclass = None
superclass = indicator_binding.TestMechanismType
+
+ xmlns = XML_NS
+ xmlns_prefix = "genericTM"
+ xml_type = "GenericTestMechanismType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
+
def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, reference_location=None, Description=None, Type=None, Specification=None):
super(GenericTestMechanismType, self).__init__(idref=idref, id=id, Efficacy=Efficacy, Producer=Producer)
- self.xmlns = XML_NS
- self.xmlns_prefix = "genericTM"
- self.xml_type = "GenericTestMechanismType"
self.reference_location = _cast(None, reference_location)
self.Description = Description
self.Type = Type
@@ -81,10 +89,10 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='generic
# already_processed.add('xmlns')
# xmlns = " xmlns:%s='%s'" % (self.xmlns_prefix, self.xmlns)
# lwrite(xmlns)
- # if 'xsi:type' not in already_processed:
- # already_processed.add('xsi:type')
- # xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
- # lwrite(xsi_type)
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
if self.reference_location is not None and 'reference_location' not in already_processed:
already_processed.add('reference_location')
lwrite(' reference_location=%s' % (quote_attrib(self.reference_location), ))
@@ -101,6 +109,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Generic
if self.Specification is not None:
self.Specification.export(lwrite, level, nsmap, namespace_, name_='Specification', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -135,7 +144,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -181,7 +190,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/test_mechanism/open_ioc_2010.py b/stix/bindings/extensions/test_mechanism/open_ioc_2010.py
index 42339cb6..88dec64d 100644
--- a/stix/bindings/extensions/test_mechanism/open_ioc_2010.py
+++ b/stix/bindings/extensions/test_mechanism/open_ioc_2010.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.indicator as indicator_binding
XML_NS = "http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1"
@@ -18,6 +21,7 @@
# Data representation classes.
#
+@register_extension
class OpenIOC2010TestMechanismType(indicator_binding.TestMechanismType):
"""The OpenIOC2010TestMechanismType provides an extension to the
indicator_binding.TestMechanismType which imports and leverages the 2010 Open IOC
@@ -25,11 +29,14 @@ class OpenIOC2010TestMechanismType(indicator_binding.TestMechanismType):
mechanism."""
subclass = None
superclass = indicator_binding.TestMechanismType
+
+ xmlns = XML_NS
+ xmlns_prefix = "stix-openioc"
+ xml_type = "OpenIOC2010TestMechanismType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, ioc=None):
super(OpenIOC2010TestMechanismType, self).__init__(idref=idref, id=id, Efficacy=Efficacy, Producer=Producer)
- self.xmlns = XML_NS
- self.xmlns_prefix = "stix-openioc"
- self.xml_type = "OpenIOC2010TestMechanismType"
self.ioc = ioc
def factory(*args_, **kwargs_):
if OpenIOC2010TestMechanismType.subclass:
@@ -69,10 +76,10 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='', name
# already_processed.add('xmlns')
# xmlns = " xmlns:%s='%s'" % (self.xmlns_prefix, self.xmlns)
# lwrite(xmlns)
- # if 'xsi:type' not in already_processed:
- # already_processed.add('xsi:type')
- # xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
- # lwrite(xsi_type)
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='OpenIOC2010TestMechanismType', fromsubclass_=False, pretty_print=True):
super(OpenIOC2010TestMechanismType, self).exportChildren(lwrite, level, nsmap, indicator_binding.XML_NS, name_, True, pretty_print=pretty_print)
if pretty_print:
@@ -81,9 +88,10 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='OpenIOC
eol_ = ''
if self.ioc is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.ioc, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.ioc, pretty_print=pretty_print).decode())
#self.ioc.export(lwrite, level, nsmap, namespace_, name_='ioc', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -104,7 +112,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -150,7 +158,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/test_mechanism/oval_5_10.py b/stix/bindings/extensions/test_mechanism/oval_5_10.py
index 6e5aba15..2ce06695 100644
--- a/stix/bindings/extensions/test_mechanism/oval_5_10.py
+++ b/stix/bindings/extensions/test_mechanism/oval_5_10.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.indicator as indicator_binding
XML_NS = "http://stix.mitre.org/extensions/TestMechanism#OVAL5.10-1"
@@ -18,17 +21,22 @@
# Data representation classes.
#
+
+@register_extension
class OVAL5_10TestMechanismType(indicator_binding.TestMechanismType):
"""The OVALTestMechanismType provides an extension to the
indicator_binding.TestMechanismType which imports and leverages the OVAL schema in
order to include OVAL Definitions as the test mechanism."""
subclass = None
superclass = indicator_binding.TestMechanismType
+
+ xmlns = XML_NS
+ xmlns_prefix = "ovalTM"
+ xml_type = "OVAL5.10TestMechanismType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, oval_definitions=None, oval_variables=None):
super(OVAL5_10TestMechanismType, self).__init__(idref=idref, id=id, Efficacy=Efficacy, Producer=Producer)
- self.xmlns = XML_NS
- self.xmlns_prefix = "ovalTM"
- self.xml_type = "OVAL5.10TestMechanismType"
self.oval_definitions = oval_definitions
self.oval_variables = oval_variables
def factory(*args_, **kwargs_):
@@ -72,10 +80,10 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='', name
# already_processed.add('xmlns')
# xmlns = " xmlns:%s='%s'" % (self.xmlns_prefix, self.xmlns)
# lwrite(xmlns)
- # if 'xsi:type' not in already_processed:
- # already_processed.add('xsi:type')
- # xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
- # lwrite(xsi_type)
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='OVAL5.10TestMechanismType', fromsubclass_=False, pretty_print=True):
super(OVAL5_10TestMechanismType, self).exportChildren(lwrite, level, nsmap, indicator_binding.XML_NS, name_, True, pretty_print=pretty_print)
if pretty_print:
@@ -84,13 +92,14 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='OVAL5.1
eol_ = ''
if self.oval_definitions is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.oval_definitions, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.oval_definitions, pretty_print=pretty_print).decode())
#self.oval_definitions.export(lwrite, level, nsmap, namespace_, name_='oval_definitions', pretty_print=pretty_print)
if self.oval_variables is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.oval_variables, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.oval_variables, pretty_print=pretty_print).decode())
#self.oval_variables.export(lwrite, level, nsmap, namespace_, name_='oval_variables', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -113,7 +122,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -159,7 +168,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/test_mechanism/snort.py b/stix/bindings/extensions/test_mechanism/snort.py
index 84a384a0..27f72d5a 100644
--- a/stix/bindings/extensions/test_mechanism/snort.py
+++ b/stix/bindings/extensions/test_mechanism/snort.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.indicator as indicator_binding
import stix.bindings.stix_common as stix_common_binding
@@ -19,17 +22,21 @@
# Data representation classes.
#
+@register_extension
class SnortTestMechanismType(indicator_binding.TestMechanismType):
"""The SnortTestMechanismType specifies an instantial extension from
the abstract TestMechanismType intended to support the inclusion
of a Snort rule as a test mechanism content."""
subclass = None
superclass = indicator_binding.TestMechanismType
+
+ xmlns = XML_NS
+ xmlns_prefix = "snortTM"
+ xml_type = "SnortTestMechanismType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, Product_Name=None, Version=None, Rule=None, Event_Filter=None, Rate_Filter=None, Event_Suppression=None):
super(SnortTestMechanismType, self).__init__(idref=idref, id=id, Efficacy=Efficacy, Producer=Producer)
- self.xmlns = XML_NS
- self.xmlns_prefix = "snortTM"
- self.xml_type = "SnortTestMechanismType"
self.Product_Name = Product_Name
self.Version = Version
if Rule is None:
@@ -109,10 +116,10 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='snortTM
# already_processed.add('xmlns')
# xmlns = " xmlns:%s='%s'" % (self.xmlns_prefix, self.xmlns)
# lwrite(xmlns)
- # if 'xsi:type' not in already_processed:
- # already_processed.add('xsi:type')
- # xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
- # lwrite(xsi_type)
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='SnortTestMechanismType', fromsubclass_=False, pretty_print=True):
super(SnortTestMechanismType, self).exportChildren(lwrite, level, nsmap, indicator_binding.XML_NS, name_, True, pretty_print=pretty_print)
if pretty_print:
@@ -134,6 +141,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='SnortTe
for Event_Suppression_ in self.Event_Suppression:
Event_Suppression_.export(lwrite, level, nsmap, namespace_, name_='Event_Suppression', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -179,7 +187,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -225,7 +233,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/test_mechanism/yara.py b/stix/bindings/extensions/test_mechanism/yara.py
index 3bacf92d..2e132b3b 100644
--- a/stix/bindings/extensions/test_mechanism/yara.py
+++ b/stix/bindings/extensions/test_mechanism/yara.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.indicator as indicator_binding
import stix.bindings.stix_common as stix_common_binding
@@ -19,17 +22,21 @@
# Data representation classes.
#
+@register_extension
class YaraTestMechanismType(indicator_binding.TestMechanismType):
"""The YaraTestMechanismType specifies an instantial extension from the
abstract indicator_binding.TestMechanismType intended to support the inclusion of
a YARA rule as a test mechanism content."""
subclass = None
superclass = indicator_binding.TestMechanismType
+
+ xmlns = XML_NS
+ xmlns_prefix = "yaraTM"
+ xml_type = "YaraTestMechanismType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, Version=None, Rule=None):
super(YaraTestMechanismType, self).__init__(idref=idref, id=id, Efficacy=Efficacy, Producer=Producer)
- self.xmlns = XML_NS
- self.xmlns_prefix = "yaraTM"
- self.xml_type = "YaraTestMechanismType"
self.Version = Version
self.Rule = Rule
def factory(*args_, **kwargs_):
@@ -73,10 +80,10 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='yaraTM:
# already_processed.add('xmlns')
# xmlns = " xmlns:%s='%s'" % (self.xmlns_prefix, self.xmlns)
# lwrite(xmlns)
- # if 'xsi:type' not in already_processed:
- # already_processed.add('xsi:type')
- # xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
- # lwrite(xsi_type)
+ if 'xsi:type' not in already_processed:
+ already_processed.add('xsi:type')
+ xsi_type = " xsi:type='%s:%s'" % (self.xmlns_prefix, self.xml_type)
+ lwrite(xsi_type)
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='YaraTestMechanismType', fromsubclass_=False, pretty_print=True):
super(YaraTestMechanismType, self).exportChildren(lwrite, level, nsmap, indicator_binding.XML_NS, name_, True, pretty_print=pretty_print)
if pretty_print:
@@ -89,6 +96,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='YaraTes
if self.Rule is not None:
self.Rule.export(lwrite, level, nsmap, namespace_, name_='Rule', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -115,7 +123,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -161,7 +169,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/extensions/vulnerability/cvrf_1_1.py b/stix/bindings/extensions/vulnerability/cvrf_1_1.py
index c7eed68e..7423a00a 100644
--- a/stix/bindings/extensions/vulnerability/cvrf_1_1.py
+++ b/stix/bindings/extensions/vulnerability/cvrf_1_1.py
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import register_extension
import stix.bindings.exploit_target as exploit_target_binding
XML_NS = "http://stix.mitre.org/extensions/Vulnerability#CVRF-1"
@@ -18,6 +21,7 @@
# Data representation classes.
#
+@register_extension
class CVRF1_1InstanceType(exploit_target_binding.VulnerabilityType):
"""The CVRF1.1InstanceType provides an extension to the
exploit_target_binding.VulnerabilityType which imports and leverages the CVRF schema
@@ -26,11 +30,14 @@ class CVRF1_1InstanceType(exploit_target_binding.VulnerabilityType):
do not have a CVE or OSVDB ID."""
subclass = None
superclass = exploit_target_binding.VulnerabilityType
+
+ xmlns = XML_NS
+ xmlns_prefix = "cvrfVuln"
+ xml_type = "CVRF1.1InstanceType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, Description=None, CVE_ID=None, OSVDB_ID=None, CVSS_Score=None, cvrfdoc=None):
super(CVRF1_1InstanceType, self).__init__(Description=Description, CVE_ID=CVE_ID, OSVDB_ID=OSVDB_ID, CVSS_Score=CVSS_Score)
- self.xmlns = XML_NS
- self.xmlns_prefix = "cvrfVuln"
- self.xml_type = "CVRF1.1InstanceType"
self.cvrfdoc = cvrfdoc
def factory(*args_, **kwargs_):
if CVRF1_1InstanceType.subclass:
@@ -82,9 +89,10 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CVRF1.1
eol_ = ''
if self.cvrfdoc is not None:
showIndent(lwrite, level, pretty_print)
- lwrite(etree_.tostring(self.cvrfdoc, pretty_print=pretty_print))
+ lwrite(etree_.tostring(self.cvrfdoc, pretty_print=pretty_print).decode())
#self.cvrfdoc.export(lwrite, level, nsmap, namespace_, name_='cvrfdoc', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -105,7 +113,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -151,7 +159,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/incident.py b/stix/bindings/incident.py
index 156067ff..b3c4052e 100644
--- a/stix/bindings/incident.py
+++ b/stix/bindings/incident.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -8,9 +8,12 @@
# Generated Thu Apr 11 15:06:24 2013 by generateDS.py version 2.9a.
#
import sys
-from stix.bindings import *
+
import cybox.bindings.cybox_core as cybox_core_binding
import cybox.bindings.cybox_common as cybox_common_binding
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -90,6 +93,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Propert
if self.Non_Public_Data_Compromised is not None:
self.Non_Public_Data_Compromised.export(lwrite, level, nsmap, namespace_, name_='Non_Public_Data_Compromised', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -214,6 +218,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Affecte
if self.Structured_Description is not None:
self.Structured_Description.export(lwrite, level, "%s:" % (nsmap[namespace_]), name_='Structured_Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -247,24 +252,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
obj_.build(child_)
self.set_Location_Class(obj_)
elif nodeName_ == 'Location':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CIQAddress3.0InstanceType":
- import stix.bindings.extensions.address.ciq_address_3_0 as ciq_address_binding
- obj_ = ciq_address_binding.CIQAddress3_0InstanceType.factory()
- else:
- raise NotImplementedError('No implementation class found for: ' + type_name_)
- else:
- raise NotImplementedError('Class not implemented for element')
-
+ from .extensions.address import ciq_address_3_0
+ obj_ = lookup_extension(child_).factory()
obj_.build(child_)
self.set_Location(obj_)
elif nodeName_ == 'Nature_Of_Security_Effect':
@@ -355,6 +344,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ImpactA
if self.External_Impact_Assessment_Model is not None:
self.External_Impact_Assessment_Model.export(lwrite, level, nsmap, namespace_, name_='External_Impact_Assessment_Model', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -457,6 +447,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='inciden
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ExternalImpactAssessmentModelType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -540,6 +531,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='COATake
if self.Course_Of_Action is not None:
self.Course_Of_Action.export(lwrite, level, nsmap, namespace_, name_='Course_Of_Action', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -560,24 +552,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
obj_.build(child_)
self.set_Contributors(obj_)
elif nodeName_ == 'Course_Of_Action':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CourseOfActionType":
- import stix.bindings.course_of_action as coa_binding
- obj_ = coa_binding.CourseOfActionType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.CourseOfActionBaseType.factory() # not abstract
-
+ from . import course_of_action
+ obj_ = lookup_extension(child_, stix_common_binding.CourseOfActionBaseType).factory()
obj_.build(child_)
self.set_Course_Of_Action(obj_)
# end class COATakenType
@@ -651,6 +627,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='inciden
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='JournalEntryType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -663,7 +640,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('time')
try:
self.time = self.gds_parse_datetime(value, node, 'time')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (time): %s' % exp)
value = find_attr_value_('time_precision', node)
if value is not None and 'time_precision' not in already_processed:
@@ -726,6 +703,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='inciden
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='COARequestedType', fromsubclass_=False, pretty_print=True):
super(COARequestedType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -793,6 +771,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Contrib
for Contributor_ in self.Contributor:
Contributor_.export(lwrite, level, "%s:" % (nsmap[namespace_]), name_='Contributor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -859,6 +838,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='COATime
if self.End is not None:
self.End.export(lwrite, level, nsmap, namespace_, name_='End', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -928,6 +908,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='inciden
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='LossEstimationType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -998,6 +979,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TotalLo
if self.Actual_Total_Loss_Estimation is not None:
self.Actual_Total_Loss_Estimation.export(lwrite, level, nsmap, namespace_, name_='Actual_Total_Loss_Estimation', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1080,6 +1062,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Indirec
if self.Legal_And_Regulatory_Costs is not None:
self.Legal_And_Regulatory_Costs.export(lwrite, level, nsmap, namespace_, name_='Legal_And_Regulatory_Costs', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1164,6 +1147,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='DirectI
if self.Response_And_Recovery_Costs is not None:
self.Response_And_Recovery_Costs.export(lwrite, level, nsmap, namespace_, name_='Response_And_Recovery_Costs', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1237,6 +1221,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NatureO
for Property_Affected_ in self.Property_Affected:
Property_Affected_.export(lwrite, level, nsmap, namespace_, name_='Property_Affected', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1303,6 +1288,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='History
if self.Journal_Entry is not None:
self.Journal_Entry.export(lwrite, level, nsmap, namespace_, name_='Journal_Entry', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1372,6 +1358,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='History
for History_Item_ in self.History_Item:
History_Item_.export(lwrite, level, nsmap, namespace_, name_='History_Item', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1437,6 +1424,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Affecte
for Affected_Asset_ in self.Affected_Asset:
Affected_Asset_.export(lwrite, level, nsmap, namespace_, name_='Affected_Asset', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1545,6 +1533,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TimeTyp
if self.Incident_Closed is not None:
self.Incident_Closed.export(lwrite, level, nsmap, namespace_, name_='Incident_Closed', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1644,6 +1633,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Categor
for Category_ in self.Category:
Category_.export(lwrite, level, nsmap, namespace_, name_='Category', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1711,6 +1701,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Effects
for Effect_ in self.Effect:
Effect_.export(lwrite, level, nsmap, namespace_, name_='Effect', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1781,6 +1772,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Attribu
for Threat_Actor_ in self.Threat_Actor:
Threat_Actor_.export(lwrite, level, nsmap, namespace_, name_='Threat_Actor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1850,6 +1842,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Indicator_ in self.Related_Indicator:
Related_Indicator_.export(lwrite, level, nsmap, namespace_, name_='Related_Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1919,6 +1912,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Observable_ in self.Related_Observable:
Related_Observable_.export(lwrite, level, nsmap, namespace_, name_='Related_Observable', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1988,6 +1982,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Leverag
for Leveraged_TTP_ in self.Leveraged_TTP:
Leveraged_TTP_.export(lwrite, level, nsmap, namespace_, name_='Leveraged_TTP', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2057,6 +2052,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Incident_ in self.Related_Incident:
Related_Incident_.export(lwrite, level, nsmap, namespace_, name_='Related_Incident', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2133,6 +2129,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AssetTy
super(AssetTypeType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -2149,6 +2146,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
# end class AssetTypeType
+
+@register_extension
class IncidentType(stix_common_binding.IncidentBaseType):
"""The IncidentType characterizes a single cyber threat
Incident.Specifies the relevant STIX-Incident schema version for
@@ -2156,11 +2155,14 @@ class IncidentType(stix_common_binding.IncidentBaseType):
Incident specification."""
subclass = None
superclass = stix_common_binding.IncidentBaseType
+
+ xmlns = "http://stix.mitre.org/Incident-1"
+ xmlns_prefix = "incident"
+ xml_type = "IncidentType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, URL=None, version=None, Title=None, External_ID=None, Time=None, Description=None, Short_Description=None, Categories=None, Reporter=None, Responder=None, Coordinator=None, Victim=None, Affected_Assets=None, Impact_Assessment=None, Status=None, Related_Indicators=None, Related_Observables=None, Leveraged_TTPs=None, Attributed_Threat_Actors=None, Intended_Effect=None, Security_Compromise=None, Discovery_Method=None, Related_Incidents=None, COA_Requested=None, COA_Taken=None, Confidence=None, Contact=None, History=None, Information_Source=None, Handling=None, Related_Packages=None):
super(IncidentType, self).__init__(timestamp=timestamp, idref=idref, id=id)
- self.xmlns = "http://stix.mitre.org/Incident-1"
- self.xmlns_prefix = "incident"
- self.xml_type = "IncidentType"
self.URL = _cast(None, URL)
self.version = _cast(None, version)
self.Title = Title
@@ -2439,6 +2441,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Inciden
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2492,21 +2495,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
obj_.build(child_)
self.Coordinator.append(obj_)
elif nodeName_ == 'Victim':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CIQIdentity3.0InstanceType":
- import stix.bindings.extensions.identity.ciq_identity_3_0 as ciq_identity_binding
- obj_ = ciq_identity_binding.CIQIdentity3_0InstanceType.factory()
- else:
- obj_ = stix_common_binding.IdentityType.factory() # IdentityType is not abstract
+ import stix.bindings.extensions.identity.ciq_identity_3_0 as ciq_identity_binding
+ obj_ = lookup_extension(child_, stix_common_binding.IdentityType).factory()
obj_.build(child_)
self.Victim.append(obj_)
elif nodeName_ == 'Affected_Assets':
@@ -2638,6 +2628,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NonPubl
super(NonPublicDataCompromisedType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2706,6 +2697,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='inciden
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ExternalIDType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -2729,7 +2721,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -2775,8 +2767,8 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
- doc = parsexml_(StringIO(inString))
+ from mixbox.vendor.six import BytesIO
+ doc = parsexml_(BytesIO(inString.encode('utf-8')))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
if rootClass is None:
diff --git a/stix/bindings/indicator.py b/stix/bindings/indicator.py
index 4bbedf65..e8b5a8af 100644
--- a/stix/bindings/indicator.py
+++ b/stix/bindings/indicator.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,8 +9,11 @@
#
import sys
-from stix.bindings import *
+
import cybox.bindings.cybox_core as cybox_core_binding
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -74,6 +77,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ValidTi
if self.End_Time is not None:
self.End_Time.export(lwrite, level, nsmap, namespace_, name_='End_Time', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -152,6 +156,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Composi
for Indicator_ in self.Indicator:
Indicator_.export(lwrite, level, nsmap, namespace_, name_='Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -220,12 +225,12 @@ class TestMechanismType(GeneratedsSuper):
reference to the ID of a Test Mechanism specified elsewhere."""
subclass = None
superclass = None
- def __init__(self, idref=None, id=None, Efficacy=None, Producer=None, xsi_type=None):
+ def __init__(self, idref=None, id=None, Efficacy=None, Producer=None):
self.idref = _cast(None, idref)
self.id = _cast(None, id)
self.Efficacy = Efficacy
self.Producer = Producer
- self.xsi_type = xsi_type
+ # self.xsi_type = xsi_type
def factory(*args_, **kwargs_):
if TestMechanismType.subclass:
return TestMechanismType.subclass(*args_, **kwargs_)
@@ -273,9 +278,9 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='indicat
if self.id is not None and 'id' not in already_processed:
already_processed.add('id')
lwrite(' id=%s' % (quote_attrib(self.id), ))
- if self.xsi_type is not None and 'xsi:type' not in already_processed:
- already_processed.add('xsi:type')
- lwrite(' xsi:type="%s"' % self.xsi_type)
+ # if self.xsi_type is not None and 'xsi:type' not in already_processed:
+ # already_processed.add('xsi:type')
+ # lwrite(' xsi:type="%s"' % self.xsi_type)
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TestMechanismType', fromsubclass_=False, pretty_print=True):
if pretty_print:
@@ -287,6 +292,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TestMec
if self.Producer is not None:
self.Producer.export(lwrite, level, nsmap, namespace_, name_='Producer', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -375,6 +381,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Sightin
for Sighting_ in self.Sighting:
Sighting_.export(lwrite, level, nsmap, namespace_, name_='Sighting', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -386,7 +393,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('sightings_count')
try:
self.sightings_count = int(value)
- except ValueError, exp:
+ except ValueError as exp:
raise_parse_error(node, 'Bad integer attribute: %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Sighting':
@@ -486,6 +493,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Sightin
if self.Related_Observables is not None:
self.Related_Observables.export(lwrite, level, nsmap, namespace_, name_='Related_Observables', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -497,7 +505,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
value = find_attr_value_('timestamp_precision', node)
if value is not None and 'timestamp_precision' not in already_processed:
@@ -582,6 +590,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Observable_ in self.Related_Observable:
Related_Observable_.export(lwrite, level, nsmap, namespace_, name_='Related_Observable', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -648,6 +657,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TestMec
for Test_Mechanism_ in self.get_Test_Mechanism():
Test_Mechanism_.export(lwrite, level, nsmap, namespace_, name_='Test_Mechanism', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -657,37 +667,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Test_Mechanism':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "OVAL5.10TestMechanismType":
- import stix.bindings.extensions.test_mechanism.oval_5_10 as oval_5_10_tm_binding
- obj_ = oval_5_10_tm_binding.OVAL5_10TestMechanismType.factory()
- elif type_name_ == "YaraTestMechanismType":
- import stix.bindings.extensions.test_mechanism.yara as yara_tm_binding
- obj_ = yara_tm_binding.YaraTestMechanismType.factory()
- elif type_name_ == "SnortTestMechanismType":
- import stix.bindings.extensions.test_mechanism.snort as snort_tm_binding
- obj_ = snort_tm_binding.SnortTestMechanismType.factory()
- elif type_name_ == "OpenIOC2010TestMechanismType":
- import stix.bindings.extensions.test_mechanism.open_ioc_2010 as openioc_tm_binding
- obj_ = openioc_tm_binding.OpenIOC2010TestMechanismType.factory()
- elif type_name_ == "GenericTestMechanismType":
- import stix.bindings.extensions.test_mechanism.generic as generic_tm_binding
- obj_ = generic_tm_binding.GenericTestMechanismType.factory()
- else:
- raise NotImplementedError('Class not implemented for element: ' + type_name_)
- else:
- raise NotImplementedError(
- 'Class not implemented for element: no xsi:type attribute found')
-
+ from .extensions.test_mechanism import (generic, oval_5_10, open_ioc_2010, snort, yara)
+ obj_ = lookup_extension(child_).factory()
obj_.build(child_)
self.Test_Mechanism.append(obj_)
# end class TestMechanismsType
@@ -746,6 +727,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Suggest
for Suggested_COA_ in self.Suggested_COA:
Suggested_COA_.export(lwrite, level, nsmap, namespace_, name_='Suggested_COA', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -815,6 +797,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Indicator_ in self.Related_Indicator:
Related_Indicator_.export(lwrite, level, nsmap, namespace_, name_='Related_Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -830,6 +813,8 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(RelatedIndicatorsType, self).buildChildren(child_, node, nodeName_, True)
# end class RelatedIndicatorsType
+
+@register_extension
class IndicatorType(stix_common_binding.IndicatorBaseType):
"""The IndicatorType characterizes a cyber threat indicator made up of
a pattern identifying certain observable conditions as well as
@@ -842,11 +827,14 @@ class IndicatorType(stix_common_binding.IndicatorBaseType):
specifies the absence of the pattern."""
subclass = None
superclass = stix_common_binding.IndicatorBaseType
+
+ xmlns = XML_NS
+ xmlns_prefix = "indicator"
+ xml_type = "IndicatorType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, negate=False, version=None, Title=None, Type=None, Alternative_ID=None, Description=None, Short_Description=None, Valid_Time_Position=None, Observable=None, Composite_Indicator_Expression=None, Indicated_TTP=None, Kill_Chain_Phases=None, Test_Mechanisms=None, Likely_Impact=None, Suggested_COAs=None, Handling=None, Confidence=None, Sightings=None, Related_Indicators=None, Related_Campaigns=None, Related_Packages=None, Producer=None):
super(IndicatorType, self).__init__(idref=idref, id=id, timestamp=timestamp)
- self.xmlns = "http://stix.mitre.org/Indicator-2"
- self.xmlns_prefix = "indicator"
- self.xml_type = "IndicatorType"
self.negate = _cast(bool, negate)
self.version = _cast(None, version)
@@ -1048,6 +1036,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Indicat
if self.Producer is not None:
self.Producer.export(lwrite, level, nsmap, namespace_, name_='Producer', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1205,6 +1194,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Campaign_ in self.Related_Campaign:
Related_Campaign_.export(lwrite, level, nsmap, namespace_, name_='Related_Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1228,7 +1218,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -1274,7 +1264,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/stix_common.py b/stix/bindings/stix_common.py
index b0c813ec..64805856 100644
--- a/stix/bindings/stix_common.py
+++ b/stix/bindings/stix_common.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,10 +9,12 @@
#
import sys
-from stix.bindings import *
+from mixbox.binding_utils import *
import cybox.bindings.cybox_common as cybox_common_binding
import cybox.bindings.cybox_core as cybox_core_binding
+from stix.bindings import get_type_info, lookup_extension
+
XML_NS = "http://stix.mitre.org/common-1"
#
@@ -87,6 +89,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Generic
if self.Relationship is not None:
self.Relationship.export(lwrite, level, nsmap, namespace_, name_='Relationship', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -170,6 +173,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='DateTimeWithPrecisionType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -238,6 +242,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Profile
showIndent(lwrite, level, pretty_print)
lwrite('<%s:Profile>%s%s:Profile>%s' % (nsmap[namespace_],quote_xml(Profile_), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -313,6 +318,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='RelatedPackageRefType', fromsubclass_=False, pretty_print=True):
super(RelatedPackageRefType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -328,7 +334,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
super(RelatedPackageRefType, self).buildAttributes(node, attrs, already_processed)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
@@ -390,6 +396,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Package_Reference_ in self.Package_Reference:
Package_Reference_.export(lwrite, level, nsmap, namespace_, name_='Package_Reference', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -473,6 +480,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ToolInf
if self.Short_Description is not None:
self.Short_Description.export(lwrite, level, nsmap, namespace_, name_='Short_Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -584,6 +592,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Informa
if self.References is not None:
self.References.export(lwrite, level, nsmap, namespace_, name_='References', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -597,22 +606,12 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
obj_.build(child_)
self.set_Description(obj_)
elif nodeName_ == 'Identity':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
- if type_name_ == "CIQIdentity3.0InstanceType":
- import stix.bindings.extensions.identity.ciq_identity_3_0 as ciq_identity_binding
- obj_ = ciq_identity_binding.CIQIdentity3_0InstanceType.factory()
- else:
- obj_ = IdentityType.factory() # IdentityType is not abstract
+ from stix.bindings.extensions.identity import ciq_identity_3_0
+ # Look for xsi:type. If not there, build an instance of
+ # IdentityType
+ obj_ = lookup_extension(child_, IdentityType).factory()
obj_.build(child_)
self.set_Identity(obj_)
elif nodeName_ == 'Role':
@@ -714,6 +713,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Confide
if self.Confidence_Assertion_Chain is not None:
self.Confidence_Assertion_Chain.export(lwrite, level, nsmap, namespace_, name_='Confidence_Assertion_Chain', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -725,7 +725,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
value = find_attr_value_('timestamp_precision', node)
@@ -803,6 +803,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Activit
if self.Description is not None:
self.Description.export(lwrite, level, nsmap, namespace_, name_='Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -872,6 +873,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='KillCha
for Kill_Chain_ in self.Kill_Chain:
Kill_Chain_.export(lwrite, level, nsmap, namespace_, name_='Kill_Chain', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -973,6 +975,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='KillCha
for Kill_Chain_Phase_ in self.Kill_Chain_Phase:
Kill_Chain_Phase_.export(lwrite, level, nsmap, namespace_, name_='Kill_Chain_Phase', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1073,6 +1076,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='KillChainPhaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1084,7 +1088,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('ordinality')
try:
self.ordinality = int(value)
- except ValueError, exp:
+ except ValueError as exp:
raise_parse_error(node, 'Bad integer attribute: %s' % exp)
value = find_attr_value_('name', node)
if value is not None and 'name' not in already_processed:
@@ -1153,6 +1157,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='KillCha
for Kill_Chain_Phase_ in self.Kill_Chain_Phase:
Kill_Chain_Phase_.export(lwrite, level, nsmap, namespace_, name_='Kill_Chain_Phase', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1221,6 +1226,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='KillCha
super(KillChainPhaseReferenceType, self).exportChildren(lwrite, level, nsmap, namespace_, name_, True, pretty_print=pretty_print)
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1261,7 +1267,6 @@ def __init__(self, idref=None, id=None, Name=None, Related_Identities=None):
self.id = _cast(None, id)
self.Name = Name
self.Related_Identities = Related_Identities
- self.xsi_type = None
def factory(*args_, **kwargs_):
if IdentityType.subclass:
return IdentityType.subclass(*args_, **kwargs_)
@@ -1318,6 +1323,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Identit
if self.Related_Identities is not None:
self.Related_Identities.export(lwrite, level, nsmap, namespace_, name_='Related_Identities', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1397,6 +1403,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='GenericRelationshipListType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1462,6 +1469,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Campaign is not None:
self.Campaign.export(lwrite, level, nsmap, namespace_, name_='Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1626,6 +1634,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Exploit_Target is not None:
self.Exploit_Target.export(lwrite, level, nsmap, namespace_, name_='Exploit_Target', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1708,6 +1717,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Incident is not None:
self.Incident.export(lwrite, level, nsmap, namespace_, name_='Incident', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1790,6 +1800,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Indicator is not None:
self.Indicator.export(lwrite, level, nsmap, namespace_, name_='Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1872,6 +1883,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Observable is not None:
self.Observable.export(lwrite, level, "%s:" % (nsmap[namespace_]), name_='Observable', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1937,6 +1949,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Threat_Actor is not None:
self.Threat_Actor.export(lwrite, level, nsmap, namespace_, name_='Threat_Actor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2019,6 +2032,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.TTP is not None:
self.TTP.export(lwrite, level, nsmap, namespace_, name_='TTP', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2101,6 +2115,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Identity is not None:
self.Identity.export(lwrite, level, nsmap, namespace_, name_='Identity', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2198,6 +2213,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='IndicatorBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2217,7 +2233,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -2299,6 +2315,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='IncidentBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2318,7 +2335,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -2400,6 +2417,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TTPBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2419,7 +2437,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -2502,6 +2520,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ExploitTargetBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2521,7 +2540,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -2603,6 +2622,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CourseOfActionBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2622,7 +2642,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -2679,6 +2699,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Campaign is not None:
self.Campaign.export(lwrite, level, nsmap, namespace_, name_='Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2759,6 +2780,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Campaig
if self.Names is not None:
self.Names.export(lwrite, level, nsmap, namespace_, name_='Names', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2774,7 +2796,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Names':
@@ -2834,6 +2856,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='NamesTy
for Name_ in self.Name:
Name_.export(lwrite, level, nsmap, namespace_, name_='Name', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2924,6 +2947,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='CampaignBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -2943,7 +2967,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -3026,6 +3050,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ThreatActorBaseType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3045,7 +3070,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
pass
@@ -3103,6 +3128,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Exploit
for Exploit_Target_ in self.Exploit_Target:
Exploit_Target_.export(lwrite, level, nsmap, namespace_, name_='Exploit_Target', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3183,6 +3209,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AddressAbstractType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3245,6 +3272,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Contrib
for Source_ in self.Source:
Source_.export(lwrite, level, nsmap, namespace_, name_='Source', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3311,6 +3339,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Referen
showIndent(lwrite, level, pretty_print)
lwrite('<%s:Reference>%s%s:Reference>%s' % (nsmap[namespace_], quote_xml(Reference_), nsmap[namespace_], eol_))
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3376,6 +3405,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Identity_ in self.Related_Identity:
Related_Identity_.export(lwrite, level, nsmap, namespace_, name_='Related_Identity', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3441,6 +3471,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Confide
for Confidence_Assertion_ in self.Confidence_Assertion:
Confidence_Assertion_.export(lwrite, level, nsmap, namespace_, name_='Confidence_Assertion', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -3551,7 +3582,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
value = find_attr_value_('timestamp_precision', node)
if value is not None and 'timestamp_precision' not in already_processed:
@@ -3632,6 +3663,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='StructuredTextType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -3706,6 +3738,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='EncodedCDATAType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -3789,6 +3822,7 @@ def exportAttributes(self, lwrite, level, already_processed, namespace_='stixCom
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ControlledVocabularyStringType', fromsubclass_=False, pretty_print=True):
pass
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
self.valueOf_ = get_all_text_(node)
@@ -3819,7 +3853,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -3865,7 +3899,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/stix_core.py b/stix/bindings/stix_core.py
index 9ee8927b..a65eaa81 100644
--- a/stix/bindings/stix_core.py
+++ b/stix/bindings/stix_core.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,10 +9,13 @@
#
import sys
-from stix.bindings import *
+
+import cybox.bindings.cybox_core as cybox_core_binding
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
-import cybox.bindings.cybox_core as cybox_core_binding
XML_NS = "http://stix.mitre.org/stix-1"
@@ -126,10 +129,6 @@ def exportAttributes(self, lwrite, level, nsmap, already_processed, namespace_=X
if self.timestamp is not None and 'timestamp' not in already_processed:
already_processed.add('timestamp')
lwrite(' timestamp="%s"' % self.gds_format_datetime(self.timestamp, input_name='timestamp'))
-
- #for ns, prefix in nsmap.iteritems():
- # lwrite(' xmlns:%s="%s"' % (prefix, ns))
-
def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='STIXType', fromsubclass_=False, pretty_print=True):
if pretty_print:
eol_ = '\n'
@@ -155,8 +154,8 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='STIXTyp
self.Threat_Actors.export(lwrite, level, nsmap, namespace_, name_='Threat_Actors', pretty_print=pretty_print)
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
-
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.nsmap = node.nsmap
self.buildAttributes(node, node.attrib, already_processed)
@@ -181,7 +180,7 @@ def buildAttributes(self, node, attrs, already_processed):
already_processed.add('timestamp')
try:
self.timestamp = self.gds_parse_datetime(value, node, 'timestamp')
- except ValueError, exp:
+ except ValueError as exp:
raise ValueError('Bad date-time attribute (timestamp): %s' % exp)
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'STIX_Header':
@@ -281,6 +280,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_Package_ in self.Related_Package:
Related_Package_.export(lwrite, level, nsmap, namespace_, name_='Related_Package', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -346,6 +346,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
if self.Package is not None:
self.Package.export(lwrite, level, nsmap, namespace_, name_='Package', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -452,6 +453,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='STIXHea
if self.Information_Source is not None:
self.Information_Source.export(lwrite, level, nsmap, namespace_, name_='Information_Source', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -541,6 +543,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Indicat
for Indicator_ in self.Indicator:
Indicator_.export(lwrite, level, nsmap, namespace_, name_='Indicator', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -550,26 +553,11 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Indicator':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "IndicatorType":
- import stix.bindings.indicator as indicator_binding
- obj_ = indicator_binding.IndicatorType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.IndicatorBaseType.factory() # not abstract
-
+ from . import indicator
+ obj_ = lookup_extension(child_, stix_common_binding.IndicatorBaseType).factory()
obj_.build(child_)
self.Indicator.append(obj_)
+
# end class IndicatorsType
class TTPsType(GeneratedsSuper):
@@ -629,6 +617,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TTPsTyp
if self.Kill_Chains is not None:
self.Kill_Chains.export(lwrite, level, nsmap, namespace_, name_='Kill_Chains', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -638,26 +627,11 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'TTP':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "TTPType":
- import stix.bindings.ttp as ttp_binding
- obj_ = ttp_binding.TTPType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.TTPBaseType.factory() # not abstract
-
+ from . import ttp
+ obj_ = lookup_extension(child_, stix_common_binding.TTPBaseType).factory()
obj_.build(child_)
self.TTP.append(obj_)
+
elif nodeName_ == 'Kill_Chains':
obj_ = stix_common_binding.KillChainsType.factory()
obj_.build(child_)
@@ -715,6 +689,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Inciden
for Incident_ in self.Incident:
Incident_.export(lwrite, level, nsmap, namespace_, name_='Incident', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -724,26 +699,11 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Incident':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "IncidentType":
- import stix.bindings.incident as incident_binding
- obj_ = incident_binding.IncidentType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.IncidentBaseType.factory() # not abstract
-
+ from . import incident
+ obj_ = lookup_extension(child_, stix_common_binding.IncidentBaseType).factory()
obj_.build(child_)
self.Incident.append(obj_)
+
# end class IncidentsType
class CoursesOfActionType(GeneratedsSuper):
@@ -797,6 +757,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Courses
for Course_Of_Action_ in self.Course_Of_Action:
Course_Of_Action_.export(lwrite, level, nsmap, namespace_, name_='Course_Of_Action', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -806,24 +767,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Course_Of_Action':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CourseOfActionType":
- import stix.bindings.course_of_action as coa_binding
- obj_ = coa_binding.CourseOfActionType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.CourseOfActionBaseType.factory() # not abstract
-
+ from . import course_of_action
+ obj_ = lookup_extension(child_, stix_common_binding.CourseOfActionBaseType).factory()
obj_.build(child_)
self.Course_Of_Action.append(obj_)
# end class CoursesOfActionType
@@ -879,6 +824,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Campaig
for Campaign_ in self.Campaign:
Campaign_.export(lwrite, level, nsmap, namespace_, name_='Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -888,24 +834,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Campaign':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CampaignType":
- import stix.bindings.campaign as campaign_binding
- obj_ = campaign_binding.CampaignType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.CampaignBaseType.factory() # not abstract
-
+ from . import campaign
+ obj_ = lookup_extension(child_, stix_common_binding.CampaignBaseType).factory()
obj_.build(child_)
self.Campaign.append(obj_)
# end class CampaignsType
@@ -961,6 +891,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ThreatA
for Threat_Actor_ in self.Threat_Actor:
Threat_Actor_.export(lwrite, level, nsmap, namespace_, name_='Threat_Actor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -970,24 +901,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Threat_Actor':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "ThreatActorType":
- import stix.bindings.threat_actor as ta_binding
- obj_ = ta_binding.ThreatActorType.factory()
- else:
- raise NotImplementedError('Class not implemented for element type: ' + type_name_)
- else:
- obj_ = stix_common_binding.ThreatActorBaseType.factory() # not abstract
-
+ from . import threat_actor
+ obj_ = lookup_extension(child_, stix_common_binding.ThreatActorBaseType).factory()
obj_.build(child_)
self.Threat_Actor.append(obj_)
# end class ThreatActorsType
@@ -1000,7 +915,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -1050,7 +965,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/threat_actor.py b/stix/bindings/threat_actor.py
index 9e84d689..ef4972c5 100644
--- a/stix/bindings/threat_actor.py
+++ b/stix/bindings/threat_actor.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
#!/usr/bin/env python
@@ -9,7 +9,10 @@
#
import sys
-from stix.bindings import *
+
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -74,6 +77,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Observe
for Observed_TTP_ in self.Observed_TTP:
Observed_TTP_.export(lwrite, level, nsmap, namespace_, name_='Observed_TTP', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -143,6 +147,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Associa
for Associated_Campaign_ in self.Associated_Campaign:
Associated_Campaign_.export(lwrite, level, nsmap, namespace_, name_='Associated_Campaign', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -212,6 +217,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Associa
for Associated_Actor_ in self.Associated_Actor:
Associated_Actor_.export(lwrite, level, nsmap, namespace_, name_='Associated_Actor', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -227,16 +233,20 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(AssociatedActorsType, self).buildChildren(child_, node, nodeName_, True)
# end class AssociatedActorsType
+@register_extension
class ThreatActorType(stix_common_binding.ThreatActorBaseType):
"""Specifies the relevant STIX-ThreatActor schema version for this
content."""
subclass = None
superclass = stix_common_binding.ThreatActorBaseType
+
+ xmlns = "http://stix.mitre.org/ThreatActor-1"
+ xmlns_prefix = "ta"
+ xml_type = "ThreatActorType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, version=None, Title=None, Description=None, Short_Description=None, Identity=None, Type=None, Motivation=None, Sophistication=None, Intended_Effect=None, Planning_And_Operational_Support=None, Observed_TTPs=None, Associated_Campaigns=None, Associated_Actors=None, Handling=None, Confidence=None, Information_Source=None, Related_Packages=None):
super(ThreatActorType, self).__init__(idref=idref, id=id, timestamp=timestamp)
- self.xmlns = "http://stix.mitre.org/ThreatActor-1"
- self.xmlns_prefix = "ta"
- self.xml_type = "ThreatActorType"
self.version = _cast(None, version)
self.Title = Title
self.Description = Description
@@ -411,6 +421,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ThreatA
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -512,7 +523,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -558,7 +569,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/bindings/ttp.py b/stix/bindings/ttp.py
index 8ba5882a..637835ab 100644
--- a/stix/bindings/ttp.py
+++ b/stix/bindings/ttp.py
@@ -1,15 +1,19 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
-# See LICENSE.txt for complete terms.
#
# Generated Thu Apr 11 15:06:30 2013 by generateDS.py version 2.9a.
#
import sys
-from stix.bindings import *
+
import cybox.bindings.cybox_core as cybox_core_binding
+from mixbox.binding_utils import *
+
+from stix.bindings import lookup_extension, register_extension
import stix.bindings.stix_common as stix_common_binding
import stix.bindings.data_marking as data_marking_binding
@@ -112,6 +116,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AttackP
if self.Short_Description is not None:
self.Short_Description.export(lwrite, level, nsmap, namespace_, name_='Short_Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -252,6 +257,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Malware
if self.Short_Description is not None:
self.Short_Description.export(lwrite, level, nsmap, namespace_, name_='Short_Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -368,6 +374,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Exploit
if self.Short_Description is not None:
self.Short_Description.export(lwrite, level, nsmap, namespace_, name_='Short_Description', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -488,6 +495,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Infrast
if self.Observable_Characterization is not None:
self.Observable_Characterization.export(lwrite, level, "%s:" % (nsmap[namespace_]), name_='Observable_Characterization', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -577,6 +585,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='ToolsTy
for Tool_ in self.Tool:
Tool_.export(lwrite, level, nsmap, namespace_, name_='Tool', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -642,6 +651,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Exploit
for Exploit_ in self.Exploit:
Exploit_.export(lwrite, level, nsmap, namespace_, name_='Exploit', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -707,6 +717,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Malware
for Malware_Instance_ in self.Malware_Instance:
Malware_Instance_.export(lwrite, level, nsmap, namespace_, name_='Malware_Instance', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -716,22 +727,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Malware_Instance':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "MAEC4.1InstanceType":
- from .extensions.malware import maec_4_1
- obj_ = maec_4_1.MAEC4_1InstanceType.factory()
- else:
- obj_ = MalwareInstanceType.factory() # MalwareInstanceType is not abstract
-
+ from .extensions.malware import maec_4_1
+ obj_ = lookup_extension(child_, MalwareInstanceType).factory()
obj_.build(child_)
self.Malware_Instance.append(obj_)
# end class MalwareType
@@ -787,6 +784,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='AttackP
for Attack_Pattern_ in self.Attack_Pattern:
Attack_Pattern_.export(lwrite, level, nsmap, namespace_, name_='Attack_Pattern', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -796,24 +794,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Attack_Pattern':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CAPEC2.7InstanceType":
- from .extensions.attack_pattern import capec_2_7
- obj_ = capec_2_7.CAPEC2_7InstanceType.factory()
- else:
- raise NotImplementedError('No implementation for type: ' + type_name_)
- else:
- obj_ = AttackPatternType.factory() # AttackPattern is not abstract
-
+ from .extensions.attack_pattern import capec_2_7
+ obj_ = lookup_extension(child_, AttackPatternType).factory()
obj_.build(child_)
self.Attack_Pattern.append(obj_)
# end class AttackPatternsType
@@ -876,6 +858,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Resourc
if self.Personas is not None:
self.Personas.export(lwrite, level, nsmap, namespace_, name_='Personas', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -949,6 +932,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Persona
for Persona_ in self.Persona:
Persona_.export(lwrite, level, nsmap, namespace_, name_='Persona', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -958,22 +942,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Persona':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CIQIdentity3.0InstanceType":
- from .extensions.identity import ciq_identity_3_0
- obj_ = ciq_identity_3_0.CIQIdentity3_0InstanceType.factory()
- else:
- obj_ = stix_common_binding.IdentityType.factory() # IdentityType is not abstract
-
+ from .extensions.identity import ciq_identity_3_0
+ obj_ = lookup_extension(child_, stix_common_binding.IdentityType).factory()
obj_.build(child_)
self.Persona.append(obj_)
# end class PersonasType
@@ -1036,6 +1006,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Behavio
if self.Exploits is not None:
self.Exploits.export(lwrite, level, nsmap, namespace_, name_='Exploits', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1133,6 +1104,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='VictimT
self.Targeted_Technical_Details.export(lwrite, level, "%s:" % (nsmap[namespace_]), name_='Targeted_Technical_Details', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1142,22 +1114,8 @@ def buildAttributes(self, node, attrs, already_processed):
pass
def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
if nodeName_ == 'Identity':
- type_name_ = child_.attrib.get('{http://www.w3.org/2001/XMLSchema-instance}type')
- if type_name_ is None:
- type_name_ = child_.attrib.get('type')
- if type_name_ is not None:
- type_names_ = type_name_.split(':')
- if len(type_names_) == 1:
- type_name_ = type_names_[0]
- else:
- type_name_ = type_names_[1]
-
- if type_name_ == "CIQIdentity3.0InstanceType":
- from .extensions.identity import ciq_identity_3_0
- obj_ = ciq_identity_3_0.CIQIdentity3_0InstanceType.factory()
- else:
- obj_ = stix_common_binding.IdentityType.factory() # IdentityType is not abstract
-
+ from .extensions.identity import ciq_identity_3_0
+ obj_ = lookup_extension(child_, stix_common_binding.IdentityType).factory()
obj_.build(child_)
self.set_Identity(obj_)
elif nodeName_ == 'Targeted_Systems':
@@ -1228,6 +1186,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Related
for Related_TTP_ in self.Related_TTP:
Related_TTP_.export(lwrite, level, nsmap, namespace_, name_='Related_TTP', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1243,18 +1202,22 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
super(RelatedTTPsType, self).buildChildren(child_, node, nodeName_, True)
# end class RelatedTTPsType
+
+@register_extension
class TTPType(stix_common_binding.TTPBaseType):
"""TTPType characterizes an individual adversary TTP.Specifies the
relevant STIX-TTP schema version for this content."""
subclass = None
superclass = stix_common_binding.TTPBaseType
+
+ xmlns = "http://stix.mitre.org/TTP-1"
+ xmlns_prefix = "ttp"
+ xml_type = "TTPType"
+ xsi_type = "%s:%s" % (xmlns_prefix, xml_type)
+
def __init__(self, idref=None, id=None, timestamp=None, version=None, Title=None, Description=None, Short_Description=None, Intended_Effect=None, Behavior=None, Resources=None, Victim_Targeting=None, Exploit_Targets=None, Related_TTPs=None, Kill_Chain_Phases=None, Information_Source=None, Kill_Chains=None, Handling=None, Related_Packages=None):
super(TTPType, self).__init__(idref=idref, id=id, timestamp=timestamp)
- self.xmlns = "http://stix.mitre.org/TTP-1"
- self.xmlns_prefix = "ttp"
- self.xml_type = "TTPType"
self.version = _cast(None, version)
-
self.Title = Title
self.Description = Description
self.Short_Description = Short_Description
@@ -1396,6 +1359,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='TTPType
if self.Related_Packages is not None:
self.Related_Packages.export(lwrite, level, nsmap, namespace_, name_='Related_Packages', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1522,6 +1486,7 @@ def exportChildren(self, lwrite, level, nsmap, namespace_=XML_NS, name_='Exploit
for Exploit_Target_ in self.Exploit_Target:
Exploit_Target_.export(lwrite, level, nsmap, namespace_, name_='Exploit_Target', pretty_print=pretty_print)
def build(self, node):
+ self.__sourcenode__ = node
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
for child in node:
@@ -1545,7 +1510,7 @@ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
"""
def usage():
- print USAGE_TEXT
+ print(USAGE_TEXT)
sys.exit(1)
def get_root_tag(node):
@@ -1591,7 +1556,7 @@ def parseEtree(inFileName):
return rootObj, rootElement
def parseString(inString):
- from StringIO import StringIO
+ from mixbox.vendor.six import StringIO
doc = parsexml_(StringIO(inString))
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
diff --git a/stix/campaign/__init__.py b/stix/campaign/__init__.py
index 5de638fb..46703142 100644
--- a/stix/campaign/__init__.py
+++ b/stix/campaign/__init__.py
@@ -1,72 +1,90 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-from stix.common import Activity, Confidence, Statement, VocabString
-from stix.common.related import (
- GenericRelationshipList, RelatedCampaign, RelatedIncident, RelatedIndicator,
- RelatedPackageRefs, RelatedThreatActor, RelatedTTP
-)
-from stix.common import vocabs
-from stix.data_marking import Marking
import stix.bindings.campaign as campaign_binding
+from stix.common import Activity, Confidence, Statement
+from stix.common import vocabs
+from stix.common.information_source import InformationSource
+from stix.common.related import (
+ GenericRelationshipList, RelatedCampaign, RelatedIncident,
+ RelatedIndicator, RelatedPackageRefs, RelatedThreatActor,
+ RelatedTTP)
+from stix.common.statement import StatementField
+from stix.common.vocabs import VocabField, CampaignStatus
class AssociatedCampaigns(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.AssociatedCampaignsType
- _binding_var = "Associated_Campaign"
- _contained_type = RelatedCampaign
- _inner_name = "campaigns"
+
+ campaign = fields.TypedField("Associated_Campaign", RelatedCampaign, multiple=True, key_name="campaigns")
class Attribution(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.AttributionType
- _binding_var = "Attributed_Threat_Actor"
- _contained_type = RelatedThreatActor
- _inner_name = "threat_actors"
+
+ threat_actor = fields.TypedField("Attributed_Threat_Actor", RelatedThreatActor, multiple=True, key_name="threat_actors")
class RelatedIncidents(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.RelatedIncidentsType
- _binding_var = "Related_Incident"
- _contained_type = RelatedIncident
- _inner_name = "incidents"
+
+ incident = fields.TypedField("Related_Incident", RelatedIncident, multiple=True, key_name="incidents")
class RelatedIndicators(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.RelatedIndicatorsType
- _binding_var = "Related_Indicator"
- _contained_type = RelatedIndicator
- _inner_name = "indicators"
+
+ indicator = fields.TypedField(name="Related_Indicator", type_=RelatedIndicator, multiple=True, key_name="indicators")
class RelatedTTPs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.RelatedTTPsType
- _binding_var = "Related_TTP"
- _contained_type = RelatedTTP
- _inner_name = "ttps"
+
+ ttp = fields.TypedField("Related_TTP", RelatedTTP, multiple=True, key_name="ttps")
class Names(stix.EntityList):
_namespace = "http://stix.mitre.org/Campaign-1"
_binding = campaign_binding
_binding_class = campaign_binding.NamesType
- _binding_var = "Name"
- _contained_type = VocabString
- _inner_name = "names"
+
+ name = VocabField("Name", multiple=True, key_name="names")
+
+ @classmethod
+ def _dict_as_list(cls):
+ return False
class Campaign(stix.BaseCoreComponent):
+ """Implementation of the STIX Campaign.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref (optional): An identifier reference. If set this will unset the
+ ``id_`` property.
+ timestamp (optional): A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ description: A description of the purpose or intent of this object.
+ short_description: A short description of the intent
+ or purpose of this object.
+ title: The title of this object.
+
+ """
_binding = campaign_binding
_binding_class = _binding.CampaignType
_namespace = "http://stix.mitre.org/Campaign-1"
@@ -74,6 +92,19 @@ class Campaign(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = 'campaign'
+ activity = fields.TypedField("Activity", Activity, multiple=True)
+ associated_campaigns = fields.TypedField("Associated_Campaigns", AssociatedCampaigns)
+ attribution = fields.TypedField("Attribution", Attribution, multiple=True)
+ confidence = fields.TypedField("Confidence", Confidence)
+ status = VocabField("Status", CampaignStatus)
+ intended_effects = StatementField("Intended_Effect", Statement, vocab_type=vocabs.IntendedEffect, multiple=True, key_name="intended_effects")
+ names = fields.TypedField("Names", Names)
+ related_incidents = fields.TypedField("Related_Incidents", RelatedIncidents)
+ related_indicators = fields.TypedField("Related_Indicators", RelatedIndicators)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ related_ttps = fields.TypedField("Related_TTPs", RelatedTTPs)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -86,170 +117,17 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.names = None
- self.intended_effects = _IntendedEffects()
- self.status = None
self.related_ttps = RelatedTTPs()
self.related_incidents = RelatedIncidents()
self.related_indicators = RelatedIndicators()
- self.attribution = _AttributionList()
- self.associated_campaigns = AssociatedCampaigns()
- self.confidence = None
- self.activity = _Activities()
- self.handling = None
self.related_packages = RelatedPackageRefs()
- @property
- def intended_effects(self):
- return self._intended_effects
-
- @intended_effects.setter
- def intended_effects(self, value):
- self._intended_effects = _IntendedEffects(value)
-
def add_intended_effect(self, value):
self.intended_effects.append(value)
- @property
- def activity(self):
- return self._activity
-
- @activity.setter
- def activity(self, value):
- self._activity = _Activities(value)
-
def add_activity(self, value):
- self.activity.append(value)
-
- @property
- def status(self):
- return self._status
-
- @status.setter
- def status(self, value):
- self._set_vocab(vocabs.CampaignStatus, status=value)
-
- @property
- def attribution(self):
- return self._attribution
-
- @attribution.setter
- def attribution(self, value):
- self._attribution = _AttributionList(value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(Campaign, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.names:
- return_obj.Names = self.names.to_obj(ns_info=ns_info)
- if self.intended_effects:
- return_obj.Intended_Effect = self.intended_effects.to_obj(ns_info=ns_info)
- if self.status:
- return_obj.Status = self.status.to_obj(ns_info=ns_info)
- if self.related_ttps:
- return_obj.Related_TTPs = self.related_ttps.to_obj(ns_info=ns_info)
- if self.related_incidents:
- return_obj.Related_Incidents = self.related_incidents.to_obj(ns_info=ns_info)
- if self.related_indicators:
- return_obj.Related_Indicators = self.related_indicators.to_obj(ns_info=ns_info)
- if self.attribution:
- return_obj.Attribution = self.attribution.to_obj(ns_info=ns_info)
- if self.associated_campaigns:
- return_obj.Associated_Campaigns = self.associated_campaigns.to_obj(ns_info=ns_info)
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.activity:
- return_obj.Activity = self.activity.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(Campaign, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class):
- return_obj.names = Names.from_obj(obj.Names)
- return_obj.intended_effects = \
- _IntendedEffects.from_obj(obj.Intended_Effect)
- return_obj.status = VocabString.from_obj(obj.Status)
- return_obj.related_ttps = RelatedTTPs.from_obj(obj.Related_TTPs)
- return_obj.related_incidents = \
- RelatedIncidents.from_obj(obj.Related_Incidents)
- return_obj.related_indicators = \
- RelatedIndicators.from_obj(obj.Related_Indicators)
- return_obj.attribution = _AttributionList.from_obj(obj.Attribution)
- return_obj.associated_campaigns = \
- AssociatedCampaigns.from_obj(obj.Associated_Campaigns)
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.activity = _Activities.from_obj(obj.Activity)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.related_packages = \
- RelatedPackageRefs.from_obj(obj.Related_Packages)
-
- return return_obj
-
- def to_dict(self):
- return super(Campaign, self).to_dict()
+ """Adds an :class:`.Activity` object to the :attr:`activity`
+ collection.
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(Campaign, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get # PEP 8 line lengths
- return_obj.names = Names.from_dict(get('names'))
- return_obj.intended_effects = \
- _IntendedEffects.from_dict(get('intended_effects'))
- return_obj.status = VocabString.from_dict(get('status'))
- return_obj.related_ttps = \
- RelatedTTPs.from_dict(get('related_ttps'))
- return_obj.related_incidents = \
- RelatedIncidents.from_dict(get('related_incidents'))
- return_obj.related_indicators = \
- RelatedIndicators.from_dict(get('related_indicators'))
- return_obj.attribution = _AttributionList.from_list(get('attribution'))
- return_obj.associated_campaigns = \
- AssociatedCampaigns.from_dict(get('associated_campaigns'))
- return_obj.confidence = \
- Confidence.from_dict(get('confidence'))
- return_obj.activity = _Activities.from_dict(get('activity'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.related_packages = \
- RelatedPackageRefs.from_dict(get('related_packages'))
-
- return return_obj
-
-
-# Not Actual STIX Types!
-class _AttributionList(stix.TypedList):
- _contained_type = Attribution
-
-
-class _Activities(stix.TypedList):
- _contained_type = Activity
-
-
-class _IntendedEffects(stix.TypedList):
- _contained_type = Statement
-
- def _fix_value(self, value):
- intended_effect = vocabs.IntendedEffect(value)
- return Statement(value=intended_effect)
+ """
+ self.activity.append(value)
diff --git a/stix/coa/__init__.py b/stix/coa/__init__.py
index de79b406..6805c973 100644
--- a/stix/coa/__init__.py
+++ b/stix/coa/__init__.py
@@ -1,34 +1,58 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# external
+from mixbox import fields
from cybox.core import Observables
# internal
import stix
-from stix.data_marking import Marking
-from stix.common import vocabs, related, VocabString, Statement
+from stix.common import vocabs
+from stix.common.related import GenericRelationshipList, RelatedPackageRefs, RelatedCOA
+from stix.common.vocabs import VocabField
+from stix.common.statement import Statement
+from stix.common.information_source import InformationSource
import stix.bindings.course_of_action as coa_binding
# relative
from .objective import Objective
-from .structured_coa import _BaseStructuredCOA
+from .structured_coa import StructuredCOAFactory, _BaseStructuredCOA
# Redefines
Stage = vocabs.COAStage
COAType = vocabs.CourseOfActionType
-class RelatedCOAs(related.GenericRelationshipList):
+class RelatedCOAs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/CourseOfAction-1"
_binding = coa_binding
_binding_class = coa_binding.RelatedCOAsType
- _binding_var = "Related_COA"
- _contained_type = related.RelatedCOA
- _inner_name = "coas"
+
+ related_coa = fields.TypedField(
+ name="Related_COA",
+ type_=RelatedCOA,
+ multiple=True,
+ key_name="coas"
+ )
class CourseOfAction(stix.BaseCoreComponent):
+ """Implementation of the STIX Course of Action.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref (optional): An identifier reference. If set this will unset the
+ ``id_`` property.
+ timestamp (optional): A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ description: A description of the purpose or intent of this object.
+ short_description: A short description of the intent
+ or purpose of this object.
+ title: The title of this object.
+
+ """
_binding = coa_binding
_binding_class = coa_binding.CourseOfActionType
_namespace = "http://stix.mitre.org/CourseOfAction-1"
@@ -36,6 +60,18 @@ class CourseOfAction(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = 'coa'
+ stage = VocabField("Stage", Stage)
+ type_ = VocabField("Type", COAType)
+ objective = fields.TypedField("Objective", Objective)
+ parameter_observables = fields.TypedField("Parameter_Observables", Observables)
+ structured_coa = fields.TypedField("Structured_COA", type_=_BaseStructuredCOA, factory=StructuredCOAFactory)
+ impact = fields.TypedField("Impact", Statement)
+ cost = fields.TypedField("Cost", Statement)
+ efficacy = fields.TypedField("Efficacy", Statement)
+ related_coas = fields.TypedField("Related_COAs", RelatedCOAs)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -48,173 +84,8 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.stage = None
- self.type_ = None
- self.objective = None
- self.parameter_observables = None
- self.structured_coa = None
- self.impact = None
- self.cost = None
- self.efficacy = None
- self.handling = None
self.related_coas = RelatedCOAs()
- self.related_packages = related.RelatedPackageRefs()
-
- @property
- def stage(self):
- return self._stage
-
- @stage.setter
- def stage(self, value):
- self._set_vocab(Stage, stage=value)
-
- @property
- def type_(self):
- return self._type
-
- @type_.setter
- def type_(self, value):
- self._set_vocab(COAType, type=value)
-
- @property
- def objective(self):
- return self._objective
-
- @objective.setter
- def objective(self, value):
- self._set_var(Objective, try_cast=False, objective=value)
-
- @property
- def impact(self):
- return self._impact
-
- @impact.setter
- def impact(self, value):
- self._set_var(Statement, impact=value)
-
- @property
- def cost(self):
- return self._cost
-
- @cost.setter
- def cost(self, value):
- self._set_var(Statement, cost=value)
-
- @property
- def efficacy(self):
- return self._efficacy
-
- @efficacy.setter
- def efficacy(self, value):
- self._set_var(Statement, efficacy=value)
-
- @property
- def handling(self):
- return self._handling
-
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, try_cast=False, handling=value)
-
- @property
- def structured_coa(self):
- return self._structured_coa
-
- @structured_coa.setter
- def structured_coa(self, value):
- self._set_var(_BaseStructuredCOA, try_cast=False, structured_coa=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(CourseOfAction, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.stage:
- return_obj.Stage = self.stage.to_obj(ns_info=ns_info)
- if self.type_:
- return_obj.Type = self.type_.to_obj(ns_info=ns_info)
- if self.objective:
- return_obj.Objective = self.objective.to_obj(ns_info=ns_info)
- if self.parameter_observables:
- return_obj.Parameter_Observables = self.parameter_observables.to_obj(ns_info=ns_info)
- if self.impact:
- return_obj.Impact = self.impact.to_obj(ns_info=ns_info)
- if self.cost:
- return_obj.Cost = self.cost.to_obj(ns_info=ns_info)
- if self.efficacy:
- return_obj.Efficacy = self.efficacy.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.related_coas:
- return_obj.Related_COAs = self.related_coas.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
- if self.structured_coa:
- return_obj.Structured_COA = self.structured_coa.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(CourseOfAction, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class): # CourseOfActionType properties
- return_obj.title = obj.Title
- return_obj.stage = VocabString.from_obj(obj.Stage)
- return_obj.type_ = VocabString.from_obj(obj.Type)
- return_obj.objective = Objective.from_obj(obj.Objective)
- return_obj.parameter_observables = \
- Observables.from_obj(obj.Parameter_Observables)
- return_obj.impact = Statement.from_obj(obj.Impact)
- return_obj.cost = Statement.from_obj(obj.Cost)
- return_obj.efficacy = Statement.from_obj(obj.Efficacy)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.related_coas = \
- RelatedCOAs.from_obj(obj.Related_COAs)
- return_obj.related_packages = \
- related.RelatedPackageRefs.from_obj(obj.Related_Packages)
- return_obj.structured_coa = \
- _BaseStructuredCOA.from_obj(obj.Structured_COA)
-
- return return_obj
-
- def to_dict(self):
- return super(CourseOfAction, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(CourseOfAction, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get
- return_obj.stage = VocabString.from_dict(get('stage'))
- return_obj.type_ = VocabString.from_dict(get('type'))
- return_obj.objective = Objective.from_dict(get('objective'))
- return_obj.parameter_observables = \
- Observables.from_dict(get('parameter_observables'))
- return_obj.impact = Statement.from_dict(get('impact'))
- return_obj.cost = Statement.from_dict(get('cost'))
- return_obj.efficacy = Statement.from_dict(get('efficacy'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.related_coas = \
- RelatedCOAs.from_dict(get('related_coas'))
- return_obj.related_packages = \
- related.RelatedPackageRefs.from_dict(get('related_packages'))
- return_obj.structured_coa = \
- _BaseStructuredCOA.from_dict(get('structured_coa'))
-
- return return_obj
+ self.related_packages = RelatedPackageRefs()
# alias for CourseOfAction
COA = CourseOfAction
diff --git a/stix/coa/objective.py b/stix/coa/objective.py
index 1dc9d405..31266ce6 100644
--- a/stix/coa/objective.py
+++ b/stix/coa/objective.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
from stix.common import StructuredText, Confidence
import stix.bindings.course_of_action as coa_binding
@@ -10,76 +12,13 @@ class Objective(stix.Entity):
_binding = coa_binding
_binding_class = coa_binding.ObjectiveType
_namespace = "http://stix.mitre.org/CourseOfAction-1"
-
- def __init__(self, description=None, short_description=None):
- self.description = description
- self.short_description = short_description
- self.applicability_confidence = None
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- @property
- def applicability_confidence(self):
- return self._applicability_confidence
-
- @applicability_confidence.setter
- def applicability_confidence(self, value):
- self._set_var(Confidence, try_cast=False, applicability_confidence=value)
- def to_obj(self, return_obj=None, ns_info=None):
- super(Objective, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ applicability_confidence = fields.TypedField("Applicability_Confidence", Confidence)
+ description = fields.TypedField("Description", StructuredText)
+ short_description = fields.TypedField("Short_Description", StructuredText)
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.applicability_confidence:
- return_obj.Applicability_Confidence = self.applicability_confidence.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.applicability_confidence = Confidence.from_obj(obj.Applicability_Confidence)
- return return_obj
-
- def to_dict(self):
- return super(Objective, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
+ def __init__(self, description=None, short_description=None):
+ super(Objective, self).__init__()
- get = dict_repr.get
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.short_description = StructuredText.from_dict(get('short_description'))
- return_obj.applicability_confidence = Confidence.from_dict(get('applicability_confidence'))
-
- return return_obj
+ self.description = description
+ self.short_description = short_description
diff --git a/stix/coa/structured_coa.py b/stix/coa/structured_coa.py
index 1b62138d..fdc82d86 100644
--- a/stix/coa/structured_coa.py
+++ b/stix/coa/structured_coa.py
@@ -1,87 +1,44 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import entities
+from mixbox import fields
+
+# internal
import stix
from stix.bindings import course_of_action as coa_binding
+class StructuredCOAFactory(entities.EntityFactory):
+ @classmethod
+ def entity_class(cls, key):
+ import stix.extensions.structured_coa.generic_structured_coa # noqa
+ return stix.lookup_extension(key)
+
+
class _BaseStructuredCOA(stix.Entity):
_namespace = "http://stix.mitre.org/CourseOfAction-1"
_binding = coa_binding
_binding_class = coa_binding.StructuredCOAType
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+
def __init__(self, id_=None, idref=None):
+ super(_BaseStructuredCOA, self).__init__()
self.id_ = id_
self.idref = idref
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- from stix.extensions.structured_coa.generic_structured_coa import GenericStructuredCOA # noqa
-
- if not return_obj:
- klass = _BaseStructuredCOA.lookup_class(obj.xml_type)
- return_obj = klass.from_obj(obj)
- else:
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(_BaseStructuredCOA, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
- return_obj.xsi_type = self._XSI_TYPE
-
- return return_obj
-
- @staticmethod
- def lookup_class(xsi_type):
- if not xsi_type:
- raise ValueError("xsi:type is required")
- for (k, v) in _EXTENSION_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- raise ValueError("Unregistered xsi:type %s" % xsi_type)
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- from stix.extensions.structured_coa.generic_structured_coa import GenericStructuredCOA # noqa
-
- if not return_obj:
- klass = _BaseStructuredCOA.lookup_class(d.get('xsi:type'))
- return_obj = klass.from_dict(d)
- else:
- return_obj.id_ = d.get('id')
- return_obj.idref = d.get('idref')
-
- return return_obj
-
def to_dict(self):
d = super(_BaseStructuredCOA, self).to_dict()
- d['xsi:type'] = self._XSI_TYPE # added by subclass
+ d['xsi:type'] = self._XSI_TYPE
return d
+ def to_obj(self, ns_info=None):
+ obj = super(_BaseStructuredCOA, self).to_obj(ns_info=ns_info)
+ obj.xsi_type = self._XSI_TYPE
+ return obj
-#: Mapping of structured coa extension types to classes
-_EXTENSION_MAP = {}
-
-
-def add_extension(cls):
- _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+# Backwards compatibility
+add_extension = stix.add_extension
diff --git a/stix/common/__init__.py b/stix/common/__init__.py
index 32a55393..06a03ca7 100644
--- a/stix/common/__init__.py
+++ b/stix/common/__init__.py
@@ -1,7 +1,11 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
from __future__ import absolute_import
+from sys import version_info
+
+from mixbox.fields import TypedField, CDATAField
+from mixbox.vendor.six import text_type
from .structured_text import StructuredText # noqa
from .vocabs import VocabString # noqa
@@ -14,6 +18,8 @@
from .tools import ToolInformation # noqa
from .names import Names # noqa
from .campaign_reference import CampaignRef # noqa
+from .references import References # noqa
+from .profiles import Profiles # noqa
from .related import ( # noqa
GenericRelationshipList, RelatedCampaign, RelatedCOA,
RelatedExploitTarget, RelatedIdentity, RelatedIncident,
@@ -21,34 +27,6 @@
RelatedPackage, RelatedPackages, RelatedCampaignRef
)
-# Patch in base types of Related* types
-from stix.core import STIXPackage
-from cybox.core import Observable
-from stix.campaign import Campaign
-from stix.coa import CourseOfAction
-from stix.exploit_target import ExploitTarget
-from stix.incident import Incident
-from stix.indicator import Indicator
-from stix.threat_actor import ThreatActor
-from stix.ttp import TTP
-
-
-RelatedCampaign._base_type = Campaign # noqa
-RelatedCOA._base_type = CourseOfAction # noqa
-RelatedExploitTarget._base_type = ExploitTarget # noqa
-RelatedIdentity._base_type = Identity # noqa
-RelatedIncident._base_type = Incident # noqa
-RelatedIndicator._base_type = Indicator # noqa
-RelatedThreatActor._base_type = ThreatActor # noqa
-RelatedTTP._base_type = TTP # noqa
-RelatedObservable._base_type = Observable # noqa
-RelatedPackage._base_type = STIXPackage # noqa
-RelatedCampaignRef._base_type = CampaignRef # noqa
-
-# Path the RelatedPackages _contained_type
-RelatedPackages._contained_type = RelatedPackage # noqa
-
-
import stix
import stix.utils as utils
import stix.bindings.stix_common as common_binding
@@ -58,73 +36,24 @@ class EncodedCDATA(stix.Entity):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = _binding.EncodedCDATAType
-
+
+ value = CDATAField("valueOf_", key_name="value")
+ encoded = TypedField("encoded")
+
def __init__(self, value=None, encoded=None):
+ super(EncodedCDATA, self).__init__()
self.value = value
self.encoded = encoded
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = utils.strip_cdata(value)
-
@property
def cdata(self):
return utils.cdata(self.value)
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = obj.valueOf_
- return_obj.encoded = obj.encoded
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(EncodedCDATA, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.encoded = self.encoded
- return_obj.valueOf_ = utils.cdata(self.value)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = utils.strip_cdata(d.get('value'))
- return_obj.encoded = bool(d.get('encoded'))
-
- return return_obj
-
- def to_dict(self):
- d = {}
-
- if not self.value:
- return d
-
- d['value'] = utils.strip_cdata(self.value)
- d['encoded'] = bool(self.encoded)
-
- return d
-
def __str__(self):
- return self.__unicode__().encode("utf-8")
+ if version_info < (3,):
+ return self.__unicode__().encode("utf-8")
+ else:
+ return self.__unicode__()
def __unicode__(self):
- return unicode(self.value)
+ return text_type(self.value)
diff --git a/stix/common/activity.py b/stix/common/activity.py
index 76f1d175..87d99bfc 100644
--- a/stix/common/activity.py
+++ b/stix/common/activity.py
@@ -1,8 +1,11 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.stix_common as common_binding
+import stix.utils
from .datetimewithprecision import DateTimeWithPrecision
from .structured_text import StructuredText
@@ -13,65 +16,8 @@ class Activity(stix.Entity):
_binding_class = common_binding.ActivityType
_namespace = 'http://stix.mitre.org/common-1'
- def __init__(self):
- self.date_time = None
- self.description = None
-
- @property
- def date_time(self):
- return self._date_time
-
- @date_time.setter
- def date_time(self, value):
- self._set_var(DateTimeWithPrecision, date_time=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Activity, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.date_time:
- return_obj.Date_Time = self.date_time.to_obj(ns_info=ns_info)
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
-
- return return_obj
+ date_time = fields.TypedField("Date_Time", DateTimeWithPrecision)
+ description = fields.TypedField("Description", StructuredText)
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.date_time = DateTimeWithPrecision.from_obj(obj.Date_Time)
- return_obj.description = StructuredText.from_obj(obj.Description)
-
- return return_obj
-
- def to_dict(self):
- return super(Activity, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.date_time = DateTimeWithPrecision.from_dict(get('date_time'))
- return_obj.description = StructuredText.from_dict(get('description'))
-
- return return_obj
+ def __init__(self):
+ super(Activity, self).__init__()
diff --git a/stix/common/campaign_reference.py b/stix/common/campaign_reference.py
index e8ff1ebe..3eee73b8 100644
--- a/stix/common/campaign_reference.py
+++ b/stix/common/campaign_reference.py
@@ -1,9 +1,11 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import fields
+
# internal
import stix
-import stix.utils as utils
import stix.bindings.stix_common as common_binding
# relative
@@ -15,77 +17,15 @@ class CampaignRef(stix.Entity):
_binding = common_binding
_binding_class = common_binding.CampaignReferenceType
- def __init__(self, idref=None, timestamp=None, **kwargs):
- super(CampaignRef, self).__init__(**kwargs)
- self.idref = idref
- self.timestamp = timestamp
- self.names = None
-
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
+ idref = fields.TypedField("idref")
+ timestamp = fields.DateTimeField("timestamp")
+ names = fields.TypedField("Names", Names)
- @property
- def names(self):
- return self._names
+ def __init__(self, idref=None, timestamp=None):
+ super(CampaignRef, self).__init__()
- @names.setter
- def names(self, value):
- self._names = Names(value)
+ self.idref = idref
+ self.timestamp = timestamp
def add_name(self, name):
self.names.append(name)
-
- def to_obj(self, return_obj=None, ns_info=None):
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj = super(CampaignRef, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- return_obj.idref = self.idref
- return_obj.timestamp = utils.serialize_value(self.timestamp)
-
- if self.names:
- return_obj.Names = self.names.to_obj()
-
- return return_obj
-
- def to_dict(self):
- return super(CampaignRef, self).to_dict()
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.idref = obj.idref
- return_obj.timestamp = obj.timestamp
- return_obj.names = Names.from_obj(obj.Names)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.idref = get("idref")
- return_obj.timestamp = get("timestamp")
- return_obj.names = Names.from_dict(get("names"))
-
- return return_obj
diff --git a/stix/common/confidence.py b/stix/common/confidence.py
index 4751c166..26b0796d 100644
--- a/stix/common/confidence.py
+++ b/stix/common/confidence.py
@@ -1,14 +1,17 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
from __future__ import absolute_import
+from mixbox import fields
+
import stix
import stix.utils as utils
import stix.bindings.stix_common as common_binding
-from . import vocabs, VocabString
+from .vocabs import VocabField
from .structured_text import StructuredText
+from .datetimewithprecision import validate_precision
class Confidence(stix.Entity):
@@ -16,117 +19,25 @@ class Confidence(stix.Entity):
_binding = common_binding
_binding_class = common_binding.ConfidenceType
- def __init__(self, value=None, timestamp=None, description=None, source=None):
+ value = VocabField("Value")
+ description = fields.TypedField("Description", StructuredText)
+ timestamp = fields.DateTimeField("timestamp")
+ timestamp_precision = fields.TypedField("timestamp_precision", preset_hook=validate_precision)
+ source = fields.TypedField("Source", type_="stix.common.InformationSource")
+
+ def __init__(self, value=None, timestamp=None, description=None,
+ source=None):
+ super(Confidence, self).__init__()
+
self.timestamp = timestamp or utils.dates.now()
self.timestamp_precision = "second"
self.value = value
self.description = description
self.source = source
+
# TODO: support confidence_assertion_chain
# self.confidence_assertion_chain = None
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._set_vocab(vocabs.HighMediumLow, value=value)
-
- @property
- def source(self):
- return self._source
-
- @source.setter
- def source(self, value):
- from .information_source import InformationSource
- self._set_var(InformationSource, try_cast=False, source=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- # @property
- # def confidence_assertion_chain(self):
- # return self._confidence_assertion_chain
-
- # @confidence_assertion_chain.setter
- # def confidence_assertion_chain(self, value):
- # if value:
- # raise NotImplementedError()
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Confidence, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- obj.timestamp = utils.dates.serialize_value(self.timestamp)
- obj.timestamp_precision = self.timestamp_precision
-
- if self.value:
- obj.Value = self.value.to_obj(ns_info=ns_info)
- if self.description:
- obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.source:
- obj.Source = self.source.to_obj(ns_info=ns_info)
-
- return obj
-
- def to_dict(self):
- d = utils.to_dict(self, skip=('timestamp_precision',))
-
- if self.timestamp_precision != 'second':
- d['timestamp_precision'] = self.timestamp_precision
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- from .information_source import InformationSource
-
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.timestamp = obj.timestamp
- return_obj.timestamp_precision = obj.timestamp_precision
- return_obj.value = VocabString.from_obj(obj.Value)
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.source = InformationSource.from_obj(obj.Source)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- from .information_source import InformationSource
-
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.timestamp = d.get('timestamp')
- return_obj.timestamp_precision = d.get('timestamp_precision', 'second')
- return_obj.value = VocabString.from_dict(d.get('value'))
- return_obj.description = StructuredText.from_dict(d.get('description'))
- return_obj.source = InformationSource.from_dict(d.get('source'))
-
- return return_obj
-
# class ConfidenceAssertionChain(stix.Entity):
# _namespace = 'http://stix.mitre.org/common-2'
diff --git a/stix/common/datetimewithprecision.py b/stix/common/datetimewithprecision.py
index 248da5f2..28b58342 100644
--- a/stix/common/datetimewithprecision.py
+++ b/stix/common/datetimewithprecision.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.utils as utils
import stix.bindings.stix_common as common_binding
@@ -11,78 +13,43 @@
DATETIME_PRECISION_VALUES = DATE_PRECISION_VALUES + TIME_PRECISION_VALUES
+def validate_precision(instance, value):
+ if value is None:
+ return
+ elif value in DATETIME_PRECISION_VALUES:
+ return
+ else:
+ error = "The precision must be one of {0}. Received '{1}'"
+ error = error.format(DATETIME_PRECISION_VALUES, value)
+ raise ValueError(error)
+
+
class DateTimeWithPrecision(stix.Entity):
_binding = common_binding
_binding_class = _binding.DateTimeWithPrecisionType
_namespace = 'http://stix.mitre.org/common-1'
+ value = fields.DateTimeField("valueOf_", key_name="value")
+ precision = fields.TypedField("precision", preset_hook=validate_precision)
+
def __init__(self, value=None, precision='second'):
super(DateTimeWithPrecision, self).__init__()
self.value = value
self.precision = precision
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = utils.dates.parse_value(value)
-
- @property
- def precision(self):
- return self._precision
-
- @precision.setter
- def precision(self, value):
- if value not in DATETIME_PRECISION_VALUES:
- error = "The precision must be one of {0}. Received '{1}'"
- error = error.format(DATE_PRECISION_VALUES, value)
- raise ValueError(error)
-
- self._precision = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(DateTimeWithPrecision, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- obj.valueOf_ = utils.dates.serialize_value(self.value)
- obj.precision = self.precision
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = obj.valueOf_
- return_obj.precision = obj.precision
- return return_obj
-
def to_dict(self):
if self.precision == 'second':
return utils.dates.serialize_value(self.value)
-
- d = {}
- d['value'] = utils.dates.serialize_value(self.value)
- d['precision'] = self.precision
- return d
+ return super(DateTimeWithPrecision, self).to_dict()
@classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
+ def from_dict(cls, cls_dict):
+ if not cls_dict:
return None
-
- if not return_obj:
- return_obj = cls()
-
- if not isinstance(dict_, dict):
- return_obj.value = dict_
+ elif not isinstance(cls_dict, dict):
+ obj = cls()
+ obj.value = cls_dict
else:
- return_obj.precision = dict_.get('precision')
- return_obj.value = dict_.get('value')
+ obj = super(DateTimeWithPrecision, cls).from_dict(cls_dict)
- return return_obj
+ return obj
diff --git a/stix/common/identity.py b/stix/common/identity.py
index dad8227b..a51b1725 100644
--- a/stix/common/identity.py
+++ b/stix/common/identity.py
@@ -1,142 +1,52 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-from __future__ import absolute_import
+# external
+from mixbox import fields
+from mixbox import entities
+# internal
import stix
import stix.bindings.stix_common as common_binding
+from stix.bindings.stix_common import IdentityType
+
+
+class IdentityFactory(entities.EntityFactory):
+ @classmethod
+ def entity_class(cls, key):
+ import stix.extensions.identity.ciq_identity_3_0 # noqa
+ return stix.lookup_extension(key, default=Identity)
class Identity(stix.Entity):
_binding = common_binding
+ _binding_class = IdentityType
_namespace = 'http://stix.mitre.org/common-1'
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ name = fields.TypedField("Name")
+ related_identities = fields.TypedField("Related_Identities", type_="stix.common.identity.RelatedIdentities")
+
def __init__(self, id_=None, idref=None, name=None, related_identities=None):
+ super(Identity, self).__init__()
+
self.id_ = id_
self.idref = idref
self.name = name
self.related_identities = related_identities
- @property
- def id_(self):
- return self._id
-
- @id_.setter
- def id_(self, value):
- if not value:
- self._id = None
- else:
- self._id = value
- self.idref = None
-
- @property
- def idref(self):
- return self._idref
-
- @idref.setter
- def idref(self, value):
- if not value:
- self._idref = None
- else:
- self._idref = value
- self.id_ = None # unset id_ if idref is present
-
- @property
- def name(self):
- return self._name
-
- @name.setter
- def name(self, value):
- self._name = value if value else None
-
- @property
- def related_identities(self):
- return self._related_identities
-
- @related_identities.setter
- def related_identities(self, value):
- self._related_identities = RelatedIdentities(value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Identity, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding.IdentityType()
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
-
- if self.name:
- return_obj.Name = self.name
- if self.related_identities:
- return_obj.Related_Identities = \
- self.related_identities.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @staticmethod
- def lookup_class(xsi_type):
- if not xsi_type:
- raise ValueError("xsi:type is required")
-
- for (k, v) in _EXTENSION_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- raise ValueError("Unregistered xsi:type %s" % xsi_type)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- import stix.extensions.identity.ciq_identity_3_0 # noqa
-
- if not obj:
- return None
-
- if not return_obj:
- if hasattr(obj, 'xml_type'):
- klass = Identity.lookup_class(obj.xml_type)
- return_obj = klass.from_obj(obj)
- else:
- return_obj = Identity.from_obj(obj, cls())
- else:
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
- return_obj.name = obj.Name
- return_obj.related_identities = \
- RelatedIdentities.from_obj(obj.Related_Identities)
-
- return return_obj
-
def to_dict(self):
- return super(Identity, self).to_dict()
+ d = super(Identity, self).to_dict()
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- import stix.extensions.identity.ciq_identity_3_0 # noqa
-
- if not dict_repr:
- return None
+ if self._XSI_TYPE:
+ d['xsi:type'] = self._XSI_TYPE
- get = dict_repr.get
-
- if not return_obj:
- xsi_type = get('xsi:type')
- if xsi_type:
- klass = Identity.lookup_class(get('xsi:type'))
- return_obj = klass.from_dict(dict_repr)
- else:
- return_obj = Identity.from_dict(dict_repr, cls())
- else:
- return_obj.name = get('name')
- return_obj.id_ = get('id')
- return_obj.idref = get('idref')
- return_obj.related_identities = \
- RelatedIdentities.from_dict(get('related_identities'))
-
- return return_obj
+ return d
+ @staticmethod
+ def lookup_class(xsi_type):
+ return stix.lookup_extension(xsi_type, default=Identity)
# We can't import RelatedIdentity until we have defined the Identity class.
from stix.common.related import RelatedIdentity
@@ -146,14 +56,13 @@ class RelatedIdentities(stix.EntityList):
_namespace = 'http://stix.mitre.org/common-1'
_binding = common_binding
_binding_class = common_binding.RelatedIdentitiesType
- _binding_var = "Related_Identity"
- _contained_type = RelatedIdentity
- _inner_name = "identities"
+ related_identity = fields.TypedField("Related_Identity", RelatedIdentity, multiple=True, key_name="identities")
-#: Mapping of identity extension types to classes
-_EXTENSION_MAP = {}
+ @classmethod
+ def _dict_as_list(cls):
+ return False
-def add_extension(cls):
- _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+# Backwards compatibility
+add_extension = stix.add_extension
diff --git a/stix/common/information_source.py b/stix/common/information_source.py
index d4fac2f0..10e6941e 100644
--- a/stix/common/information_source.py
+++ b/stix/common/information_source.py
@@ -1,19 +1,19 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-from __future__ import absolute_import
-
# external
+from mixbox import fields
import cybox.common
+from cybox.common.tools import ToolInformationList
# internal
import stix
-import stix.utils as utils
import stix.bindings.stix_common as stix_common_binding
# relative
-from . import vocabs, VocabString
-from .identity import Identity
+from .vocabs import VocabField
+from .references import References
+from .identity import Identity, IdentityFactory
from .structured_text import StructuredText
@@ -22,182 +22,47 @@ class InformationSource(stix.Entity):
_binding_class = stix_common_binding.InformationSourceType
_namespace = 'http://stix.mitre.org/common-1'
- def __init__(self, description=None, identity=None, time=None, tools=None, contributing_sources=None, references=None):
- self.description = description
+ identity = fields.TypedField("Identity", type_=Identity, factory=IdentityFactory)
+ description = fields.TypedField("Description", StructuredText)
+ contributing_sources = fields.TypedField("Contributing_Sources", type_="stix.common.information_source.ContributingSources")
+ time = fields.TypedField("Time", cybox.common.Time)
+ roles = VocabField("Role", multiple=True, key_name="roles")
+ tools = fields.TypedField("Tools", ToolInformationList)
+ references = fields.TypedField("References", References)
+
+ def __init__(self, description=None, identity=None, time=None, tools=None,
+ contributing_sources=None, references=None):
+ super(InformationSource, self).__init__()
+
self.identity = identity
+ self.description = description
self.contributing_sources = contributing_sources
self.time = time
self.tools = tools
self.references = references
- self.roles = None
-
- @property
- def contributing_sources(self):
- return self._contributing_sources
-
- @contributing_sources.setter
- def contributing_sources(self, value):
- self._contributing_sources = ContributingSources(value)
def add_contributing_source(self, value):
self.contributing_sources.append(value)
-
- @property
- def references(self):
- return self._references
-
- @references.setter
- def references(self, value):
- self._references = []
- if not value:
- return
- elif utils.is_sequence(value):
- for v in value:
- self.add_reference(v)
- else:
- self.add_reference(value)
-
def add_reference(self, value):
if not value:
return
+ if self.references is None:
+ self.references = References()
# TODO: Check if it's a valid URI?
self.references.append(value)
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- """Sets the value of the description property.
-
- If the value is an instance of basestring, it will be coerced into an
- instance of StructuredText, with its 'text' property set to the input
- value.
-
- """
- self._set_var(StructuredText, description=value)
-
- @property
- def identity(self):
- return self._identity
-
- @identity.setter
- def identity(self, value):
- self._set_var(Identity, try_cast=False, identity=value)
-
- @property
- def time(self):
- return self._time
-
- @time.setter
- def time(self, value):
- self._set_var(cybox.common.Time, try_cast=False, time=value)
-
- @property
- def tools(self):
- return self._tools
-
- @tools.setter
- def tools(self, value):
- self._set_var(cybox.common.ToolInformationList, try_cast=False, tools=value)
-
- @property
- def roles(self):
- return self._roles
-
- @roles.setter
- def roles(self, value):
- self._roles = _Roles(value)
-
def add_role(self, value):
self.roles.append(value)
- def to_obj(self, return_obj=None, ns_info=None):
- super(InformationSource, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.description is not None:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.references:
- return_obj.References = stix_common_binding.ReferencesType(Reference=self.references)
- if self.contributing_sources:
- return_obj.Contributing_Sources = self.contributing_sources.to_obj(ns_info=ns_info)
- if self.identity:
- return_obj.Identity = self.identity.to_obj(ns_info=ns_info)
- if self.time:
- return_obj.Time = self.time.to_obj(ns_info=ns_info)
- if self.tools:
- return_obj.Tools = self.tools.to_obj(ns_info=ns_info)
- if self.roles:
- return_obj.Role = self.roles.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.identity = Identity.from_obj(obj.Identity)
- return_obj.contributing_sources = ContributingSources.from_obj(obj.Contributing_Sources)
- return_obj.roles = _Roles.from_obj(obj.Role)
-
- if obj.References:
- return_obj.references = obj.References.Reference
- if obj.Time:
- return_obj.time = cybox.common.Time.from_obj(obj.Time)
- if obj.Tools:
- return_obj.tools = cybox.common.ToolInformationList.from_obj(obj.Tools)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- # To resolve circular dependency
- # TODO: Improve how this extension is handled.
-
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.references = get('references')
- return_obj.contributing_sources = ContributingSources.from_dict(get('contributing_sources'))
- return_obj.identity = Identity.from_dict(get('identity'))
- return_obj.time = cybox.common.Time.from_dict(get('time'))
- return_obj.tools = cybox.common.ToolInformationList.from_list(get('tools'))
- return_obj.roles = _Roles.from_dict(get('roles'))
-
- return return_obj
-
- def to_dict(self):
- return super(InformationSource, self).to_dict()
-
class ContributingSources(stix.EntityList):
_namespace = "http://stix.mitre.org/common-1"
_binding = stix_common_binding
_binding_class = stix_common_binding.ContributingSourcesType
- _binding_var = "Source"
- _contained_type = InformationSource
- _inner_name = "sources"
+ source = fields.TypedField("Source", InformationSource, multiple=True, key_name="sources")
-# NOT AN ACTUAL STIX TYPE!
-class _Roles(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.InformationSourceRole(value)
+ @classmethod
+ def _dict_as_list(cls):
+ return False
diff --git a/stix/common/kill_chains/__init__.py b/stix/common/kill_chains/__init__.py
index 02189dda..0214c4fd 100644
--- a/stix/common/kill_chains/__init__.py
+++ b/stix/common/kill_chains/__init__.py
@@ -1,50 +1,40 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+from mixbox import typedlist
+
# internal
import stix
import stix.bindings.stix_common as common_binding
+from mixbox.vendor.six import string_types
+
class KillChain(stix.Entity):
_binding = common_binding
_namespace = 'http://stix.mitre.org/common-1'
_binding_class = _binding.KillChainType
+ id_ = fields.TypedField("id")
+ name = fields.TypedField("name")
+ definer = fields.TypedField("definer")
+ reference = fields.TypedField("reference")
+ number_of_phases = fields.TypedField("number_of_phases")
+ kill_chain_phases = fields.TypedField("Kill_Chain_Phase", type_="stix.common.kill_chains.KillChainPhase", multiple=True, key_name="kill_chain_phases")
+
def __init__(self, id_=None, name=None, definer=None, reference=None):
+ super(KillChain, self).__init__()
+
self.id_ = id_
self.name = name
self.definer = definer
self.reference = reference
self.number_of_phases = None # can we just do len(self.kill_chain_phases)?
- self.kill_chain_phases = None
-
- @property
- def kill_chain_phases(self):
- return self._kill_chain_phases
-
- @kill_chain_phases.setter
- def kill_chain_phases(self, value):
- self._kill_chain_phases = _KillChainPhases(value)
def add_kill_chain_phase(self, value):
self.kill_chain_phases.append(value)
- def to_obj(self, return_obj=None, ns_info=None):
- super(KillChain, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.name = self.name
- return_obj.definer = self.definer
- return_obj.reference = self.reference
- return_obj.number_of_phases = self.number_of_phases
- return_obj.Kill_Chain_Phase = self.kill_chain_phases.to_obj(ns_info=ns_info)
-
- return return_obj
-
def __eq__(self, other):
if self is other:
return True
@@ -57,48 +47,17 @@ def __eq__(self, other):
def __ne__(self, other):
return not self.__eq__(other)
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.name = obj.name
- return_obj.definer = obj.definer
- return_obj.reference = obj.reference
- return_obj.number_of_phases = obj.number_of_phases
- return_obj.kill_chain_phases = _KillChainPhases.from_obj(obj.Kill_Chain_Phase)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = d.get
- return_obj.id_ = get('id')
- return_obj.name = get('name')
- return_obj.definer = get('definer')
- return_obj.reference = get('reference')
- return_obj.number_of_phases = get('number_of_phases')
- return_obj.kill_chain_phases = \
- _KillChainPhases.from_dict(get('kill_chain_phases'))
-
- return return_obj
-
class KillChains(stix.EntityList):
_binding = common_binding
_namespace = 'http://stix.mitre.org/common-1'
_binding_class = _binding.KillChainsType
- _contained_type = KillChain
- _binding_var = "Kill_Chain"
- _inner_name = "kill_chains"
+
+ kill_chain = fields.TypedField("Kill_Chain", KillChain, multiple=True, key_name="kill_chains")
+
+ @classmethod
+ def _dict_as_list(cls):
+ return False
class KillChainPhase(stix.Entity):
@@ -106,42 +65,17 @@ class KillChainPhase(stix.Entity):
_namespace = 'http://stix.mitre.org/common-1'
_binding_class = _binding.KillChainPhaseType
+ phase_id = fields.TypedField("phase_id")
+ name = fields.TypedField("name")
+ ordinality = fields.IntegerField("ordinality")
+
def __init__(self, phase_id=None, name=None, ordinality=None):
+ super(KillChainPhase, self).__init__()
+
self.phase_id = phase_id
self.name = name
self.ordinality = ordinality
- @property
- def phase_id(self):
- return self._phase_id
-
- @phase_id.setter
- def phase_id(self, value):
- self._set_var(basestring, try_cast=False, phase_id=value)
-
- @property
- def ordinality(self):
- return self._ordinality
-
- @ordinality.setter
- def ordinality(self, value):
- if value is not None:
- self._ordinality = int(value)
- else:
- self._ordinality = None
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(KillChainPhase, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- return_obj.phase_id = self.phase_id
- return_obj.name = self.name
- return_obj.ordinality = self.ordinality
-
- return return_obj
-
def __eq__(self, other):
if other is self:
return True
@@ -155,103 +89,54 @@ def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
+ # TODO (bworrell): Is all the tuple(sorted(...))) needed?
return hash(tuple(sorted(self.to_dict().items())))
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.phase_id = obj.phase_id
- return_obj.name = obj.name
- return_obj.ordinality = obj.ordinality
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.phase_id = d.get('phase_id')
- return_obj.name = d.get('name')
- return_obj.ordinality = d.get('ordinality')
-
- return return_obj
-
- def to_dict(self):
- return super(KillChainPhase, self).to_dict()
-
class KillChainPhaseReference(KillChainPhase):
_binding = common_binding
_namespace = 'http://stix.mitre.org/common-1'
_binding_class = _binding.KillChainPhaseReferenceType
+ kill_chain_id = fields.TypedField("kill_chain_id")
+ kill_chain_name = fields.TypedField("kill_chain_name")
+
def __init__(self, phase_id=None, name=None, ordinality=None, kill_chain_id=None, kill_chain_name=None):
super(KillChainPhaseReference, self).__init__(phase_id, name, ordinality)
self.kill_chain_id = kill_chain_id
self.kill_chain_name = kill_chain_name
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(KillChainPhaseReference, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- return_obj.kill_chain_id = self.kill_chain_id
- return_obj.kill_chain_name = self.kill_chain_name
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
- super(KillChainPhaseReference, cls).from_obj(obj, return_obj=return_obj)
+class _KillChainPhaseReferenceList(typedlist.TypedList):
+ def __init__(self, *args):
+ super(_KillChainPhaseReferenceList, self).__init__(type=KillChainPhaseReference, *args)
- return_obj.kill_chain_id = obj.kill_chain_id
- return_obj.kill_chain_name = obj.kill_chain_name
- return return_obj
-
- def to_dict(self):
- return super(KillChainPhaseReference, self).to_dict()
+ def _fix_value(self, value):
+ if not isinstance(value, KillChainPhase):
+ return super(_KillChainPhaseReferenceList, self)._fix_value(value)
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
+ if value.phase_id:
+ return KillChainPhaseReference(phase_id=value.phase_id)
- super(KillChainPhaseReference, cls).from_dict(d, return_obj=return_obj)
- return_obj.kill_chain_id = d.get('kill_chain_id')
- return_obj.kill_chain_name = d.get('kill_chain_name')
- return return_obj
+ raise ValueError("KillChainPhase must have a phase_id.")
class KillChainPhasesReference(stix.EntityList):
_binding = common_binding
_namespace = 'http://stix.mitre.org/common-1'
_binding_class = _binding.KillChainPhasesReferenceType
- _contained_type = KillChainPhaseReference
- _binding_var = "Kill_Chain_Phase"
- _inner_name = "kill_chain_phases"
- def _fix_value(self, value):
- if not isinstance(value, KillChainPhase):
- return super(KillChainPhasesReference, self)._fix_value(value)
+ kill_chain_phase = fields.TypedField(
+ name="Kill_Chain_Phase",
+ type_=KillChainPhaseReference,
+ multiple=True,
+ listfunc=_KillChainPhaseReferenceList,
+ key_name="kill_chain_phases"
+ )
- if value.phase_id:
- return KillChainPhaseReference(phase_id=value.phase_id)
-
- raise ValueError("KillChainPhase must have a phase_id.")
+ @classmethod
+ def _dict_as_list(cls):
+ return False
# NOT AN ACTUAL STIX TYPE!
diff --git a/stix/common/kill_chains/lmco.py b/stix/common/kill_chains/lmco.py
index 76430d4f..ad087e43 100644
--- a/stix/common/kill_chains/lmco.py
+++ b/stix/common/kill_chains/lmco.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
from . import KillChain, KillChainPhase
diff --git a/stix/common/names.py b/stix/common/names.py
index 31a95943..a0f59320 100644
--- a/stix/common/names.py
+++ b/stix/common/names.py
@@ -1,19 +1,20 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import fields
+
# internal
import stix
import stix.bindings.stix_common as common_binding
# relative
-from .vocabs import VocabString
+from .vocabs import VocabField
class Names(stix.EntityList):
- _namespace = "http://stix.mitre.org/common-1"
+ _namespace = 'http://stix.mitre.org/common-1'
_binding = common_binding
_binding_class = _binding.NamesType
- _contained_type = VocabString
- _binding_var = 'Name'
- _inner_name = 'names'
- _dict_as_list = True
+
+ name = VocabField("Name", multiple=True)
diff --git a/stix/common/profiles.py b/stix/common/profiles.py
new file mode 100644
index 00000000..3e2f2d8d
--- /dev/null
+++ b/stix/common/profiles.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
+import collections
+
+from mixbox import compat
+from mixbox import fields
+
+import stix
+from stix.bindings import stix_common as stix_common_binding
+
+
+class Profiles(compat.MutableSequence, stix.Entity):
+ _binding = stix_common_binding
+ _binding_class = stix_common_binding.ProfilesType
+ _namespace = 'http://stix.mitre.org/common-1'
+
+ # Fields
+ profile = fields.TypedField("Profile", multiple=True)
+
+ def __init__(self, profiles=None):
+ super(Profiles, self).__init__()
+ self.profile = profiles
+
+ def __len__(self):
+ return self.profile.__len__()
+
+ def __getitem__(self, item):
+ return self.profile.__getitem__(item)
+
+ def __setitem__(self, key, value):
+ self.profile.__setitem__(key, value)
+
+ def __delitem__(self, key):
+ self.profile.__delitem__(key)
+
+ def insert(self, index, value):
+ self.profile.insert(index, value)
+
+ def to_dict(self):
+ return [x for x in self]
+
+ @classmethod
+ def from_dict(cls, cls_dict=None):
+ if not cls_dict:
+ return None
+
+ obj = cls()
+ obj.profile = [x for x in cls_dict]
+ return obj
diff --git a/stix/common/references.py b/stix/common/references.py
new file mode 100644
index 00000000..9bedda4d
--- /dev/null
+++ b/stix/common/references.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
+import collections
+
+from mixbox import compat
+from mixbox import fields
+
+import stix
+from stix.bindings import stix_common as stix_common_binding
+
+
+class References(compat.MutableSequence, stix.Entity):
+ _binding = stix_common_binding
+ _binding_class = stix_common_binding.ReferencesType
+ _namespace = 'http://stix.mitre.org/common-1'
+
+ # Fields
+ reference = fields.TypedField("Reference", multiple=True)
+
+ def __init__(self, references=None):
+ super(References, self).__init__()
+ self.reference = references
+
+ def __len__(self):
+ return self.reference.__len__()
+
+ def __getitem__(self, item):
+ return self.reference.__getitem__(item)
+
+ def __setitem__(self, key, value):
+ self.reference.__setitem__(key, value)
+
+ def __delitem__(self, key):
+ self.reference.__delitem__(key)
+
+ def insert(self, index, value):
+ self.reference.insert(index, value)
+
+ def to_dict(self):
+ return [x for x in self]
+
+ @classmethod
+ def from_dict(cls, cls_dict=None):
+ if not cls_dict:
+ return None
+
+ obj = cls()
+ obj.reference = [x for x in cls_dict]
+ return obj
diff --git a/stix/common/related.py b/stix/common/related.py
index f3718dfb..26736950 100644
--- a/stix/common/related.py
+++ b/stix/common/related.py
@@ -1,190 +1,91 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-from __future__ import absolute_import
+# stdlib
+import functools
+
+# mixbox
+from mixbox import fields
+from mixbox import typedlist
+
+# cybox
+from cybox.core import Observable
# internal
import stix
-import stix.utils as utils
import stix.bindings.stix_common as common_binding
import stix.bindings.stix_core as core_binding
# relative
-from .vocabs import VocabString
+from .vocabs import VocabField
from .information_source import InformationSource
from .confidence import Confidence
+ALLOWED_SCOPE = ('inclusive', 'exclusive')
+
+
+def validate_scope(instance, value):
+ if not value:
+ return
+ elif value in ALLOWED_SCOPE:
+ return
+ else:
+ msg = "Scope must be one of {0}. Received '{1}'"
+ msg = msg.format(ALLOWED_SCOPE, value)
+ raise ValueError(msg)
+
+
class GenericRelationship(stix.Entity):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.GenericRelationshipType
+ confidence = fields.TypedField("Confidence", Confidence)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+ relationship = VocabField("Relationship")
+
def __init__(self, confidence=None, information_source=None, relationship=None):
+ super(GenericRelationship, self).__init__()
+
self.confidence = confidence
self.information_source = information_source
self.relationship = relationship
- @property
- def confidence(self):
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._set_var(Confidence, confidence=value)
-
- @property
- def information_source(self):
- return self._information_source
-
- @information_source.setter
- def information_source(self, value):
- self._set_var(InformationSource, try_cast=False, information_source=value)
-
- @property
- def relationship(self):
- return self._relationship
-
- @relationship.setter
- def relationship(self, value):
- self._set_vocab(relationship=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.information_source = InformationSource.from_obj(obj.Information_Source)
- return_obj.relationship = VocabString.from_obj(obj.Relationship)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(GenericRelationship, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.information_source:
- return_obj.Information_Source = self.information_source.to_obj(ns_info=ns_info)
- if self.relationship:
- return_obj.Relationship = self.relationship.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.confidence = Confidence.from_dict(dict_repr.get('confidence'))
- return_obj.information_source = InformationSource.from_dict(dict_repr.get('information_source'))
- return_obj.relationship = VocabString.from_dict(dict_repr.get('relationship'))
-
- return return_obj
-
- def to_dict(self,):
- d = {}
- if self.confidence:
- d['confidence'] = self.confidence.to_dict()
- if self.information_source:
- d['information_source'] = self.information_source.to_dict()
- if self.relationship:
- d['relationship'] = self.relationship.to_dict()
-
- return d
-
class RelatedPackageRef(GenericRelationship):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedPackageRefType
- def __init__(self, **kwargs):
- super(RelatedPackageRef, self).__init__(**kwargs)
- self.idref = None
- self.timestamp = None
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj = super(RelatedPackageRef, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.idref:
- return_obj.idref = self.idref
- if self.timestamp:
- return_obj.timestamp = self.timestamp
-
- return return_obj
-
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- def to_dict(self):
- d = super(RelatedPackageRef, self).to_dict()
-
- if self.idref:
- d['idref'] = self.idref
- if self.timestamp:
- d['timestamp'] = utils.dates.serialize_value(self.timestamp)
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(RelatedPackageRef, cls).from_obj(obj, return_obj)
-
- return_obj.idref = obj.idref
- return_obj.timestamp = obj.timestamp
-
- return return_obj
+ idref = fields.IdrefField("idref")
+ timestamp = fields.DateTimeField("timestamp")
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(RelatedPackageRef, cls).from_dict(dict_repr, return_obj)
+ def __init__(self, idref=None, timestamp=None, confidence=None,
+ information_source=None, relationship=None):
- return_obj.idref = dict_repr.get("idref")
- return_obj.timestamp = dict_repr.get("timestamp")
+ super(RelatedPackageRef, self).__init__(
+ confidence=confidence,
+ information_source=information_source,
+ relationship=relationship
+ )
- return return_obj
+ self.idref = idref
+ self.timestamp = timestamp
-class GenericRelationshipList(stix.EntityList):
+class GenericRelationshipEntity(stix.Entity):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = _binding.GenericRelationshipListType
_ALLOWED_SCOPE = ('inclusive', 'exclusive')
+ scope = fields.TypedField("scope")
+
def __init__(self, scope=None, *args):
- super(GenericRelationshipList, self).__init__(*args)
+
+ super(GenericRelationshipEntity, self).__init__(*args)
self.scope = scope
def __nonzero__(self):
@@ -193,260 +94,195 @@ def __nonzero__(self):
bool(self.scope)
)
- @property
- def scope(self):
- return self._scope
- @scope.setter
- def scope(self, value):
- if value is None or value in self._ALLOWED_SCOPE:
- self._scope = value
- return
+class GenericRelationshipList(stix.EntityList):
+ """Base class for concrete GenericRelationshipList types.
- msg = "Scope must be one of {0}. Received '{1}'"
- msg = msg.format(self._ALLOWED_SCOPE, value)
- raise ValueError(msg)
+ Note:
+ Subclasses must supply exactly one multiple TypedField.
+ """
- def to_obj(self, return_obj=None, ns_info=None):
- list_obj = super(GenericRelationshipList, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
+ _namespace = "http://stix.mitre.org/common-1"
+ _binding = common_binding
+ _binding_class = _binding.GenericRelationshipListType
- list_obj.scope = self.scope
- return list_obj
+ scope = fields.TypedField("scope", preset_hook=validate_scope)
- def to_dict(self):
- return super(GenericRelationshipList, self).to_dict()
+ def __init__(self, scope=None, *args):
+ super(GenericRelationshipList, self).__init__(*args)
+ self.scope = scope
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if return_obj is None:
- return_obj = cls()
-
- super(GenericRelationshipList, cls).from_obj(
- obj,
- return_obj=return_obj,
- contained_type=cls._contained_type,
- binding_var=cls._binding_var
- )
+ def __nonzero__(self):
+ return (super(GenericRelationshipList, self).__nonzero__() or
+ bool(self.scope))
- return_obj.scope = obj.scope
+ @classmethod
+ def _dict_as_list(cls):
+ return False
- return return_obj
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if return_obj is None:
- return_obj = cls()
-
- super(GenericRelationshipList, cls).from_dict(
- dict_repr,
- return_obj=return_obj,
- contained_type=cls._contained_type,
- inner_name=cls._inner_name
- )
+class _RelatedPackageList(typedlist.TypedList):
+ def __init__(self, *args):
+ super(_RelatedPackageList, self).__init__(type=RelatedPackageRef, *args)
- return_obj.scope = dict_repr.get('scope')
+ def _fix_value(self, value):
+ from stix.core import STIXPackage
- return return_obj
+ if isinstance(value, STIXPackage) and value.id_:
+ return RelatedPackageRef(idref=value.id_, timestamp=value.timestamp)
+ fmt = ("Cannot add type '{0}' to RelatedPackageRefs collection. "
+ "Expected RelatedPackageRef or STIXPackage")
+ error = fmt.format(type(value))
+ raise TypeError(error)
-class RelatedPackages(GenericRelationshipList):
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding = core_binding
- _binding_class = core_binding.RelatedPackagesType
- _binding_var = "Related_Package"
- # _contained_type is patched in common/__init__.py
- _inner_name = "related_packages"
+ def _is_valid(self, value):
+ return super(_RelatedPackageList, self)._is_valid(value)
class RelatedPackageRefs(stix.EntityList):
_namespace = 'http://stix.mitre.org/common-1'
_binding = common_binding
_binding_class = common_binding.RelatedPackageRefsType
- _binding_var = "Package_Reference"
- _contained_type = RelatedPackageRef
- _inner_name = "packages"
+
+ package = fields.TypedField(
+ name="Package_Reference",
+ type_=RelatedPackageRef,
+ multiple=True,
+ key_name="packages",
+ listfunc=_RelatedPackageList
+ )
+
+ @classmethod
+ def _dict_as_list(cls):
+ return False
class _BaseRelated(GenericRelationship):
"""A base class for related types.
This class is not a real STIX type and should not be directly instantiated.
+
+ Note:
+ Subclasses must supply a TypedField named `item`!
"""
- # Subclasses should define
- # - _base_type
- # - _inner_var (This is the name of the contained XML element, and the
- # lowercase version is used for the key name in the
- # dictionary representation).
- _base_type = None
- _inner_var = None
+ item = None # override in subclass.
def __init__(self, item=None, confidence=None,
information_source=None, relationship=None):
+
super(_BaseRelated, self).__init__(
confidence,
information_source,
relationship
)
- self.item = item
-
- @property
- def item(self):
- return self._item
-
- @item.setter
- def item(self, value):
- self._set_item(value)
-
- def _set_item(self, value):
- if value and not isinstance(value, self._base_type):
- error = "Value must be instance of %s" % self._base_type.__name__
- raise ValueError(error)
-
- self._item = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(_BaseRelated, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.item:
- setattr(return_obj, self._inner_var, self.item.to_obj(ns_info=ns_info))
-
- return return_obj
-
- def to_dict(self):
- d = utils.to_dict(self, skip=('item',))
-
- if self.item:
- d[self._inner_var.lower()] = self.item.to_dict()
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(_BaseRelated, cls).from_obj(obj, return_obj)
-
- contained_item = getattr(obj, cls._inner_var)
- return_obj.item = cls._base_type.from_obj(contained_item)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(_BaseRelated, cls).from_dict(dict_repr, return_obj)
-
- contained_item = dict_repr.get(cls._inner_var.lower())
- return_obj.item = cls._base_type.from_dict(contained_item)
-
- return return_obj
+ self.item = item
class RelatedCampaign(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedCampaignType
- # _base_type is set in common/__init__.py
- _inner_var = "Campaign"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Campaign", type_="stix.campaign.Campaign")
class RelatedCOA(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedCourseOfActionType
- # _base_type is set in common/__init__.py
- _inner_var = "Course_Of_Action"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Course_Of_Action", type_="stix.coa.CourseOfAction")
class RelatedExploitTarget(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedExploitTargetType
- # _base_type is set in common/__init__.py
- _inner_var = "Exploit_Target"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Exploit_Target", type_="stix.exploit_target.ExploitTarget")
class RelatedIdentity(_BaseRelated):
_namespace = 'http://stix.mitre.org/common-1'
_binding = common_binding
_binding_class = common_binding.RelatedIdentityType
- # _base_type is set in common/__init__.py
- _inner_var = "Identity"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Identity", type_="stix.common.identity.Identity", factory="stix.common.identity.IdentityFactory")
class RelatedIncident(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedIncidentType
- # _base_type is set in common/__init__.py
- _inner_var = "Incident"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Incident", type_="stix.incident.Incident")
class RelatedIndicator(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedIndicatorType
- # _base_type is set in common/__init__.py
- _inner_var = "Indicator"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Indicator", type_="stix.indicator.Indicator")
class RelatedObservable(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedObservableType
- # _base_type is set in common/__init__.py
- _inner_var = "Observable"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Observable", type_=Observable)
class RelatedThreatActor(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedThreatActorType
- # _base_type is set in common/__init__.py
- _inner_var = "Threat_Actor"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Threat_Actor", type_="stix.threat_actor.ThreatActor")
class RelatedTTP(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = common_binding.RelatedTTPType
- # _base_type is set in common/__init__.py
- _inner_var = "TTP"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("TTP", type_="stix.ttp.TTP")
class RelatedPackage(_BaseRelated):
_namespace = "http://stix.mitre.org/stix-1"
_binding = core_binding
_binding_class = core_binding.RelatedPackageType
- # _base_type is set in common/__init__.py
- _inner_var = "Package"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Package", type_="stix.core.STIXPackage")
class RelatedCampaignRef(_BaseRelated):
_namespace = "http://stix.mitre.org/common-1"
_binding = common_binding
_binding_class = _binding.RelatedCampaignReferenceType
- # _base_type is set in common/__init__.py
- _inner_var = "Campaign"
+
+ # _BaseRelated requires an "item" field.
+ item = fields.TypedField("Campaign", type_="stix.common.CampaignRef")
+
+
+class RelatedPackages(GenericRelationshipList):
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding = core_binding
+ _binding_class = core_binding.RelatedPackagesType
+
+ related_package = fields.TypedField("Related_Package", RelatedPackage, multiple=True, key_name="related_packages")
diff --git a/stix/common/statement.py b/stix/common/statement.py
index 69294d18..b1950266 100644
--- a/stix/common/statement.py
+++ b/stix/common/statement.py
@@ -1,15 +1,20 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
from __future__ import absolute_import
+from mixbox import fields
+
import stix
import stix.utils as utils
import stix.bindings.stix_common as common_binding
+from .datetimewithprecision import validate_precision
from .confidence import Confidence
from .structured_text import StructuredText
-from .vocabs import VocabString, HighMediumLow
+from .vocabs import VocabField, HighMediumLow
+import mixbox
+from stix.common.vocabs import VocabString
class Statement(stix.Entity):
@@ -17,8 +22,18 @@ class Statement(stix.Entity):
_binding = common_binding
_binding_class = common_binding.StatementType
+ # Fields
+ timestamp = fields.DateTimeField("timestamp")
+ timestamp_precision = fields.TypedField("timestamp_precision", preset_hook=validate_precision)
+ value = VocabField("Value", VocabString)
+ description = fields.TypedField("Description", StructuredText)
+ confidence = fields.TypedField("Confidence", Confidence)
+ source = fields.TypedField("Source", type_="stix.common.InformationSource")
+
def __init__(self, value=None, timestamp=None, description=None,
source=None):
+ super(Statement, self).__init__()
+
self.timestamp = timestamp or utils.dates.now()
self.timestamp_precision = "second"
self.value = value
@@ -26,100 +41,20 @@ def __init__(self, value=None, timestamp=None, description=None,
self.source = source
self.confidence = None
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._set_vocab(HighMediumLow, value=value)
-
- @property
- def source(self):
- return self._source
-
- @source.setter
- def source(self, value):
- from .information_source import InformationSource
- self._set_var(InformationSource, try_cast=False, source=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Statement, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
-
- if self.timestamp:
- obj.timestamp = self.timestamp.isoformat()
- obj.timestamp_precision = self.timestamp_precision
- if self.value:
- obj.Value = self.value.to_obj(ns_info=ns_info)
- if self.description:
- obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.source:
- obj.Source = self.source.to_obj(ns_info=ns_info)
- if self.confidence:
- obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- return obj
+class StatementField(mixbox.fields.TypedField):
+ def __init__(self, *args, **kwargs):
+ self._vocab_type = kwargs.pop("vocab_type")
+ super(StatementField, self).__init__(*args, **kwargs)
+ self.type_ = Statement
- def to_dict(self):
- d = utils.to_dict(self, skip=('timestamp_precision',))
-
- if self.timestamp_precision != 'second':
- d['timestamp_precision'] = self.timestamp_precision
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- from .information_source import InformationSource
-
- if not obj:
+ def _clean(self, value):
+ if value is None:
return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.timestamp = obj.timestamp
- return_obj.timestamp_precision = obj.timestamp_precision
- return_obj.value = VocabString.from_obj(obj.Value)
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.source = InformationSource.from_obj(obj.Source)
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- from .information_source import InformationSource
-
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.timestamp = d.get('timestamp')
- return_obj.timestamp_precision = d.get('timestamp_precision', 'second')
- return_obj.value = VocabString.from_dict(d.get('value'))
- return_obj.description = StructuredText.from_dict(d.get('description'))
- return_obj.source = InformationSource.from_dict(d.get('source'))
- return_obj.confidence = Confidence.from_dict(d.get('confidence'))
-
- return return_obj
+ elif isinstance(value, Statement):
+ return value
+ elif isinstance(value, stix.common.VocabString):
+ return Statement(value)
+ else:
+ vocabklass = self._vocab_type
+ return Statement(vocabklass(value))
diff --git a/stix/common/structured_text.py b/stix/common/structured_text.py
index f9b07d89..66f6c187 100644
--- a/stix/common/structured_text.py
+++ b/stix/common/structured_text.py
@@ -1,69 +1,77 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+import itertools
+import contextlib
+import collections
+from sys import version_info
+
+from mixbox import fields
+
import stix
+import stix.utils as utils
import stix.bindings.stix_common as stix_common_binding
+from mixbox.vendor.six import text_type
class StructuredText(stix.Entity):
+ """Used for storing descriptive text elements.
+
+ Attributes:
+ id_: An id for the text element, typically used for controlled
+ structure xpath selectors.
+ value: The text value of this object.
+ structuring_format: The format of the text. For example, ``html5``.
+ """
+
_binding = stix_common_binding
+ _binding_class = _binding.StructuredTextType
_namespace = 'http://stix.mitre.org/common-1'
+ id_ = fields.IdField("id")
+ value = fields.TypedField("valueOf_", key_name="value")
+ structuring_format = fields.TypedField("structuring_format")
+
def __init__(self, value=None):
+ super(StructuredText, self).__init__()
+
+ self.id_ = None
self.value = value
self.structuring_format = None
- def to_obj(self, return_obj=None, ns_info=None):
- super(StructuredText, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
+ def is_plain(self):
+ plain = (
+ (not self.id_) and
+ (not self.structuring_format)
)
- text_obj = self._binding.StructuredTextType()
-
- text_obj.valueOf_ = self.value
- if self.structuring_format is not None:
- text_obj.structuring_format = self.structuring_format
- return text_obj
+ return plain
def to_dict(self):
+ """Converts this object into a dictionary representation.
+
+ Note:
+ If no properies or attributes are set other than ``value``,
+ this will return a string.
+
+ """
# Return a plain string if there is no format specified.
- if self.structuring_format is None:
+ if self.is_plain():
return self.value
else:
return super(StructuredText, self).to_dict()
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = obj.valueOf_
- return_obj.structuring_format = obj.structuring_format
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
+ def __str__(self):
+ """Returns a UTF-8 encoded string representation of the ``value``.
- if not isinstance(d, dict):
- return_obj.value = d
+ """
+ if version_info < (3,):
+ return self.__unicode__().encode("utf-8")
else:
- return_obj.value = d.get('value')
- return_obj.structuring_format = d.get('structuring_format')
-
- return return_obj
-
- def __str__(self):
- return self.__unicode__().encode("utf-8")
+ return self.__unicode__()
def __unicode__(self):
- return unicode(self.value)
+ """Returns a ``unicode`` string representation of the ``value``.
+
+ """
+ return text_type(self.value)
diff --git a/stix/common/tools.py b/stix/common/tools.py
index 046b4332..2bcca8f7 100644
--- a/stix/common/tools.py
+++ b/stix/common/tools.py
@@ -1,8 +1,11 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# external
+from mixbox import fields
+
import cybox.common
+from cybox.common.vocabs import VocabField
# internal
import stix
@@ -10,83 +13,25 @@
# relative
from .structured_text import StructuredText
+from .vocabs import AttackerToolType
+
class ToolInformation(stix.Entity, cybox.common.ToolInformation):
_namespace = 'http://stix.mitre.org/common-1'
_binding = common_binding
_binding_class = common_binding.ToolInformationType
-
- def __init__(self, title=None, short_description=None, tool_name=None, tool_vendor=None):
- super(ToolInformation, self).__init__(tool_name=tool_name, tool_vendor=tool_vendor)
- self.title = title
- self.short_description = short_description
-
- @property
- def title(self):
- return self._title
- @title.setter
- def title(self, value):
- self._title = value
+ title = fields.TypedField("Title")
+ short_description = fields.TypedField("Short_Description", StructuredText)
+ type_ = VocabField("Type", AttackerToolType, multiple=True)
- @property
- def short_description(self):
- return self._short_description
+ def __init__(self, title=None, short_description=None, tool_name=None,
+ tool_vendor=None):
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- stix.Entity.to_obj(self, return_obj=return_obj, ns_info=ns_info)
- cybox.common.ToolInformation.to_obj(
- self,
- return_obj=return_obj,
- ns_info=ns_info
+ super(ToolInformation, self).__init__(
+ tool_name=tool_name,
+ tool_vendor=tool_vendor
)
- return_obj.Title = self.title
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- cybox.common.ToolInformation.from_obj(obj, return_obj)
-
- return_obj.title = obj.Title
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
-
- return return_obj
-
- def to_dict(self):
- d = cybox.common.ToolInformation.to_dict(self)
-
- if self.title:
- d['title'] = self.title
- if self.short_description:
- d['short_description'] = self.short_description.to_dict()
-
- return d
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- cybox.common.ToolInformation.from_dict(dict_repr, return_obj)
- return_obj.title = dict_repr.get('title')
- return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description'))
-
- return return_obj
+ self.title = title
+ self.short_description = short_description
diff --git a/stix/common/vocabs.py b/stix/common/vocabs.py
index db0ef3bd..105056da 100644
--- a/stix/common/vocabs.py
+++ b/stix/common/vocabs.py
@@ -1,15 +1,89 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# stdlib
+from functools import partial
+
+# mixbox
+from mixbox import entities, fields, typedlist
+
+# cybox
+from cybox.common import vocabs
+
+# stix
import stix
import stix.bindings.stix_common as stix_common_binding
-# TODO: handle normalization
-# from cybox.utils import normalize_to_xml, denormalize_from_xml
+def validate_value(instance, value):
+ allowed = instance._ALLOWED_VALUES
+
+ if not value:
+ return
+ elif not allowed:
+ return
+ elif value in allowed:
+ return
+ else:
+ error = "Value for vocab {instance.__class__} must be one of {allowed}. Received '{value}'"
+ error = error.format(**locals())
+ raise ValueError(error)
+
+
+class VocabList(typedlist.TypedList):
+ """VocabString fields can be any type of VocabString, though there is often
+ a preferred/default VocabString type.
+
+ The TypedList will attempt to make sure that every input item is an instance
+ of the default VocabString and throw an error if it isn't. This sublcass
+ overrides that behavior and allows any instance of VocabString to be
+ inserted.
+ """
+
+ def _is_valid(self, value):
+ return isinstance(value, VocabString)
+
+
+class VocabField(fields.TypedField):
+ """TypedField subclass for VocabString fields."""
+
+ def __init__(self, *args, **kwargs):
+ """Intercepts the __init__() call to TypedField.
+
+ Set the type that will be used in from_dict and from_obj calls to
+ :class:`VocabString`.
+
+ Set the type that will be used in ``__set__`` for casting as the
+ original ``type_`` argument, or :class:`VocabString` if no `type_`
+ argument was provided.
+
+ """
+ super(VocabField, self).__init__(*args, **kwargs)
+ self.factory = VocabFactory # force this factory
+
+ if self._unresolved_type is None:
+ self.type_ = VocabString
+
+ self._listfunc = partial(VocabList, type=self._unresolved_type)
+
+ def check_type(self, value):
+ return isinstance(value, VocabString)
+
+
+class VocabFactory(entities.EntityFactory):
+ _convert_strings = True
+
+ @classmethod
+ def entity_class(cls, key):
+ try:
+ return stix.lookup_extension(key, default=VocabString)
+ except ValueError:
+ return VocabString
class VocabString(stix.Entity):
+ __hash__ = entities.Entity.__hash__
+
_binding = stix_common_binding
_binding_class = stix_common_binding.ControlledVocabularyStringType
_namespace = 'http://stix.mitre.org/common-1'
@@ -18,31 +92,16 @@ class VocabString(stix.Entity):
_XSI_TYPE = None
_ALLOWED_VALUES = None
+ value = fields.TypedField("valueOf_", key_name="value", preset_hook=validate_value)
+ vocab_name = fields.TypedField("vocab_name")
+ vocab_reference = fields.TypedField("vocab_reference")
+ xsi_type = fields.TypedField("xsi_type", key_name="xsi:type")
+
def __init__(self, value=None):
super(VocabString, self).__init__()
self.value = value
self.xsi_type = self._XSI_TYPE
- self.vocab_name = None
- self.vocab_reference = None
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, v):
- allowed = self._ALLOWED_VALUES
-
- if not v:
- self._value = None
- elif allowed and (v not in allowed):
- error = "Value must be one of {0}. Received '{1}'"
- error = error.format(allowed, v)
- raise ValueError(error)
- else:
- self._value = v
-
def __str__(self):
return str(self.value)
@@ -56,111 +115,32 @@ def __eq__(self, other):
def is_plain(self):
"""Whether the VocabString can be represented as a single value."""
return (
- self._XSI_TYPE is None and
+ self.xsi_type is None and
self.vocab_name is None and
self.vocab_reference is None
)
- @staticmethod
- def lookup_class(xsi_type):
- if not xsi_type:
- return VocabString
-
- for (k, v) in _VOCAB_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- return VocabString
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(VocabString, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- # TODO: handle normalization
- # vocab_obj.valueOf_ = normalize_to_xml(self.value)
- return_obj.valueOf_ = self.value
- return_obj.xsi_type = self.xsi_type
-
- if self.vocab_name is not None:
- return_obj.vocab_name = self.vocab_name
- if self.vocab_reference is not None:
- return_obj.vocab_reference = self.vocab_reference
-
- return return_obj
-
def to_dict(self):
if self.is_plain():
return self.value
-
- d = {}
- if self.value is not None:
- d['value'] = self.value
- if self.xsi_type is not None:
- d['xsi:type'] = self.xsi_type
- if self.vocab_name is not None:
- d['vocab_name'] = self.vocab_name
- if self.vocab_reference is not None:
- d['vocab_reference'] = self.vocab_reference
-
- return d
-
- @classmethod
- def from_obj(cls, vocab_obj, return_obj=None):
- if not vocab_obj:
- return None
-
- if not return_obj:
- klass = VocabString.lookup_class(vocab_obj.xsi_type)
- return klass.from_obj(vocab_obj, klass())
-
- # xsi_type should be set automatically by the class's constructor.
-
- # TODO: handle denormalization
- # vocab_str.value = denormalize_from_xml(vocab_obj.valueOf_)
- return_obj.value = vocab_obj.valueOf_
- return_obj.vocab_name = vocab_obj.vocab_name
- return_obj.vocab_reference = vocab_obj.vocab_reference
- return_obj.xsi_type = vocab_obj.xsi_type
-
- return return_obj
+ return super(VocabString, self).to_dict()
@classmethod
- def from_dict(cls, vocab_dict, return_obj=None):
- if not vocab_dict:
- return None
-
- if not return_obj:
- if isinstance(vocab_dict, dict):
- klass = VocabString.lookup_class(vocab_dict.get('xsi:type'))
- return klass.from_dict(vocab_dict, klass())
- else:
- return_obj = cls()
-
- # xsi_type should be set automatically by the class's constructor.
-
- # In case this is a "plain" string, just set it.
- if not isinstance(vocab_dict, dict):
- return_obj.value = vocab_dict
+ def from_dict(cls, cls_dict):
+ if not cls_dict:
+ vocab = None
+ elif not isinstance(cls_dict, dict):
+ vocab = cls()
+ vocab.value = cls_dict
else:
- return_obj.value = vocab_dict.get('value')
- return_obj.vocab_name = vocab_dict.get('vocab_name')
- return_obj.vocab_reference = vocab_dict.get('vocab_reference')
- return_obj.xsi_type = vocab_dict.get('xsi:type')
-
- return return_obj
+ vocab = super(VocabString, cls).from_dict(cls_dict)
-
-#: Mapping of Controlled Vocabulary xsi:type's to their class implementations.
-_VOCAB_MAP = {}
+ return vocab
def _get_terms(vocab_class):
"""Helper function used by register_vocab."""
- for k, v in vocab_class.__dict__.items():
+ for k, v in vars(vocab_class).items():
if k.startswith("TERM_"):
yield v
@@ -172,11 +152,11 @@ def add_vocab(cls):
The :meth:`register_vocab` class decorator has replaced this method.
"""
- _VOCAB_MAP[cls._XSI_TYPE] = cls
+ stix.add_extension(cls)
def register_vocab(cls):
- """Register a VocabString subclass.
+ """Class decorator that registers a VocabString subclass.
Also, calculate all the permitted values for class being decorated by
adding an ``_ALLOWED_VALUES`` tuple of all the values of class members
@@ -190,31 +170,43 @@ def register_vocab(cls):
@register_vocab
-class AvailabilityLossType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:AvailabilityLossTypeVocab-1.1.1'
+class AvailabilityLossType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:AvailabilityLossTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_ACCELERATION = "Acceleration"
+ TERM_DEGREDATION = "Degredation"
TERM_DESTRUCTION = "Destruction"
- TERM_LOSS = "Loss"
TERM_INTERRUPTION = "Interruption"
- TERM_DEGRADATION = "Degradation"
+ TERM_LOSS = "Loss"
+ TERM_OBSCURATION = "Obscuration"
+ TERM_UNKNOWN = "Unknown"
+
+
+@register_vocab
+class AvailabilityLossType_1_1_1(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:AvailabilityLossTypeVocab-1.1.1"
+ _VOCAB_VERSION = "1.1.1"
+
TERM_ACCELERATION = "Acceleration"
+ TERM_DEGRADATION = "Degradation"
+ TERM_DESTRUCTION = "Destruction"
+ TERM_INTERRUPTION = "Interruption"
+ TERM_LOSS = "Loss"
TERM_OBSCURATION = "Obscuration"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class ThreatActorType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:ThreatActorTypeVocab-1.0'
+class ThreatActorType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ThreatActorTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_CYBER_ESPIONAGE_OPERATIONS = "Cyber Espionage Operations"
- TERM_HACKER = "Hacker"
- TERM_HACKER_WHITE_HAT = "Hacker - White hat"
- TERM_HACKER_GRAY_HAT = "Hacker - Gray hat"
- TERM_HACKER_BLACK_HAT = "Hacker - Black hat"
- TERM_HACKTIVIST = "Hacktivist"
- TERM_STATE_ACTOR_OR_AGENCY = "State Actor / Agency"
+ TERM_DISGRUNTLED_CUSTOMER_OR_USER = "Disgruntled Customer / User"
TERM_ECRIME_ACTOR_CREDENTIAL_THEFT_BOTNET_OPERATOR = "eCrime Actor - Credential Theft Botnet Operator"
TERM_ECRIME_ACTOR_CREDENTIAL_THEFT_BOTNET_SERVICE = "eCrime Actor - Credential Theft Botnet Service"
TERM_ECRIME_ACTOR_MALWARE_DEVELOPER = "eCrime Actor - Malware Developer"
@@ -223,14 +215,20 @@ class ThreatActorType(VocabString):
TERM_ECRIME_ACTOR_SPAM_SERVICE = "eCrime Actor - Spam Service"
TERM_ECRIME_ACTOR_TRAFFIC_SERVICE = "eCrime Actor - Traffic Service"
TERM_ECRIME_ACTOR_UNDERGROUND_CALL_SERVICE = "eCrime Actor - Underground Call Service"
+ TERM_HACKER = "Hacker"
+ TERM_HACKER_BLACK_HAT = "Hacker - Black hat"
+ TERM_HACKER_GRAY_HAT = "Hacker - Gray hat"
+ TERM_HACKER_WHITE_HAT = "Hacker - White hat"
+ TERM_HACKTIVIST = "Hacktivist"
TERM_INSIDER_THREAT = "Insider Threat"
- TERM_DISGRUNTLED_CUSTOMER_OR_USER = "Disgruntled Customer / User"
+ TERM_STATE_ACTOR_OR_AGENCY = "State Actor / Agency"
@register_vocab
-class AttackerInfrastructureType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:AttackerInfrastructureTypeVocab-1.0'
+class AttackerInfrastructureType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:AttackerInfrastructureTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_ANONYMIZATION = "Anonymization"
TERM_ANONYMIZATION_PROXY = "Anonymization - Proxy"
@@ -249,96 +247,144 @@ class AttackerInfrastructureType(VocabString):
TERM_DOMAIN_REGISTRATION_LEGITIMATE_DOMAIN_REGISTRATION_SERVICES = "Domain Registration - Legitimate Domain Registration Services"
TERM_DOMAIN_REGISTRATION_MALICIOUS_DOMAIN_REGISTRARS = "Domain Registration - Malicious Domain Registrars"
TERM_DOMAIN_REGISTRATION_TOPLEVEL_DOMAIN_REGISTRARS = "Domain Registration - Top-Level Domain Registrars"
+ TERM_ELECTRONIC_PAYMENT_METHODS = "Electronic Payment Methods"
TERM_HOSTING = "Hosting"
TERM_HOSTING_BULLETPROOF_OR_ROGUE_HOSTING = "Hosting - Bulletproof / Rogue Hosting"
TERM_HOSTING_CLOUD_HOSTING = "Hosting - Cloud Hosting"
TERM_HOSTING_COMPROMISED_SERVER = "Hosting - Compromised Server"
TERM_HOSTING_FAST_FLUX_BOTNET_HOSTING = "Hosting - Fast Flux Botnet Hosting"
TERM_HOSTING_LEGITIMATE_HOSTING = "Hosting - Legitimate Hosting"
- TERM_ELECTRONIC_PAYMENT_METHODS = "Electronic Payment Methods"
@register_vocab
-class DiscoveryMethod(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:DiscoveryMethodVocab-1.0'
+class DiscoveryMethod_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:DiscoveryMethodVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_AGENT_DISCLOSURE = "Agent Disclosure"
+ TERM_ANTIVIRUS = "Antivirus"
+ TERM_AUDIT = "Audit"
+ TERM_CUSTOMER = "Customer"
+ TERM_FINANCIAL_AUDIT = "Financial Audit"
TERM_FRAUD_DETECTION = "Fraud Detection"
- TERM_MONITORING_SERVICE = "Monitoring Service"
+ TERM_HIPS = "HIPS"
+ TERM_INCIDENT_RESPONSE = "Incident Response"
+ TERM_IT_AUDIT = "IT Audit"
TERM_LAW_ENFORCEMENT = "Law Enforcement"
- TERM_CUSTOMER = "Customer"
+ TERM_LOG_REVIEW = "Log Review"
+ TERM_MONITORING_SERVICE = "Monitoring Service"
+ TERM_NIDS = "NIDS"
+ TERM_SECURITY_ALARM = "Security Alarm"
+ TERM_UNKNOWN = "Unknown"
TERM_UNRELATED_PARTY = "Unrelated Party"
- TERM_AUDIT = "Audit"
+ TERM_USER = "User"
+
+@register_vocab
+class DiscoveryMethod_2_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:DiscoveryMethodVocab-2.0"
+ _VOCAB_VERSION = "2.0"
+
+ TERM_AGENT_DISCLOSURE = "Agent Disclosure"
TERM_ANTIVIRUS = "Antivirus"
- TERM_INCIDENT_RESPONSE = "Incident Response"
+ TERM_AUDIT = "Audit"
+ TERM_CUSTOMER = "Customer"
+ TERM_EXTERNAL_FRAUD_DETECTION = "External - Fraud Detection"
TERM_FINANCIAL_AUDIT = "Financial Audit"
TERM_HIPS = "HIPS"
+ TERM_INCIDENT_RESPONSE = "Incident Response"
+ TERM_INTERNAL_FRAUD_DETECTION = "Internal - Fraud Detection"
TERM_IT_AUDIT = "IT Audit"
+ TERM_LAW_ENFORCEMENT = "Law Enforcement"
TERM_LOG_REVIEW = "Log Review"
+ TERM_MONITORING_SERVICE = "Monitoring Service"
TERM_NIDS = "NIDS"
TERM_SECURITY_ALARM = "Security Alarm"
- TERM_USER = "User"
TERM_UNKNOWN = "Unknown"
+ TERM_UNRELATED_PARTY = "Unrelated Party"
+ TERM_USER = "User"
+@vocabs.register_vocab
@register_vocab
-class AttackerToolType(VocabString):
+class AttackerToolType_1_0(vocabs.VocabString):
_namespace = 'http://stix.mitre.org/default_vocabularies-1'
_XSI_TYPE = 'stixVocabs:AttackerToolTypeVocab-1.0'
+ _VOCAB_VERSION = '1.0'
+ TERM_APPLICATION_SCANNER = "Application Scanner"
TERM_MALWARE = "Malware"
+ TERM_PASSWORD_CRACKING = "Password Cracking"
TERM_PENETRATION_TESTING = "Penetration Testing"
TERM_PORT_SCANNER = "Port Scanner"
TERM_TRAFFIC_SCANNER = "Traffic Scanner"
TERM_VULNERABILITY_SCANNER = "Vulnerability Scanner"
- TERM_APPLICATION_SCANNER = "Application Scanner"
- TERM_PASSWORD_CRACKING = "Password Cracking"
@register_vocab
-class IndicatorType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:IndicatorTypeVocab-1.1'
+class IndicatorType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IndicatorTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_MALICIOUS_EMAIL = "Malicious E-mail"
- TERM_IP_WATCHLIST = "IP Watchlist"
- TERM_FILE_HASH_WATCHLIST = "File Hash Watchlist"
+ TERM_ANONYMIZATION = "Anonymization"
+ TERM_C2 = "C2"
TERM_DOMAIN_WATCHLIST = "Domain Watchlist"
- TERM_URL_WATCHLIST = "URL Watchlist"
+ TERM_EXFILTRATION = "Exfiltration"
+ TERM_FILE_HASH_WATCHLIST = "File Hash Watchlist"
+ TERM_HOST_CHARACTERISTICS = "Host Characteristics"
+ TERM_IP_WATCHLIST = "IP Watchlist"
+ TERM_MALICIOUS_EMAIL = "Malicious E-mail"
TERM_MALWARE_ARTIFACTS = "Malware Artifacts"
- TERM_C2 = "C2"
+ TERM_URL_WATCHLIST = "URL Watchlist"
+
+
+@register_vocab
+class IndicatorType_1_1(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IndicatorTypeVocab-1.1"
+ _VOCAB_VERSION = "1.1"
+
TERM_ANONYMIZATION = "Anonymization"
+ TERM_C2 = "C2"
+ TERM_COMPROMISED_PKI_CERTIFICATE = "Compromised PKI Certificate"
+ TERM_DOMAIN_WATCHLIST = "Domain Watchlist"
TERM_EXFILTRATION = "Exfiltration"
+ TERM_FILE_HASH_WATCHLIST = "File Hash Watchlist"
TERM_HOST_CHARACTERISTICS = "Host Characteristics"
- TERM_COMPROMISED_PKI_CERTIFICATE = "Compromised PKI Certificate"
- TERM_LOGIN_NAME = "Login Name"
TERM_IMEI_WATCHLIST = "IMEI Watchlist"
TERM_IMSI_WATCHLIST = "IMSI Watchlist"
+ TERM_IP_WATCHLIST = "IP Watchlist"
+ TERM_LOGIN_NAME = "Login Name"
+ TERM_MALICIOUS_EMAIL = "Malicious E-mail"
+ TERM_MALWARE_ARTIFACTS = "Malware Artifacts"
+ TERM_URL_WATCHLIST = "URL Watchlist"
@register_vocab
-class SystemType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:SystemTypeVocab-1.0'
+class SystemType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:SystemTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_ENTERPRISE_SYSTEMS = "Enterprise Systems"
TERM_ENTERPRISE_SYSTEMS_APPLICATION_LAYER = "Enterprise Systems - Application Layer"
TERM_ENTERPRISE_SYSTEMS_DATABASE_LAYER = "Enterprise Systems - Database Layer"
TERM_ENTERPRISE_SYSTEMS_ENTERPRISE_TECHNOLOGIES_AND_SUPPORT_INFRASTRUCTURE = "Enterprise Systems - Enterprise Technologies and Support Infrastructure"
- TERM_ENTERPRISE_SYSTEMS_NETWORK_SYSTEMS = "Enterprise Systems - Network Systems"
TERM_ENTERPRISE_SYSTEMS_NETWORKING_DEVICES = "Enterprise Systems - Networking Devices"
- TERM_ENTERPRISE_SYSTEMS_WEB_LAYER = "Enterprise Systems - Web Layer"
+ TERM_ENTERPRISE_SYSTEMS_NETWORK_SYSTEMS = "Enterprise Systems - Network Systems"
TERM_ENTERPRISE_SYSTEMS_VOIP = "Enterprise Systems - VoIP"
+ TERM_ENTERPRISE_SYSTEMS_WEB_LAYER = "Enterprise Systems - Web Layer"
TERM_INDUSTRIAL_CONTROL_SYSTEMS = "Industrial Control Systems"
TERM_INDUSTRIAL_CONTROL_SYSTEMS_EQUIPMENT_UNDER_CONTROL = "Industrial Control Systems - Equipment Under Control"
TERM_INDUSTRIAL_CONTROL_SYSTEMS_OPERATIONS_MANAGEMENT = "Industrial Control Systems - Operations Management"
TERM_INDUSTRIAL_CONTROL_SYSTEMS_SAFETY_PROTECTION_AND_LOCAL_CONTROL = "Industrial Control Systems - Safety, Protection and Local Control"
TERM_INDUSTRIAL_CONTROL_SYSTEMS_SUPERVISORY_CONTROL = "Industrial Control Systems - Supervisory Control"
TERM_MOBILE_SYSTEMS = "Mobile Systems"
+ TERM_MOBILE_SYSTEMS_MOBILE_DEVICES = "Mobile Systems - Mobile Devices"
TERM_MOBILE_SYSTEMS_MOBILE_OPERATING_SYSTEMS = "Mobile Systems - Mobile Operating Systems"
TERM_MOBILE_SYSTEMS_NEAR_FIELD_COMMUNICATIONS = "Mobile Systems - Near Field Communications"
- TERM_MOBILE_SYSTEMS_MOBILE_DEVICES = "Mobile Systems - Mobile Devices"
TERM_THIRDPARTY_SERVICES = "Third-Party Services"
TERM_THIRDPARTY_SERVICES_APPLICATION_STORES = "Third-Party Services - Application Stores"
TERM_THIRDPARTY_SERVICES_CLOUD_SERVICES = "Third-Party Services - Cloud Services"
@@ -347,99 +393,180 @@ class SystemType(VocabString):
TERM_THIRDPARTY_SERVICES_SOFTWARE_UPDATE = "Third-Party Services - Software Update"
TERM_USERS = "Users"
TERM_USERS_APPLICATION_AND_SOFTWARE = "Users - Application And Software"
- TERM_USERS_WORKSTATION = "Users - Workstation"
TERM_USERS_REMOVABLE_MEDIA = "Users - Removable Media"
+ TERM_USERS_WORKSTATION = "Users - Workstation"
@register_vocab
-class CampaignStatus(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:CampaignStatusVocab-1.0'
+class CampaignStatus_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:CampaignStatusVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_ONGOING = "Ongoing"
- TERM_HISTORIC = "Historic"
TERM_FUTURE = "Future"
+ TERM_HISTORIC = "Historic"
+ TERM_ONGOING = "Ongoing"
@register_vocab
-class IncidentStatus(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:IncidentStatusVocab-1.0'
+class IncidentStatus_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IncidentStatusVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_NEW = "New"
- TERM_OPEN = "Open"
- TERM_STALLED = "Stalled"
+ TERM_CLOSED = "Closed"
TERM_CONTAINMENT_ACHIEVED = "Containment Achieved"
- TERM_RESTORATION_ACHIEVED = "Restoration Achieved"
+ TERM_DELETED = "Deleted"
TERM_INCIDENT_REPORTED = "Incident Reported"
- TERM_CLOSED = "Closed"
+ TERM_NEW = "New"
+ TERM_OPEN = "Open"
TERM_REJECTED = "Rejected"
- TERM_DELETED = "Deleted"
+ TERM_RESTORATION_ACHIEVED = "Restoration Achieved"
+ TERM_STALLED = "Stalled"
@register_vocab
-class ManagementClass(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:ManagementClassVocab-1.0'
+class ManagementClass_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ManagementClassVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INTERNALLYMANAGED = "Internally-Managed"
- TERM_EXTERNALLYMANAGEMENT = "Externally-Management"
TERM_COMANAGEMENT = "Co-Management"
+ TERM_EXTERNALLYMANAGEMENT = "Externally-Management"
+ TERM_INTERNALLYMANAGED = "Internally-Managed"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class Motivation(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:MotivationVocab-1.1'
+class Motivation_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:MotivationVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_EGO = "Ego"
+ TERM_FINANCIAL_OR_ECONOMIC = "Financial or Economic"
TERM_IDEOLOGICAL = "Ideological"
TERM_IDEOLOGICAL_ANTICORRUPTION = "Ideological - Anti-Corruption"
- TERM_IDEOLOGICAL_ANTIESTABLISHMENT = "Ideological - Anti-Establishment"
+ TERM_IDEOLOGICAL_ANTIESTABLISMENT = "Ideological - Anti-Establisment"
TERM_IDEOLOGICAL_ENVIRONMENTAL = "Ideological - Environmental"
- TERM_IDEOLOGICAL_ETHNIC_OR_NATIONALIST = "Ideological - Ethnic / Nationalist"
+ TERM_IDEOLOGICAL_ETHNIC_NATIONALIST = "Ideological - Ethnic / Nationalist"
+ TERM_IDEOLOGICAL_HUMAN_RIGHTS = "Ideological - Human Rights"
TERM_IDEOLOGICAL_INFORMATION_FREEDOM = "Ideological - Information Freedom"
TERM_IDEOLOGICAL_RELIGIOUS = "Ideological - Religious"
TERM_IDEOLOGICAL_SECURITY_AWARENESS = "Ideological - Security Awareness"
+ TERM_MILITARY = "Military"
+ TERM_OPPORTUNISTIC = "Opportunistic"
+ TERM_POLICITAL = "Policital"
+
+
+@register_vocab
+class Motivation_1_0_1(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:MotivationVocab-1.0.1"
+ _VOCAB_VERSION = "1.0.1"
+
+ TERM_EGO = "Ego"
+ TERM_FINANCIAL_OR_ECONOMIC = "Financial or Economic"
+ TERM_IDEOLOGICAL = "Ideological"
+ TERM_IDEOLOGICAL_ANTI_CORRUPTION = "Ideological - Anti-Corruption"
+ TERM_IDEOLOGICAL_ANTI_ESTABLISHMENT = "Ideological - Anti-Establishment"
+ TERM_IDEOLOGICAL_ENVIRONMENTAL = "Ideological - Environmental"
+ TERM_IDEOLOGICAL_ETHNIC_NATIONALIST = "Ideological - Ethnic / Nationalist"
TERM_IDEOLOGICAL_HUMAN_RIGHTS = "Ideological - Human Rights"
+ TERM_IDEOLOGICAL_INFORMATION_FREEDOM = "Ideological - Information Freedom"
+ TERM_IDEOLOGICAL_SECURITY_AWARENESS = "Ideological - Security Awareness"
+ TERM_IDEOLOGICAL__RELIGIOUS = "Ideological - Religious"
+ TERM_MILITARY = "Military"
+ TERM_OPPORTUNISTIC = "Opportunistic"
+ TERM_POLICITAL = "Policital"
+
+
+@register_vocab
+class Motivation_1_1(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:MotivationVocab-1.1"
+ _VOCAB_VERSION = "1.1"
+
TERM_EGO = "Ego"
TERM_FINANCIAL_OR_ECONOMIC = "Financial or Economic"
+ TERM_IDEOLOGICAL = "Ideological"
+ TERM_IDEOLOGICAL_ANTICORRUPTION = "Ideological - Anti-Corruption"
+ TERM_IDEOLOGICAL_ANTIESTABLISHMENT = "Ideological - Anti-Establishment"
+ TERM_IDEOLOGICAL_ENVIRONMENTAL = "Ideological - Environmental"
+ TERM_IDEOLOGICAL_ETHNIC_NATIONALIST = "Ideological - Ethnic / Nationalist"
+ TERM_IDEOLOGICAL_HUMAN_RIGHTS = "Ideological - Human Rights"
+ TERM_IDEOLOGICAL_INFORMATION_FREEDOM = "Ideological - Information Freedom"
+ TERM_IDEOLOGICAL_RELIGIOUS = "Ideological - Religious"
+ TERM_IDEOLOGICAL_SECURITY_AWARENESS = "Ideological - Security Awareness"
TERM_MILITARY = "Military"
TERM_OPPORTUNISTIC = "Opportunistic"
TERM_POLITICAL = "Political"
@register_vocab
-class IncidentCategory(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:IncidentCategoryVocab-1.0'
+class IncidentCategory_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IncidentCategoryVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_EXERCISEORNETWORK_DEFENSE_TESTING = "Exercise/Network Defense Testing"
- TERM_UNAUTHORIZED_ACCESS = "Unauthorized Access"
TERM_DENIAL_OF_SERVICE = "Denial of Service"
- TERM_MALICIOUS_CODE = "Malicious Code"
+ TERM_EXERCISEORNETWORK_DEFENSE_TESTING = "Exercise/Network Defense Testing"
TERM_IMPROPER_USAGE = "Improper Usage"
- TERM_SCANSORPROBESORATTEMPTED_ACCESS = "Scans/Probes/Attempted Access"
TERM_INVESTIGATION = "Investigation"
+ TERM_MALICIOUS_CODE = "Malicious Code"
+ TERM_SCANSORPROBESORATTEMPTED_ACCESS = "Scans/Probes/Attempted Access"
+ TERM_UNAUTHORIZED_ACCESS = "Unauthorized Access"
@register_vocab
-class ImpactQualification(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:ImpactQualificationVocab-1.0'
+class ImpactQualification_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ImpactQualificationVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INSIGNIFICANT = "Insignificant"
+ TERM_CATASTROPHIC = "Catastrophic"
+ TERM_DAMAGING = "Damaging"
TERM_DISTRACTING = "Distracting"
+ TERM_INSIGNIFICANT = "Insignificant"
TERM_PAINFUL = "Painful"
- TERM_DAMAGING = "Damaging"
- TERM_CATASTROPHIC = "Catastrophic"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class PlanningAndOperationalSupport(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:PlanningAndOperationalSupportVocab-1.0.1'
+class PlanningAndOperationalSupport_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:PlanningAndOperationalSupportVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+
+ TERM_DATA_EXPLOITATION = "Data Exploitation"
+ TERM_DATA_EXPLOITATION_ANALYTIC_SUPPORT = "Data Exploitation - Analytic Support"
+ TERM_DATA_EXPLOITATION_TRANSLATION_SUPPORT = "Data Exploitation - Translation Support"
+ TERM_FINANCIAL_RESOURCES = "Financial Resources"
+ TERM_FINANCIAL_RESOURCES_ACADEMIC = "Financial Resources - Academic"
+ TERM_FINANCIAL_RESOURCES_COMMERCIAL = "Financial Resources - Commercial"
+ TERM_FINANCIAL_RESOURCES_GOVERNMENT = "Financial Resources - Government"
+ TERM_FINANCIAL_RESOURCES_HACKTIVIST_OR_GRASSROOT = "Financial Resources - Hacktivist or Grassroot"
+ TERM_FINANCIAL_RESOURCES_NONATTRIBUTABLE_FINANCE = "Financial Resources - Non-Attributable Finance"
+ TERM_PLANNING = "Planning"
+ TERM_PLANNING_OPEN_SOURCE_INTELLIGENCE_OSINT_GETHERING = "Planning - Open-Source Intelligence (OSINT) Gethering"
+ TERM_PLANNING_OPERATIONAL_COVER_PLAN = "Planning - Operational Cover Plan"
+ TERM_PLANNING_PRE_OPERATIONAL_SURVEILLANCE_AND_RECONNAISSANCE = "Planning - Pre-Operational Surveillance and Reconnaissance"
+ TERM_PLANNING_TARGET_SELECTION = "Planning - Target Selection"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT = "Skill Development / Recruitment"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_CONTRACTING_AND_HIRING = "Skill Development / Recruitment - Contracting and Hiring"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_DOCUMENT_EXPLOITATION_DOCEX_TRAINING = "Skill Development / Recruitment - Document Exploitation (DOCEX) Training"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_INTERNAL_TRAINING = "Skill Development / Recruitment - Internal Training"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_MILITARY_PROGRAMS = "Skill Development / Recruitment - Military Programs"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_SECURITY_HACKER_CONFERENCES = "Skill Development / Recruitment - Security / Hacker Conferences"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_UNDERGROUND_FORUMS = "Skill Development / Recruitment - Underground Forums"
+ TERM_SKILL_DEVELOPMENT_RECRUITMENT_UNIVERSITY_PROGRAMS = "Skill Development / Recruitment - University Programs"
+
+
+@register_vocab
+class PlanningAndOperationalSupport_1_0_1(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:PlanningAndOperationalSupportVocab-1.0.1"
+ _VOCAB_VERSION = "1.0.1"
TERM_DATA_EXPLOITATION = "Data Exploitation"
TERM_DATA_EXPLOITATION_ANALYTIC_SUPPORT = "Data Exploitation - Analytic Support"
@@ -450,6 +577,11 @@ class PlanningAndOperationalSupport(VocabString):
TERM_FINANCIAL_RESOURCES_GOVERNMENT = "Financial Resources - Government"
TERM_FINANCIAL_RESOURCES_HACKTIVIST_OR_GRASSROOT = "Financial Resources - Hacktivist or Grassroot"
TERM_FINANCIAL_RESOURCES_NONATTRIBUTABLE_FINANCE = "Financial Resources - Non-Attributable Finance"
+ TERM_PLANNING = "Planning"
+ TERM_PLANNING_OPENSOURCE_INTELLIGENCE_OSINT_GATHERING = "Planning - Open-Source Intelligence (OSINT) Gathering"
+ TERM_PLANNING_OPERATIONAL_COVER_PLAN = "Planning - Operational Cover Plan"
+ TERM_PLANNING_PREOPERATIONAL_SURVEILLANCE_AND_RECONNAISSANCE = "Planning - Pre-Operational Surveillance and Reconnaissance"
+ TERM_PLANNING_TARGET_SELECTION = "Planning - Target Selection"
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT = "Skill Development / Recruitment"
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT_CONTRACTING_AND_HIRING = "Skill Development / Recruitment - Contracting and Hiring"
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT_DOCUMENT_EXPLOITATION_DOCEX_TRAINING = "Skill Development / Recruitment - Document Exploitation (DOCEX) Training"
@@ -458,167 +590,170 @@ class PlanningAndOperationalSupport(VocabString):
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT_SECURITY_OR_HACKER_CONFERENCES = "Skill Development / Recruitment - Security / Hacker Conferences"
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT_UNDERGROUND_FORUMS = "Skill Development / Recruitment - Underground Forums"
TERM_SKILL_DEVELOPMENT_OR_RECRUITMENT_UNIVERSITY_PROGRAMS = "Skill Development / Recruitment - University Programs"
- TERM_PLANNING = "Planning"
- TERM_PLANNING_OPERATIONAL_COVER_PLAN = "Planning - Operational Cover Plan"
- TERM_PLANNING_OPENSOURCE_INTELLIGENCE_OSINT_GATHERING = "Planning - Open-Source Intelligence (OSINT) Gathering"
- TERM_PLANNING_PREOPERATIONAL_SURVEILLANCE_AND_RECONNAISSANCE = "Planning - Pre-Operational Surveillance and Reconnaissance"
- TERM_PLANNING_TARGET_SELECTION = "Planning - Target Selection"
@register_vocab
-class CourseOfActionType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:CourseOfActionTypeVocab-1.0'
+class CourseOfActionType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:CourseOfActionTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_PERIMETER_BLOCKING = "Perimeter Blocking"
- TERM_INTERNAL_BLOCKING = "Internal Blocking"
- TERM_REDIRECTION = "Redirection"
- TERM_REDIRECTION_HONEY_POT = "Redirection (Honey Pot)"
- TERM_HARDENING = "Hardening"
- TERM_PATCHING = "Patching"
+ TERM_DIPLOMATIC_ACTIONS = "Diplomatic Actions"
TERM_ERADICATION = "Eradication"
- TERM_REBUILDING = "Rebuilding"
- TERM_TRAINING = "Training"
+ TERM_HARDENING = "Hardening"
+ TERM_INTERNAL_BLOCKING = "Internal Blocking"
+ TERM_LOGICAL_ACCESS_RESTRICTIONS = "Logical Access Restrictions"
TERM_MONITORING = "Monitoring"
+ TERM_OTHER = "Other"
+ TERM_PATCHING = "Patching"
+ TERM_PERIMETER_BLOCKING = "Perimeter Blocking"
TERM_PHYSICAL_ACCESS_RESTRICTIONS = "Physical Access Restrictions"
- TERM_LOGICAL_ACCESS_RESTRICTIONS = "Logical Access Restrictions"
- TERM_PUBLIC_DISCLOSURE = "Public Disclosure"
- TERM_DIPLOMATIC_ACTIONS = "Diplomatic Actions"
TERM_POLICY_ACTIONS = "Policy Actions"
- TERM_OTHER = "Other"
+ TERM_PUBLIC_DISCLOSURE = "Public Disclosure"
+ TERM_REBUILDING = "Rebuilding"
+ TERM_REDIRECTION = "Redirection"
+ TERM_REDIRECTION_HONEY_POT = "Redirection (Honey Pot)"
+ TERM_TRAINING = "Training"
@register_vocab
-class SecurityCompromise(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:SecurityCompromiseVocab-1.0'
+class SecurityCompromise_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:SecurityCompromiseVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_YES = "Yes"
- TERM_SUSPECTED = "Suspected"
TERM_NO = "No"
+ TERM_SUSPECTED = "Suspected"
TERM_UNKNOWN = "Unknown"
+ TERM_YES = "Yes"
@register_vocab
-class ImpactRating(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:ImpactRatingVocab-1.0'
+class ImpactRating_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ImpactRatingVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_NONE = "None"
+ TERM_MAJOR = "Major"
TERM_MINOR = "Minor"
TERM_MODERATE = "Moderate"
- TERM_MAJOR = "Major"
+ TERM_NONE = "None"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class AssetType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:AssetTypeVocab-1.0'
+class AssetType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:AssetTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+
- TERM_BACKUP = "Backup"
- TERM_DATABASE = "Database"
- TERM_DHCP = "DHCP"
- TERM_DIRECTORY = "Directory"
- TERM_DCS = "DCS"
- TERM_DNS = "DNS"
- TERM_FILE = "File"
- TERM_LOG = "Log"
- TERM_MAIL = "Mail"
- TERM_MAINFRAME = "Mainframe"
- TERM_PAYMENT_SWITCH = "Payment switch"
- TERM_POS_CONTROLLER = "POS controller"
- TERM_PRINT = "Print"
- TERM_PROXY = "Proxy"
- TERM_REMOTE_ACCESS = "Remote access"
- TERM_SCADA = "SCADA"
- TERM_WEB_APPLICATION = "Web application"
- TERM_SERVER = "Server"
TERM_ACCESS_READER = "Access reader"
- TERM_CAMERA = "Camera"
- TERM_FIREWALL = "Firewall"
- TERM_HSM = "HSM"
- TERM_IDS = "IDS"
- TERM_BROADBAND = "Broadband"
- TERM_PBX = "PBX"
- TERM_PRIVATE_WAN = "Private WAN"
- TERM_PLC = "PLC"
- TERM_PUBLIC_WAN = "Public WAN"
- TERM_RTU = "RTU"
- TERM_ROUTER_OR_SWITCH = "Router or switch"
- TERM_SAN = "SAN"
- TERM_TELEPHONE = "Telephone"
- TERM_VOIP_ADAPTER = "VoIP adapter"
- TERM_LAN = "LAN"
- TERM_WLAN = "WLAN"
- TERM_NETWORK = "Network"
- TERM_AUTH_TOKEN = "Auth token"
- TERM_ATM = "ATM"
- TERM_DESKTOP = "Desktop"
- TERM_PED_PAD = "PED pad"
- TERM_GAS_TERMINAL = "Gas terminal"
- TERM_LAPTOP = "Laptop"
- TERM_MEDIA = "Media"
- TERM_MOBILE_PHONE = "Mobile phone"
- TERM_PERIPHERAL = "Peripheral"
- TERM_POS_TERMINAL = "POS terminal"
- TERM_KIOSK = "Kiosk"
- TERM_TABLET = "Tablet"
- TERM_VOIP_PHONE = "VoIP phone"
- TERM_USER_DEVICE = "User Device"
- TERM_TAPES = "Tapes"
- TERM_DISK_MEDIA = "Disk media"
- TERM_DOCUMENTS = "Documents"
- TERM_FLASH_DRIVE = "Flash drive"
- TERM_DISK_DRIVE = "Disk drive"
- TERM_SMART_CARD = "Smart card"
- TERM_PAYMENT_CARD = "Payment card"
TERM_ADMINISTRATOR = "Administrator"
+ TERM_ATM = "ATM"
TERM_AUDITOR = "Auditor"
+ TERM_AUTH_TOKEN = "Auth token"
+ TERM_BACKUP = "Backup"
+ TERM_BROADBAND = "Broadband"
TERM_CALL_CENTER = "Call center"
+ TERM_CAMERA = "Camera"
TERM_CASHIER = "Cashier"
TERM_CUSTOMER = "Customer"
+ TERM_DATABASE = "Database"
+ TERM_DCS = "DCS"
+ TERM_DESKTOP = "Desktop"
TERM_DEVELOPER = "Developer"
+ TERM_DHCP = "DHCP"
+ TERM_DIRECTORY = "Directory"
+ TERM_DISK_DRIVE = "Disk drive"
+ TERM_DISK_MEDIA = "Disk media"
+ TERM_DNS = "DNS"
+ TERM_DOCUMENTS = "Documents"
TERM_ENDUSER = "End-user"
TERM_EXECUTIVE = "Executive"
+ TERM_FILE = "File"
TERM_FINANCE = "Finance"
+ TERM_FIREWALL = "Firewall"
+ TERM_FLASH_DRIVE = "Flash drive"
TERM_FORMER_EMPLOYEE = "Former employee"
+ TERM_GAS_TERMINAL = "Gas terminal"
TERM_GUARD = "Guard"
TERM_HELPDESK = "Helpdesk"
+ TERM_HSM = "HSM"
TERM_HUMAN_RESOURCES = "Human resources"
+ TERM_IDS = "IDS"
+ TERM_KIOSK = "Kiosk"
+ TERM_LAN = "LAN"
+ TERM_LAPTOP = "Laptop"
+ TERM_LOG = "Log"
+ TERM_MAIL = "Mail"
+ TERM_MAINFRAME = "Mainframe"
TERM_MAINTENANCE = "Maintenance"
TERM_MANAGER = "Manager"
+ TERM_MEDIA = "Media"
+ TERM_MOBILE_PHONE = "Mobile phone"
+ TERM_NETWORK = "Network"
TERM_PARTNER = "Partner"
+ TERM_PAYMENT_CARD = "Payment card"
+ TERM_PAYMENT_SWITCH = "Payment switch"
+ TERM_PBX = "PBX"
+ TERM_PED_PAD = "PED pad"
+ TERM_PERIPHERAL = "Peripheral"
TERM_PERSON = "Person"
+ TERM_PLC = "PLC"
+ TERM_POS_CONTROLLER = "POS controller"
+ TERM_POS_TERMINAL = "POS terminal"
+ TERM_PRINT = "Print"
+ TERM_PRIVATE_WAN = "Private WAN"
+ TERM_PROXY = "Proxy"
+ TERM_PUBLIC_WAN = "Public WAN"
+ TERM_REMOTE_ACCESS = "Remote access"
+ TERM_ROUTER_OR_SWITCH = "Router or switch"
+ TERM_RTU = "RTU"
+ TERM_SAN = "SAN"
+ TERM_SCADA = "SCADA"
+ TERM_SERVER = "Server"
+ TERM_SMART_CARD = "Smart card"
+ TERM_TABLET = "Tablet"
+ TERM_TAPES = "Tapes"
+ TERM_TELEPHONE = "Telephone"
TERM_UNKNOWN = "Unknown"
-
+ TERM_USER_DEVICE = "User Device"
+ TERM_VOIP_ADAPTER = "VoIP adapter"
+ TERM_VOIP_PHONE = "VoIP phone"
+ TERM_WEB_APPLICATION = "Web application"
+ TERM_WLAN = "WLAN"
@register_vocab
-class COAStage(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:COAStageVocab-1.0'
+class COAStage_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:COAStageVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_REMEDY = "Remedy"
TERM_RESPONSE = "Response"
@register_vocab
-class LocationClass(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:LocationClassVocab-1.0'
+class LocationClass_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:LocationClassVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INTERNALLYLOCATED = "Internally-Located"
- TERM_EXTERNALLYLOCATED = "Externally-Located"
TERM_COLOCATED = "Co-Located"
+ TERM_EXTERNALLYLOCATED = "Externally-Located"
+ TERM_INTERNALLYLOCATED = "Internally-Located"
TERM_MOBILE = "Mobile"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class InformationType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:InformationTypeVocab-1.0'
+class InformationType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:InformationTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_AUTHENTICATION_COOKIES = "Authentication Cookies"
TERM_INFORMATION_ASSETS = "Information Assets"
TERM_INFORMATION_ASSETS_CORPORATE_EMPLOYEE_INFORMATION = "Information Assets - Corporate Employee Information"
TERM_INFORMATION_ASSETS_CUSTOMER_PII = "Information Assets - Customer PII"
@@ -627,60 +762,58 @@ class InformationType(VocabString):
TERM_INFORMATION_ASSETS_INTELLECTUAL_PROPERTY = "Information Assets - Intellectual Property"
TERM_INFORMATION_ASSETS_MOBILE_PHONE_CONTACTS = "Information Assets - Mobile Phone Contacts"
TERM_INFORMATION_ASSETS_USER_CREDENTIALS = "Information Assets - User Credentials"
- TERM_AUTHENTICATION_COOKIES = "Authentication Cookies"
@register_vocab
-class ThreatActorSophistication(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:ThreatActorSophisticationVocab-1.0'
+class ThreatActorSophistication_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ThreatActorSophisticationVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INNOVATOR = "Innovator"
+ TERM_ASPIRANT = "Aspirant"
TERM_EXPERT = "Expert"
- TERM_PRACTITIONER = "Practitioner"
+ TERM_INNOVATOR = "Innovator"
TERM_NOVICE = "Novice"
- TERM_ASPIRANT = "Aspirant"
+ TERM_PRACTITIONER = "Practitioner"
@register_vocab
-class HighMediumLow(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:HighMediumLowVocab-1.0'
+class HighMediumLow_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:HighMediumLowVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_HIGH = "High"
- TERM_MEDIUM = "Medium"
TERM_LOW = "Low"
+ TERM_MEDIUM = "Medium"
TERM_NONE = "None"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class LossProperty(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:LossPropertyVocab-1.0'
+class LossProperty_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:LossPropertyVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_ACCOUNTABILITY = "Accountability"
+ TERM_AVAILABILITY = "Availability"
TERM_CONFIDENTIALITY = "Confidentiality"
TERM_INTEGRITY = "Integrity"
- TERM_AVAILABILITY = "Availability"
- TERM_ACCOUNTABILITY = "Accountability"
TERM_NONREPUDIATION = "Non-Repudiation"
@register_vocab
-class IntendedEffect(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:IntendedEffectVocab-1.0'
+class IntendedEffect_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IntendedEffectVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_ACCOUNT_TAKEOVER = "Account Takeover"
TERM_ADVANTAGE = "Advantage"
TERM_ADVANTAGE_ECONOMIC = "Advantage - Economic"
TERM_ADVANTAGE_MILITARY = "Advantage - Military"
TERM_ADVANTAGE_POLITICAL = "Advantage - Political"
- TERM_THEFT = "Theft"
- TERM_THEFT_INTELLECTUAL_PROPERTY = "Theft - Intellectual Property"
- TERM_THEFT_CREDENTIAL_THEFT = "Theft - Credential Theft"
- TERM_THEFT_IDENTITY_THEFT = "Theft - Identity Theft"
- TERM_THEFT_THEFT_OF_PROPRIETARY_INFORMATION = "Theft - Theft of Proprietary Information"
- TERM_ACCOUNT_TAKEOVER = "Account Takeover"
TERM_BRAND_DAMAGE = "Brand Damage"
TERM_COMPETITIVE_ADVANTAGE = "Competitive Advantage"
TERM_DEGRADATION_OF_SERVICE = "Degradation of Service"
@@ -693,76 +826,113 @@ class IntendedEffect(VocabString):
TERM_FRAUD = "Fraud"
TERM_HARASSMENT = "Harassment"
TERM_ICS_CONTROL = "ICS Control"
+ TERM_THEFT = "Theft"
+ TERM_THEFT_CREDENTIAL_THEFT = "Theft - Credential Theft"
+ TERM_THEFT_IDENTITY_THEFT = "Theft - Identity Theft"
+ TERM_THEFT_INTELLECTUAL_PROPERTY = "Theft - Intellectual Property"
+ TERM_THEFT_THEFT_OF_PROPRIETARY_INFORMATION = "Theft - Theft of Proprietary Information"
TERM_TRAFFIC_DIVERSION = "Traffic Diversion"
TERM_UNAUTHORIZED_ACCESS = "Unauthorized Access"
@register_vocab
-class PackageIntent(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:PackageIntentVocab-1.0'
+class PackageIntent_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:PackageIntentVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+ TERM_ATTACK_PATTERN_CHARACTERIZATION = "Attack Pattern Characterization"
+ TERM_CAMPAIGN_CHARACTERIZATION = "Campaign Characterization"
TERM_COLLECTIVE_THREAT_INTELLIGENCE = "Collective Threat Intelligence"
- TERM_THREAT_REPORT = "Threat Report"
+ TERM_COURSES_OF_ACTION = "Courses of Action"
+ TERM_EXPLOIT_CHARACTERIZATION = "Exploit Characterization"
+ TERM_INCIDENT = "Incident"
TERM_INDICATORS = "Indicators"
- TERM_INDICATORS_PHISHING = "Indicators - Phishing"
- TERM_INDICATORS_WATCHLIST = "Indicators - Watchlist"
+ TERM_INDICATORS_ENDPOINT_CHARACTERISTICS = "Indicators - Endpoint Characteristics"
TERM_INDICATORS_MALWARE_ARTIFACTS = "Indicators - Malware Artifacts"
TERM_INDICATORS_NETWORK_ACTIVITY = "Indicators - Network Activity"
- TERM_INDICATORS_ENDPOINT_CHARACTERISTICS = "Indicators - Endpoint Characteristics"
- TERM_CAMPAIGN_CHARACTERIZATION = "Campaign Characterization"
- TERM_THREAT_ACTOR_CHARACTERIZATION = "Threat Actor Characterization"
- TERM_EXPLOIT_CHARACTERIZATION = "Exploit Characterization"
- TERM_ATTACK_PATTERN_CHARACTERIZATION = "Attack Pattern Characterization"
+ TERM_INDICATORS_PHISHING = "Indicators - Phishing"
+ TERM_INDICATORS_WATCHLIST = "Indicators - Watchlist"
TERM_MALWARE_CHARACTERIZATION = "Malware Characterization"
+ TERM_MALWARE_SAMPLES = "Malware Samples"
+ TERM_OBSERVATIONS = "Observations"
+ TERM_OBSERVATIONS_EMAIL = "Observations - Email"
+ TERM_THREAT_ACTOR_CHARACTERIZATION = "Threat Actor Characterization"
+ TERM_THREAT_REPORT = "Threat Report"
TERM_TTP_INFRASTRUCTURE = "TTP - Infrastructure"
TERM_TTP_TOOLS = "TTP - Tools"
+
+
+@register_vocab
+class ReportIntent_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:ReportIntentVocab-1.0"
+ _VOCAB_VERSION = "1.0"
+
+ TERM_ATTACK_PATTERN_CHARACTERIZATION = "Attack Pattern Characterization"
+ TERM_CAMPAIGN_CHARACTERIZATION = "Campaign Characterization"
+ TERM_COLLECTIVE_THREAT_INTELLIGENCE = "Collective Threat Intelligence"
TERM_COURSES_OF_ACTION = "Courses of Action"
+ TERM_EXPLOIT_CHARACTERIZATION = "Exploit Characterization"
TERM_INCIDENT = "Incident"
+ TERM_INDICATORS = "Indicators"
+ TERM_INDICATORS_ENDPOINT_CHARACTERISTICS = "Indicators - Endpoint Characteristics"
+ TERM_INDICATORS_MALWARE_ARTIFACTS = "Indicators - Malware Artifacts"
+ TERM_INDICATORS_NETWORK_ACTIVITY = "Indicators - Network Activity"
+ TERM_INDICATORS_PHISHING = "Indicators - Phishing"
+ TERM_INDICATORS_WATCHLIST = "Indicators - Watchlist"
+ TERM_MALWARE_CHARACTERIZATION = "Malware Characterization"
+ TERM_MALWARE_SAMPLES = "Malware Samples"
TERM_OBSERVATIONS = "Observations"
TERM_OBSERVATIONS_EMAIL = "Observations - Email"
- TERM_MALWARE_SAMPLES = "Malware Samples"
+ TERM_THREAT_ACTOR_CHARACTERIZATION = "Threat Actor Characterization"
+ TERM_THREAT_REPORT = "Threat Report"
+ TERM_TTP_INFRASTRUCTURE = "TTP - Infrastructure"
+ TERM_TTP_TOOLS = "TTP - Tools"
@register_vocab
-class LossDuration(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:LossDurationVocab-1.0'
+class LossDuration_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:LossDurationVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_PERMANENT = "Permanent"
- TERM_WEEKS = "Weeks"
TERM_DAYS = "Days"
TERM_HOURS = "Hours"
TERM_MINUTES = "Minutes"
+ TERM_PERMANENT = "Permanent"
TERM_SECONDS = "Seconds"
TERM_UNKNOWN = "Unknown"
+ TERM_WEEKS = "Weeks"
@register_vocab
-class OwnershipClass(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:OwnershipClassVocab-1.0'
+class OwnershipClass_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:OwnershipClassVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INTERNALLYOWNED = "Internally-Owned"
+ TERM_CUSTOMEROWNED = "Customer-Owned"
TERM_EMPLOYEEOWNED = "Employee-Owned"
+ TERM_INTERNALLYOWNED = "Internally-Owned"
TERM_PARTNEROWNED = "Partner-Owned"
- TERM_CUSTOMEROWNED = "Customer-Owned"
TERM_UNKNOWN = "Unknown"
@register_vocab
-class MalwareType(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:MalwareTypeVocab-1.0'
+class MalwareType_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:MalwareTypeVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_AUTOMATED_TRANSFER_SCRIPTS = "Automated Transfer Scripts"
TERM_ADWARE = "Adware"
- TERM_DIALER = "Dialer"
+ TERM_AUTOMATED_TRANSFER_SCRIPTS = "Automated Transfer Scripts"
TERM_BOT = "Bot"
TERM_BOT_CREDENTIAL_THEFT = "Bot - Credential Theft"
TERM_BOT_DDOS = "Bot - DDoS"
TERM_BOT_LOADER = "Bot - Loader"
TERM_BOT_SPAM = "Bot - Spam"
+ TERM_DIALER = "Dialer"
TERM_DOS_OR_DDOS = "DoS / DDoS"
TERM_DOS_OR_DDOS_PARTICIPATORY = "DoS / DDoS - Participatory"
TERM_DOS_OR_DDOS_SCRIPT = "DoS / DDoS - Script"
@@ -776,20 +946,21 @@ class MalwareType(VocabString):
@register_vocab
-class IncidentEffect(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:IncidentEffectVocab-1.0'
+class IncidentEffect_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:IncidentEffectVocab-1.0"
+ _VOCAB_VERSION = "1.0"
TERM_BRAND_OR_IMAGE_DEGRADATION = "Brand or Image Degradation"
- TERM_LOSS_OF_COMPETITIVE_ADVANTAGE = "Loss of Competitive Advantage"
- TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_ECONOMIC = "Loss of Competitive Advantage - Economic"
- TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_MILITARY = "Loss of Competitive Advantage - Military"
- TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_POLITICAL = "Loss of Competitive Advantage - Political"
TERM_DATA_BREACH_OR_COMPROMISE = "Data Breach or Compromise"
TERM_DEGRADATION_OF_SERVICE = "Degradation of Service"
TERM_DESTRUCTION = "Destruction"
TERM_DISRUPTION_OF_SERVICE_OR_OPERATIONS = "Disruption of Service / Operations"
TERM_FINANCIAL_LOSS = "Financial Loss"
+ TERM_LOSS_OF_COMPETITIVE_ADVANTAGE = "Loss of Competitive Advantage"
+ TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_ECONOMIC = "Loss of Competitive Advantage - Economic"
+ TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_MILITARY = "Loss of Competitive Advantage - Military"
+ TERM_LOSS_OF_COMPETITIVE_ADVANTAGE_POLITICAL = "Loss of Competitive Advantage - Political"
TERM_LOSS_OF_CONFIDENTIAL_OR_PROPRIETARY_INFORMATION_OR_INTELLECTUAL_PROPERTY = "Loss of Confidential / Proprietary Information or Intellectual Property"
TERM_REGULATORY_COMPLIANCE_OR_LEGAL_IMPACT = "Regulatory, Compliance or Legal Impact"
TERM_UNINTENDED_ACCESS = "Unintended Access"
@@ -797,12 +968,47 @@ class IncidentEffect(VocabString):
@register_vocab
-class InformationSourceRole(VocabString):
- _namespace = 'http://stix.mitre.org/default_vocabularies-1'
- _XSI_TYPE = 'stixVocabs:InformationSourceRoleVocab-1.0'
+class InformationSourceRole_1_0(VocabString):
+ _namespace = "http://stix.mitre.org/default_vocabularies-1"
+ _XSI_TYPE = "stixVocabs:InformationSourceRoleVocab-1.0"
+ _VOCAB_VERSION = "1.0"
- TERM_INITIAL_AUTHOR = "Initial Author"
- TERM_CONTENT_ENHANCERORREFINER = "Content Enhancer/Refiner"
TERM_AGGREGATOR = "Aggregator"
+ TERM_CONTENT_ENHANCERORREFINER = "Content Enhancer/Refiner"
+ TERM_INITIAL_AUTHOR = "Initial Author"
TERM_TRANSFORMERORTRANSLATOR = "Transformer/Translator"
+# Vocab aliases which resolve to the most recent version of the
+# associated VocabString.
+AssetType = AssetType_1_0
+AttackerInfrastructureType = AttackerInfrastructureType_1_0
+AttackerToolType = AttackerToolType_1_0
+AvailabilityLossType = AvailabilityLossType_1_1_1
+CampaignStatus = CampaignStatus_1_0
+COAStage = COAStage_1_0
+CourseOfActionType = CourseOfActionType_1_0
+DiscoveryMethod = DiscoveryMethod_2_0
+HighMediumLow = HighMediumLow_1_0
+ImpactQualification = ImpactQualification_1_0
+ImpactRating = ImpactRating_1_0
+IncidentCategory = IncidentCategory_1_0
+IncidentEffect = IncidentEffect_1_0
+IncidentStatus = IncidentStatus_1_0
+IndicatorType = IndicatorType_1_1
+InformationSourceRole = InformationSourceRole_1_0
+InformationType = InformationType_1_0
+IntendedEffect = IntendedEffect_1_0
+LocationClass = LocationClass_1_0
+LossDuration = LossDuration_1_0
+LossProperty = LossProperty_1_0
+MalwareType = MalwareType_1_0
+ManagementClass = ManagementClass_1_0
+Motivation = Motivation_1_1
+OwnershipClass = OwnershipClass_1_0
+PackageIntent = PackageIntent_1_0
+PlanningAndOperationalSupport = PlanningAndOperationalSupport_1_0_1
+ReportIntent = ReportIntent_1_0
+SecurityCompromise = SecurityCompromise_1_0
+SystemType = SystemType_1_0
+ThreatActorSophistication = ThreatActorSophistication_1_0
+ThreatActorType = ThreatActorType_1_0
diff --git a/stix/core/__init__.py b/stix/core/__init__.py
index f744e7d1..a4817895 100644
--- a/stix/core/__init__.py
+++ b/stix/core/__init__.py
@@ -1,5 +1,100 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-from stix_package import STIXPackage # noqa
-from stix_header import STIXHeader # noqa
+# stdlib
+from functools import partial
+
+# mixbox
+from mixbox import fields
+
+# base import
+import stix
+
+# component imports
+from stix.campaign import Campaign
+from stix.coa import CourseOfAction
+from stix.exploit_target import ExploitTarget
+from stix.indicator import Indicator
+from stix.incident import Incident
+from stix.threat_actor import ThreatActor
+
+# binding imports
+from stix.bindings import stix_core as stix_core_binding
+from stix.bindings import stix_common as stix_common_binding
+
+
+class Campaigns(stix.EntityList):
+ _binding = stix_core_binding
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding_class = _binding.CampaignsType
+
+ campaign = fields.TypedField(
+ name="Campaign",
+ type_=Campaign,
+ multiple=True
+ )
+
+
+class CoursesOfAction(stix.EntityList):
+ _binding = stix_core_binding
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding_class = _binding.CoursesOfActionType
+
+ course_of_action = fields.TypedField(
+ name="Course_Of_Action",
+ type_=CourseOfAction,
+ multiple=True
+ )
+
+
+class ExploitTargets(stix.EntityList):
+ _binding = stix_common_binding
+ _namespace = 'http://stix.mitre.org/common-1'
+ _binding_class = _binding.ExploitTargetsType
+
+ exploit_target = fields.TypedField(
+ name="Exploit_Target",
+ type_=ExploitTarget,
+ multiple=True
+ )
+
+
+class Incidents(stix.EntityList):
+ _binding = stix_core_binding
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding_class = _binding.IncidentsType
+
+ incident = fields.TypedField(
+ name="Incident",
+ type_=Incident,
+ multiple=True
+ )
+
+
+class Indicators(stix.EntityList):
+ _binding = stix_core_binding
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding_class = _binding.IndicatorsType
+
+ indicator = fields.TypedField(
+ name="Indicator",
+ type_=Indicator,
+ multiple=True
+ )
+
+
+class ThreatActors(stix.EntityList):
+ _binding = stix_core_binding
+ _namespace = 'http://stix.mitre.org/stix-1'
+ _binding_class = _binding.ThreatActorsType
+
+ threat_actor = fields.TypedField(
+ name="Threat_Actor",
+ type_=ThreatActor,
+ multiple=True
+ )
+
+
+# Namespace flattening
+from .stix_package import STIXPackage # noqa
+from .stix_header import STIXHeader # noqa
diff --git a/stix/core/stix_header.py b/stix/core/stix_header.py
index 37afdd5e..90c58f9b 100644
--- a/stix/core/stix_header.py
+++ b/stix/core/stix_header.py
@@ -1,168 +1,67 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-import stix.bindings.stix_common as stix_common_binding
-import stix.bindings.stix_core as stix_core_binding
-from stix.common import vocabs, InformationSource, StructuredText, VocabString
+from stix.common import InformationSource, StructuredText, Profiles
+from stix.common.vocabs import VocabField, PackageIntent
from stix.data_marking import Marking
+import stix.bindings.stix_core as stix_core_binding
class STIXHeader(stix.Entity):
+ """The STIX Package Header.
+
+ Args:
+ handling: The data marking section of the Header.
+ information_source: The :class:`.InformationSource` section of the
+ Header.
+ package_intents: A collection of :class:`.VocabString`
+ defining the intent of the parent :class:`.STIXPackage`.
+ description: A description of the intent or purpose
+ of the parent :class:`.STIXPackage`.
+ short_description: A short description of the intent
+ or purpose of the parent :class:`.STIXPackage`.
+ title: The title of the :class:`.STIXPackage`.
+
+ Attributes:
+ profiles: A collection of STIX Profiles the parent
+ :class:`.STIXPackage` conforms to.
+ title: The title of the parent :class:`.STIXPackage`.
+
+ """
_binding = stix_core_binding
+ _binding_class = _binding.STIXHeaderType
_namespace = 'http://stix.mitre.org/stix-1'
+ title = fields.TypedField("Title")
+ package_intents = VocabField("Package_Intent", PackageIntent, multiple=True)
+ description = fields.TypedField("Description", StructuredText)
+ short_description = fields.TypedField("Short_Description", StructuredText)
+ handling = fields.TypedField("Handling", Marking)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+ profiles = fields.TypedField("Profiles", Profiles)
+
def __init__(self, package_intents=None, description=None, handling=None,
information_source=None, title=None, short_description=None):
+ super(STIXHeader, self).__init__()
+
self.package_intents = package_intents
self.title = title
self.description = description
self.short_description = short_description
self.handling = handling
self.information_source = information_source
- self.profiles = []
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- """Sets the value of the description property.
-
- If the value is an instance of basestring, it will be coerced into an
- instance of StructuredText, with its 'text' property set to the input
- value.
-
- """
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- """The ``short_description`` property for this entity.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- @property
- def handling(self):
- return self._handling
-
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, try_cast=False, handling=value)
-
- @property
- def package_intents(self):
- return self._package_intents
-
- @package_intents.setter
- def package_intents(self, value):
- self._package_intents = _PackageIntents(value)
+ self.profiles = None
def add_package_intent(self, package_intent):
self.package_intents.append(package_intent)
- @property
- def information_source(self):
- return self._information_source
-
- @information_source.setter
- def information_source(self, value):
- self._set_var(InformationSource, try_cast=False, information_source=value)
-
def add_profile(self, profile):
"""Adds a profile to the STIX Header. A Profile is represented by a
string URI.
"""
self.profiles.append(profile)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.information_source = InformationSource.from_obj(obj.Information_Source)
- return_obj.package_intents = _PackageIntents.from_obj(obj.Package_Intent)
- return_obj.profiles = obj.Profiles.Profile if obj.Profiles else []
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(STIXHeader, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding.STIXHeaderType()
-
- if self.title:
- return_obj.Title = self.title
- if self.package_intents:
- return_obj.Package_Intent = self.package_intents.to_obj(ns_info=ns_info)
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.information_source:
- return_obj.Information_Source = self.information_source.to_obj(ns_info=ns_info)
- if self.profiles:
- return_obj.Profiles = stix_common_binding.ProfilesType(Profile=self.profiles)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
-
- return_obj.title = get('title')
- return_obj.package_intents = _PackageIntents.from_list(get('package_intents'))
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.short_description = StructuredText.from_dict(get('short_description'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.information_source = InformationSource.from_dict(get('information_source'))
- return_obj.profiles = get('profiles')
-
- return return_obj
-
- def to_dict(self):
- return super(STIXHeader, self).to_dict()
-
-
-# NOT AN ACTUAL STIX TYPE!
-class _PackageIntents(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.PackageIntent(value)
diff --git a/stix/core/stix_package.py b/stix/core/stix_package.py
index 64c1842e..40d4b5ca 100644
--- a/stix/core/stix_package.py
+++ b/stix/core/stix_package.py
@@ -1,195 +1,189 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# external
+# mixbox
+from mixbox import idgen
+from mixbox import fields
+
+# cybox
from cybox.core import Observable, Observables
-# internal
+# base
import stix
-import stix.utils as utils
-import stix.utils.parser as parser
-
-from stix.campaign import Campaign
-from stix.coa import CourseOfAction
-from stix.exploit_target import ExploitTarget
-from stix.indicator import Indicator
-from stix.incident import Incident
-from stix.threat_actor import ThreatActor
-from stix.ttp import TTP
-from stix.common.related import RelatedPackages
+
+# utility imports
+from .. import utils
+from ..utils import parser
+# component imports
+from ..campaign import Campaign
+from ..coa import CourseOfAction
+from ..exploit_target import ExploitTarget
+from ..indicator import Indicator
+from ..incident import Incident
+from ..threat_actor import ThreatActor
+from ..ttp import TTP
+
+# relationship imports
+from ..common.related import RelatedPackages
# relative imports
from .stix_header import STIXHeader
from .ttps import TTPs
+from . import (Campaigns, CoursesOfAction, ExploitTargets, Incidents,
+ Indicators, ThreatActors)
# binding imports
-import stix.bindings.stix_common as stix_common_binding
import stix.bindings.stix_core as stix_core_binding
+import mixbox.entities
class STIXPackage(stix.Entity):
+ """A STIX Package object.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref: An identifier reference. If set this will unset
+ the ``id_`` property.
+ timestamp: A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ stix_header: A Report :class:`.Header` object.
+ campaigns: A collection of :class:`.Campaign` objects.
+ courses_of_action: A collection of :class:`.CourseOfAction` objects.
+ exploit_targets: A collection of :class:`.ExploitTarget` objects.
+ incidents: A collection of :class:`.Incident` objects.
+ indicators: A collection of :class:`.Indicator` objects.
+ threat_actors: A collection of :class:`.ThreatActor` objects.
+ ttps: A collection of :class:`.TTP` objects.
+ related_packages: A collection of
+ :class:`.RelatedPackage` objects.
+
+ """
_binding = stix_core_binding
_binding_class = _binding.STIXType
_namespace = 'http://stix.mitre.org/stix-1'
_version = "1.1.1"
+ _ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
+
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ version = fields.TypedField("version")
+ timestamp = fields.DateTimeField("timestamp")
+ stix_header = fields.TypedField("STIX_Header", STIXHeader)
+ campaigns = fields.TypedField("Campaigns", Campaigns)
+ courses_of_action = fields.TypedField("Courses_Of_Action", CoursesOfAction)
+ exploit_targets = fields.TypedField("Exploit_Targets", ExploitTargets)
+ observables = fields.TypedField("Observables", Observables)
+ indicators = fields.TypedField("Indicators", Indicators)
+ incidents = fields.TypedField("Incidents", Incidents)
+ threat_actors = fields.TypedField("Threat_Actors", ThreatActors)
+ ttps = fields.TypedField("TTPs", TTPs)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackages)
def __init__(self, id_=None, idref=None, timestamp=None, stix_header=None,
courses_of_action=None, exploit_targets=None, indicators=None,
observables=None, incidents=None, threat_actors=None,
- ttps=None, campaigns=None):
+ ttps=None, campaigns=None, related_packages=None):
- self.id_ = id_ or stix.utils.create_id("Package")
+ super(STIXPackage, self).__init__()
+
+ self.id_ = id_ or idgen.create_id("Package")
self.idref = idref
- self.version = self._version
+ self.version = STIXPackage._version
self.stix_header = stix_header
- self.campaigns = campaigns
- self.courses_of_action = courses_of_action
- self.exploit_targets = exploit_targets
- self.observables = observables
- self.indicators = indicators
- self.incidents = incidents
- self.threat_actors = threat_actors
+ self.campaigns = campaigns or Campaigns()
+ self.courses_of_action = courses_of_action or CoursesOfAction()
+ self.exploit_targets = exploit_targets or ExploitTargets()
+ self.observables = observables or Observables()
+ self.indicators = indicators or Indicators()
+ self.incidents = incidents or Incidents()
+ self.threat_actors = threat_actors or ThreatActors()
self.ttps = ttps
- self.related_packages = RelatedPackages()
-
- if timestamp:
- self.timestamp = timestamp
- else:
- self.timestamp = utils.dates.now() if not idref else None
-
- @property
- def id_(self):
- return self._id
-
- @id_.setter
- def id_(self, value):
- if not value:
- self._id = None
- else:
- self._id = value
- self.idref = None
-
- @property
- def idref(self):
- return self._idref
-
- @idref.setter
- def idref(self, value):
- if not value:
- self._idref = None
- else:
- self._idref = value
- self.id_ = None # unset id_ if idref is present
-
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- @property
- def stix_header(self):
- return self._stix_header
-
- @stix_header.setter
- def stix_header(self, value):
- self._set_var(STIXHeader, try_cast=False, stix_header=value)
-
- @property
- def indicators(self):
- return self._indicators
-
- @indicators.setter
- def indicators(self, value):
- self._indicators = Indicators(value)
+ self.related_packages = related_packages
+ self.timestamp = timestamp
def add_indicator(self, indicator):
- self.indicators.append(indicator)
-
- @property
- def campaigns(self):
- return self._campaigns
+ """Adds an :class:`.Indicator` object to the :attr:`indicators`
+ collection.
- @campaigns.setter
- def campaigns(self, value):
- self._campaigns = Campaigns(value)
+ """
+ if self.indicators is None:
+ self.indicators = Indicators()
+ self.indicators.append(indicator)
def add_campaign(self, campaign):
+ """Adds a :class:`Campaign` object to the :attr:`campaigns` collection.
+
+ """
+ if self.campaigns is None:
+ self.campaigns = Campaigns()
self.campaigns.append(campaign)
- @property
- def observables(self):
- return self._observables
+ def add_observable(self, observable):
+ """Adds an ``Observable`` object to the :attr:`observables` collection.
- @observables.setter
- def observables(self, value):
- self._set_var(Observables, observables=value)
+ If `observable` is not an ``Observable`` instance, an effort will be
+ made to convert it to one.
- def add_observable(self, observable):
- if not self.observables:
+ """
+ if self.observables is None:
self.observables = Observables(observables=observable)
else:
self.observables.add(observable)
- @property
- def incidents(self):
- return self._incidents
-
- @incidents.setter
- def incidents(self, value):
- self._incidents = Incidents(value)
-
def add_incident(self, incident):
- self.incidents.append(incident)
+ """Adds an :class:`.Incident` object to the :attr:`incidents`
+ collection.
- @property
- def threat_actors(self):
- return self._threat_actors
-
- @threat_actors.setter
- def threat_actors(self, value):
- self._threat_actors = ThreatActors(value)
+ """
+ if self.incidents is None:
+ self.incidents = Incidents()
+ self.incidents.append(incident)
def add_threat_actor(self, threat_actor):
- self._threat_actors.append(threat_actor)
+ """Adds an :class:`.ThreatActor` object to the :attr:`threat_actors`
+ collection.
- @property
- def courses_of_action(self):
- return self._courses_of_action
-
- @courses_of_action.setter
- def courses_of_action(self, value):
- self._courses_of_action = CoursesOfAction(value)
+ """
+ if self.threat_actors is None:
+ self.threat_actors = ThreatActors()
+ self.threat_actors.append(threat_actor)
def add_course_of_action(self, course_of_action):
- self._courses_of_action.append(course_of_action)
+ """Adds an :class:`.CourseOfAction` object to the
+ :attr:`courses_of_action` collection.
- @property
- def exploit_targets(self):
- return self._exploit_targets
-
- @exploit_targets.setter
- def exploit_targets(self, value):
- self._exploit_targets = ExploitTargets(value)
+ """
+ if self.courses_of_action is None:
+ self.courses_of_action = CoursesOfAction()
+ self.courses_of_action.append(course_of_action)
def add_exploit_target(self, exploit_target):
- self._exploit_targets.append(exploit_target)
-
- @property
- def ttps(self):
- return self._ttps
-
- @ttps.setter
- def ttps(self, value):
- if isinstance(value, TTPs):
- self._ttps = value
- else:
- self._ttps = TTPs(value)
-
+ """Adds an :class:`.ExploitTarget` object to the
+ :attr:`exploit_targets` collection.
+
+ """
+ if self.exploit_targets is None:
+ self.exploit_targets = ExploitTargets()
+ self.exploit_targets.append(exploit_target)
+
def add_ttp(self, ttp):
- self.ttps.append(ttp)
+ """Adds an :class:`.TTP` object to the :attr:`ttps` collection.
+
+ """
+ if self.ttps is None:
+ self.ttps = TTPs()
+ self.ttps.ttp.append(ttp)
+
+ def add_related_package(self, related_package):
+ """Adds a :class:`.RelatedPackage` object to the
+ :attr:`related_packages` collection.
+
+ """
+ if self.related_packages is None:
+ self.related_packages = RelatedPackages()
+ self.related_packages.append(related_package)
def add(self, entity):
"""Adds `entity` to a top-level collection. For example, if `entity` is
@@ -208,7 +202,7 @@ def add(self, entity):
Incident: self.add_incident,
Indicator: self.add_indicator,
ThreatActor: self.add_threat_actor,
- TTP: self.add_threat_actor,
+ TTP: self.add_ttp,
Observable: self.add_observable,
}
@@ -220,90 +214,6 @@ def add(self, entity):
error = error.format(type(entity))
raise TypeError(error)
- def to_obj(self, return_obj=None, ns_info=None):
- super(STIXPackage, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
- return_obj.version = self.version
- return_obj.timestamp = utils.dates.serialize_value(self.timestamp)
-
- if self.stix_header:
- return_obj.STIX_Header = self.stix_header.to_obj(ns_info=ns_info)
- if self.campaigns:
- return_obj.Campaigns = self.campaigns.to_obj(ns_info=ns_info)
- if self.courses_of_action:
- return_obj.Courses_Of_Action = self.courses_of_action.to_obj(ns_info=ns_info)
- if self.exploit_targets:
- return_obj.Exploit_Targets = self.exploit_targets.to_obj(ns_info=ns_info)
- if self.indicators:
- return_obj.Indicators = self.indicators.to_obj(ns_info=ns_info)
- if self.observables:
- return_obj.Observables = self.observables.to_obj(ns_info=ns_info)
- if self.incidents:
- return_obj.Incidents = self.incidents.to_obj(ns_info=ns_info)
- if self.threat_actors:
- return_obj.Threat_Actors = self.threat_actors.to_obj(ns_info=ns_info)
- if self.ttps:
- return_obj.TTPs = self.ttps.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
-
- return return_obj
-
- def to_dict(self):
- return super(STIXPackage, self).to_dict()
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
- return_obj.timestamp = obj.timestamp
- return_obj.stix_header = STIXHeader.from_obj(obj.STIX_Header)
- return_obj.campaigns = Campaigns.from_obj(obj.Campaigns)
- return_obj.courses_of_action = CoursesOfAction.from_obj(obj.Courses_Of_Action)
- return_obj.exploit_targets = ExploitTargets.from_obj(obj.Exploit_Targets)
- return_obj.indicators = Indicators.from_obj(obj.Indicators)
- return_obj.observables = Observables.from_obj(obj.Observables)
- return_obj.incidents = Incidents.from_obj(obj.Incidents)
- return_obj.threat_actors = ThreatActors.from_obj(obj.Threat_Actors)
- return_obj.ttps = TTPs.from_obj(obj.TTPs)
- return_obj.related_packages = RelatedPackages.from_obj(obj.Related_Packages)
-
- # Don't overwrite unless a version is passed in
- if obj.version:
- return_obj.version = obj.version
-
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = dict_repr.get('id')
- return_obj.idref = dict_repr.get('idref')
- return_obj.timestamp = dict_repr.get('timestamp')
- return_obj.version = dict_repr.get('version', cls._version)
- return_obj.stix_header = STIXHeader.from_dict(dict_repr.get('stix_header'))
- return_obj.campaigns = Campaigns.from_dict(dict_repr.get('campaigns'))
- return_obj.courses_of_action = CoursesOfAction.from_dict(dict_repr.get('courses_of_action'))
- return_obj.exploit_targets = ExploitTargets.from_dict(dict_repr.get('exploit_targets'))
- return_obj.indicators = Indicators.from_dict(dict_repr.get('indicators'))
- return_obj.observables = Observables.from_dict(dict_repr.get('observables'))
- return_obj.incidents = Incidents.from_dict(dict_repr.get('incidents'))
- return_obj.threat_actors = ThreatActors.from_dict(dict_repr.get('threat_actors'))
- return_obj.ttps = TTPs.from_dict(dict_repr.get('ttps'))
- return_obj.related_packages = RelatedPackages.from_dict(dict_repr.get('related_packages'))
-
- return return_obj
-
@classmethod
def from_xml(cls, xml_file, encoding=None):
"""Parses the `xml_file` file-like object and returns a
@@ -322,63 +232,3 @@ def from_xml(cls, xml_file, encoding=None):
"""
entity_parser = parser.EntityParser()
return entity_parser.parse_xml(xml_file, encoding=encoding)
-
-
-class Campaigns(stix.EntityList):
- _binding = stix_core_binding
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding_class = _binding.CampaignsType
- _contained_type = Campaign
- _binding_var = "Campaign"
- _inner_name = "campaigns"
- _dict_as_list = True
-
-
-class CoursesOfAction(stix.EntityList):
- _binding = stix_core_binding
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding_class = _binding.CoursesOfActionType
- _contained_type = CourseOfAction
- _binding_var = "Course_Of_Action"
- _inner_name = "courses_of_action"
- _dict_as_list = True
-
-
-class ExploitTargets(stix.EntityList):
- _binding = stix_common_binding
- _namespace = 'http://stix.mitre.org/common-1'
- _binding_class = _binding.ExploitTargetsType
- _contained_type = ExploitTarget
- _binding_var = "Exploit_Target"
- _inner_name = "exploit_targets"
- _dict_as_list = True
-
-
-class Incidents(stix.EntityList):
- _binding = stix_core_binding
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding_class = _binding.IncidentsType
- _contained_type = Incident
- _binding_var = "Incident"
- _inner_name = "incidents"
- _dict_as_list = True
-
-
-class Indicators(stix.EntityList):
- _binding = stix_core_binding
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding_class = _binding.IndicatorsType
- _contained_type = Indicator
- _binding_var = "Indicator"
- _inner_name = "indicators"
- _dict_as_list = True
-
-
-class ThreatActors(stix.EntityList):
- _binding = stix_core_binding
- _namespace = 'http://stix.mitre.org/stix-1'
- _binding_class = _binding.ThreatActorsType
- _contained_type = ThreatActor
- _binding_var = "Threat_Actor"
- _inner_name = "threat_actors"
- _dict_as_list = True
diff --git a/stix/core/ttps.py b/stix/core/ttps.py
index 071280c1..29e50102 100644
--- a/stix/core/ttps.py
+++ b/stix/core/ttps.py
@@ -1,78 +1,33 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# mixbox
+from mixbox import fields
+
+# stix
import stix
from stix.ttp import TTP
-from stix.bindings import stix_core as core_binding
from stix.common.kill_chains import KillChains
+from stix.bindings import stix_core as core_binding
-class TTPs(stix.EntityList):
+class TTPs(stix.Entity):
_binding = core_binding
_binding_class = _binding.TTPsType
_namespace = 'http://stix.mitre.org/stix-1'
- _contained_type = TTP
- _binding_var = "TTP"
- _inner_name = "ttps"
-
- def __init__(self, ttps=None):
- super(TTPs, self).__init__(ttps)
- self.kill_chains = KillChains()
- def __nonzero__(self):
- return super(TTPs, self).__nonzero__() or bool(self.kill_chains)
+ ttp = fields.TypedField("TTP", TTP, multiple=True, key_name="ttps")
+ kill_chains = fields.TypedField("Kill_Chains", KillChains)
- @property
- def ttps(self):
- return self._inner
-
- @ttps.setter
- def ttps(self, value):
- self._inner = []
- self.append(value)
+ def __init__(self, ttps=None):
+ super(TTPs, self).__init__()
+ self.ttp = ttps
+ self.kill_chains = KillChains()
def add_ttp(self, ttp):
- self.ttps.append(ttp)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(TTPs, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.kill_chains:
- return_obj.Kill_Chains = self.kill_chains.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None): # noqa
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(TTPs, cls).from_obj(obj, return_obj=return_obj)
-
- return_obj.kill_chains = KillChains.from_obj(obj.Kill_Chains)
-
- return return_obj
-
- def to_dict(self):
- return super(TTPs, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None): # noqa
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(TTPs, cls).from_dict(dict_repr, return_obj)
-
- get = dict_repr.get
- return_obj.kill_chains = KillChains.from_dict(get('kill_chains'))
+ self.ttp.append(ttp)
- return return_obj
+ def add_kill_chain(self, kc):
+ if self.kill_chains is None:
+ self.kill_chains = KillChains()
+ self.kill_chains.kill_chain.append(kc)
diff --git a/stix/data_marking.py b/stix/data_marking.py
index 805f6ad5..8c5c939d 100644
--- a/stix/data_marking.py
+++ b/stix/data_marking.py
@@ -1,162 +1,25 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import fields
+from mixbox import entities
+
+# internal
import stix
from stix.common import InformationSource
-import stix.bindings.data_marking as stix_data_marking_binding
-
-
-class Marking(stix.Entity):
- _binding = stix_data_marking_binding
- _binding_class = stix_data_marking_binding.MarkingType
- _namespace = 'http://data-marking.mitre.org/Marking-1'
-
- def __init__(self, markings=None):
- self.markings = _MarkingSpecifications(markings)
-
- @property
- def markings(self):
- return self._markings
-
- @markings.setter
- def markings(self, value):
- self._markings = _MarkingSpecifications(value)
-
- def add_marking(self, value):
- self._markings.append(value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Marking, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- obj = self._binding_class()
-
- if self.markings:
- obj.Marking = self.markings.to_obj(ns_info=ns_info)
-
- return obj
-
- def to_list(self):
- return self.markings.to_list() if self.markings else []
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.markings = _MarkingSpecifications.from_obj(obj.Marking)
-
- return return_obj
-
- @classmethod
- def from_list(cls, markings_list, return_obj=None):
- if not markings_list:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- mlist = _MarkingSpecifications.from_list(markings_list)
- return_obj.markings = mlist
-
- return return_obj
-
- to_dict = to_list
- from_dict = from_list
-
-
-class MarkingSpecification(stix.Entity):
- _binding = stix_data_marking_binding
- _binding_class = stix_data_marking_binding.MarkingSpecificationType
- _namespace = 'http://data-marking.mitre.org/Marking-1'
-
- def __init__(self, controlled_structure=None, marking_structures=None):
- self.id_ = None
- self.idref = None
- self.version = None
- self.controlled_structure = controlled_structure
- self.marking_structures = _MarkingStructures(marking_structures)
- self.information_source = None
-
- @property
- def information_source(self):
- return self._information_source
-
- @information_source.setter
- def information_source(self, value):
- self._set_var(InformationSource, try_cast=False, information_source=value)
-
- @property
- def marking_structures(self):
- return self._marking_structures
-
- @marking_structures.setter
- def marking_structures(self, value):
- self._marking_structures = _MarkingStructures(value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(MarkingSpecification, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- obj = self._binding_class()
-
- obj.id = self.id_
- obj.idref = self.idref
- obj.version = self.version
- obj.Controlled_Structure = self.controlled_structure
- obj.Marking_Structure = self.marking_structures.to_obj(ns_info=ns_info)
- if self.information_source:
- obj.Information_Source = self.information_source.to_obj(ns_info=ns_info)
-
- return obj
-
- def to_dict(self):
- return super(MarkingSpecification, self).to_dict()
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
- return_obj.version = obj.version
- return_obj.controlled_structure = obj.Controlled_Structure
- return_obj.marking_structures = _MarkingStructures.from_obj(obj.Marking_Structure)
- return_obj.information_source = InformationSource.from_obj(obj.Information_Source)
+# bindings
+import stix.bindings.data_marking as stix_data_marking_binding
- return return_obj
+class MarkingStructureFactory(entities.EntityFactory):
@classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = d.get # PEP8 line length fix
- return_obj.id_ = get('id')
- return_obj.idref = get('idref')
- return_obj.version = get('version')
- return_obj.controlled_structure = get('controlled_structure')
- return_obj.marking_structures = _MarkingStructures.from_dict(
- get('marking_structures')
- )
- return_obj.information_source = InformationSource.from_dict(
- get('information_source')
- )
-
- return return_obj
+ def entity_class(cls, key):
+ import stix.extensions.marking.tlp # noqa
+ import stix.extensions.marking.simple_marking # noqa
+ import stix.extensions.marking.terms_of_use_marking # noqa
+ return stix.lookup_extension(key, default=MarkingStructure)
class MarkingStructure(stix.Entity):
@@ -165,120 +28,68 @@ class MarkingStructure(stix.Entity):
_namespace = 'http://data-marking.mitre.org/Marking-1'
_XSI_TYPE = None # overridden by subclasses
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ marking_model_name = fields.TypedField("marking_model_name")
+ marking_model_ref = fields.TypedField("marking_model_ref")
+
def __init__(self):
+ super(MarkingStructure, self).__init__()
+
self.id_ = None
self.idref = None
self.marking_model_name = None
self.marking_model_ref = None
- def to_obj(self, return_obj=None, ns_info=None):
- super(MarkingStructure, self).to_obj(
- return_obj=return_obj,
- ns_info=ns_info
- )
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
- return_obj.marking_model_name = self.marking_model_name
- return_obj.marking_model_ref = self.marking_model_ref
-
- return return_obj
-
def to_dict(self):
- d = {}
+ d = super(MarkingStructure, self).to_dict()
if self._XSI_TYPE:
d['xsi:type'] = self._XSI_TYPE
- if self.id_:
- d['id'] = self.id_
- if self.idref:
- d['idref'] = self.idref
- if self.marking_model_name:
- d['marking_model_name'] = self.marking_model_name
- if self.marking_model_ref:
- d['marking_model_ref'] = self.marking_model_ref
-
return d
@staticmethod
def lookup_class(xsi_type):
- if not xsi_type:
- return MarkingStructure
-
- for (k, v) in _EXTENSION_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- raise ValueError("Unregistered xsi:type %s" % xsi_type)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- import stix.extensions.marking.tlp # noqa
- import stix.extensions.marking.simple_marking # noqa
- import stix.extensions.marking.terms_of_use_marking # noqa
-
- if not obj:
- return None
+ return stix.lookup_extension(xsi_type, default=MarkingStructure)
- if return_obj:
- m = return_obj
- m.id_ = obj.id
- m.idref = obj.idref
- m.marking_model_name = obj.marking_model_name
- m.marking_model_ref = obj.marking_model_ref
- else:
- if hasattr(obj, 'xml_type'):
- klass = MarkingStructure.lookup_class(obj.xml_type)
- m = klass.from_obj(obj)
- else:
- m = cls.from_obj(obj, cls())
-
- return m
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- import stix.extensions.marking.tlp # noqa
- import stix.extensions.marking.simple_marking # noqa
- import stix.extensions.marking.terms_of_use_marking # noqa
-
- if not d:
- return None
+class MarkingSpecification(stix.Entity):
+ _binding = stix_data_marking_binding
+ _binding_class = stix_data_marking_binding.MarkingSpecificationType
+ _namespace = 'http://data-marking.mitre.org/Marking-1'
- if return_obj is not None:
- m = return_obj
- m.id_ = d.get('id')
- m.idref = d.get('idref')
- m.marking_model_name = d.get('marking_model_name')
- m.marking_model_ref = d.get('marking_model_ref')
- else:
- if 'xsi:type' in d:
- cls = MarkingStructure.lookup_class(d.get('xsi:type'))
- m = cls.from_dict(d)
- else:
- m = cls.from_dict(d, cls())
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ version = fields.TypedField("version")
+ controlled_structure = fields.TypedField("Controlled_Structure")
+ marking_structures = fields.TypedField("Marking_Structure", MarkingStructure, factory=MarkingStructureFactory, multiple=True, key_name="marking_structures")
+ information_source = fields.TypedField("Information_Source", InformationSource)
- return m
+ def __init__(self, controlled_structure=None, marking_structures=None):
+ super(MarkingSpecification, self).__init__()
+ self.id_ = None
+ self.idref = None
+ self.version = None
+ self.controlled_structure = controlled_structure
+ self.marking_structures = marking_structures
+ self.information_source = None
-# Not Actual STIX Types!
-class _MarkingSpecifications(stix.TypedList):
- _contained_type = MarkingSpecification
+class Marking(stix.EntityList):
+ _binding = stix_data_marking_binding
+ _binding_class = stix_data_marking_binding.MarkingType
+ _namespace = 'http://data-marking.mitre.org/Marking-1'
-class _MarkingStructures(stix.TypedList):
- _contained_type = MarkingStructure
+ marking = fields.TypedField("Marking", MarkingSpecification, multiple=True)
+ def __init__(self, markings=None):
+ super(Marking, self).__init__(markings)
-#: Mapping of marking extension types to classes
-_EXTENSION_MAP = {}
+ def add_marking(self, value):
+ self.marking.append(value)
-def add_extension(cls):
- _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+# Backwards compatibility
+add_extension = stix.add_extension
diff --git a/stix/exploit_target/__init__.py b/stix/exploit_target/__init__.py
index 98214d5b..dd9a41dd 100644
--- a/stix/exploit_target/__init__.py
+++ b/stix/exploit_target/__init__.py
@@ -1,6 +1,9 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# mixbox
+from mixbox import fields
+
# internal
import stix
import stix.bindings.exploit_target as exploit_target_binding
@@ -8,20 +11,20 @@
GenericRelationshipList, RelatedCOA, RelatedExploitTarget,
RelatedPackageRefs
)
-from stix.data_marking import Marking
# relative
-from .vulnerability import Vulnerability, _Vulnerabilities # noqa
-from .weakness import Weakness, _Weaknesses # noqa
-from .configuration import Configuration, _Configurations # noqa
+from .vulnerability import Vulnerability # noqa
+from .weakness import Weakness # noqa
+from .configuration import Configuration # noqa
+from stix.common import InformationSource
class ExploitTarget(stix.BaseCoreComponent):
- """Implementation of STIX ``ExploitTarget``.
+ """Implementation of STIX Exploit Target.
Args:
id_ (optional): An identifier. If ``None``, a value will be generated
- via ``stix.utils.create_id()``. If set, this will unset the
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
``idref`` property.
idref (optional): An identifier reference. If set this will unset the
``id_`` property.
@@ -39,6 +42,14 @@ class ExploitTarget(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = 'et'
+ potential_coas = fields.TypedField("Potential_COAs", type_="stix.exploit_target.PotentialCOAs")
+ related_exploit_targets = fields.TypedField("Related_Exploit_Targets", type_="stix.exploit_target.RelatedExploitTargets")
+ vulnerabilities = fields.TypedField("Vulnerability", Vulnerability, multiple=True, key_name="vulnerabilities")
+ weaknesses = fields.TypedField("Weakness", Weakness, multiple=True, key_name="weaknesses")
+ configuration = fields.TypedField("Configuration", Configuration, multiple=True)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -51,204 +62,53 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.handling = None
self.potential_coas = PotentialCOAs()
self.related_exploit_targets = RelatedExploitTargets()
- self.vulnerabilities = None
- self.weaknesses = None
- self.configuration = None
self.related_packages = RelatedPackageRefs()
- @property
- def handling(self):
-
- return self._handling
-
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, try_cast=False, handling=value)
-
- @property
- def vulnerabilities(self):
- """A list of ``Vulnerability`` objects
-
- Default Value: ``None``
-
- Returns:
- A list of
- :class:`stix.exploit_target.vulnerability`
-
- Raises:
- ValueError: If set to a value that is not ``None`` and not an
- instance of
- :class:`stix.exploit_target.vulnerability`
-
- """
-
- return self._vulnerabilities
-
- @vulnerabilities.setter
- def vulnerabilities(self, value):
- self._vulnerabilities = _Vulnerabilities(value)
-
- def add_vulnerability(self, v):
- """Adds a vulnerability to the ``vulnerabilies`` list property.
+ def add_vulnerability(self, value):
+ """Adds a vulnerability to the :attr:`vulnerabilities` list property.
Note:
If ``None`` is passed in no value is added
Args:
- v: A Vulnerability value.
+ value: A :class:`.Vulnerability` object..
- Raises: ValueError if the ``v`` param is of type
- :class:`stix.exploit_target.vulnerability`
-
-
- """
- self.vulnerabilities.append(v)
-
- @property
- def weaknesses(self):
- """A list of ``Weakness`` objects
-
- Default Value: ``None``
-
- Returns:
- A list of
- :class:`stix.exploit_target.weakness`
-
Raises:
- ValueError: If set to a value that is not ``None`` and not an
- instance of
- :class:`stix.exploit_target.weakness`
+ ValueError: if the `value` param is of type :class:`.Vulnerability`
"""
-
- return self._weaknesses
-
- @weaknesses.setter
- def weaknesses(self, value):
- self._weaknesses = _Weaknesses(value)
-
- def add_weakness(self, v):
- """Adds a weakness to the ``weaknesses`` list property.
+ self.vulnerabilities.append(value)
+
+ def add_weakness(self, value):
+ """Adds a weakness to the :attr:`weaknesses` list property.
Note:
If ``None`` is passed in no value is added
Args:
- v: A weakness value.
+ value: A :class:`.Weakness` object.
- Raises: ValueError if the ``v`` param is of type :class:`stix.exploit_target.weakness`
-
-
- """
- self.weaknesses.append(v)
-
- @property
- def configuration(self):
- """A list of ``Configuration`` objects
-
- Default Value: ``None``
-
- Returns:
- A list of
- :class:`stix.exploit_target.configuration`
-
- Raises:
- ValueError: If set to a value that is not ``None`` and not an
- instance of
- :class:`stix.exploit_target.configuration`
+ Raises: ValueError if the `value` param is of type :class:`.Weakness`
"""
-
- return self._configuration
-
- @configuration.setter
- def configuration(self, value):
- self._configuration = _Configurations(value)
+ self.weaknesses.append(value)
- def add_configuration(self, v):
- """Adds a configuration to the ``configurations`` list property.
+ def add_configuration(self, value):
+ """Adds a configuration to the :attr:`configurations` list property.
Note:
If ``None`` is passed in no value is added
Args:
- v: A configuration value.
+ value: A configuration value.
- Raises: ValueError if the ``v`` param is of type :class:`stix.exploit_target.configuration`
+ Raises:
+ ValueError: If the `value` param is of type :class:`.Configuration`
"""
- self.configuration.append(v)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(ExploitTarget, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.potential_coas:
- return_obj.Potential_COAs = self.potential_coas.to_obj(ns_info=ns_info)
- if self.related_exploit_targets:
- return_obj.Related_Exploit_Targets = self.related_exploit_targets.to_obj(ns_info=ns_info)
- if self.vulnerabilities:
- return_obj.Vulnerability = self.vulnerabilities.to_obj(ns_info=ns_info)
- if self.weaknesses:
- return_obj.Weakness = self.weaknesses.to_obj(ns_info=ns_info)
- if self.configuration:
- return_obj.Configuration = self.configuration.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(ExploitTarget, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class):
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.potential_coas = PotentialCOAs.from_obj(obj.Potential_COAs)
- return_obj.related_exploit_targets = RelatedExploitTargets.from_obj(obj.Related_Exploit_Targets)
- return_obj.vulnerabilities = _Vulnerabilities.from_obj(obj.Vulnerability)
- return_obj.weaknesses = _Weaknesses.from_obj(obj.Weakness)
- return_obj.configuration = _Configurations.from_obj(obj.Configuration)
- return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages)
-
- return return_obj
-
- def to_dict(self):
- return super(ExploitTarget, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(ExploitTarget, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.potential_coas = PotentialCOAs.from_dict(get('potential_coas'))
- return_obj.related_exploit_targets = RelatedExploitTargets.from_dict(get('related_exploit_targets'))
- return_obj.vulnerabilities = _Vulnerabilities.from_dict(get('vulnerabilities'))
- return_obj.weaknesses = _Weaknesses.from_dict(get('weaknesses'))
- return_obj.configuration = _Configurations.from_dict(get('configuration'))
- return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages'))
-
- return return_obj
+ self.configuration.append(value)
class PotentialCOAs(GenericRelationshipList):
@@ -258,14 +118,11 @@ class PotentialCOAs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/ExploitTarget-1"
_binding = exploit_target_binding
_binding_class = exploit_target_binding.PotentialCOAsType
- _binding_var = "Potential_COA"
- _contained_type = RelatedCOA
- _inner_name = "coas"
+
+ potential_coa = fields.TypedField("Potential_COA", RelatedCOA, multiple=True, key_name="coas")
def __init__(self, coas=None, scope=None):
- if coas is None:
- coas = []
- super(PotentialCOAs, self).__init__(scope, *coas)
+ super(PotentialCOAs, self).__init__(scope, coas)
class RelatedExploitTargets(GenericRelationshipList):
@@ -275,9 +132,8 @@ class RelatedExploitTargets(GenericRelationshipList):
_namespace = "http://stix.mitre.org/ExploitTarget-1"
_binding = exploit_target_binding
_binding_class = exploit_target_binding.RelatedExploitTargetsType
- _binding_var = "Related_Exploit_Target"
- _contained_type = RelatedExploitTarget
- _inner_name = "related_exploit_targets"
+
+ related_exploit_target = fields.TypedField("Related_Exploit_Target", RelatedExploitTarget, multiple=True, key_name="related_exploit_targets")
def __init__(self, related_exploit_targets=None, scope=None):
super(RelatedExploitTargets, self).__init__(scope, related_exploit_targets)
diff --git a/stix/exploit_target/configuration.py b/stix/exploit_target/configuration.py
index 45a624ed..e5f1fd4a 100644
--- a/stix/exploit_target/configuration.py
+++ b/stix/exploit_target/configuration.py
@@ -1,9 +1,11 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-import stix.bindings.exploit_target as exploit_target_binding
from stix.common import StructuredText
+import stix.bindings.exploit_target as exploit_target_binding
class Configuration(stix.Entity):
@@ -19,119 +21,13 @@ class Configuration(stix.Entity):
_binding_class = _binding.ConfigurationType
_namespace = "http://stix.mitre.org/ExploitTarget-1"
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+ cce_id = fields.TypedField("CCE_ID")
+
def __init__(self, description=None, short_description=None, cce_id=None):
+ super(Configuration, self).__init__()
+
self.description = description
self.short_description = short_description
self.cce_id = cce_id
-
- @property
- def description(self):
- """The ``description`` property for this :class:`Configuration`.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- """The ``short_description`` property for this :class:`Configuration`.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
- self._set_var(StructuredText, short_description=value)
-
- @property
- def cce_id(self):
- """Common Configuration Enumeration value for this :class:`Configuration`.
-
- Default Value: ``None``
-
- Returns:
- A string representing the CCE ID
- """
- return self._cce_id
-
- @cce_id.setter
- def cce_id(self, value):
- self._cce_id = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Configuration, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- return_obj.CCE_ID = self.cce_id
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.cce_id = obj.CCE_ID
-
- return return_obj
-
- def to_dict(self):
- return super(Configuration, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.short_description = StructuredText.from_dict(get('short_description'))
- return_obj.cce_id = get('cce_id')
-
- return return_obj
-
-
-# NOT AN ACTUAL STIX TYPE!
-class _Configurations(stix.TypedList):
- _contained_type = Configuration
diff --git a/stix/exploit_target/vulnerability.py b/stix/exploit_target/vulnerability.py
index 0d8702bf..87970241 100644
--- a/stix/exploit_target/vulnerability.py
+++ b/stix/exploit_target/vulnerability.py
@@ -1,15 +1,15 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-import stix.utils as utils
import stix.bindings.exploit_target as exploit_target_binding
-import stix.bindings.stix_common as stix_common_binding
from stix.common import DateTimeWithPrecision, StructuredText
from stix.common.related import GenericRelationshipList, RelatedObservable
+from stix.common import References
-# TODO document these
class Vulnerability(stix.Entity):
"""Implementation of STIX ``Vulnerability``.
@@ -19,210 +19,39 @@ class Vulnerability(stix.Entity):
short_description (optional): A string short description.
"""
-
_binding = exploit_target_binding
_binding_class = _binding.VulnerabilityType
_namespace = "http://stix.mitre.org/ExploitTarget-1"
- def __init__(self, title=None, description=None, short_description=None):
- self.is_known = None
- self.is_publicly_acknowledged = None
+ is_known = fields.BooleanField("is_known")
+ is_publicly_acknowledged = fields.BooleanField("is_publicly_acknowledged")
+ title = fields.TypedField("Title")
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+ cve_id = fields.TypedField("CVE_ID")
+ osvdb_id = fields.TypedField("OSVDB_ID")
+ source = fields.TypedField("Source")
+ cvss_score = fields.TypedField("CVSS_Score", "stix.exploit_target.vulnerability.CVSSVector")
+ discovered_datetime = fields.TypedField("Discovered_DateTime", DateTimeWithPrecision)
+ published_datetime = fields.TypedField("Published_DateTime", DateTimeWithPrecision)
+ affected_software = fields.TypedField("Affected_Software", "stix.exploit_target.vulnerability.AffectedSoftware")
+ references = fields.TypedField("References", References)
+
+ def __init__(self, title=None, description=None, short_description=None, references=None):
+ super(Vulnerability, self).__init__()
+
self.title = title
self.description = description
self.short_description = short_description
- self.cve_id = None
- self.osvdb_id = None
- self.source = None
- self.cvss_score = None
- self.discovered_datetime = None
- self.published_datetime = None
- self.affected_software = AffectedSoftware()
- self.references = []
-
- @property
- def title(self):
- """
- String representing the Vulnerability Title
- """
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- """The ``description`` property for this :class:`Vulnerability`.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
-
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- """The ``short_description`` property for this :class:`Vulnerability`.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- @property
- def discovered_datetime(self):
- """
- Returns:
- The time this vulnerability was discovered, represented as
- class:`DateTimeWithPrecision`
- """
- return self._discovered_datetime
-
- @discovered_datetime.setter
- def discovered_datetime(self, value):
- """
- Sets the time this vulnerability was discovered, represented as
- class:`DateTimeWithPrecision`
-
- Default Value: ``None``
-
- Returns:
- None
-
- """
- self._set_var(DateTimeWithPrecision, discovered_datetime=value)
-
- @property
- def references(self):
- return self._references
-
- @references.setter
- def references(self, value):
- self._references = []
-
- if not value:
- return
- elif utils.is_sequence(value):
- self._references.extend(x for x in value if x)
- else:
- self._references.append(value)
+ self.references = references
def add_reference(self, reference):
if not reference:
return
-
+ if self.references is None:
+ self.references = References()
self.references.append(reference)
- def to_obj(self, return_obj=None, ns_info=None):
- super(Vulnerability, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.Title = self.title
- return_obj.CVE_ID = self.cve_id
- return_obj.OSVDB_ID = self.osvdb_id
- return_obj.Source = self.source
- return_obj.is_known = utils.xml_bool(self.is_known)
- return_obj.is_publicly_acknowledged = utils.xml_bool(self.is_publicly_acknowledged)
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.cvss_score:
- return_obj.CVSS_Score = self.cvss_score.to_obj(ns_info=ns_info)
- if self.discovered_datetime:
- return_obj.Discovered_DateTime = self.discovered_datetime.to_obj(ns_info=ns_info)
- if self.published_datetime:
- return_obj.Published_DateTime = self.published_datetime.to_obj(ns_info=ns_info)
- if self.affected_software:
- return_obj.Affected_Software = self.affected_software.to_obj(ns_info=ns_info)
- if self.references:
- return_obj.References = stix_common_binding.ReferencesType(Reference=self.references)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.is_known = utils.xml_bool(obj.is_known)
- return_obj.is_publicly_acknowledged = utils.xml_bool(obj.is_publicly_acknowledged)
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.cve_id = obj.CVE_ID
- return_obj.osvdb_id = obj.OSVDB_ID
- return_obj.source = obj.Source
- return_obj.cvss_score = CVSSVector.from_obj(obj.CVSS_Score)
- return_obj.discovered_datetime = DateTimeWithPrecision.from_obj(obj.Discovered_DateTime)
- return_obj.published_datetime = DateTimeWithPrecision.from_obj(obj.Published_DateTime)
- return_obj.affected_software = AffectedSoftware.from_obj(obj.Affected_Software)
-
- if obj.References:
- return_obj.references = obj.References.Reference
-
- return return_obj
-
- def to_dict(self):
- return super(Vulnerability, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.is_known = utils.xml_bool(get('is_known'))
- return_obj.is_publicly_acknowledged = utils.xml_bool(get('is_publicly_acknowledged'))
- return_obj.title = get('title')
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.short_description = StructuredText.from_dict(get('short_description'))
- return_obj.cve_id = get('cve_id')
- return_obj.osvdb_id = get('osvdb_id')
- return_obj.source = get('source')
- return_obj.cvss_score = CVSSVector.from_dict(get('cvss_score'))
- return_obj.discovered_datetime = DateTimeWithPrecision.from_dict(get('discovered_datetime'))
- return_obj.published_datetime = DateTimeWithPrecision.from_dict(get('published_datetime'))
- return_obj.affected_software = AffectedSoftware.from_dict(get('affected_software'))
- return_obj.references = get('references')
-
- return return_obj
-
class CVSSVector(stix.Entity):
"""
@@ -233,93 +62,24 @@ class CVSSVector(stix.Entity):
_binding_class = exploit_target_binding.CVSSVectorType
_namespace = "http://stix.mitre.org/ExploitTarget-1"
- def __init__(self):
- self.overall_score = None
- self.base_score = None
- self.base_vector = None
- self.temporal_score = None
- self.temporal_vector = None
- self.environmental_score = None
- self.environmental_vector = None
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(CVSSVector, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.Overall_Score = self.overall_score
- return_obj.Base_Score = self.base_score
- return_obj.Base_Vector = self.base_vector
- return_obj.Temporal_Score = self.temporal_score
- return_obj.Temporal_Vector = self.temporal_vector
- return_obj.Environmental_Score = self.environmental_score
- return_obj.Environmental_Vector = self.environmental_vector
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.overall_score = obj.Overall_Score
- return_obj.base_score = obj.Base_Score
- return_obj.base_vector = obj.Base_Vector
- return_obj.temporal_score = obj.Temporal_Score
- return_obj.temporal_vector = obj.Temporal_Vector
- return_obj.environmental_score = obj.Environmental_Score
- return_obj.environmental_vector = obj.Environmental_Vector
-
- return return_obj
+ overall_score = fields.TypedField("Overall_Score")
+ base_score = fields.TypedField("Base_Score")
+ base_vector = fields.TypedField("Base_Vector")
+ temporal_score = fields.TypedField("Temporal_Score")
+ temporal_vector = fields.TypedField("Temporal_Vector")
+ environmental_score = fields.TypedField("Environmental_Score")
+ environmental_vector = fields.TypedField("Environmental_Vector")
- def to_dict(self):
- d = {}
-
- if self.overall_score:
- d['overall_score'] = self.overall_score
- if self.base_score:
- d['base_score'] = self.base_score
- if self.base_vector:
- d['base_vector'] = self.base_vector
- if self.temporal_score:
- d['temporal_score'] = self.temporal_score
- if self.temporal_vector:
- d['temporal_vector'] = self.temporal_vector
- if self.environmental_score:
- d['environmental_score'] = self.environmental_score
- if self.environmental_vector:
- d['environmental_vector'] = self.environmental_vector
-
- return d
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.overall_score = dict_repr.get('overall_score')
- return_obj.base_score = dict_repr.get('base_score')
- return_obj.base_vector = dict_repr.get('base_vector')
- return_obj.temporal_score = dict_repr.get('temporal_score')
- return_obj.temporal_vector = dict_repr.get('temporal_vector')
- return_obj.environmental_score = dict_repr.get('environmental_score')
- return_obj.environmental_vector = dict_repr.get('environmental_vector')
-
- return return_obj
+ def __init__(self):
+ super(CVSSVector, self).__init__()
class AffectedSoftware(GenericRelationshipList):
_binding = exploit_target_binding
_binding_class = exploit_target_binding.AffectedSoftwareType
_namespace = "http://stix.mitre.org/ExploitTarget-1"
- _binding_var = "Affected_Software"
- _contained_type = RelatedObservable
- _inner_name = "affected_software"
+
+ affected_software = fields.TypedField("Affected_Software", RelatedObservable, multiple=True, key_name="affected_software")
# NOT AN ACTUAL STIX TYPE!
diff --git a/stix/exploit_target/weakness.py b/stix/exploit_target/weakness.py
index fce3607f..e9e7b4ef 100644
--- a/stix/exploit_target/weakness.py
+++ b/stix/exploit_target/weakness.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.exploit_target as exploit_target_binding
from stix.common import StructuredText
@@ -18,83 +20,15 @@ class Weakness(stix.Entity):
_binding_class = _binding.WeaknessType
_namespace = "http://stix.mitre.org/ExploitTarget-1"
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ cwe_id = fields.TypedField("CWE_ID")
+
def __init__(self, description=None, cwe_id=None):
+ super(Weakness, self).__init__()
+
self.description = description
self.cwe_id = cwe_id
- @property
- def cwe_id(self):
- """
- Common Weakness Enumeration value as a string
- """
- return self._cwe_id
-
- @cwe_id.setter
- def cwe_id(self, value):
- self._cwe_id = value
-
- @property
- def description(self):
- """The ``description`` property for this :class:`Weakness`.
-
- Default Value: ``None``
-
- Note:
- If set to a value that is not an instance of
- :class:`stix.common.structured_text.StructuredText`, an attempt to
- will be made to convert the value into an instance of
- :class:`stix.common.structured_text.StructuredText`.
-
- Returns:
- An instance of
- :class:`stix.common.structured_text.StructuredText`
-
- """
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Weakness, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- return_obj.CWE_ID = self.cwe_id
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.cwe_id = obj.CWE_ID
-
- return return_obj
-
- def to_dict(self):
- return super(Weakness, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.description = StructuredText.from_dict(dict_repr.get('description'))
- return_obj.cwe_id = dict_repr.get('cwe_id')
-
- return return_obj
-
class _Weaknesses(stix.TypedList):
_contained_type = Weakness
diff --git a/stix/extensions/__init__.py b/stix/extensions/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/__init__.py
+++ b/stix/extensions/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/identity/__init__.py b/stix/extensions/identity/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/identity/__init__.py
+++ b/stix/extensions/identity/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/identity/ciq_identity_3_0.py b/stix/extensions/identity/ciq_identity_3_0.py
index 8e0b7cf6..2523841c 100644
--- a/stix/extensions/identity/ciq_identity_3_0.py
+++ b/stix/extensions/identity/ciq_identity_3_0.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import lxml.etree as et
@@ -6,9 +6,10 @@
import stix
import stix.utils as utils
import stix.common as common
-import stix.common.identity as identity
import stix.bindings.extensions.identity.ciq_identity_3_0 as ciq_identity_binding
+from mixbox.vendor.six import string_types
+
XML_NS_XPIL = "urn:oasis:names:tc:ciq:xpil:3"
XML_NS_XNL = "urn:oasis:names:tc:ciq:xnl:3"
@@ -18,16 +19,17 @@
et.register_namespace('xpil', XML_NS_XPIL)
et.register_namespace('xnl', XML_NS_XNL)
et.register_namespace('xal', XML_NS_XAL)
-et.register_namespace('ExtSch', XML_NS_STIX_EXT)
+et.register_namespace('stix-ciqidentity', XML_NS_STIX_EXT)
+@stix.register_extension
class CIQIdentity3_0Instance(common.Identity):
- _binding = ciq_identity_binding
- _binding_class = _binding.CIQIdentity3_0InstanceType
- _namespace = "http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1"
- _XML_NS_PREFIX = "ciqIdentity"
- _XML_TYPE = "CIQIdentity3.0InstanceType"
- _XSI_TYPE = "ciqIdentity:CIQIdentity3.0InstanceType"
+ _binding = ciq_identity_binding
+ _binding_class = _binding.CIQIdentity3_0InstanceType
+ _namespace = "http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1"
+ _XML_NS_PREFIX = "stix-ciqidentity"
+ _XML_TYPE = "CIQIdentity3.0InstanceType"
+ _XSI_TYPE = "stix-ciqidentity:CIQIdentity3.0InstanceType"
def __init__(self, roles=None, specification=None):
super(CIQIdentity3_0Instance, self).__init__()
@@ -49,8 +51,8 @@ def roles(self, valuelist):
self.add_role(role)
def add_role(self, role):
- if not isinstance(role, basestring):
- raise ValueError('role is not instance of basestring')
+ if not isinstance(role, string_types):
+ raise ValueError('role is not instance of string_types')
self.roles.append(role)
@@ -65,50 +67,39 @@ def specification(self, value):
self._specification = value
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(CIQIdentity3_0Instance, self).to_obj(return_obj)
-
- # return_obj.id = self.id_
- # return_obj.idref = self.idref_
- return_obj.xsi_type = self._XSI_TYPE
+ def to_obj(self, ns_info=None):
+ obj = super(CIQIdentity3_0Instance, self).to_obj(ns_info=ns_info)
+ obj.xsi_type = self._XSI_TYPE
if self.roles:
for role in self.roles:
- return_obj.add_Role(role)
+ obj.add_Role(role)
if self.specification:
- return_obj.Specification = self.specification.to_obj(ns_info=ns_info)
+ obj.Specification = self.specification.to_obj(ns_info=ns_info)
- return return_obj
+ return obj
@classmethod
- def from_obj(cls, obj, return_obj=None):
- if obj is None:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(CIQIdentity3_0Instance, cls).from_obj(obj, return_obj)
+ def from_obj(cls, cls_obj):
+ obj = super(CIQIdentity3_0Instance, cls).from_obj(cls_obj)
- roles = obj.Role
- specification = obj.Specification
+ roles = cls_obj.Role
+ specification = cls_obj.Specification
if roles:
for role in roles:
- return_obj.add_role(role)
+ obj.add_role(role)
if specification is not None:
- return_obj.specification = STIXCIQIdentity3_0.from_obj(specification)
+ obj.specification = STIXCIQIdentity3_0.from_obj(specification)
- return return_obj
+ return obj
def to_dict(self):
d = super(CIQIdentity3_0Instance, self).to_dict()
d['xsi:type'] = self._XSI_TYPE
-
+
if self.roles:
d['roles'] = [str(x) for x in self.roles]
if self.specification:
@@ -116,34 +107,32 @@ def to_dict(self):
return d
@classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
+ def from_dict(cls, cls_dict):
+ if not cls_dict:
return None
- if not return_obj:
- return_obj = cls()
+ obj = super(CIQIdentity3_0Instance, cls).from_dict(cls_dict)
- super(CIQIdentity3_0Instance, cls).from_dict(dict_repr, return_obj)
-
- roles = dict_repr.get('roles', [])
- specification = dict_repr.get('specification')
+ roles = cls_dict.get('roles', [])
+ specification = cls_dict.get('specification')
for role in roles:
- return_obj.add_role(role)
+ obj.add_role(role)
if specification:
- return_obj.specification = STIXCIQIdentity3_0.from_dict(specification)
+ obj.specification = STIXCIQIdentity3_0.from_dict(specification)
- return return_obj
+ return obj
class STIXCIQIdentity3_0(stix.Entity):
- _namespace = "http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1"
+ _namespace = "http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1"
XML_TAG = "{%s}Specification" % _namespace
- def __init__(self, party_name=None, languages=None, addresses=None,
+ def __init__(self, party_name=None, languages=None, addresses=None,
organisation_info=None, electronic_address_identifiers=None,
- free_text_lines=None, contact_numbers=None, nationalities=None):
+ free_text_lines=None, contact_numbers=None,
+ nationalities=None):
self.party_name = party_name
self.languages = languages
self.addresses = addresses
@@ -152,11 +141,11 @@ def __init__(self, party_name=None, languages=None, addresses=None,
self.free_text_lines = free_text_lines
self.contact_numbers = contact_numbers
self.nationalities = nationalities
-
+
@property
def addresses(self):
- return self._addresses
-
+ return self._addresses
+
@addresses.setter
def addresses(self, value):
self._addresses = []
@@ -167,7 +156,7 @@ def addresses(self, value):
self.add_address(v)
else:
self.add_address(value)
-
+
def add_address(self, value):
if not value:
return
@@ -175,11 +164,11 @@ def add_address(self, value):
self.addresses.append(value)
else:
raise ValueError('value must be instance of Address')
-
+
@property
def languages(self):
return self._languages
-
+
@languages.setter
def languages(self, value):
self._languages = []
@@ -190,7 +179,7 @@ def languages(self, value):
self.add_language(v)
else:
self.add_language(value)
-
+
def add_language(self, value):
if not value:
return
@@ -198,7 +187,7 @@ def add_language(self, value):
self.languages.append(value)
else:
self.languages.append(Language(value))
-
+
@property
def party_name(self):
return self._party_name
@@ -214,8 +203,8 @@ def party_name(self, value):
@property
def electronic_address_identifiers(self):
- return self._electronic_address_identifiers
-
+ return self._electronic_address_identifiers
+
@electronic_address_identifiers.setter
def electronic_address_identifiers(self, value):
self._electronic_address_identifiers = []
@@ -226,7 +215,7 @@ def electronic_address_identifiers(self, value):
self.add_electronic_address_identifier(v)
else:
self.add_electronic_address_identifier(value)
-
+
def add_electronic_address_identifier(self, value):
if not value:
return
@@ -249,7 +238,7 @@ def free_text_lines(self, value):
self.add_free_text_line(v)
else:
self.add_free_text_line(value)
-
+
def add_free_text_line(self, value):
if not value:
return
@@ -272,7 +261,7 @@ def contact_numbers(self, value):
self.add_contact_number(v)
else:
self.add_contact_number(value)
-
+
def add_contact_number(self, value):
if not value:
return
@@ -302,7 +291,20 @@ def add_nationality(self, value):
elif isinstance(value, Country):
self.nationalities.append(value)
else:
- self.nationalities.append(Country(value))
+ self.nationalities.append(Country(value))
+
+ @property
+ def organisation_info(self):
+ return self._organisation_info
+
+ @organisation_info.setter
+ def organisation_info(self, value):
+ if not value:
+ self._organisation_info = None
+ elif isinstance(value, OrganisationInfo):
+ self._organisation_info = value
+ else:
+ raise ValueError('organisation_info must be instance of OrganisationInfo')
@classmethod
def from_obj(cls, obj, return_obj=None):
@@ -318,7 +320,7 @@ def from_obj(cls, obj, return_obj=None):
languages = obj.findall("{%s}Languages" % XML_NS_XPIL)
if languages is not None and len(languages) > 0:
return_obj.languages = [Language.from_obj(x) for x in languages[0]]
-
+
addresses = obj.findall("{%s}Addresses" % XML_NS_XPIL)
if addresses is not None and len(addresses) > 0:
return_obj.addresses = [Address.from_obj(x) for x in addresses[0]]
@@ -326,27 +328,33 @@ def from_obj(cls, obj, return_obj=None):
nationalities = obj.findall("{%s}Nationalities" % XML_NS_XPIL)
if nationalities is not None and len(nationalities) > 0:
return_obj.nationalities = [Country.from_obj(x) for x in nationalities[0]]
-
+
organisation_info = obj.findall(OrganisationInfo.XML_TAG)
if organisation_info is not None and len(organisation_info) > 0:
return_obj.organisation_info = OrganisationInfo.from_obj(organisation_info[0])
-
+
electronic_address_identifiers = obj.findall("{%s}ElectronicAddressIdentifiers" % XML_NS_XPIL)
if electronic_address_identifiers is not None and len(electronic_address_identifiers) > 0:
return_obj.electronic_address_identifiers = [ElectronicAddressIdentifier.from_obj(x) for x in electronic_address_identifiers[0]]
-
+
free_text_lines = obj.findall("{%s}FreeTextLines" % XML_NS_XPIL)
if free_text_lines is not None and len(free_text_lines) > 0:
return_obj.free_text_lines = [FreeTextLine.from_obj(x) for x in free_text_lines[0]]
-
+
contact_numbers = obj.findall("{%s}ContactNumbers" % XML_NS_XPIL)
if contact_numbers is not None and len(contact_numbers) > 0:
return_obj.contact_numbers = [ContactNumber.from_obj(x) for x in contact_numbers[0]]
-
+
return return_obj
def to_obj(self, return_obj=None, ns_info=None):
- super(STIXCIQIdentity3_0, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ # Throw away return value; this class has no _binding_class, so
+ # it will return None anyway. This to_obj() is anomalous in that it
+ # returns an etree Element instead of a generateDS object. Bindings
+ # have all been hacked up to make this work. The super call does,
+ # however, do namespace collection (if ns_info is given), so it's
+ # still important.
+ super(STIXCIQIdentity3_0, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = STIXCIQIdentity3_0.XML_TAG
@@ -357,7 +365,7 @@ def to_obj(self, return_obj=None, ns_info=None):
return_obj.append(ftl_root)
for ftl in self.free_text_lines:
ftl_root.append(ftl.to_obj(ns_info=ns_info))
-
+
if self.party_name:
return_obj.append(self.party_name.to_obj(ns_info=ns_info))
@@ -366,22 +374,22 @@ def to_obj(self, return_obj=None, ns_info=None):
return_obj.append(addresses_root)
for address in self.addresses:
addresses_root.append(address.to_obj(ns_info=ns_info))
-
+
if self.contact_numbers:
contact_numbers_root = et.Element("{%s}ContactNumbers" % XML_NS_XPIL)
return_obj.append(contact_numbers_root)
for contact_number in self.contact_numbers:
contact_numbers_root.append(contact_number.to_obj(ns_info=ns_info))
-
+
if self.electronic_address_identifiers:
eai_root = et.Element("{%s}ElectronicAddressIdentifiers" % XML_NS_XPIL)
return_obj.append(eai_root)
for eai in self.electronic_address_identifiers:
eai_root.append(eai.to_obj(ns_info=ns_info))
-
+
if self.organisation_info:
return_obj.append(self.organisation_info.to_obj(ns_info=ns_info))
-
+
if self.languages:
languages_root = et.Element("{%s}Languages" % XML_NS_XPIL)
return_obj.append(languages_root)
@@ -395,7 +403,7 @@ def to_obj(self, return_obj=None, ns_info=None):
country_obj = country.to_obj(ns_info=ns_info)
country_obj.tag = "{%s}Country" % XML_NS_XPIL
nationalities_root.append(country_obj)
-
+
return return_obj
@classmethod
@@ -412,6 +420,7 @@ def from_dict(cls, dict_repr, return_obj=None):
return_obj.free_text_lines = [FreeTextLine.from_dict(x) for x in dict_repr.get('free_text_lines', [])]
return_obj.contact_numbers = [ContactNumber.from_dict(x) for x in dict_repr.get('contact_numbers', [])]
return_obj.nationalities = [Country.from_dict(x) for x in dict_repr.get('nationalities', [])]
+ return_obj.organisation_info = OrganisationInfo.from_dict(dict_repr.get('organisation_info'))
return return_obj
@@ -432,6 +441,8 @@ def to_dict(self):
d['contact_numbers'] = [x.to_dict() for x in self.contact_numbers]
if self.nationalities:
d['nationalities'] = [x.to_dict() for x in self.nationalities]
+ if self.organisation_info:
+ d['organisation_info'] = self.organisation_info.to_dict()
return d
@@ -439,8 +450,9 @@ def to_dict(self):
class Address(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}Address" % _namespace
-
- def __init__(self, free_text_address=None, country=None, administrative_area=None):
+
+ def __init__(self, free_text_address=None, country=None,
+ administrative_area=None):
self.free_text_address = free_text_address
self.country = country
self.administrative_area = administrative_area
@@ -470,7 +482,7 @@ def free_text_address(self, value):
self._set_var(FreeTextAddress, free_text_address=value)
def to_obj(self, return_obj=None, ns_info=None):
- super(Address, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(Address, self).to_obj(ns_info=ns_info)
if not return_obj:
return_obj = et.Element(self.XML_TAG)
@@ -500,34 +512,34 @@ def from_obj(cls, obj, return_obj=None):
return None
if not return_obj:
return_obj = cls()
-
+
free_text_address = obj.findall("{%s}FreeTextAddress" % XML_NS_XAL)
if len(free_text_address) > 0:
return_obj.free_text_address = FreeTextAddress.from_obj(free_text_address[0])
-
+
country = obj.findall("{%s}Country" % XML_NS_XAL)
if len(country) > 0:
return_obj.country = Country.from_obj(country[0])
-
+
administrative_area = obj.findall("{%s}AdministrativeArea" % XML_NS_XAL)
if len(administrative_area) > 0:
return_obj.administrative_area = AdministrativeArea.from_obj(administrative_area[0])
-
+
return return_obj
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
return None
if not return_obj:
return_obj = cls()
-
+
return_obj.free_text_address = FreeTextAddress.from_dict(d.get('free_text_address'))
return_obj.country = Country.from_dict(d.get('country'))
return_obj.administrative_area = AdministrativeArea.from_dict(d.get('administrative_area'))
return return_obj
-
+
class AdministrativeArea(stix.Entity):
_namespace = XML_NS_XAL
XML_TAG = "{%s}AdministrativeArea" % _namespace
@@ -538,7 +550,7 @@ def __init__(self, name_elements=None):
@property
def name_elements(self):
return self._name_elements
-
+
@name_elements.setter
def name_elements(self, value):
self._name_elements = []
@@ -564,42 +576,42 @@ def from_obj(cls, obj, return_obj=None):
return None
if not return_obj:
return_obj = cls()
-
+
name_elements = obj.findall(NameElement.XML_TAG)
if name_elements:
for name_element in name_elements:
return_obj.name_elements.append(NameElement.from_obj(name_element))
-
+
return return_obj
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(AdministrativeArea, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(AdministrativeArea, self).to_obj(ns_info=ns_info)
if not return_obj:
return_obj = et.Element(self.XML_TAG)
-
+
for name_element in self.name_elements:
return_obj.append(name_element.to_obj(ns_info=ns_info))
-
+
return return_obj
-
+
def to_dict(self):
d = {}
if self.name_elements:
d['name_elements'] = [x.to_dict() for x in self.name_elements]
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
return None
if not return_obj:
return_obj = cls()
-
+
return_obj.name_elements = [NameElement.from_dict(x) for x in d.get('name_elements', [])]
return return_obj
-
+
class Country(stix.Entity):
_namespace = XML_NS_XAL
XML_TAG = "{%s}Country" % _namespace
@@ -610,7 +622,7 @@ def __init__(self, name_elements=None):
@property
def name_elements(self):
return self._name_elements
-
+
@name_elements.setter
def name_elements(self, value):
self._name_elements = []
@@ -636,38 +648,38 @@ def from_obj(cls, obj, return_obj=None):
return None
if not return_obj:
return_obj = cls()
-
+
name_elements = obj.findall("{%s}NameElement" % XML_NS_XAL)
if name_elements:
for name_element in name_elements:
return_obj.name_elements.append(NameElement.from_obj(name_element))
-
+
return return_obj
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(Country, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(Country, self).to_obj(ns_info=ns_info)
if not return_obj:
return_obj = et.Element(self.XML_TAG)
-
+
for name_element in self.name_elements:
return_obj.append(name_element.to_obj(ns_info=ns_info))
-
+
return return_obj
-
+
def to_dict(self):
d = {}
if self.name_elements:
d['name_elements'] = [x.to_dict() for x in self.name_elements]
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
return None
if not return_obj:
return_obj = cls()
-
+
return_obj.name_elements = [NameElement.from_dict(x) for x in d.get('name_elements', [])]
return return_obj
@@ -675,17 +687,29 @@ def from_dict(cls, d, return_obj=None):
class NameElement(stix.Entity):
_namespace = XML_NS_XAL
XML_TAG = "{%s}NameElement" % XML_NS_XAL
-
- def __init__(self, value=None):
+
+ def __init__(self, value=None, name_type=None, name_code=None,
+ name_code_type=None):
self.value = value
-
+ self.name_type = name_type
+ self.name_code = name_code
+ self.name_code_type = name_code_type
+
def to_obj(self, return_obj=None, ns_info=None):
- super(NameElement, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(NameElement, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
return_obj.text = self.value
+
+ if self.name_type:
+ return_obj.set('{%s}NameType' % self._namespace, self.name_type)
+ if self.name_code:
+ return_obj.set('{%s}NameCode' % self._namespace, self.name_code)
+ if self.name_code_type:
+ return_obj.set('{%s}NameCodeType' % self._namespace, self.name_code_type)
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -695,14 +719,24 @@ def from_obj(cls, obj, return_obj=None):
return_obj = cls()
return_obj.value = obj.text
+ return_obj.name_type = obj.get('{%s}NameType' % cls._namespace)
+ return_obj.name_code = obj.get('{%s}NameCode' % cls._namespace)
+ return_obj.name_code_type = obj.get('{%s}NameCodeType' % cls._namespace)
+
return return_obj
-
+
def to_dict(self):
d = {}
if self.value:
d['value'] = self.value
+ if self.name_type:
+ d['name_type'] = self.name_type
+ if self.name_code:
+ d['name_code'] = self.name_code
+ if self.name_code_type:
+ d['name_code_type'] = self.name_code_type
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -712,20 +746,23 @@ def from_dict(cls, d, return_obj=None):
return_obj = cls()
return_obj.value = d.get('value')
+ return_obj.name_type = d.get('name_type')
+ return_obj.name_code = d.get('name_code')
+ return_obj.name_code_type = d.get('name_code_type')
return return_obj
class FreeTextAddress(stix.Entity):
_namespace = XML_NS_XAL
XML_TAG = "{%s}FreeTextAddress" % XML_NS_XAL
-
+
def __init__(self, address_lines=None):
self.address_lines = address_lines
@property
def address_lines(self):
return self._address_lines
-
+
@address_lines.setter
def address_lines(self, value):
self._address_lines = []
@@ -743,17 +780,17 @@ def from_obj(cls, obj, return_obj=None):
return None
if not return_obj:
return_obj = cls()
-
+
address_line_tag = "{%s}AddressLine" % XML_NS_XAL
address_lines = obj.findall(address_line_tag)
if address_lines:
for address_line in address_lines:
return_obj.address_lines.append(address_line.text)
-
+
return return_obj
def to_obj(self, return_obj=None, ns_info=None):
- super(FreeTextAddress, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(FreeTextAddress, self).to_obj(ns_info=ns_info)
if not return_obj:
return_obj = et.Element(self.XML_TAG)
@@ -762,9 +799,9 @@ def to_obj(self, return_obj=None, ns_info=None):
address_line = et.Element("{%s}AddressLine" % XML_NS_XAL)
address_line.text = address
return_obj.append(address_line)
-
+
return return_obj
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -772,10 +809,10 @@ def from_dict(cls, d, return_obj=None):
if not return_obj:
return_obj = cls()
-
+
return_obj.address_lines = d.get('address_lines', [])
return return_obj
-
+
def to_dict(self):
d = {}
if self.address_lines:
@@ -805,31 +842,31 @@ def __init__(self, name_lines=None, person_names=None, organisation_names=None):
self.add_organisation_name(value)
def add_name_line(self, value):
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
self.name_lines.append(NameLine(value))
elif isinstance(value, NameLine):
self.name_lines.append(value)
else:
- raise ValueError('value must be a basestring or NameLine instance')
+ raise ValueError('value must be a string_types or NameLine instance')
def add_person_name(self, value):
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
self.person_names.append(PersonName(name_elements=[value]))
elif isinstance(value, PersonName):
- self.person_names.append(value)
+ self.person_names.append(value)
else:
- raise ValueError('value must be instance of PersonName or basestring')
+ raise ValueError('value must be instance of PersonName or string_types')
def add_organisation_name(self, value):
- if isinstance(value, basestring):
- self.organisation_names.append(OrganisationName(name_elements=[value]))
+ if isinstance(value, string_types):
+ self.organisation_names.append(OrganisationName(name_elements=[value]))
elif isinstance(value, OrganisationName):
self.organisation_names.append(value)
- else:
+ else:
raise ValueError('value must be instance of OrganisationName')
def to_obj(self, return_obj=None, ns_info=None):
- super(PartyName, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(PartyName, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = PartyName.XML_TAG
@@ -913,7 +950,7 @@ def from_dict(cls, dict_repr, return_obj=None):
for pn in pn_dicts:
person_name = PersonName.from_dict(pn)
- return_obj.add_person_name(person_name)
+ return_obj.add_person_name(person_name)
return return_obj
@@ -928,17 +965,17 @@ def __init__(self, value=None, type_=None):
@property
def value(self):
- return self._value
+ return self._value
@value.setter
def value(self, value):
- if value and not isinstance(value, basestring):
- raise ValueError('value must be instance of basestring')
+ if value and not isinstance(value, string_types):
+ raise ValueError('value must be instance of string_types')
self._value = value
def to_obj(self, return_obj=None, ns_info=None):
- super(NameLine, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(NameLine, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = NameLine.XML_TAG
@@ -947,7 +984,7 @@ def to_obj(self, return_obj=None, ns_info=None):
if self.type:
return_obj.attrib['Type'] = self.type
- if self.value:
+ if self.value:
return_obj.text = self.value
return return_obj
@@ -966,8 +1003,7 @@ def from_obj(cls, obj, return_obj=None):
return return_obj
def to_dict(self):
- d = {}
- d['value'] = self.value
+ d = {'value': self.value}
if self.type:
d['type'] = self.type
@@ -992,15 +1028,55 @@ class PersonName(stix.Entity):
_namespace = XML_NS_XNL
XML_TAG = "{%s}PersonName" % _namespace
- def __init__(self, name_elements=None):
+ TYPE_ALIAS = 'Alias'
+ TYPE_LEGAL_NAME = 'LegalName'
+ TYPE_KNOWN_AS = 'KnownAs'
+ TYPE_MAIDEN_NAME = 'MaidenName'
+ TYPE_FORMER_NAME = 'FormerName'
+ TYPE_COMMON_USE = 'CommonUse'
+ TYPE_NAME_AT_BIRTH = 'NameAtBirth'
+ TYPE_PREFERRED_NAME = 'PreferredName'
+ TYPE_OFFICIAL_NAME = 'OfficialName'
+ TYPE_UNOFFICIAL_NAME = 'UnofficialName'
+ TYPE_NICK_NAME = 'NickName'
+ TYPE_PET_NAME = 'PetName'
+
+ TYPES = (
+ TYPE_ALIAS,
+ TYPE_LEGAL_NAME,
+ TYPE_KNOWN_AS,
+ TYPE_MAIDEN_NAME,
+ TYPE_FORMER_NAME,
+ TYPE_COMMON_USE,
+ TYPE_NAME_AT_BIRTH,
+ TYPE_PREFERRED_NAME,
+ TYPE_OFFICIAL_NAME,
+ TYPE_UNOFFICIAL_NAME,
+ TYPE_NICK_NAME,
+ TYPE_PET_NAME,
+ )
+
+ def __init__(self, name_elements=None, type_=None):
self.name_elements = []
+ self.type_ = type_
if name_elements:
for name_element in name_elements:
self.add_name_element(name_element)
+ @property
+ def type_(self):
+ return self._type
+
+ @type_.setter
+ def type_(self, value):
+ if value and value not in self.TYPES:
+ raise ValueError('value must be one of %s: ' % (self.TYPES,))
+
+ self._type = value
+
def add_name_element(self, value):
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
self.name_elements.append(PersonNameElement(value=value))
elif isinstance(value, PersonNameElement):
self.name_elements.append(value)
@@ -1008,12 +1084,15 @@ def add_name_element(self, value):
raise ValueError('value must be instance of PersonNameElement')
def to_obj(self, return_obj=None, ns_info=None):
- super(PersonName, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(PersonName, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = PersonName.XML_TAG
return_obj = et.Element(root_tag)
+ if self.type_:
+ return_obj.attrib['{%s}Type' % XML_NS_XNL] = self.type_
+
for name_element in self.name_elements:
return_obj.append(name_element.to_obj(ns_info=ns_info))
@@ -1027,6 +1106,8 @@ def from_obj(cls, obj, return_obj=None):
if not return_obj:
return_obj = cls()
+ return_obj.type_ = obj.attrib.get('{%s}Type' % XML_NS_XNL)
+
name_elements = obj.findall(PersonNameElement.XML_TAG)
if name_elements:
for name_element_obj in name_elements:
@@ -1038,6 +1119,9 @@ def from_obj(cls, obj, return_obj=None):
def to_dict(self):
d = {}
+ if self.type_:
+ d['type'] = self.type_
+
if self.name_elements:
for ne in self.name_elements:
d.setdefault('name_elements', []).append(ne.to_dict())
@@ -1052,6 +1136,8 @@ def from_dict(cls, dict_repr, return_obj=None):
if not return_obj:
return_obj = cls()
+ return_obj.type_ = dict_repr.get('type')
+
ne_dicts = dict_repr.get('name_elements', [])
for ne_dict in ne_dicts:
@@ -1064,11 +1150,40 @@ class OrganisationName(stix.Entity):
_namespace = XML_NS_XNL
XML_TAG = "{%s}OrganisationName" % _namespace
+ TYPE_LEGAL_NAME = 'LegalName'
+ TYPE_FORMER_NAME = 'FormerName'
+ TYPE_COMMON_USE = 'CommonUse'
+ TYPE_PUBLISHING_NAME = 'PublishingName'
+ TYPE_OFFICIAL_NAME = 'OfficialName'
+ TYPE_UNOFFICIAL_NAME = 'UnofficialName'
+ TYPE_UNDEFINED = 'Undefined'
+
+ TYPES = (
+ TYPE_LEGAL_NAME,
+ TYPE_FORMER_NAME,
+ TYPE_COMMON_USE,
+ TYPE_PUBLISHING_NAME,
+ TYPE_OFFICIAL_NAME,
+ TYPE_UNOFFICIAL_NAME,
+ TYPE_UNDEFINED,
+ )
+
def __init__(self, name_elements=None, subdivision_names=None, type_=None):
self.type_ = type_
self.name_elements = name_elements
self.subdivision_names = subdivision_names
+ @property
+ def type_(self):
+ return self._type
+
+ @type_.setter
+ def type_(self, value):
+ if value and value not in self.TYPES:
+ raise ValueError('value must be one of %s: ' % (self.TYPES,))
+
+ self._type = value
+
@property
def name_elements(self):
return self._name_elements
@@ -1085,7 +1200,7 @@ def name_elements(self, value):
self.add_organisation_name_element(value)
def add_organisation_name_element(self, value):
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
self.name_elements.append(OrganisationNameElement(value=value))
elif isinstance(value, OrganisationNameElement):
self.name_elements.append(value)
@@ -1095,7 +1210,7 @@ def add_organisation_name_element(self, value):
@property
def subdivision_names(self):
return self._subdivision_names
-
+
@subdivision_names.setter
def subdivision_names(self, value):
self._subdivision_names = []
@@ -1114,7 +1229,7 @@ def add_subdivision_name(self, value):
self.subdivision_names.append(value)
def to_obj(self, return_obj=None, ns_info=None):
- super(OrganisationName, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(OrganisationName, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = OrganisationName.XML_TAG
@@ -1137,7 +1252,7 @@ def from_obj(cls, obj, return_obj=None):
return_obj = cls()
return_obj.type_ = obj.attrib.get('{%s}Type' % XML_NS_XNL)
-
+
name_elements = obj.findall(OrganisationNameElement.XML_TAG)
if name_elements:
for name_element_obj in name_elements:
@@ -1154,7 +1269,7 @@ def from_obj(cls, obj, return_obj=None):
def to_dict(self):
d = {}
-
+
if self.type_:
d['type'] = self.type_
if self.name_elements:
@@ -1183,13 +1298,14 @@ def from_dict(cls, dict_repr, return_obj=None):
return_obj.add_subdivision_name(SubDivisionName.from_dict(sn_dict))
return return_obj
-
+
class _BaseNameElement(stix.Entity):
"""Do not instantiate directly: use PersonNameElement or
OrganisationNameElement
"""
+
def __init__(self, value=None):
self.value = value
@@ -1199,9 +1315,6 @@ def value(self):
@value.setter
def value(self, value):
- # if not value:
- # raise ValueError('value cannot be None')
-
self._value = value
@classmethod
@@ -1213,7 +1326,7 @@ def from_obj(cls, obj, return_obj=None):
return return_obj
def to_obj(self, return_obj=None, ns_info=None):
- super(_BaseNameElement, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(_BaseNameElement, self).to_obj(ns_info=ns_info)
return_obj.text = self.value
return return_obj
@@ -1234,8 +1347,8 @@ class PersonNameElement(_BaseNameElement):
_namespace = XML_NS_XNL
XML_TAG = "{%s}NameElement" % _namespace
- TYPE_TITLE = 'Title'
TYPE_PRECEDING_TITLE = 'PrecedingTitle'
+ TYPE_TITLE = 'Title'
TYPE_FIRST_NAME = 'FirstName'
TYPE_MIDDLE_NAME = 'MiddleName'
TYPE_LAST_NAME = 'LastName'
@@ -1263,7 +1376,7 @@ def element_type(self, value):
if value and value not in self.TYPES:
raise ValueError('value must be one of %s: ' % (self.TYPES,))
- self._element_type = value
+ self._element_type = value
def to_obj(self, return_obj=None, ns_info=None):
if not return_obj:
@@ -1285,14 +1398,13 @@ def from_obj(cls, obj, return_obj=None):
if not return_obj:
return_obj = cls()
- return_obj.element_type = obj.get('ElementType')
+ return_obj.element_type = obj.get('ElementType')
return_obj.value = obj.text
return return_obj
def to_dict(self):
- d = {}
- d['value'] = self.value
+ d = {'value': self.value}
if self.element_type:
d['element_type'] = self.element_type
@@ -1419,7 +1531,7 @@ def type(self, value):
self._type = value
def to_obj(self, return_obj=None, ns_info=None):
- super(SubDivisionName, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(SubDivisionName, self).to_obj(ns_info=ns_info)
if not return_obj:
root_tag = SubDivisionName.XML_TAG
@@ -1445,8 +1557,8 @@ def from_obj(cls, obj, return_obj=None):
return return_obj
def to_dict(self):
- d = {}
- d['value'] = self.value
+ d = {'value': self.value}
+
if self.type:
d['type'] = self.type
@@ -1468,61 +1580,61 @@ def from_dict(cls, dict_repr, return_obj=None):
class Language(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}Language" % _namespace
-
+
def __init__(self, value=None):
self.value = value
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(Language, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(Language, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
return_obj.text = self.value
return return_obj
-
+
@classmethod
def from_obj(cls, obj):
if obj is None:
return None
-
+
return_obj = cls()
return_obj.value = obj.text
return return_obj
-
+
def to_dict(self):
d = {}
if self.value:
d['value'] = self.value
return d
-
+
@classmethod
def from_dict(cls, d):
if not d:
return None
-
+
return_obj = cls()
return_obj.value = d.get('value')
return return_obj
-
+
class ElectronicAddressIdentifier(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}ElectronicAddressIdentifier" % _namespace
-
+
def __init__(self, value=None, type_=None):
self.type_ = type_
self.value = value
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(ElectronicAddressIdentifier, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(ElectronicAddressIdentifier, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
return_obj.text = self.value
-
+
if self.type_:
return_obj.attrib['{%s}Type' % XML_NS_XPIL] = self.type_
-
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -1534,7 +1646,7 @@ def from_obj(cls, obj, return_obj=None):
return_obj.type_ = obj.attrib.get('{%s}Type' % XML_NS_XPIL)
return_obj.value = obj.text
return return_obj
-
+
def to_dict(self):
d = {}
if self.value:
@@ -1542,7 +1654,7 @@ def to_dict(self):
if self.type_:
d['type'] = self.type_
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -1562,16 +1674,16 @@ class OrganisationInfo(stix.Entity):
def __init__(self, industry_type=None):
self.industry_type = industry_type
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(OrganisationInfo, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(OrganisationInfo, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
if self.industry_type:
return_obj.attrib['{%s}IndustryType' % self._namespace] = self.industry_type
-
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -1588,7 +1700,7 @@ def to_dict(self):
if self.industry_type:
d['industry_type'] = self.industry_type
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -1604,22 +1716,22 @@ def from_dict(cls, d, return_obj=None):
class FreeTextLine(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}FreeTextLine" % _namespace
-
+
def __init__(self, value=None, type_=None):
self.value = value
self.type_ = type_
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(FreeTextLine, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(FreeTextLine, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
if self.type_:
return_obj.attrib['{%s}Type' % self._namespace] = self.type_
if self.value:
return_obj.text = self.value
-
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -1639,7 +1751,7 @@ def to_dict(self):
if self.value:
d['value'] = self.value
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -1656,26 +1768,26 @@ def from_dict(cls, d, return_obj=None):
class ContactNumber(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}ContactNumber" % _namespace
-
+
COM_MEDIA_TYPE_CELLPHONE = "Cellphone"
COM_MEDIA_TYPE_FAX = "Fax"
COM_MEDIA_TYPE_PAGER = "Pager"
COM_MEDIA_TYPE_TELEPHONE = "Telephone"
COM_MEDIA_TYPE_VOIP = "VOIP"
-
+
ALLOWED_COM_MEDIA_TYPES = (
COM_MEDIA_TYPE_CELLPHONE, COM_MEDIA_TYPE_FAX, COM_MEDIA_TYPE_PAGER,
COM_MEDIA_TYPE_TELEPHONE, COM_MEDIA_TYPE_VOIP
)
-
+
def __init__(self, contact_number_elements=None, communication_media_type=None):
self.communication_media_type = communication_media_type
self.contact_number_elements = contact_number_elements
-
+
@property
def contact_number_elements(self):
return self._contact_number_elements
-
+
@contact_number_elements.setter
def contact_number_elements(self, value):
self._contact_number_elements = []
@@ -1686,7 +1798,7 @@ def contact_number_elements(self, value):
self.add_contact_number_element(v)
else:
self.add_contact_number_element(value)
-
+
def add_contact_number_element(self, value):
if not value:
return
@@ -1694,11 +1806,11 @@ def add_contact_number_element(self, value):
self.contact_number_elements.append(value)
else:
self.contact_number_elements.append(ContactNumberElement(value))
-
+
@property
def communication_media_type(self):
return self._communication_media_type
-
+
@communication_media_type.setter
def communication_media_type(self, value):
if not value:
@@ -1707,17 +1819,18 @@ def communication_media_type(self, value):
raise ValueError('value must be one of %s' % (self.ALLOWED_COM_MEDIA_TYPES,))
else:
self._communication_media_type = value
-
+
def to_obj(self, return_obj=None, ns_info=None):
+ super(ContactNumber, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
if self.communication_media_type:
return_obj.attrib['{%s}CommunicationMediaType' % self._namespace] = self.communication_media_type
if self.contact_number_elements:
for contact_number_element in self.contact_number_elements:
return_obj.append(contact_number_element.to_obj(ns_info=ns_info))
-
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -1727,11 +1840,11 @@ def from_obj(cls, obj, return_obj=None):
return_obj = cls()
return_obj.communication_media_type = obj.get('{%s}CommunicationMediaType' % cls._namespace)
-
+
contact_number_elements = obj.findall("{%s}ContactNumberElement" % XML_NS_XPIL)
if contact_number_elements is not None and len(contact_number_elements) > 0:
return_obj.contact_number_elements = [ContactNumberElement.from_obj(x) for x in contact_number_elements]
-
+
return return_obj
def to_dict(self):
@@ -1740,9 +1853,9 @@ def to_dict(self):
d['communication_media_type'] = self.communication_media_type
if self.contact_number_elements:
d['contact_number_elements'] = [x.to_dict() for x in self.contact_number_elements]
-
+
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -1753,14 +1866,14 @@ def from_dict(cls, d, return_obj=None):
return_obj.communication_media_type = d.get('communication_media_type')
return_obj.contact_number_elements = [ContactNumberElement.from_dict(x) for x in d.get('contact_number_elements', [])]
-
+
return return_obj
class ContactNumberElement(stix.Entity):
_namespace = XML_NS_XPIL
XML_TAG = "{%s}ContactNumberElement" % _namespace
-
+
TYPE_COUNTRY_CODE = "CountryCode"
TYPE_AREA_CODE = "AreaCode"
TYPE_LOCAL_NUMBER = "LocalNumber"
@@ -1769,21 +1882,21 @@ class ContactNumberElement(stix.Entity):
TYPE_SEPARATOR = "Separator"
TYPE_NATIONAL_NUMBER = "NationalNumber"
TYPE_INTERNATIONAL_NUMBER = "InternationalNumber"
-
+
ALLOWED_TYPES = (
TYPE_AREA_CODE, TYPE_COUNTRY_CODE, TYPE_EXTENSION,
TYPE_INTERNATIONAL_NUMBER, TYPE_LOCAL_NUMBER, TYPE_NATIONAL_NUMBER,
TYPE_SEPARATOR, TYPE_PIN
)
-
+
def __init__(self, value=None, type_=None):
self.value = value
self.type_ = type_
-
+
@property
def type_(self):
return self._type
-
+
@type_.setter
def type_(self, value):
if not value:
@@ -1792,18 +1905,18 @@ def type_(self, value):
raise ValueError('value must be one of %s' % (self.ALLOWED_TYPES,))
else:
self._type = value
-
+
def to_obj(self, return_obj=None, ns_info=None):
- super(ContactNumberElement, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ super(ContactNumberElement, self).to_obj(ns_info=ns_info)
return_obj = et.Element(self.XML_TAG)
if self.type_:
return_obj.attrib['{%s}Type' % self._namespace] = self.type_
if self.value:
return_obj.text = self.value
-
+
return return_obj
-
+
@classmethod
def from_obj(cls, obj, return_obj=None):
if obj is None:
@@ -1823,7 +1936,7 @@ def to_dict(self):
if self.value:
d['value'] = self.value
return d
-
+
@classmethod
def from_dict(cls, d, return_obj=None):
if not d:
@@ -1835,7 +1948,3 @@ def from_dict(cls, d, return_obj=None):
return_obj.type_ = d.get('type')
return_obj.value = d.get('value')
return return_obj
-
-
-# Register the extension
-identity.add_extension(CIQIdentity3_0Instance)
diff --git a/stix/extensions/malware/__init__.py b/stix/extensions/malware/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/malware/__init__.py
+++ b/stix/extensions/malware/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/malware/maec_4_1_malware.py b/stix/extensions/malware/maec_4_1_malware.py
index 8c5e45be..0144ee7c 100644
--- a/stix/extensions/malware/maec_4_1_malware.py
+++ b/stix/extensions/malware/maec_4_1_malware.py
@@ -1,224 +1,37 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# stdlib
-from StringIO import StringIO
-from distutils.version import LooseVersion
-
# external
-from lxml import etree
+from mixbox import fields
+
# internal
import stix
-import stix.utils as utils
-import stix.utils.parser as parser
-import stix.ttp.malware_instance
+from stix.bindings.extensions.malware import maec_4_1 as maec_instance_binding
from stix.ttp.malware_instance import MalwareInstance
-import stix.bindings.extensions.malware.maec_4_1 as ext_binding
-
-
-_MIN_PYTHON_MAEC_VERSION = '4.1.0.12'
-
-
-class UnsupportedVersion(Exception):
- def __init__(self, message, expected, found):
- super(UnsupportedVersion, self).__init__(message)
- self.expected = expected
- self.found = found
-def _check_maec_version():
- """Checks that the installed python-maec has a version greater than or
- equal to the minimum supported version.
-
- Note:
- We do this rather than having a python-maec dependency requirement
- listed in setup.py because MAEC is used as an extension to STIX and
- not a core component to STIX (like CybOX).
-
- Raises:
- ImportError: If python-maec is not installed.
- UnsupportedVersion: If the python-maec installation does not satisfy
- the version requirements.
-
+@stix.register_extension
+class MAECInstance(MalwareInstance):
"""
- import maec
-
- found = maec.__version__
- expected = _MIN_PYTHON_MAEC_VERSION
-
- if LooseVersion(found) >= LooseVersion(expected):
- return
+ The MAECInstance object provides an extension to the MalwareInstanceType
+ which imports and leverages the MAEC 4.1 schema for structured
+ characterization of Malware.
- fmt = ("Unsupported python-maec version installed: '%s'. Minimum version "
- "is '%s'.")
- error = fmt % (found, expected)
- raise UnsupportedVersion(error, expected=expected, found=found)
-
-
-try:
- # Check that the correct version of python-maec is installed.
- _check_maec_version()
-
- # Import maecPackage into global space
- from maec.package.package import Package as maecPackage
-
- _MAEC_INSTALLED = True
-except ImportError:
- maecPackage, Package = None, None
- _MAEC_INSTALLED = False
-
-
-def is_maec(obj):
- """Checks if the input object is python-maec object.
-
- Returns:
- True if python-maec is ins
+ This class extension is automatically registered by the
+ MalwareInstanceFactory.
+ Warnings:
+ Interacting with the ``maec`` field will fail if the maec library is
+ not installed in your Python environment.
"""
- if not _MAEC_INSTALLED:
- return False
-
- return isinstance(obj, maecPackage)
-
-
-class MAECInstance(MalwareInstance):
- _binding = ext_binding
+ _binding = maec_instance_binding
_binding_class = _binding.MAEC4_1InstanceType
- _namespace = 'http://stix.mitre.org/extensions/Malware#MAEC4.1-1'
- _xml_ns_prefix = "stix-maec"
+ _namespace = "http://stix.mitre.org/extensions/Malware#MAEC4.1-1"
_XSI_TYPE = "stix-maec:MAEC4.1InstanceType"
- _TAG_MAEC = "{%s}MAEC" % _namespace
+
+ maec = fields.TypedField("MAEC", type_="maec.package.package.Package")
def __init__(self, maec=None):
super(MAECInstance, self).__init__()
- self.__input_namespaces__ = {}
- self.__input_schemalocations__ = {}
self.maec = maec
-
- @property
- def maec(self):
- return self._maec
-
- @maec.setter
- def maec(self, value):
- if value is None:
- self._maec = None
- elif _MAEC_INSTALLED and is_maec(value):
- self._maec = value
- elif utils.is_element(value) or utils.is_etree(value):
- tree = parser.get_etree(value)
- root = parser.get_etree_root(tree)
- self._parse_etree(root)
- self._maec = root
- else:
- error = (
- "Cannot set maec to '{0}'. Expected 'lxml.etree._Element' or "
- "'maec.package.package.Package'."
- )
- error = error.format(type(value))
- raise ValueError(error)
-
- def _parse_etree(self, root):
- node_tag = root.tag
-
- if node_tag != self._TAG_MAEC:
- self._cast_maec(root)
-
- self._collect_namespaces(root)
- self._collect_schemalocs(root)
-
- def _cast_maec(self, node):
- ns_maec = "http://maec.mitre.org/XMLSchema/maec-package-2"
- node_ns = etree.QName(node).namespace
-
- if node_ns == ns_maec:
- etree.register_namespace(self._xml_ns_prefix, self._namespace)
- node.tag = self._TAG_MAEC
- else:
- error = "Cannot set maec. Expected tag '{0}' found '{1}'."
- error = error.format(self._TAG_MAEC, node.tag)
- raise ValueError(error)
-
- def _collect_schemalocs(self, node):
- try:
- schemaloc = parser.get_schemaloc_pairs(node)
- self.__input_schemalocations__ = dict(schemaloc)
- except KeyError:
- self.__input_schemalocations__ = {}
-
- def _collect_namespaces(self, node):
- self.__input_namespaces__ = dict(node.nsmap.iteritems())
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(MAECInstance, cls).from_obj(obj, return_obj)
-
- if _MAEC_INSTALLED:
- return_obj.maec = maecPackage.from_obj(obj.MAEC)
- else:
- return_obj.maec = obj.MAEC
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(MAECInstance, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if _MAEC_INSTALLED and isinstance(self.maec, maecPackage):
- return_obj.MAEC = self.maec.to_obj(ns_info=ns_info)
- else:
- return_obj.MAEC = self.maec
-
- return return_obj
-
- @classmethod
- def _maec_from_dict(cls, d):
- if _MAEC_INSTALLED:
- return maecPackage.from_dict(d)
-
- raise ValueError(
- "Unable to parse 'maec' value in dictionary. Please "
- "install python-maec to parse dictionary value."
- )
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(MAECInstance, cls).from_dict(d, return_obj)
-
- with utils.ignored(KeyError):
- maec = d['maec']
- if isinstance(maec, dict):
- return_obj.maec = cls._maec_from_dict(maec)
- else:
- parser = stix.utils.parser.get_xml_parser()
- return_obj.maec = etree.parse(StringIO(maec), parser=parser)
-
- return return_obj
-
- def to_dict(self):
- d = super(MAECInstance, self).to_dict()
-
- if self.maec is not None:
- if _MAEC_INSTALLED and isinstance(self.maec, maecPackage):
- d['maec'] = self.maec.to_dict()
- else:
- d['maec'] = etree.tostring(self.maec)
-
- return d
-
-# Register the extension
-stix.ttp.malware_instance.add_extension(MAECInstance)
diff --git a/stix/extensions/marking/__init__.py b/stix/extensions/marking/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/marking/__init__.py
+++ b/stix/extensions/marking/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/marking/ais.py b/stix/extensions/marking/ais.py
new file mode 100644
index 00000000..5c6b36d2
--- /dev/null
+++ b/stix/extensions/marking/ais.py
@@ -0,0 +1,339 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
+"""
+STIX Extension for AIS Data Markings
+
+Unlike the other marking extensions, the AIS marking extension is not loaded
+automatically, since AIS markings are not a part of the published STIX 1.x
+specifications. They are included in python-stix because they're common enough
+that it is not worth creating a separate package.
+
+If you are writing code that needs to parse AIS markings, make sure that your
+program imports this module before beginning to parse any STIX documents:
+
+.. code-block:: python
+
+ import stix.extensions.marking.ais
+
+"""
+
+from mixbox import fields
+from mixbox.namespaces import Namespace
+
+import stix.bindings.extensions.marking.ais as ais_binding
+import stix.data_marking
+from stix.data_marking import MarkingStructure
+
+
+def validate_value(instance, value):
+ allowed = instance._ALLOWED_VALUES
+ if not value:
+ return
+ elif not allowed:
+ return
+ elif value in allowed:
+ return
+ else:
+ error = "Value must be one of {allowed}. Received '{value}'"
+ error = error.format(**locals())
+ raise ValueError(error)
+
+
+class AISConsentType(stix.Entity):
+ _binding = ais_binding
+ _binding_class = _binding.AISConsentType
+ _namespace = 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2'
+ _ALLOWED_VALUES = ('EVERYONE', 'USG', 'NONE')
+
+ consent = fields.TypedField("consent", preset_hook=validate_value)
+
+ def __init__(self, consent=None):
+ super(AISConsentType, self).__init__()
+ self.consent = consent
+
+
+class TLPMarkingType(stix.Entity):
+ _binding = ais_binding
+ _binding_class = _binding.TLPMarkingType
+ _namespace = 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2'
+ _ALLOWED_VALUES = ('WHITE', 'GREEN', 'AMBER')
+
+ color = fields.TypedField("color", preset_hook=validate_value)
+
+ def __init__(self, color=None):
+ super(TLPMarkingType, self).__init__()
+ self.color = color
+
+
+class NotProprietary(stix.Entity):
+ _binding = ais_binding
+ _binding_class = _binding.NotProprietary
+ _namespace = 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2'
+
+ cisa_proprietary = fields.TypedField("CISA_Proprietary")
+ ais_consent = fields.TypedField("AISConsent", AISConsentType, key_name="ais_consent")
+ tlp_marking = fields.TypedField("TLPMarking", TLPMarkingType, key_name="tlp_marking")
+
+ def __init__(self, cisa_proprietary='false', ais_consent=None,
+ tlp_marking=None):
+ super(NotProprietary, self).__init__()
+
+ self.cisa_proprietary = cisa_proprietary
+ self.ais_consent = ais_consent
+ self.tlp_marking = tlp_marking
+
+
+class IsProprietary(stix.Entity):
+ _binding = ais_binding
+ _binding_class = _binding.IsProprietary
+ _namespace = 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2'
+
+ cisa_proprietary = fields.TypedField("CISA_Proprietary")
+ ais_consent = fields.TypedField("AISConsent", AISConsentType, key_name="ais_consent")
+ tlp_marking = fields.TypedField("TLPMarking", TLPMarkingType, key_name="tlp_marking")
+
+ def __init__(self, cisa_proprietary='true', ais_consent=None,
+ tlp_marking=None):
+ super(IsProprietary, self).__init__()
+
+ self.cisa_proprietary = cisa_proprietary
+ self.ais_consent = ais_consent
+ self.tlp_marking = tlp_marking
+
+
+@stix.register_extension
+class AISMarkingStructure(MarkingStructure):
+ _binding = ais_binding
+ _binding_class = _binding.AISMarkingStructure
+ _namespace = 'http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2'
+ _XSI_TYPE = "AIS:AISMarkingStructure"
+
+ is_proprietary = fields.TypedField("Is_Proprietary", IsProprietary)
+ not_proprietary = fields.TypedField("Not_Proprietary", NotProprietary)
+
+ def __init__(self, is_proprietary=None, not_proprietary=None):
+ super(AISMarkingStructure, self).__init__()
+
+ self.is_proprietary = is_proprietary
+ self.not_proprietary = not_proprietary
+
+
+NAMESPACES = [
+ Namespace('http://www.us-cert.gov/STIXMarkingStructure#AISConsentMarking-2', 'AIS', 'http://www.us-cert.gov/sites/default/files/STIX_Namespace/AIS_Bundle_Marking_1.1.1_v1.0.xsd')
+]
+
+
+def _update_namespaces():
+ # Update the python-stix namespace dictionary
+ from stix.utils import nsparser
+ import mixbox.namespaces
+
+ nsparser.STIX_NAMESPACES.add_namespace(NAMESPACES[0])
+ mixbox.namespaces.register_namespace(NAMESPACES[0])
+
+
+_update_namespaces()
+
+
+# IndustryType allowed sectors
+#: Chemical Sector
+CHEMICAL_SECTOR = 'Chemical Sector'
+#: Chemical Sector
+COMMERCIAL_FACILITIES_SECTOR = 'Commercial Facilities Sector'
+#: Commercial Facilities Sector
+COMMUNICATIONS_SECTOR = 'Communications Sector'
+#: Critical Manufacturing Sector
+CRITICAL_MANUFACTURING_SECTOR = 'Critical Manufacturing Sector'
+#: Dams Sector
+DAMS_SECTOR = 'Dams Sector'
+#: Defense Industrial Base Sector
+DEFENSE_INDUSTRIAL_BASE_SECTOR = 'Defense Industrial Base Sector'
+#: Emergency Services Sector
+EMERGENCY_SERVICES_SECTOR = 'Emergency Services Sector'
+#: Energy Sector
+ENERGY_SECTOR = 'Energy Sector'
+#: Financial Services Sector
+FINANCIAL_SERVICES_SECTOR = 'Financial Services Sector'
+#: Food and Agriculture Sector
+FOOD_AND_AGRICULTURE_SECTOR = 'Food and Agriculture Sector'
+#: Government Facilities Sector
+GOVERNMENT_FACILITIES_SECTOR = 'Government Facilities Sector'
+#: Healthcare and Public Health Sector
+HEALTH_CARE_AND_PUBLIC_HEALTH_SECTOR = 'Healthcare and Public Health Sector'
+#: Information Technology Sector
+INFORMATION_TECHNOLOGY_SECTOR = 'Information Technology Sector'
+#: Nuclear Reactors, Materials, and Waste Sector
+NUCLEAR_REACTORS_MATERIALS_AND_WASTE_SECTOR = 'Nuclear Reactors, Materials, and Waste Sector'
+#: Other
+OTHER = 'Other'
+#: Transportation Systems Sector
+TRANSPORTATION_SYSTEMS_SECTOR = 'Transportation Systems Sector'
+#: Water and Wastewater Systems Sector
+WATER_AND_WASTEWATER_SYSTEMS_SECTOR = 'Water and Wastewater Systems Sector'
+
+
+def _validate_and_create_industry_type(industry_type):
+ INDUSTRY_SECTORS = (CHEMICAL_SECTOR, COMMERCIAL_FACILITIES_SECTOR,
+ COMMUNICATIONS_SECTOR, CRITICAL_MANUFACTURING_SECTOR,
+ DAMS_SECTOR, DEFENSE_INDUSTRIAL_BASE_SECTOR,
+ EMERGENCY_SERVICES_SECTOR, ENERGY_SECTOR,
+ FINANCIAL_SERVICES_SECTOR, FOOD_AND_AGRICULTURE_SECTOR,
+ GOVERNMENT_FACILITIES_SECTOR,
+ HEALTH_CARE_AND_PUBLIC_HEALTH_SECTOR,
+ INFORMATION_TECHNOLOGY_SECTOR,
+ NUCLEAR_REACTORS_MATERIALS_AND_WASTE_SECTOR,
+ TRANSPORTATION_SYSTEMS_SECTOR, OTHER,
+ WATER_AND_WASTEWATER_SYSTEMS_SECTOR)
+
+ lower_case_sectors = tuple(x.lower() for x in INDUSTRY_SECTORS)
+ result = ""
+ error = False
+ val = []
+
+ if isinstance(industry_type, str):
+ # Pipe-delimited or single string supplied.
+ val = [x.lower().strip() for x in industry_type.split("|")]
+
+ elif isinstance(industry_type, (list, tuple)):
+ # Create pipe-delimited string when list of strings is provided.
+ val = [x.lower().strip() for x in industry_type]
+
+ else:
+ error = True
+
+ for item in val:
+ for idx, sector in enumerate(lower_case_sectors):
+ if item == sector:
+ if not result:
+ result = INDUSTRY_SECTORS[idx]
+ else:
+ result = "{0}|{1}".format(result, INDUSTRY_SECTORS[idx])
+ break
+ else:
+ # The sectors collection was exhausted. No match found.
+ error = True
+ break
+
+ if not error and val:
+ return result
+
+ msg = 'IndustryType must be one of the following: {0}. Received \'{1}\'.'
+ raise ValueError(msg.format(INDUSTRY_SECTORS, industry_type))
+
+
+def add_ais_marking(stix_package, proprietary, consent, color, **kwargs):
+ """
+ This utility functions aids in the creation of an AIS marking and appends
+ it to the provided STIX package.
+
+ Args:
+ stix_package: A stix.core.STIXPackage object.
+ proprietary: True if marking uses IsProprietary, False for
+ NotProprietary.
+ consent: A string with one of the following values: "EVERYONE", "NONE"
+ or "USG".
+ color: A string that corresponds to TLP values: "WHITE", "GREEN" or
+ "AMBER".
+ **kwargs: Six required keyword arguments that are used to create a CIQ
+ identity object. These are: country_name_code,
+ country_name_code_type, admin_area_name_code,
+ admin_area_name_code_type, organisation_name, industry_type.
+
+ Raises:
+ ValueError: When keyword arguments are missing. User did not supply
+ correct values for: proprietary, color and consent.
+
+ Note:
+ The following line is required to register the AIS extension::
+
+ >>> import stix.extensions.marking.ais
+
+ Any Markings under STIX Header will be removed. Please follow the
+ guidelines for `AIS`_.
+
+ The industry_type keyword argument accepts: a list of string based on
+ defined sectors, a pipe-delimited string of sectors, or a single
+ sector.
+
+ .. _AIS:
+ https://www.us-cert.gov/ais
+
+ """
+ from stix.common import InformationSource
+ from stix.extensions.identity.ciq_identity_3_0 import (
+ CIQIdentity3_0Instance, STIXCIQIdentity3_0, PartyName, Address,
+ Country, NameElement, OrganisationInfo, AdministrativeArea)
+ from stix.core.stix_header import STIXHeader
+ from stix.data_marking import MarkingSpecification, Marking
+
+ args = ('country_name_code', 'country_name_code_type', 'industry_type',
+ 'admin_area_name_code', 'admin_area_name_code_type',
+ 'organisation_name')
+
+ diff = set(args) - set(kwargs.keys())
+
+ if diff:
+ msg = 'All keyword arguments must be provided. Missing: {0}'
+ raise ValueError(msg.format(tuple(diff)))
+
+ party_name = PartyName()
+ party_name.add_organisation_name(kwargs['organisation_name'])
+
+ country = Country()
+ country_name = NameElement()
+ country_name.name_code = kwargs['country_name_code']
+ country_name.name_code_type = kwargs['country_name_code_type']
+ country.add_name_element(country_name)
+
+ admin_area = AdministrativeArea()
+ admin_area_name = NameElement()
+ admin_area_name.name_code = kwargs['admin_area_name_code']
+ admin_area_name.name_code_type = kwargs['admin_area_name_code_type']
+ admin_area.add_name_element(admin_area_name)
+
+ address = Address()
+ address.country = country
+ address.administrative_area = admin_area
+
+ org_info = OrganisationInfo()
+ org_info.industry_type = _validate_and_create_industry_type(kwargs['industry_type'])
+
+ id_spec = STIXCIQIdentity3_0()
+ id_spec.party_name = party_name
+ id_spec.add_address(address)
+ id_spec.organisation_info = org_info
+
+ identity = CIQIdentity3_0Instance()
+ identity.specification = id_spec
+
+ if proprietary is True:
+ proprietary_obj = IsProprietary()
+ consent = 'EVERYONE'
+ elif proprietary is False:
+ proprietary_obj = NotProprietary()
+ else:
+ raise ValueError('proprietary expected True or False.')
+
+ proprietary_obj.ais_consent = AISConsentType(consent=consent)
+ proprietary_obj.tlp_marking = TLPMarkingType(color=color)
+
+ ais_marking = AISMarkingStructure()
+
+ if isinstance(proprietary_obj, IsProprietary):
+ ais_marking.is_proprietary = proprietary_obj
+ else:
+ ais_marking.not_proprietary = proprietary_obj
+
+ marking_spec = MarkingSpecification()
+ marking_spec.controlled_structure = '//node() | //@*'
+ marking_spec.marking_structures.append(ais_marking)
+ marking_spec.information_source = InformationSource()
+ marking_spec.information_source.identity = identity
+
+ if not stix_package.stix_header:
+ stix_package.stix_header = STIXHeader()
+
+ # Removes any other Markings if present.
+ stix_package.stix_header.handling = Marking()
+ stix_package.stix_header.handling.add_marking(marking_spec)
diff --git a/stix/extensions/marking/simple_marking.py b/stix/extensions/marking/simple_marking.py
index 9e072f02..3e0f5b53 100644
--- a/stix/extensions/marking/simple_marking.py
+++ b/stix/extensions/marking/simple_marking.py
@@ -1,65 +1,22 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-import stix.bindings.extensions.marking.simple_marking as simple_marking_binding
-import stix.data_marking
+from mixbox import fields
+
+import stix
from stix.data_marking import MarkingStructure
+import stix.bindings.extensions.marking.simple_marking as simple_marking_binding
+@stix.register_extension
class SimpleMarkingStructure(MarkingStructure):
_binding = simple_marking_binding
_binding_class = simple_marking_binding.SimpleMarkingStructureType
_namespace = 'http://data-marking.mitre.org/extensions/MarkingStructure#Simple-1'
_XSI_TYPE = "simpleMarking:SimpleMarkingStructureType"
+ statement = fields.TypedField("Statement")
+
def __init__(self, statement=None):
super(SimpleMarkingStructure, self).__init__()
self.statement = statement
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(SimpleMarkingStructure, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- MarkingStructure.to_obj(self, return_obj=return_obj, ns_info=ns_info)
- return_obj.Statement = self.statement
-
- return return_obj
-
- def to_dict(self):
- d = MarkingStructure.to_dict(self)
- if self.statement:
- d['statement'] = self.statement
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_obj(obj, return_obj)
- return_obj.statement = obj.Statement
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_dict(d, return_obj=return_obj)
- return_obj.statement = d.get('statement')
-
- return return_obj
-
-
-# Register extension
-stix.data_marking.add_extension(SimpleMarkingStructure)
diff --git a/stix/extensions/marking/terms_of_use_marking.py b/stix/extensions/marking/terms_of_use_marking.py
index 72eadd17..da12f5cc 100644
--- a/stix/extensions/marking/terms_of_use_marking.py
+++ b/stix/extensions/marking/terms_of_use_marking.py
@@ -1,66 +1,22 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-import stix.bindings.extensions.marking.terms_of_use_marking as tou_marking_binding
-import stix.data_marking
+from mixbox import fields
+
+import stix
from stix.data_marking import MarkingStructure
+import stix.bindings.extensions.marking.terms_of_use_marking as tou_marking_binding
+@stix.register_extension
class TermsOfUseMarkingStructure(MarkingStructure):
_binding = tou_marking_binding
_binding_class = tou_marking_binding.TermsOfUseMarkingStructureType
_namespace = 'http://data-marking.mitre.org/extensions/MarkingStructure#Terms_Of_Use-1'
_XSI_TYPE = "TOUMarking:TermsOfUseMarkingStructureType"
+ terms_of_use = fields.TypedField("Terms_Of_Use")
+
def __init__(self, terms_of_use=None):
super(TermsOfUseMarkingStructure, self).__init__()
self.terms_of_use = terms_of_use
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(TermsOfUseMarkingStructure, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- MarkingStructure.to_obj(self, return_obj=return_obj, ns_info=ns_info)
- return_obj.Terms_Of_Use = self.terms_of_use
-
- return return_obj
-
- def to_dict(self):
- d = MarkingStructure.to_dict(self)
-
- if self.terms_of_use:
- d['terms_of_use'] = self.terms_of_use
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_obj(obj, return_obj=return_obj)
- return_obj.terms_of_use = obj.Terms_Of_Use
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_dict(d, return_obj)
- return_obj.terms_of_use = d.get('terms_of_use')
-
- return return_obj
-
-
-# Register extension
-stix.data_marking.add_extension(TermsOfUseMarkingStructure)
diff --git a/stix/extensions/marking/tlp.py b/stix/extensions/marking/tlp.py
index 9476d87a..6b95d7fd 100644
--- a/stix/extensions/marking/tlp.py
+++ b/stix/extensions/marking/tlp.py
@@ -1,65 +1,22 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-import stix.bindings.extensions.marking.tlp as tlp_binding
-import stix.data_marking
+from mixbox import fields
+
+import stix
from stix.data_marking import MarkingStructure
+import stix.bindings.extensions.marking.tlp as tlp_binding
+@stix.register_extension
class TLPMarkingStructure(MarkingStructure):
_binding = tlp_binding
_binding_class = tlp_binding.TLPMarkingStructureType
_namespace = 'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1'
_XSI_TYPE = "tlpMarking:TLPMarkingStructureType"
+ color = fields.TypedField("color")
+
def __init__(self, color=None):
super(TLPMarkingStructure, self).__init__()
self.color = color
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(TLPMarkingStructure, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- MarkingStructure.to_obj(self, return_obj=return_obj, ns_info=ns_info)
- return_obj.color = self.color
-
- return return_obj
-
- def to_dict(self):
- d = MarkingStructure.to_dict(self)
- if self.color:
- d['color'] = self.color
-
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_obj(obj, return_obj=return_obj)
- return_obj.color = obj.color
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- MarkingStructure.from_dict(d, return_obj)
- return_obj.color = d.get('color')
-
- return return_obj
-
-
-# Register extension
-stix.data_marking.add_extension(TLPMarkingStructure)
diff --git a/stix/extensions/structured_coa/__init__.py b/stix/extensions/structured_coa/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/structured_coa/__init__.py
+++ b/stix/extensions/structured_coa/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/structured_coa/generic_structured_coa.py b/stix/extensions/structured_coa/generic_structured_coa.py
index c83ee5c2..549196d8 100644
--- a/stix/extensions/structured_coa/generic_structured_coa.py
+++ b/stix/extensions/structured_coa/generic_structured_coa.py
@@ -1,101 +1,30 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import fields
+
+# internal
import stix
-import stix.utils
-import stix.coa.structured_coa
-from stix.common import EncodedCDATA, StructuredText, VocabString
+from stix.common import EncodedCDATA, StructuredText
+from stix.common.vocabs import VocabField
from stix.coa.structured_coa import _BaseStructuredCOA
+
+# bindings
import stix.bindings.extensions.structured_coa.generic as generic_structured_coa_binding
+@stix.register_extension
class GenericStructuredCOA(_BaseStructuredCOA):
_namespace = "http://stix.mitre.org/extensions/StructuredCOA#Generic-1"
_binding = generic_structured_coa_binding
_binding_class = _binding.GenericStructuredCOAType
_XSI_TYPE = "genericStructuredCOA:GenericStructuredCOAType"
+ specification = fields.TypedField("Specification", EncodedCDATA)
+ description = fields.TypedField("Description", StructuredText)
+ reference_location = fields.TypedField("reference_location")
+ type_ = VocabField("Type")
+
def __init__(self, id_=None, idref=None):
super(GenericStructuredCOA, self).__init__(id_=id_, idref=idref)
- self.reference_location = None
- self.description = None
- self.type_ = None
- self.specification = None
-
- @property
- def specification(self):
- return self._specification
-
- @specification.setter
- def specification(self, value):
- self._set_var(EncodedCDATA, specification=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def type_(self):
- return self._type
-
- @type_.setter
- def type_(self, value):
- self._set_vocab(type=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(GenericStructuredCOA, cls).from_obj(obj, return_obj)
- return_obj.reference_location = obj.reference_location
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.type_ = VocabString.from_obj(obj.Type)
- return_obj.specification = EncodedCDATA.from_obj(obj.Specification)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(GenericStructuredCOA, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- if self.reference_location:
- return_obj.reference_location = self.reference_location
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.type_:
- return_obj.Type = self.type_.to_obj(ns_info=ns_info)
- if self.specification:
- return_obj.Specification = self.specification.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(GenericStructuredCOA, cls).from_dict(d, return_obj)
- return_obj.reference_location = d.get('reference_location')
- return_obj.description = StructuredText.from_dict(d.get('description'))
- return_obj.type_ = VocabString.from_dict(d.get('type'))
- return_obj.specification = EncodedCDATA.from_dict(d.get('specification'))
-
- return return_obj
-
- def to_dict(self):
- return super(GenericStructuredCOA, self).to_dict()
-
-
-# Register the extension
-stix.coa.structured_coa.add_extension(GenericStructuredCOA)
diff --git a/stix/extensions/test_mechanism/__init__.py b/stix/extensions/test_mechanism/__init__.py
index 9a9569c5..2e7a26b0 100644
--- a/stix/extensions/test_mechanism/__init__.py
+++ b/stix/extensions/test_mechanism/__init__.py
@@ -1,2 +1,3 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
diff --git a/stix/extensions/test_mechanism/generic_test_mechanism.py b/stix/extensions/test_mechanism/generic_test_mechanism.py
index f0edba67..dd20d433 100644
--- a/stix/extensions/test_mechanism/generic_test_mechanism.py
+++ b/stix/extensions/test_mechanism/generic_test_mechanism.py
@@ -1,125 +1,27 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-import stix.utils
import stix.indicator.test_mechanism
+from stix.common.vocabs import VocabField
from stix.common import EncodedCDATA, StructuredText, VocabString
from stix.indicator.test_mechanism import _BaseTestMechanism
import stix.bindings.extensions.test_mechanism.generic as generic_tm_binding
+@stix.register_extension
class GenericTestMechanism(_BaseTestMechanism):
_namespace = "http://stix.mitre.org/extensions/TestMechanism#Generic-1"
_binding = generic_tm_binding
_binding_class = _binding.GenericTestMechanismType
_XSI_TYPE = "genericTM:GenericTestMechanismType"
+ reference_location = fields.TypedField("reference_location")
+ description = fields.TypedField("Description", StructuredText)
+ specification = fields.TypedField("Specification", EncodedCDATA)
+ type_ = VocabField("Type")
+
def __init__(self, id_=None, idref=None):
super(GenericTestMechanism, self).__init__(id_=id_, idref=idref)
- self.reference_location = None
- self.description = None
- self.type_ = None
- self.specification = None
-
- @property
- def specification(self):
- return self._specification
-
- @specification.setter
- def specification(self, value):
- if not value:
- self._specification = None
- if isinstance(value, EncodedCDATA):
- self._specification = value
- else:
- self._specification = EncodedCDATA(value=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- if not value:
- self._description = None
- elif isinstance(value, StructuredText):
- self._description = value
- else:
- self._description = StructuredText(value)
-
- @property
- def type_(self):
- return self._type
-
- @type_.setter
- def type_(self, value):
- if not value:
- self._type = None
- elif isinstance(value, VocabString):
- self._type = value
- else:
- self._type = VocabString(value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(GenericTestMechanism, cls).from_obj(obj, return_obj)
- return_obj.reference_location = obj.reference_location
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.type_ = VocabString.from_obj(obj.Type)
- return_obj.specification = EncodedCDATA.from_obj(obj.Specification)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(GenericTestMechanism, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- if self.reference_location:
- return_obj.reference_location = self.reference_location
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.type_:
- return_obj.Type = self.type_.to_obj(ns_info=ns_info)
- if self.specification:
- return_obj.Specification = self.specification.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(GenericTestMechanism, cls).from_dict(d, return_obj)
- return_obj.reference_location = d.get('reference_location')
- return_obj.description = StructuredText.from_dict(d.get('description'))
- return_obj.type_ = VocabString.from_dict(d.get('type'))
- return_obj.specification = EncodedCDATA.from_dict(d.get('specification'))
-
- return return_obj
-
- def to_dict(self):
- d = super(GenericTestMechanism, self).to_dict()
-
- if self.reference_location:
- d['reference_location'] = self.reference_location
- if self.description:
- d['description'] = self.description.to_dict()
- if self.type_:
- d['type'] = self.type_.to_dict()
- if self.specification:
- d['specification'] = self.specification.to_dict()
-
- return d
-
-
-stix.indicator.test_mechanism.add_extension(GenericTestMechanism)
diff --git a/stix/extensions/test_mechanism/open_ioc_2010_test_mechanism.py b/stix/extensions/test_mechanism/open_ioc_2010_test_mechanism.py
index 44a7f37b..71ce210d 100644
--- a/stix/extensions/test_mechanism/open_ioc_2010_test_mechanism.py
+++ b/stix/extensions/test_mechanism/open_ioc_2010_test_mechanism.py
@@ -1,20 +1,19 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# stdlib
-from StringIO import StringIO
-
# external
from lxml import etree
+import mixbox.xml
+from mixbox.fields import TypedField
+from mixbox.vendor.six import BytesIO, iteritems
# internal
import stix
-import stix.utils.parser as parser
-import stix.indicator.test_mechanism
from stix.indicator.test_mechanism import _BaseTestMechanism
import stix.bindings.extensions.test_mechanism.open_ioc_2010 as open_ioc_tm_binding
+@stix.register_extension
class OpenIOCTestMechanism(_BaseTestMechanism):
_namespace = "http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1"
_binding = open_ioc_tm_binding
@@ -23,41 +22,23 @@ class OpenIOCTestMechanism(_BaseTestMechanism):
_XSI_TYPE = "stix-openioc:OpenIOC2010TestMechanismType"
_TAG_IOC = "{%s}ioc" % _namespace
+ ioc = TypedField("ioc")
+
def __init__(self, id_=None, idref=None):
super(OpenIOCTestMechanism, self).__init__(id_=id_, idref=idref)
self.ioc = None
self.__input_namespaces__ = {}
self.__input_schemalocations__ = {}
- @property
- def ioc(self):
- return self._ioc
-
- @ioc.setter
- def ioc(self, value):
- if value is None:
- self._ioc = None
- return
-
- tree = parser.get_etree(value)
- root = parser.get_etree_root(tree)
-
- if root.tag != self._TAG_IOC:
- self._cast_ioc(root)
-
- self._collect_namespaces(root)
- self._collect_schemalocs(root)
- self._ioc = tree
-
def _collect_schemalocs(self, node):
try:
- schemaloc = parser.get_schemaloc_pairs(node)
+ schemaloc = mixbox.xml.get_schemaloc_pairs(node)
self.__input_schemalocations__ = dict(schemaloc)
except KeyError:
self.__input_schemalocations__ = {}
def _collect_namespaces(self, node):
- self.__input_namespaces__ = dict(node.nsmap.iteritems())
+ self.__input_namespaces__ = dict(iteritems(node.nsmap))
def _cast_ioc(self, node):
ns_ioc = "http://schemas.mandiant.com/2010/ioc"
@@ -71,14 +52,26 @@ def _cast_ioc(self, node):
error = error.format(self._TAG_IOC, node.tag)
raise ValueError(error)
+ def _processed_ioc(self):
+ if self.ioc is None:
+ return None
+
+ tree = mixbox.xml.get_etree(self.ioc)
+ root = mixbox.xml.get_etree_root(tree)
+
+ if root.tag != self._TAG_IOC:
+ self._cast_ioc(root)
+
+ self._collect_namespaces(root)
+ self._collect_schemalocs(root)
+ return tree
+
@classmethod
- def from_obj(cls, obj, return_obj=None):
+ def from_obj(cls, obj):
if not obj:
return None
- if not return_obj:
- return_obj = cls()
- super(OpenIOCTestMechanism, cls).from_obj(obj, return_obj)
+ return_obj = super(OpenIOCTestMechanism, cls).from_obj(obj)
return_obj.ioc = obj.ioc
return return_obj
@@ -86,21 +79,20 @@ def to_obj(self, return_obj=None, ns_info=None):
if not return_obj:
return_obj = self._binding_class()
- super(OpenIOCTestMechanism, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- return_obj.ioc = self.ioc
+ super(OpenIOCTestMechanism, self).to_obj(ns_info=ns_info)
+ return_obj.ioc = self._processed_ioc()
return return_obj
@classmethod
- def from_dict(cls, d, return_obj=None):
+ def from_dict(cls, d):
if not d:
return None
- if not return_obj:
- return_obj = cls()
-
- super(OpenIOCTestMechanism, cls).from_dict(d, return_obj)
+
+ return_obj = super(OpenIOCTestMechanism, cls).from_dict(d)
+
if 'ioc' in d:
- parser = stix.utils.parser.get_xml_parser()
- return_obj.ioc = etree.parse(StringIO(d['ioc']), parser=parser)
+ parser = mixbox.xml.get_xml_parser()
+ return_obj.ioc = etree.parse(BytesIO(d['ioc']), parser=parser)
return return_obj
@@ -108,8 +100,6 @@ def to_dict(self):
d = super(OpenIOCTestMechanism, self).to_dict()
if self.ioc:
- d['ioc'] = etree.tostring(self.ioc)
+ d['ioc'] = etree.tostring(self._processed_ioc())
return d
-
-stix.indicator.test_mechanism.add_extension(OpenIOCTestMechanism)
diff --git a/stix/extensions/test_mechanism/snort_test_mechanism.py b/stix/extensions/test_mechanism/snort_test_mechanism.py
index 944ce88e..7e3658a9 100644
--- a/stix/extensions/test_mechanism/snort_test_mechanism.py
+++ b/stix/extensions/test_mechanism/snort_test_mechanism.py
@@ -1,135 +1,27 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
from stix.common import EncodedCDATA
from stix.indicator import test_mechanism
import stix.bindings.extensions.test_mechanism.snort as snort_tm_binding
+@stix.register_extension
class SnortTestMechanism(test_mechanism._BaseTestMechanism):
_namespace = "http://stix.mitre.org/extensions/TestMechanism#Snort-1"
_binding = snort_tm_binding
_binding_class = _binding.SnortTestMechanismType
_XSI_TYPE = "snortTM:SnortTestMechanismType"
-
- def __init__(self, id_=None, idref=None):
- super(SnortTestMechanism, self).__init__(id_=id_, idref=idref)
- self.product_name = None
- self.version = None
- self.rules = None
- self.event_filters = None
- self.rate_filters = None
- self.event_suppressions = None
-
- @property
- def rules(self):
- return self._rules
-
- @rules.setter
- def rules(self, value):
- self._rules = _EncodedCDATAs(value)
-
- def add_rule(self, rule):
- self.rules.append(rule)
-
- @property
- def event_filters(self):
- return self._event_filters
-
- @event_filters.setter
- def event_filters(self, value):
- self._event_filters = _EncodedCDATAs(value)
-
- def add_event_filter(self, item):
- self.event_filters.append(item)
-
- @property
- def rate_filters(self):
- return self._rate_filters
-
- @rate_filters.setter
- def rate_filters(self, value):
- self._rate_filters = _EncodedCDATAs(value)
-
- def add_rate_filter(self, item):
- self.rate_filters.append(item)
-
- @property
- def event_suppressions(self):
- return self._event_suppressions
-
- @event_suppressions.setter
- def event_suppressions(self, value):
- self._event_suppressions = _EncodedCDATAs(value)
-
- def add_event_suppression(self, item):
- self.event_suppressions.append(item)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(SnortTestMechanism, cls).from_obj(obj, return_obj)
- return_obj.product_name = obj.Product_Name
- return_obj.version = obj.Version
- return_obj.rules = _EncodedCDATAs.from_obj(obj.Rule)
- return_obj.event_filters = _EncodedCDATAs.from_obj(obj.Event_Filter)
- return_obj.rate_filters = _EncodedCDATAs.from_obj(obj.Rate_Filter)
- return_obj.event_suppressions = _EncodedCDATAs.from_obj(obj.Event_Suppression)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(SnortTestMechanism, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- return_obj.Product_Name = self.product_name
- return_obj.Version = self.version
-
- if self.rules:
- return_obj.Rule = self.rules.to_obj(ns_info=ns_info)
- if self.event_filters:
- return_obj.Event_Filter = self.event_filters.to_obj(ns_info=ns_info)
- if self.rate_filters:
- return_obj.Rate_Filter = self.rate_filters.to_obj(ns_info=ns_info)
- if self.event_suppressions:
- return_obj.Event_Suppression = self.event_suppressions.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(SnortTestMechanism, cls).from_dict(d, return_obj)
-
- get = d.get
- return_obj.product_name = get('product_name')
- return_obj.version = get('version')
- return_obj.rules = _EncodedCDATAs.from_dict(get('rules'))
- return_obj.event_filters = _EncodedCDATAs.from_dict(get('event_filters'))
- return_obj.rate_filters = _EncodedCDATAs.from_dict(get('rate_filters'))
- return_obj.event_suppressions = _EncodedCDATAs.from_dict(get('event_suppressions'))
-
- return return_obj
- def to_dict(self):
- return super(SnortTestMechanism, self).to_dict()
+ product_name = fields.TypedField("Product_Name", EncodedCDATA)
+ version = fields.TypedField("Version", EncodedCDATA)
+ rules = fields.TypedField("Rule", EncodedCDATA, multiple=True, key_name="rules")
+ event_filters = fields.TypedField("Event_Filter", EncodedCDATA, multiple=True, key_name="event_filters")
+ rate_filters = fields.TypedField("Rate_Filter", EncodedCDATA, multiple=True, key_name="rate_filters")
+ event_suppressions = fields.TypedField("Event_Suppression", EncodedCDATA, multiple=True, key_name="event_suppressions")
-
-# Not an actual STIX data type!
-class _EncodedCDATAs(stix.TypedList):
- _contained_type = EncodedCDATA
-
-
-# Register this extension
-test_mechanism.add_extension(SnortTestMechanism)
+ def __init__(self, id_=None, idref=None):
+ super(SnortTestMechanism, self).__init__(id_=id_, idref=idref)
diff --git a/stix/extensions/test_mechanism/yara_test_mechanism.py b/stix/extensions/test_mechanism/yara_test_mechanism.py
index 79f5891e..35edcbcf 100644
--- a/stix/extensions/test_mechanism/yara_test_mechanism.py
+++ b/stix/extensions/test_mechanism/yara_test_mechanism.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.utils
import stix.indicator.test_mechanism
@@ -9,77 +11,15 @@
import stix.bindings.extensions.test_mechanism.yara as yara_tm_binding
+@stix.register_extension
class YaraTestMechanism(_BaseTestMechanism):
_namespace = "http://stix.mitre.org/extensions/TestMechanism#YARA-1"
_binding = yara_tm_binding
_binding_class = _binding.YaraTestMechanismType
_XSI_TYPE = "yaraTM:YaraTestMechanismType"
-
+
+ version = fields.TypedField("Version")
+ rule = fields.TypedField("Rule", EncodedCDATA)
+
def __init__(self, id_=None, idref=None):
super(YaraTestMechanism, self).__init__(id_=id_, idref=idref)
- self.version = None
- self.rule = None
-
- @property
- def rule(self):
- return self._rule
-
- @rule.setter
- def rule(self, value):
- if not value:
- self._rule = None
- if isinstance(value, EncodedCDATA):
- self._rule = value
- else:
- self._rule = EncodedCDATA(value=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(YaraTestMechanism, cls).from_obj(obj, return_obj)
- return_obj.version = obj.Version
- return_obj.rule = EncodedCDATA.from_obj(obj.Rule)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(YaraTestMechanism, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.version:
- return_obj.Version = self.version
- if self.rule:
- return_obj.Rule = self.rule.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(YaraTestMechanism, cls).from_dict(d, return_obj)
- return_obj.version = d.get('version')
- return_obj.rule = EncodedCDATA.from_dict(d.get('rule'))
-
- return return_obj
-
- def to_dict(self):
- d = super(YaraTestMechanism, self).to_dict()
-
- if self.version:
- d['version'] = self.version
- if self.rule:
- d['rule'] = self.rule.to_dict()
-
- return d
-
-stix.indicator.test_mechanism.add_extension(YaraTestMechanism)
diff --git a/stix/incident/__init__.py b/stix/incident/__init__.py
index 26f96008..b2ee2d9f 100644
--- a/stix/incident/__init__.py
+++ b/stix/incident/__init__.py
@@ -1,18 +1,18 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
import stix
import stix.bindings.incident as incident_binding
-from stix.common import (
- vocabs, Identity, Statement, VocabString,
- InformationSource, Confidence
-)
-from stix.common.related import (
- GenericRelationshipList, RelatedIndicator, RelatedThreatActor, RelatedTTP,
- RelatedObservable, RelatedIncident
-)
-from stix.data_marking import Marking
+from stix.common import vocabs
+from stix.common import Statement, VocabString, InformationSource, Confidence
+from stix.common.vocabs import VocabField
+from stix.common.statement import StatementField
+from stix.common.identity import Identity, IdentityFactory
+from stix.common.related import (GenericRelationshipList, RelatedIndicator,
+ RelatedThreatActor, RelatedTTP, RelatedObservable, RelatedIncident,
+ RelatedPackageRefs)
# relative
from .affected_asset import AffectedAsset
@@ -20,11 +20,27 @@
from .time import Time
from .external_id import ExternalID
from .impact_assessment import ImpactAssessment
-from .coa import COATaken, COARequested, COATime # noqa
+from .coa import COATaken, COARequested, COATime # noqa
from .history import History
class Incident(stix.BaseCoreComponent):
+ """Implementation of the STIX Incident.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref (optional): An identifier reference. If set this will unset the
+ ``id_`` property.
+ timestamp (optional): A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ description: A description of the purpose or intent of this object.
+ short_description: A short description of the intent
+ or purpose of this object.
+ title: The title of this object.
+
+ """
_binding = incident_binding
_binding_class = _binding.IncidentType
_namespace = "http://stix.mitre.org/Incident-1"
@@ -32,7 +48,35 @@ class Incident(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = 'incident'
- def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None):
+ status = vocabs.VocabField("Status", vocabs.IncidentStatus)
+ time = fields.TypedField("Time", Time)
+ victims = fields.TypedField("Victim", Identity, factory=IdentityFactory, multiple=True, key_name="victims")
+ attributed_threat_actors = fields.TypedField("Attributed_Threat_Actors", type_="stix.incident.AttributedThreatActors")
+ related_indicators = fields.TypedField("Related_Indicators", type_="stix.incident.RelatedIndicators")
+ related_observables = fields.TypedField("Related_Observables", type_="stix.incident.RelatedObservables")
+ related_incidents = fields.TypedField("Related_Incidents", type_="stix.incident.RelatedIncidents")
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ affected_assets = fields.TypedField("Affected_Assets", type_="stix.incident.AffectedAssets")
+ categories = fields.TypedField("Categories", type_="stix.incident.IncidentCategories")
+ intended_effects = StatementField("Intended_Effect", Statement, vocab_type=vocabs.IntendedEffect, multiple=True, key_name="intended_effects")
+ leveraged_ttps = fields.TypedField("Leveraged_TTPs", type_="stix.incident.LeveragedTTPs")
+ discovery_methods = vocabs.VocabField("Discovery_Method", vocabs.DiscoveryMethod, multiple=True, key_name="discovery_methods")
+ reporter = fields.TypedField("Reporter", InformationSource)
+ responders = fields.TypedField("Responder", InformationSource, multiple=True, key_name="responders")
+ coordinators = fields.TypedField("Coordinator", InformationSource, multiple=True, key_name="coordinators")
+ external_ids = fields.TypedField("External_ID", ExternalID, multiple=True, key_name="external_ids")
+ impact_assessment = fields.TypedField("Impact_Assessment", ImpactAssessment)
+ security_compromise = vocabs.VocabField("Security_Compromise", vocabs.SecurityCompromise)
+ confidence = fields.TypedField("Confidence", Confidence)
+ coa_taken = fields.TypedField("COA_Taken", COATaken, multiple=True)
+ coa_requested = fields.TypedField("COA_Requested", COARequested, multiple=True)
+ history = fields.TypedField("History", History)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+ url = fields.TypedField("URL")
+ contacts = fields.TypedField("Contact", InformationSource, multiple=True, key_name="contacts")
+
+ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
+ description=None, short_description=None):
super(Incident, self).__init__(
id_=id_,
idref=idref,
@@ -41,214 +85,108 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None, description
description=description,
short_description=short_description
)
-
- self.status = None
- self.time = None
- self.victims = None
- self.attributed_threat_actors = AttributedThreatActors()
self.related_indicators = RelatedIndicators()
self.related_observables = RelatedObservables()
self.related_incidents = RelatedIncidents()
- self.affected_assets = None
- self.categories = None
- self.intended_effects = None
+ self.related_packages = RelatedPackageRefs()
+ self.categories = IncidentCategories()
+ self.affected_assets = AffectedAssets()
self.leveraged_ttps = LeveragedTTPs()
- self.discovery_methods = None
- self.reporter = None
- self.responders = None
- self.coordinators = None
- self.external_ids = None
- self.impact_assessment = None
- self.security_compromise = None
- self.confidence = None
- self.coa_taken = None
- self.coa_requested = None
- self.handling = None
- self.history = History()
-
-
- @property
- def status(self):
- return self._status
-
- @status.setter
- def status(self, value):
- self._set_vocab(vocabs.IncidentStatus, status=value)
-
- @property
- def time(self):
- return self._time
-
- @time.setter
- def time(self, value):
- self._set_var(Time, try_cast=False, time=value)
-
- @property
- def handling(self):
- return self._handling
-
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, try_cast=False, handling=value)
- @property
- def intended_effects(self):
- return self._intended_effects
+ def add_intended_effect(self, value):
+ """Adds a :class:`.Statement` object to the :attr:`intended_effects`
+ collection.
- @intended_effects.setter
- def intended_effects(self, value):
- self._intended_effects = _IntendedEffects(value)
+ If `value` is a string, an attempt will be made to convert it into an
+ instance of :class:`.Statement`.
- def add_intended_effect(self, value):
+ """
self.intended_effects.append(value)
- @property
- def victims(self):
- return self._victims
+ def add_leveraged_ttps(self, ttp):
+ """Adds a :class:`.RelatedTTP` value to the :attr:`leveraged_ttps`
+ collection.
- @victims.setter
- def victims(self, value):
- self._victims = _Victims(value)
+ """
+ self.leveraged_ttps.append(ttp)
def add_victim(self, victim):
- self._victims.append(victim)
+ """Adds a :class:`.IdentityType` value to the :attr:`victims`
+ collection.
- @property
- def categories(self):
- return self._categories
-
- @categories.setter
- def categories(self, value):
- self._categories = IncidentCategories(value)
+ """
+ self.victims.append(victim)
def add_category(self, category):
+ """Adds a :class:`.VocabString` object to the :attr:`categories`
+ collection.
+
+ If `category` is a string, an attempt will be made to convert it into
+ an instance of :class:`.IncidentCategory`.
+
+ """
self.categories.append(category)
- @property
- def affected_assets(self):
- return self._affected_assets
-
- @affected_assets.setter
- def affected_assets(self, value):
- self._affected_assets = AffectedAssets(value)
-
def add_affected_asset(self, v):
- self.affected_assets.append(v)
+ """Adds a :class:`.AffectedAsset` object to the :attr:`affected_assets`
+ collection.
- @property
- def discovery_methods(self):
- return self._discovery_methods
-
- @discovery_methods.setter
- def discovery_methods(self, value):
- self._discovery_methods = DiscoveryMethods(value)
+ """
+ self.affected_assets.append(v)
def add_discovery_method(self, value):
- self.discovery_methods.append(value)
-
- @property
- def reporter(self):
- return self._reporter
+ """Adds a :class:`.VocabString` object to the :attr:`discovery_methods`
+ collection.
- @reporter.setter
- def reporter(self, value):
- self._set_var(InformationSource, try_cast=False, reporter=value)
+ If `value` is a string, an attempt will be made to convert it to an
+ instance of :class:`.DiscoveryMethod`.
- @property
- def responders(self):
- return self._responders
-
- @responders.setter
- def responders(self, value):
- self._responders = _InformationSources(value)
+ """
+ self.discovery_methods.append(value)
def add_responder(self, value):
- self.responders.append(value)
-
- @property
- def coordinators(self):
- return self._coordinators
+ """Adds a :class:`.InformationSource` object to the :attr:`responders`
+ collection.
- @coordinators.setter
- def coordinators(self, value):
- self._coordinators = _InformationSources(value)
+ """
+ self.responders.append(value)
def add_coordinator(self, value):
- self.coordinators.append(value)
-
- @property
- def external_ids(self):
- return self._external_ids
+ """Adds a :class:`.InformationSource` object to the :attr:`coordinators`
+ collection.
- @external_ids.setter
- def external_ids(self, value):
- self._external_ids = _ExternalIDs(value)
+ """
+ self.coordinators.append(value)
def add_external_id(self, value):
- self.external_ids.append(value)
-
- @property
- def impact_assessment(self):
- return self._impact_assessment
-
- @impact_assessment.setter
- def impact_assessment(self, value):
- self._set_var(ImpactAssessment, try_cast=False, impact_assessment=value)
-
- @property
- def security_compromise(self):
- return self._security_compromise
-
- @security_compromise.setter
- def security_compromise(self, value):
- self._set_vocab(vocabs.SecurityCompromise, security_compromise=value)
+ """Adds a :class:`.ExternalID` object to the :attr:`external_ids`
+ collection.
- @property
- def confidence(self):
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._set_var(Confidence, confidence=value)
-
- @property
- def coa_taken(self):
- return self._coa_taken
-
- @coa_taken.setter
- def coa_taken(self, value):
- self._coa_taken = _COAsTaken(value)
+ """
+ self.external_ids.append(value)
def add_coa_taken(self, value):
- self.coa_taken.append(value)
-
- @property
- def coa_requested(self):
- return self._coa_requested
+ """Adds a :class:`.COATaken` object to the :attr:`coas_taken`
+ collection.
- @coa_requested.setter
- def coa_requested(self, value):
- self._coa_requested = _COAsRequested(value)
+ """
+ self.coa_taken.append(value)
def add_coa_requested(self, value):
- self.coa_requested.append(value)
+ """Adds a :class:`.COARequested` object to the :attr:`coas_requested`
+ collection.
- @property
- def related_indicators(self):
- return self._related_indicators
-
- @related_indicators.setter
- def related_indicators(self, value):
- self._set_var(RelatedIndicators, related_indicators=value)
+ """
+ self.coa_requested.append(value)
def add_related_indicator(self, value):
- """Adds an Related Indicator to the ``related_indicators`` list
+ """Adds an Related Indicator to the :attr:`related_indicators` list
property of this :class:`Incident`.
The `indicator` parameter must be an instance of
:class:`.RelatedIndicator` or :class:`Indicator`.
- If the `indicator` parameter is ``None``, no item wil be added to the
+ If the `indicator` parameter is ``None``, no item will be added to the
``related_indicators`` list property.
Calling this method is the same as calling ``append()`` on the
@@ -263,7 +201,7 @@ def add_related_indicator(self, value):
made to convert it to one.
Args:
- indicator: An instance of :class:`Indicator` or
+ value: An instance of :class:`Indicator` or
:class:`.RelatedIndicator`.
Raises:
@@ -273,14 +211,6 @@ def add_related_indicator(self, value):
"""
self.related_indicators.append(value)
- @property
- def related_observables(self):
- return self._related_observables
-
- @related_observables.setter
- def related_observables(self, value):
- self._set_var(RelatedObservables, related_observables=value)
-
def add_related_observable(self, value):
"""Adds a Related Observable to the ``related_observables`` list
property of this :class:`Incident`.
@@ -313,241 +243,99 @@ def add_related_observable(self, value):
"""
self.related_observables.append(value)
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(Incident, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.time:
- return_obj.Time = self.time.to_obj(ns_info=ns_info)
- if self.victims:
- return_obj.Victim = self.victims.to_obj(ns_info=ns_info)
- if self.attributed_threat_actors:
- return_obj.Attributed_Threat_Actors = self.attributed_threat_actors.to_obj(ns_info=ns_info)
- if self.related_indicators:
- return_obj.Related_Indicators = self.related_indicators.to_obj(ns_info=ns_info)
- if self.related_observables:
- return_obj.Related_Observables = self.related_observables.to_obj(ns_info=ns_info)
- if self.related_incidents:
- return_obj.Related_Incidents = self.related_incidents.to_obj(ns_info=ns_info)
- if self.categories:
- return_obj.Categories = self.categories.to_obj(ns_info=ns_info)
- if self.intended_effects:
- return_obj.Intended_Effect = self.intended_effects.to_obj(ns_info=ns_info)
- if self.leveraged_ttps:
- return_obj.Leveraged_TTPs = self.leveraged_ttps.to_obj(ns_info=ns_info)
- if self.affected_assets:
- return_obj.Affected_Assets = self.affected_assets.to_obj(ns_info=ns_info)
- if self.discovery_methods:
- return_obj.Discovery_Method = self.discovery_methods.to_obj(ns_info=ns_info)
- if self.reporter:
- return_obj.Reporter = self.reporter.to_obj(ns_info=ns_info)
- if self.responders:
- return_obj.Responder = self.responders.to_obj(ns_info=ns_info)
- if self.coordinators:
- return_obj.Coordinator = self.coordinators.to_obj(ns_info=ns_info)
- if self.external_ids:
- return_obj.External_ID = self.external_ids.to_obj(ns_info=ns_info)
- if self.impact_assessment:
- return_obj.Impact_Assessment = self.impact_assessment.to_obj(ns_info=ns_info)
- if self.security_compromise:
- return_obj.Security_Compromise = self.security_compromise.to_obj(ns_info=ns_info)
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.coa_taken:
- return_obj.COA_Taken = self.coa_taken.to_obj(ns_info=ns_info)
- if self.coa_requested:
- return_obj.COA_Requested = self.coa_requested.to_obj(ns_info=ns_info)
- if self.status:
- return_obj.Status = self.status.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.history:
- return_obj.History = self.history.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(Incident, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class):
- return_obj.time = Time.from_obj(obj.Time)
- return_obj.victims = _Victims.from_obj(obj.Victim)
- return_obj.categories = IncidentCategories.from_obj(obj.Categories)
- return_obj.intended_effects = _IntendedEffects.from_obj(obj.Intended_Effect)
- return_obj.affected_assets = AffectedAssets.from_obj(obj.Affected_Assets)
- return_obj.discovery_methods = DiscoveryMethods.from_obj(obj.Discovery_Method)
- return_obj.coa_taken = _COAsTaken.from_obj(obj.COA_Taken)
- return_obj.coa_requested = _COAsRequested.from_obj(obj.COA_Requested)
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.attributed_threat_actors = AttributedThreatActors.from_obj(obj.Attributed_Threat_Actors)
- return_obj.related_indicators = RelatedIndicators.from_obj(obj.Related_Indicators)
- return_obj.related_observables = RelatedObservables.from_obj(obj.Related_Observables)
- return_obj.leveraged_ttps = LeveragedTTPs.from_obj(obj.Leveraged_TTPs)
- return_obj.related_incidents = RelatedIncidents.from_obj(obj.Related_Incidents)
- return_obj.status = VocabString.from_obj(obj.Status)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.history = History.from_obj(obj.History)
- return_obj.responders = _InformationSources.from_obj(obj.Responder)
- return_obj.coordinators = _InformationSources.from_obj(obj.Coordinator)
- return_obj.external_ids = _ExternalIDs.from_obj(obj.External_ID)
- return_obj.reporter = InformationSource.from_obj(obj.Reporter)
- return_obj.impact_assessment = ImpactAssessment.from_obj(obj.Impact_Assessment)
- return_obj.security_compromise = VocabString.from_obj(obj.Security_Compromise)
-
- return return_obj
-
- def to_dict(self):
- return super(Incident, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(Incident, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get
- return_obj.time = Time.from_dict(get('time'))
- return_obj.victims = _Victims.from_dict(get('victims'))
- return_obj.categories = IncidentCategories.from_dict(get('categories'))
- return_obj.attributed_threat_actors = AttributedThreatActors.from_dict(get('attributed_threat_actors'))
- return_obj.related_indicators = RelatedIndicators.from_dict(get('related_indicators'))
- return_obj.related_observables = RelatedObservables.from_dict(get('related_observables'))
- return_obj.related_incidents = RelatedIncidents.from_dict(get('related_incidents'))
- return_obj.intended_effects = _IntendedEffects.from_list(get('intended_effects'))
- return_obj.leveraged_ttps = LeveragedTTPs.from_dict(get('leveraged_ttps'))
- return_obj.affected_assets = AffectedAssets.from_dict(get('affected_assets'))
- return_obj.discovery_methods = DiscoveryMethods.from_dict(get('discovery_methods'))
- return_obj.reporter = InformationSource.from_dict(get('reporter'))
- return_obj.responders = _InformationSources.from_dict(get('responders'))
- return_obj.coordinators = _InformationSources.from_dict(get('coordinators'))
- return_obj.external_ids = _ExternalIDs.from_dict(get('external_ids'))
- return_obj.impact_assessment = ImpactAssessment.from_dict(get('impact_assessment'))
- return_obj.security_compromise = VocabString.from_dict(get('security_compromise'))
- return_obj.confidence = Confidence.from_dict(get('confidence'))
- return_obj.coa_taken = _COAsTaken.from_dict(get('coa_taken'))
- return_obj.coa_requested = _COAsRequested.from_dict(get('coa_requested'))
- return_obj.status = VocabString.from_dict(get('status'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.history = History.from_dict(get('history'))
-
- return return_obj
+ def add_related_package(self, value):
+ self.related_packages.append(value)
+
+ def add_related_incidents(self, value):
+ self.related_incidents.append(value)
class AttributedThreatActors(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.AttributedThreatActorsType
- _binding_var = "Threat_Actor"
- _contained_type = RelatedThreatActor
- _inner_name = "threat_actors"
+
+ threat_actor = fields.TypedField(
+ name="Threat_Actor",
+ type_=RelatedThreatActor,
+ multiple=True,
+ key_name="threat_actors"
+ )
class RelatedIndicators(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.RelatedIndicatorsType
- _binding_var = "Related_Indicator"
- _contained_type = RelatedIndicator
- _inner_name = "indicators"
+
+ indicator = fields.TypedField(
+ name="Related_Indicator",
+ type_=RelatedIndicator,
+ multiple=True,
+ key_name="indicators"
+ )
class RelatedObservables(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.RelatedObservablesType
- _binding_var = "Related_Observable"
- _contained_type = RelatedObservable
- _inner_name = "observables"
+
+ observable = fields.TypedField(
+ name="Related_Observable",
+ type_=RelatedObservable,
+ multiple=True,
+ key_name="observables"
+ )
class LeveragedTTPs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = _binding.LeveragedTTPsType
- _binding_var = "Leveraged_TTP"
- _contained_type = RelatedTTP
- _inner_name = "ttps"
+
+ ttp = fields.TypedField(
+ name="Leveraged_TTP",
+ type_=RelatedTTP,
+ multiple=True,
+ key_name="ttps"
+ )
class RelatedIncidents(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.RelatedIncidentsType
- _binding_var = "Related_Incident"
- _contained_type = RelatedIncident
- _inner_name = "incidents"
+
+ incident = fields.TypedField(
+ name="Related_Incident",
+ type_=RelatedIncident,
+ multiple=True,
+ key_name="incidents"
+ )
class IncidentCategories(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
- _contained_type = VocabString
_binding = incident_binding
_binding_class = _binding.CategoriesType
- _binding_var = "Category"
- _inner_name = "categories"
- _dict_as_list = True
- def _fix_value(self, value):
- return vocabs.IncidentCategory(value)
+ category = VocabField(
+ name="Category",
+ type_=vocabs.IncidentCategory,
+ multiple=True,
+ key_name="categories"
+ )
class AffectedAssets(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
- _contained_type = AffectedAsset
_binding = incident_binding
_binding_class = _binding.AffectedAssetsType
- _binding_var = "Affected_Asset"
- _inner_name = "affected_assets"
- _dict_as_list = True
-
-
-# NOT ACTUAL STIX TYPES!
-
-class DiscoveryMethods(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.DiscoveryMethod(value)
-
-
-class _COAsTaken(stix.TypedList):
- _contained_type = COATaken
-
-
-class _COAsRequested(stix.TypedList):
- _contained_type = COARequested
-
-
-class _ExternalIDs(stix.TypedList):
- _contained_type = ExternalID
-
-
-class _InformationSources(stix.TypedList):
- _contained_type = InformationSource
-
-
-class _Victims(stix.TypedList):
- _contained_type = Identity
-
- def _fix_value(self, value):
- return Identity(name=value)
-
-
-class _IntendedEffects(stix.TypedList):
- _contained_type = Statement
- def _fix_value(self, value):
- return Statement(value=vocabs.IntendedEffect(value))
+ affected_asset = fields.TypedField(
+ name="Affected_Asset",
+ type_=AffectedAsset,
+ multiple=True,
+ key_name="affected_assets"
+ )
diff --git a/stix/incident/affected_asset.py b/stix/incident/affected_asset.py
index 2a5dac02..571e96f9 100644
--- a/stix/incident/affected_asset.py
+++ b/stix/incident/affected_asset.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# external
from cybox.core import Observables
@@ -17,221 +19,47 @@ class AffectedAsset(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.AffectedAssetType
-
+
+ description = fields.TypedField("Description", StructuredText)
+ business_function_or_roles = fields.TypedField("Business_Function_Or_Role", StructuredText)
+ ownership_class = vocabs.VocabField("Ownership_Class", vocabs.OwnershipClass)
+ management_class = vocabs.VocabField("Management_Class", vocabs.ManagementClass)
+ location_class = vocabs.VocabField("Location_Class", vocabs.LocationClass)
+ # location = fields.TypedField("Location")
+ nature_of_security_effect = fields.TypedField("Nature_Of_Security_Effect", type_="stix.incident.affected_asset.NatureOfSecurityEffect")
+ structured_description = fields.TypedField("Structured_Description", Observables)
+ type_ = fields.TypedField("Type", type_="stix.incident.affected_asset.AssetType", key_name="type")
+
def __init__(self):
- self.type_ = None
- self.description = None
- self.business_function_or_role = None
- self.ownership_class = None
- self.management_class = None
- self.location_class = None
- # self.location = None
- self.nature_of_security_effect = None
- self.structured_description = None
-
- @property
- def type_(self):
- return self._type
-
- @type_.setter
- def type_(self, value):
- self._set_var(AssetType, type=value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def business_function_or_role(self):
- return self._business_function_or_role
-
- @business_function_or_role.setter
- def business_function_or_role(self, value):
- self._set_var(StructuredText, business_function_or_role=value)
-
- @property
- def ownership_class(self):
- return self._ownership_class
-
- @ownership_class.setter
- def ownership_class(self, value):
- self._set_vocab(vocabs.OwnershipClass, ownership_class=value)
-
- @property
- def management_class(self):
- return self._management_class
-
- @management_class.setter
- def management_class(self, value):
- self._set_vocab(vocabs.ManagementClass, management_class=value)
-
- @property
- def location_class(self):
- return self._location_class
-
- @location_class.setter
- def location_class(self, value):
- self._set_vocab(vocabs.LocationClass, location_class=value)
-
- @property
- def nature_of_security_effect(self):
- return self._nature_of_security_effect
-
- @nature_of_security_effect.setter
- def nature_of_security_effect(self, value):
- self._nature_of_security_effect = NatureOfSecurityEffect(value)
+ super(AffectedAsset, self).__init__()
def add_property_affected(self, v):
self.nature_of_security_effect.append(v)
-
- @property
- def structured_description(self):
- return self._structured_description
-
- @structured_description.setter
- def structured_description(self, value):
- self._set_var(Observables, structured_description=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.type_ = AssetType.from_obj(obj.Type)
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.business_function_or_role = StructuredText.from_obj(obj.Business_Function_Or_Role)
- return_obj.ownership_class = VocabString.from_obj(obj.Ownership_Class)
- return_obj.management_class = VocabString.from_obj(obj.Management_Class)
- return_obj.location_class = VocabString.from_obj(obj.Location_Class)
- # return_obj.location = None
-
- if obj.Nature_Of_Security_Effect:
- n = obj.Nature_Of_Security_Effect
- return_obj.nature_of_security_effect = [PropertyAffected.from_obj(x) for x in n.Property_Affected]
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(AffectedAsset, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.type_:
- return_obj.Type = self.type_.to_obj(ns_info=ns_info)
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.business_function_or_role:
- return_obj.Business_Function_Or_Role = self.business_function_or_role.to_obj(ns_info=ns_info)
- if self.ownership_class:
- return_obj.Ownership_Class = self.ownership_class.to_obj(ns_info=ns_info)
- if self.management_class:
- return_obj.Management_Class = self.management_class.to_obj(ns_info=ns_info)
- if self.location_class:
- return_obj.Location_Class = self.location_class.to_obj(ns_info=ns_info)
- # if self.location:
- # return_obj.Location = self.location.to_obj(ns_info=ns_info)
- if self.nature_of_security_effect:
- property_affected_list = [x.to_obj(ns_info=ns_info) for x in self.nature_of_security_effect]
- n = self._binding.NatureOfSecurityEffectType(Property_Affected=property_affected_list)
- return_obj.Nature_Of_Security_Effect = n
- if self.structured_description:
- return_obj.Structured_Description = self.structured_description.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = d.get
- return_obj.type_ = AssetType.from_dict(get('type'))
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.business_function_or_role = StructuredText.from_dict(get('business_function_or_role'))
- return_obj.ownership_class = VocabString.from_dict(get('ownership_class'))
- return_obj.management_class = VocabString.from_dict(get('management_class'))
- return_obj.location_class = VocabString.from_dict(get('location_class'))
- # return_obj.location = Location.from_dict(get('location'))
- return_obj.nature_of_security_effect = NatureOfSecurityEffect.from_dict(get('nature_of_security_effect'))
- return_obj.structured_description = Observables.from_dict(get('structured_description'))
- return return_obj
-
- def to_dict(self):
- return super(AffectedAsset, self).to_dict()
class AssetType(VocabString):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.AssetTypeType
-
+
+ count_affected = fields.IntegerField("count_affected")
+
def __init__(self, value=None, count_affected=None):
- self.count_affected = count_affected
super(AssetType, self).__init__(value)
-
+ self.count_affected = count_affected
+
def is_plain(self):
"""Override VocabString.is_plain()"""
return False
- @property
- def count_affected(self):
- return self._count_affected
-
- @count_affected.setter
- def count_affected(self, value):
- self._set_var(int, count_affected=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(AssetType, cls).from_obj(obj, return_obj=return_obj)
- return_obj.count_affected = obj.count_affected
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(AssetType, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- return_obj.count_affected = self.count_affected
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(AssetType, cls).from_dict(d, return_obj=return_obj)
- return_obj.count_affected = d.get('count_affected')
- return return_obj
-
- def to_dict(self):
- d = super(AssetType, self).to_dict()
- if self.count_affected:
- d['count_affected'] = self.count_affected
- return d
-
class NatureOfSecurityEffect(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
- _contained_type = PropertyAffected
_binding = incident_binding
_binding_class = _binding.NatureOfSecurityEffectType
- _binding_var = "Property_Affected"
- _inner_name = "nature_of_security_effect"
- _dict_as_list = True
+
+ nature_of_security_effect = fields.TypedField("Property_Affected", PropertyAffected, multiple=True, key_name="nature_of_security_effect")
+
+ @classmethod
+ def _dict_as_list(cls):
+ return True
diff --git a/stix/incident/coa.py b/stix/incident/coa.py
index 10828b6d..3384f838 100644
--- a/stix/incident/coa.py
+++ b/stix/incident/coa.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# internal
import stix
import stix.utils as utils
@@ -16,208 +18,42 @@ class COATaken(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = _binding.COATakenType
-
+
+ course_of_action = fields.TypedField("Course_Of_Action", CourseOfAction)
+ contributors = fields.TypedField("Contributors", Contributors)
+ time = fields.TypedField("Time", type_="stix.incident.coa.COATime")
+
def __init__(self, course_of_action=None):
+ super(COATaken, self).__init__()
+
self.time = None
self.course_of_action = course_of_action
- self.contributors = Contributors()
-
- @property
- def time(self):
- return self._time
-
- @time.setter
- def time(self, value):
- self._set_var(COATime, try_cast=False, time=value)
-
- @property
- def course_of_action(self):
- return self._course_of_action
-
- @course_of_action.setter
- def course_of_action(self, value):
- self._set_var(CourseOfAction, try_cast=False, course_of_action=value)
-
- @property
- def contributors(self):
- return self._contributors
-
- @contributors.setter
- def contributors(self, value):
- self._contributors = Contributors(value)
def add_contributor(self, value):
self.contributors.append(value)
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.time = COATime.from_obj(obj.Time)
- return_obj.contributors = Contributors.from_obj(obj.Contributors)
- return_obj.course_of_action = CourseOfAction.from_obj(obj.Course_Of_Action)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(COATaken, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.time:
- return_obj.Time = self.time.to_obj(ns_info=ns_info)
- if self.contributors:
- return_obj.Contributors = self.contributors.to_obj(ns_info=ns_info)
- if self.course_of_action:
- return_obj.Course_Of_Action = self.course_of_action.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.time = COATime.from_dict(d.get('time'))
- return_obj.contributors = Contributors.from_dict(d.get('contributors'))
- return_obj.course_of_action = CourseOfAction.from_dict(d.get('course_of_action'))
-
- return return_obj
-
- def to_dict(self):
- return super(COATaken, self).to_dict()
-
class COARequested(COATaken):
namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = _binding.COARequestedType
+ priority = fields.TypedField("priority")
+
def __init__(self, course_of_action=None):
super(COARequested, self).__init__(course_of_action=course_of_action)
- self.priority = None
-
- @property
- def priority(self):
- return self._priority
-
- @priority.setter
- def priority(self, value):
- if value is None:
- self._priority = None
- else:
- self._priority = value
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(COARequested, cls).from_obj(obj, return_obj=return_obj)
- return_obj.priority = obj.priority
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(COARequested, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- return_obj.priority = self.priority
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(COARequested, cls).from_dict(d, return_obj=return_obj)
- return_obj.priority = d.get('priority')
-
- return return_obj
-
- def to_dict(self):
- d = utils.to_dict(self)
- return d
class COATime(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = _binding.COATimeType
-
+
+ start = fields.TypedField("Start", DateTimeWithPrecision)
+ end = fields.TypedField("End", DateTimeWithPrecision)
+
def __init__(self, start=None, end=None):
+ super(COATime, self).__init__()
+
self.start = start
self.end = end
-
- @property
- def start(self):
- return self._start
-
- @start.setter
- def start(self, value):
- self._set_var(DateTimeWithPrecision, start=value)
-
- @property
- def end(self):
- return self._end
-
- @end.setter
- def end(self, value):
- self._set_var(DateTimeWithPrecision, end=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.start = DateTimeWithPrecision.from_obj(obj.Start)
- return_obj.end = DateTimeWithPrecision.from_obj(obj.End)
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(COATime, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.start:
- return_obj.Start = self.start.to_obj(ns_info=ns_info)
- if self.end:
- return_obj.End = self.end.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.start = DateTimeWithPrecision.from_dict(d.get('start'))
- return_obj.end = DateTimeWithPrecision.from_dict(d.get('end'))
- return return_obj
-
- def to_dict(self):
- d = {}
-
- if self.start:
- d['start'] = self.start.to_dict()
- if self.end:
- d['end'] = self.end.to_dict()
-
- return d
diff --git a/stix/incident/contributors.py b/stix/incident/contributors.py
index d00c33cc..919f8199 100644
--- a/stix/incident/contributors.py
+++ b/stix/incident/contributors.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# external
from cybox.common import Contributor
@@ -14,6 +16,5 @@ class Contributors(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = _binding.ContributorsType
- _contained_type = Contributor
- _binding_var = "Contributor"
- _inner_name = "contributors"
+
+ contributors = fields.TypedField("Contributor", Contributor, multiple=True, key_name="contributors")
\ No newline at end of file
diff --git a/stix/incident/direct_impact_summary.py b/stix/incident/direct_impact_summary.py
index 1f942e56..952174d5 100644
--- a/stix/incident/direct_impact_summary.py
+++ b/stix/incident/direct_impact_summary.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
from stix.common import VocabString
from stix.common.vocabs import ImpactRating
@@ -9,77 +11,12 @@
class DirectImpactSummary(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.DirectImpactSummaryType
+ asset_losses = fields.TypedField("Asset_Losses", ImpactRating)
+ business_mission_disruption = fields.TypedField("Business_Mission_Disruption", ImpactRating)
+ response_and_recovery_costs = fields.TypedField("Response_And_Recovery_Costs", ImpactRating)
+
def __init__(self):
super(DirectImpactSummary, self).__init__()
- self.asset_losses = None
- self.business_mission_disruption = None
- self.response_and_recovery_costs = None
-
- @property
- def asset_losses(self):
- return self._asset_losses
-
- @asset_losses.setter
- def asset_losses(self, value):
- self._set_vocab(ImpactRating, asset_losses=value)
-
- @property
- def business_mission_disruption(self):
- return self._business_mission_disruption
-
- @business_mission_disruption.setter
- def business_mission_disruption(self, value):
- self._set_vocab(ImpactRating, business_mission_disruption=value)
-
- @property
- def response_and_recovery_costs(self):
- return self._response_and_recovery_costs
-
- @response_and_recovery_costs.setter
- def response_and_recovery_costs(self, value):
- self._set_vocab(ImpactRating, response_and_recovery_costs=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(DirectImpactSummary, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- if self.asset_losses:
- obj.Asset_Losses = self.asset_losses.to_obj(ns_info=ns_info)
- if self.business_mission_disruption:
- obj.Business_Mission_Disruption = self.business_mission_disruption.to_obj(ns_info=ns_info)
- if self.response_and_recovery_costs:
- obj.Response_And_Recovery_Costs = self.response_and_recovery_costs.to_obj(ns_info=ns_info)
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.asset_losses = VocabString.from_obj(obj.Asset_Losses)
- return_obj.business_mission_disruption = VocabString.from_obj(obj.Business_Mission_Disruption)
- return_obj.response_and_recovery_costs = VocabString.from_obj(obj.Response_And_Recovery_Costs)
- return return_obj
-
- def to_dict(self):
- return super(DirectImpactSummary, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.asset_losses = VocabString.from_dict(dict_.get('asset_losses'))
- return_obj.business_mission_disruption = VocabString.from_dict(dict_.get('business_mission_disruption'))
- return_obj.response_and_recovery_costs = VocabString.from_dict(dict_.get('response_and_recovery_costs'))
-
- return return_obj
diff --git a/stix/incident/external_id.py b/stix/incident/external_id.py
index dcb86d5b..bb39ccc2 100644
--- a/stix/incident/external_id.py
+++ b/stix/incident/external_id.py
@@ -1,74 +1,21 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.incident as incident_binding
class ExternalID(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.ExternalIDType
+ value = fields.TypedField("valueOf_", key_name="value")
+ source = fields.TypedField("source")
+
def __init__(self, value=None, source=None):
super(ExternalID, self).__init__()
self.value = value
self.source = source
-
- @property
- def value(self):
- return self._value
-
- @value.setter
- def value(self, value):
- self._value = value
-
- @property
- def source(self):
- return self._source
-
- @source.setter
- def source(self, value):
- self._source = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(ExternalID, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- obj.valueOf_ = self.value
- obj.source = self.source
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = obj.valueOf_
- return_obj.source = obj.source
- return return_obj
-
- def to_dict(self):
- d = {}
- d['value'] = self.value
- d['source'] = self.source
- return d
-
- @classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- if not isinstance(dict_, dict):
- return_obj.value = dict_
- else:
- return_obj.source = dict_.get('source')
- return_obj.value = dict_.get('value')
-
- return return_obj
diff --git a/stix/incident/history.py b/stix/incident/history.py
index 9650a007..bffb4fb9 100644
--- a/stix/incident/history.py
+++ b/stix/incident/history.py
@@ -1,9 +1,10 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# internal
import stix
-import stix.utils as utils
import stix.bindings.incident as incident_binding
from stix.common.datetimewithprecision import DATETIME_PRECISION_VALUES
@@ -11,157 +12,48 @@
from .coa import COATaken
+def validate_precision(instance, value):
+ if value and (value not in DATETIME_PRECISION_VALUES):
+ error = "time_precision must be one of {0}. Received '{1}'"
+ error = error.format(DATETIME_PRECISION_VALUES, value)
+ raise ValueError(error)
+
+
class JournalEntry(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.JournalEntryType
-
+
+ value = fields.TypedField("valueOf_", key_name="value")
+ author = fields.TypedField("author")
+ time = fields.DateTimeField("time")
+ time_precision = fields.TypedField("time_precision", preset_hook=validate_precision)
+
def __init__(self, value=None):
+ super(JournalEntry, self).__init__()
self.value = value
- self.author = None
- self.time = None
self.time_precision = 'second'
-
- @property
- def time(self):
- return self._time
-
- @time.setter
- def time(self, value):
- self._time = utils.dates.parse_value(value)
-
- @property
- def time_precision(self):
- return self._time_precision
-
- @time_precision.setter
- def time_precision(self, value):
- if value and (value not in DATETIME_PRECISION_VALUES):
- error = "time_precision must be one of {0}. Received '{1}'"
- error = error.format(DATETIME_PRECISION_VALUES, value)
- raise ValueError(error)
-
- self._time_precision = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(JournalEntry, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.valueOf_ = self.value
- return_obj.author = self.author
- return_obj.time = utils.dates.serialize_value(self.time)
- return_obj.time_precision = self.time_precision
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = obj.valueOf_
- return_obj.author = obj.author
- return_obj.time = obj.time
- return_obj.time_precision = obj.time_precision
-
- return return_obj
-
- def to_dict(self):
- return super(JournalEntry, self).to_dict()
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.value = d.get('value')
- return_obj.author = d.get('author')
- return_obj.time = d.get('time')
- return_obj.time_precision = d.get('time_precision')
-
- return return_obj
class HistoryItem(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.HistoryItemType
-
+
+ action_entry = fields.TypedField("Action_Entry", COATaken)
+ journal_entry = fields.TypedField("Journal_Entry", JournalEntry)
+
def __init__(self):
- self.action_entry = None
- self.journal_entry = None
-
- @property
- def action_entry(self):
- return self._action_entry
-
- @action_entry.setter
- def action_entry(self, value):
- self._set_var(COATaken, try_cast=False, action_entry=value)
-
- @property
- def journal_entry(self):
- return self._journal_entry
-
- @journal_entry.setter
- def journal_entry(self, value):
- self._set_var(JournalEntry, journal_entry=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(HistoryItem, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.action_entry:
- return_obj.Action_Entry = self.action_entry.to_obj(ns_info=ns_info)
- if self.journal_entry:
- return_obj.Journal_Entry = self.journal_entry.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.action_entry = COATaken.from_obj(obj.Action_Entry)
- return_obj.journal_entry = JournalEntry.from_obj(obj.Journal_Entry)
-
- return return_obj
-
- def to_dict(self):
- return super(HistoryItem, self).to_dict()
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.action_entry = COATaken.from_dict(d.get('action_entry'))
- return_obj.journal_entry = JournalEntry.from_dict(d.get('journal_entry'))
-
- return return_obj
+ super(HistoryItem, self).__init__()
class History(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.HistoryType
- _binding_var = "History_Item"
- _contained_type = HistoryItem
- _inner_name = "history_items"
+
+ history_items = fields.TypedField("History_Item", HistoryItem, multiple=True, key_name="history_items")
+
+ @classmethod
+ def _dict_as_list(cls):
+ return False
diff --git a/stix/incident/impact_assessment.py b/stix/incident/impact_assessment.py
index 2f106e30..52ed2b53 100644
--- a/stix/incident/impact_assessment.py
+++ b/stix/incident/impact_assessment.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# internal
import stix
import stix.bindings.incident as incident_binding
@@ -11,12 +13,20 @@
from .indirect_impact_summary import IndirectImpactSummary
from .total_loss_estimation import TotalLossEstimation
+from stix.common.vocabs import VocabField
+
class ImpactAssessment(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.ImpactAssessmentType
+ direct_impact_summary = fields.TypedField("Direct_Impact_Summary", DirectImpactSummary)
+ indirect_impact_summary = fields.TypedField("Indirect_Impact_Summary", IndirectImpactSummary)
+ total_loss_estimation = fields.TypedField("Total_Loss_Estimation", TotalLossEstimation)
+ impact_qualification = vocabs.VocabField("Impact_Qualification", vocabs.ImpactQualification)
+ effects = fields.TypedField("Effects", type_="stix.incident.impact_assessment.Effects")
+
def __init__(self):
super(ImpactAssessment, self).__init__()
self.direct_impact_summary = None
@@ -26,111 +36,17 @@ def __init__(self):
self.effects = None
# self.external_impact_assessment_model = None
- @property
- def effects(self):
- return self._effects
-
- @effects.setter
- def effects(self, value):
- self._effects = Effects(value)
-
- def add_effect(self, value):
- self.effects.append(value)
-
- @property
- def direct_impact_summary(self):
- return self._direct_impact_summary
-
- @direct_impact_summary.setter
- def direct_impact_summary(self, value):
- self._set_var(DirectImpactSummary, try_cast=False, direct_impact_summary=value)
-
- @property
- def indirect_impact_summary(self):
- return self._indirect_impact_summary
-
- @indirect_impact_summary.setter
- def indirect_impact_summary(self, value):
- self._set_var(IndirectImpactSummary, try_cast=False, indirect_impact_summary=value)
-
- @property
- def total_loss_estimation(self):
- return self._total_loss_estimation
-
- @total_loss_estimation.setter
- def total_loss_estimation(self, value):
- self._set_var(TotalLossEstimation, try_cast=False, total_loss_estimation=value)
-
- @property
- def impact_qualification(self):
- return self._impact_qualification
-
- @impact_qualification.setter
- def impact_qualification(self, value):
- self._set_vocab(vocabs.ImpactQualification, impact_qualification=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(ImpactAssessment, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
-
- if self.direct_impact_summary:
- obj.Direct_Impact_Summary = self.direct_impact_summary.to_obj(ns_info=ns_info)
- if self.indirect_impact_summary:
- obj.Indirect_Impact_Summary = self.indirect_impact_summary.to_obj(ns_info=ns_info)
- if self.total_loss_estimation:
- obj.Total_Loss_Estimation = self.total_loss_estimation.to_obj(ns_info=ns_info)
- if self.impact_qualification:
- obj.Impact_Qualification = self.impact_qualification.to_obj(ns_info=ns_info)
- if self.effects:
- obj.Effects = self.effects.to_obj(ns_info=ns_info)
-
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.direct_impact_summary = DirectImpactSummary.from_obj(obj.Direct_Impact_Summary)
- return_obj.indirect_impact_summary = IndirectImpactSummary.from_obj(obj.Indirect_Impact_Summary)
- return_obj.total_loss_estimation = TotalLossEstimation.from_obj(obj.Total_Loss_Estimation)
- return_obj.impact_qualification = VocabString.from_obj(obj.Impact_Qualification)
- return_obj.effects = Effects.from_obj(obj.Effects)
-
- return return_obj
-
- def to_dict(self):
- return super(ImpactAssessment, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.direct_impact_summary = DirectImpactSummary.from_dict(get('direct_impact_summary'))
- return_obj.indirect_impact_summary = IndirectImpactSummary.from_dict(get('indirect_impact_summary'))
- return_obj.total_loss_estimation = TotalLossEstimation.from_dict(get('total_loss_estimation'))
- return_obj.impact_qualification = VocabString.from_dict(get('impact_qualification'))
- return_obj.effects = Effects.from_dict(get('effects'))
-
- return return_obj
-
class Effects(stix.EntityList):
_namespace = "http://stix.mitre.org/Incident-1"
- _contained_type = VocabString
_binding = incident_binding
_binding_class = _binding.EffectsType
- _inner_name = "effects"
- _binding_var = "Effect"
- _dict_as_list = True
+
+ effects = VocabField("Effect", VocabString, multiple=True, key_name="effects")
+
+ @classmethod
+ def _dict_as_list(cls):
+ return True
def _fix_value(self, value):
return vocabs.IncidentEffect(value=value)
diff --git a/stix/incident/indirect_impact_summary.py b/stix/incident/indirect_impact_summary.py
index 9c89a945..93d339f5 100644
--- a/stix/incident/indirect_impact_summary.py
+++ b/stix/incident/indirect_impact_summary.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.incident as incident_binding
from stix.common import vocabs, VocabString
@@ -8,90 +10,13 @@
class IndirectImpactSummary(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.IndirectImpactSummaryType
+ loss_of_competitive_advantage = vocabs.VocabField("Loss_Of_Competitive_Advantage", vocabs.SecurityCompromise)
+ brand_and_market_damage = vocabs.VocabField("Brand_And_Market_Damage", vocabs.SecurityCompromise)
+ increased_operating_costs = vocabs.VocabField("Increased_Operating_Costs", vocabs.SecurityCompromise)
+ legal_and_regulatory_costs = vocabs.VocabField("Legal_And_Regulatory_Costs", vocabs.SecurityCompromise)
+
def __init__(self):
super(IndirectImpactSummary, self).__init__()
- self.loss_of_competitive_advantage = None
- self.brand_and_market_damage = None
- self.increased_operating_costs = None
- self.legal_and_regulatory_costs = None
-
- @property
- def loss_of_competitive_advantage(self):
- return self._loss_of_competitive_advantage
-
- @loss_of_competitive_advantage.setter
- def loss_of_competitive_advantage(self, value):
- self._set_vocab(vocabs.SecurityCompromise, loss_of_competitive_advantage=value)
-
- @property
- def brand_and_market_damage(self):
- return self._brand_and_market_damage
-
- @brand_and_market_damage.setter
- def brand_and_market_damage(self, value):
- self._set_vocab(vocabs.SecurityCompromise, brand_and_market_damage=value)
-
- @property
- def increased_operating_costs(self):
- return self._increased_operating_costs
-
- @increased_operating_costs.setter
- def increased_operating_costs(self, value):
- self._set_vocab(vocabs.SecurityCompromise, increased_operating_costs=value)
-
- @property
- def legal_and_regulatory_costs(self):
- return self._legal_and_regulatory_costs
-
- @legal_and_regulatory_costs.setter
- def legal_and_regulatory_costs(self, value):
- self._set_vocab(vocabs.SecurityCompromise, legal_and_regulatory_costs=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(IndirectImpactSummary, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- if self.loss_of_competitive_advantage:
- obj.Loss_Of_Competitive_Advantage = self.loss_of_competitive_advantage.to_obj(ns_info=ns_info)
- if self.brand_and_market_damage:
- obj.Brand_And_Market_Damage = self.brand_and_market_damage.to_obj(ns_info=ns_info)
- if self.increased_operating_costs:
- obj.Increased_Operating_Costs = self.increased_operating_costs.to_obj(ns_info=ns_info)
- if self.legal_and_regulatory_costs:
- obj.Legal_And_Regulatory_Costs = self.legal_and_regulatory_costs.to_obj(ns_info=ns_info)
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.loss_of_competitive_advantage = VocabString.from_obj(obj.Loss_Of_Competitive_Advantage)
- return_obj.brand_and_market_damage = VocabString.from_obj(obj.Brand_And_Market_Damage)
- return_obj.increased_operating_costs = VocabString.from_obj(obj.Increased_Operating_Costs)
- return_obj.legal_and_regulatory_costs = VocabString.from_obj(obj.Legal_And_Regulatory_Costs)
- return return_obj
-
- def to_dict(self):
- return super(IndirectImpactSummary, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.loss_of_competitive_advantage = VocabString.from_dict(dict_.get('loss_of_competitive_advantage'))
- return_obj.brand_and_market_damage = VocabString.from_dict(dict_.get('brand_and_market_damage'))
- return_obj.increased_operating_costs = VocabString.from_dict(dict_.get('increased_operating_costs'))
- return_obj.legal_and_regulatory_costs = VocabString.from_dict(dict_.get('legal_and_regulatory_costs'))
-
- return return_obj
diff --git a/stix/incident/loss_estimation.py b/stix/incident/loss_estimation.py
index dc9540d3..51a682d0 100644
--- a/stix/incident/loss_estimation.py
+++ b/stix/incident/loss_estimation.py
@@ -1,70 +1,19 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.incident as incident_binding
class LossEstimation(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.LossEstimationType
+ iso_currency_code = fields.TypedField("iso_currency_code")
+ amount = fields.TypedField("amount")
+
def __init__(self):
super(LossEstimation, self).__init__()
- self.iso_currency_code = None
- self.amount = None
-
- @property
- def amount(self):
- return self._amount
-
- @amount.setter
- def amount(self, value):
- self._amount = value
-
- @property
- def iso_currency_code(self):
- return self._iso_currency_code
-
- @iso_currency_code.setter
- def iso_currency_code(self, value):
- self._iso_currency_code = value
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(LossEstimation, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- if self.amount:
- obj.amount = self.amount
- if self.iso_currency_code:
- obj.iso_currency_code = self.iso_currency_code
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.amount = obj.amount
- return_obj.iso_currency_code = obj.iso_currency_code
- return return_obj
-
- def to_dict(self):
- return super(LossEstimation, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.amount = dict_.get('amount')
- return_obj.iso_currency_code = dict_.get('iso_currency_code')
-
- return return_obj
diff --git a/stix/incident/property_affected.py b/stix/incident/property_affected.py
index a699ef37..00e674d9 100644
--- a/stix/incident/property_affected.py
+++ b/stix/incident/property_affected.py
@@ -1,6 +1,7 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
import stix
from stix.common import vocabs, VocabString, StructuredText
@@ -9,156 +10,29 @@
class NonPublicDataCompromised(VocabString):
_namespace = "http://stix.mitre.org/Incident-1"
- _binding = incident_binding
+ _binding = incident_binding
_binding_class = incident_binding.NonPublicDataCompromisedType
-
- def __init__(self, value=None, data_encrypted=None):
- self.data_encrypted = data_encrypted
- super(NonPublicDataCompromised, self).__init__(value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(NonPublicDataCompromised, cls).from_obj(obj, return_obj=return_obj)
- return_obj.data_encrypted = obj.data_encrypted
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(NonPublicDataCompromised, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- return_obj.data_encrypted = self.data_encrypted
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
+ data_encrypted = fields.TypedField("data_encrypted")
- if not return_obj:
- return_obj = cls()
-
- super(NonPublicDataCompromised, cls).from_dict(d, return_obj=return_obj)
- return_obj.data_encrypted = d.get('data_encrypted')
- return return_obj
+ def __init__(self, value=None, data_encrypted=None):
+ super(NonPublicDataCompromised, self).__init__(value)
+ self.data_encrypted = data_encrypted
def is_plain(self):
return False
- def to_dict(self):
- d = super(NonPublicDataCompromised, self).to_dict()
-
- if self.data_encrypted:
- d['data_encrypted'] = self.data_encrypted
-
- return d
-
class PropertyAffected(stix.Entity):
_namespace = "http://stix.mitre.org/Incident-1"
_binding = incident_binding
_binding_class = incident_binding.PropertyAffectedType
-
- def __init__(self):
- self.property_ = None
- self.description_of_effect = None
- self.type_of_availability_loss = None
- self.duration_of_availability_loss = None
- self.non_public_data_compromised = None
-
- @property
- def property_(self):
- return self._property
-
- @property_.setter
- def property_(self, value):
- self._set_vocab(vocabs.LossProperty, property=value)
-
- @property
- def description_of_effect(self):
- return self._description_of_effect
-
- @description_of_effect.setter
- def description_of_effect(self, value):
- self._set_var(StructuredText, description_of_effect=value)
- @property
- def type_of_availability_loss(self):
- return self._type_of_availability_loss
-
- @type_of_availability_loss.setter
- def type_of_availability_loss(self, value):
- self._set_vocab(vocabs.AvailabilityLossType, type_of_availability_loss=value)
-
- @property
- def duration_of_availability_loss(self):
- return self._duration_of_availability_loss
-
- @duration_of_availability_loss.setter
- def duration_of_availability_loss(self, value):
- self._set_vocab(vocabs.LossDuration, duration_of_availability_loss=value)
-
- @property
- def non_public_data_compromised(self):
- return self._non_public_data_compromised
-
- @non_public_data_compromised.setter
- def non_public_data_compromised(self, value):
- self._set_var(NonPublicDataCompromised, non_public_data_compromised=value)
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.property_ = VocabString.from_obj(obj.Property)
- return_obj.description_of_effect = StructuredText.from_obj(obj.Description_Of_Effect)
- return_obj.type_of_availability_loss = VocabString.from_obj(obj.Type_Of_Availability_Loss)
- return_obj.duration_of_availability_loss = VocabString.from_obj(obj.Duration_Of_Availability_Loss)
- return_obj.non_public_data_compromised = NonPublicDataCompromised.from_obj(obj.Non_Public_Data_Compromised)
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(PropertyAffected, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ property_ = vocabs.VocabField("Property", vocabs.LossProperty, key_name="property")
+ descriptions_of_effect = fields.TypedField("Description_Of_Effect", StructuredText)
+ type_of_availability_loss = vocabs.VocabField("Type_Of_Availability_Loss", vocabs.AvailabilityLossType)
+ duration_of_availability_loss = vocabs.VocabField("Duration_Of_Availability_Loss", vocabs.LossDuration)
+ non_public_data_compromised = fields.TypedField("Non_Public_Data_Compromised", NonPublicDataCompromised)
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.property_:
- return_obj.Property = self.property_.to_obj(ns_info=ns_info)
- if self.description_of_effect:
- return_obj.Description_Of_Effect = self.description_of_effect.to_obj(ns_info=ns_info)
- if self.type_of_availability_loss:
- return_obj.Type_Of_Availability_Loss = self.type_of_availability_loss.to_obj(ns_info=ns_info)
- if self.duration_of_availability_loss:
- return_obj.Duration_Of_Availability_Loss = self.duration_of_availability_loss.to_obj(ns_info=ns_info)
- if self.non_public_data_compromised:
- return_obj.Non_Public_Data_Compromised = self.non_public_data_compromised.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.property_ = VocabString.from_dict(d.get('property'))
- return_obj.description_of_effect = StructuredText.from_dict(d.get('description_of_effect'))
- return_obj.type_of_availability_loss = VocabString.from_dict(d.get('type_of_availability_loss'))
- return_obj.duration_of_availability_loss = VocabString.from_dict(d.get('duration_of_availability_loss'))
- return_obj.non_public_data_compromised = NonPublicDataCompromised.from_dict(d.get('non_public_data_compromised'))
-
- return return_obj
-
- def to_dict(self):
- return super(PropertyAffected, self).to_dict()
+ def __init__(self):
+ super(PropertyAffected, self).__init__()
diff --git a/stix/incident/time.py b/stix/incident/time.py
index d794b070..42cca222 100644
--- a/stix/incident/time.py
+++ b/stix/incident/time.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
import stix.bindings.incident as incident_binding
from stix.common import DateTimeWithPrecision
@@ -11,11 +13,22 @@ class Time(stix.Entity):
_binding_class = _binding.TimeType
_namespace = "http://stix.mitre.org/Incident-1"
+ first_malicious_action = fields.TypedField("First_Malicious_Action", DateTimeWithPrecision)
+ initial_compromise = fields.TypedField("Initial_Compromise", DateTimeWithPrecision)
+ first_data_exfiltration = fields.TypedField("First_Data_Exfiltration", DateTimeWithPrecision)
+ incident_discovery = fields.TypedField("Incident_Discovery", DateTimeWithPrecision)
+ incident_opened = fields.TypedField("Incident_Opened", DateTimeWithPrecision)
+ containment_achieved = fields.TypedField("Containment_Achieved", DateTimeWithPrecision)
+ restoration_achieved = fields.TypedField("Restoration_Achieved", DateTimeWithPrecision)
+ incident_reported = fields.TypedField("Incident_Reported", DateTimeWithPrecision)
+ incident_closed = fields.TypedField("Incident_Closed", DateTimeWithPrecision)
+
def __init__(self, first_malicious_action=None, initial_compromise=None,
first_data_exfiltration=None, incident_discovery=None,
incident_opened=None, containment_achieved=None,
restoration_achieved=None, incident_reported=None,
incident_closed=None):
+ super(Time, self).__init__()
self.first_malicious_action = first_malicious_action
self.initial_compromise = initial_compromise
@@ -26,145 +39,3 @@ def __init__(self, first_malicious_action=None, initial_compromise=None,
self.restoration_achieved = restoration_achieved
self.incident_reported = incident_reported
self.incident_closed = incident_closed
-
- @property
- def first_malicious_action(self):
- return self._first_malicious_action
-
- @first_malicious_action.setter
- def first_malicious_action(self, value):
- self._set_var(DateTimeWithPrecision, first_malicious_action=value)
-
- @property
- def initial_compromise(self):
- return self._initial_compromise
-
- @initial_compromise.setter
- def initial_compromise(self, value):
- self._set_var(DateTimeWithPrecision, initial_compromise=value)
-
- @property
- def first_data_exfiltration(self):
- return self._first_data_exfiltration
-
- @first_data_exfiltration.setter
- def first_data_exfiltration(self, value):
- self._set_var(DateTimeWithPrecision, first_data_exfiltration=value)
-
- @property
- def incident_discovery(self):
- return self._incident_discovery
-
- @incident_discovery.setter
- def incident_discovery(self, value):
- self._set_var(DateTimeWithPrecision, incident_discovery=value)
-
- @property
- def incident_opened(self):
- return self._incident_opened
-
- @incident_opened.setter
- def incident_opened(self, value):
- self._set_var(DateTimeWithPrecision, incident_opened=value)
-
- @property
- def containment_achieved(self):
- return self._containment_achieved
-
- @containment_achieved.setter
- def containment_achieved(self, value):
- self._set_var(DateTimeWithPrecision, containment_achieved=value)
-
- @property
- def restoration_achieved(self):
- return self._restoration_achieved
-
- @restoration_achieved.setter
- def restoration_achieved(self, value):
- self._set_var(DateTimeWithPrecision, restoration_achieved=value)
-
- @property
- def incident_reported(self):
- return self._incident_reported
-
- @incident_reported.setter
- def incident_reported(self, value):
- self._set_var(DateTimeWithPrecision, incident_reported=value)
-
- @property
- def incident_closed(self):
- return self._incident_closed
-
- @incident_closed.setter
- def incident_closed(self, value):
- self._set_var(DateTimeWithPrecision, incident_closed=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Time, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.first_malicious_action:
- return_obj.First_Malicious_Action = self.first_malicious_action.to_obj(ns_info=ns_info)
- if self.initial_compromise:
- return_obj.Initial_Compromise = self.initial_compromise.to_obj(ns_info=ns_info)
- if self.first_data_exfiltration:
- return_obj.First_Data_Exfiltration = self.first_data_exfiltration.to_obj(ns_info=ns_info)
- if self._incident_discovery:
- return_obj.Incident_Discovery = self.incident_discovery.to_obj(ns_info=ns_info)
- if self.incident_opened:
- return_obj.Incident_Opened = self.incident_opened.to_obj(ns_info=ns_info)
- if self.containment_achieved:
- return_obj.Containment_Achieved = self.containment_achieved.to_obj(ns_info=ns_info)
- if self.restoration_achieved:
- return_obj.Restoration_Achieved = self.restoration_achieved.to_obj(ns_info=ns_info)
- if self.incident_reported:
- return_obj.Incident_Reported = self.incident_reported.to_obj(ns_info=ns_info)
- if self.incident_closed:
- return_obj.Incident_Closed = self.incident_closed.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.first_malicious_action = DateTimeWithPrecision.from_obj(obj.First_Malicious_Action)
- return_obj.initial_compromise = DateTimeWithPrecision.from_obj(obj.Initial_Compromise)
- return_obj.first_data_exfiltration = DateTimeWithPrecision.from_obj(obj.First_Data_Exfiltration)
- return_obj.incident_discovery = DateTimeWithPrecision.from_obj(obj.Incident_Discovery)
- return_obj.incident_opened = DateTimeWithPrecision.from_obj(obj.Incident_Opened)
- return_obj.containment_achieved = DateTimeWithPrecision.from_obj(obj.Containment_Achieved)
- return_obj.restoration_achieved = DateTimeWithPrecision.from_obj(obj.Restoration_Achieved)
- return_obj.incident_reported = DateTimeWithPrecision.from_obj(obj.Incident_Reported)
- return_obj.incident_closed = DateTimeWithPrecision.from_obj(obj.Incident_Closed)
-
- return return_obj
-
- def to_dict(self):
- return super(Time, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.first_malicious_action = DateTimeWithPrecision.from_dict(dict_repr.get('first_malicious_action'))
- return_obj.initial_compromise = DateTimeWithPrecision.from_dict(dict_repr.get('initial_compromise'))
- return_obj.first_data_exfiltration = DateTimeWithPrecision.from_dict(dict_repr.get('first_data_exfiltration'))
- return_obj.incident_discovery = DateTimeWithPrecision.from_dict(dict_repr.get('incident_discovery'))
- return_obj.incident_opened = DateTimeWithPrecision.from_dict(dict_repr.get('incident_opened'))
- return_obj.containment_achieved = DateTimeWithPrecision.from_dict(dict_repr.get('containment_achieved'))
- return_obj.restoration_achieved = DateTimeWithPrecision.from_dict(dict_repr.get('restoration_achieved'))
- return_obj.incident_reported = DateTimeWithPrecision.from_dict(dict_repr.get('incident_reported'))
- return_obj.incident_closed = DateTimeWithPrecision.from_dict(dict_repr.get('incident_closed'))
-
- return return_obj
diff --git a/stix/incident/total_loss_estimation.py b/stix/incident/total_loss_estimation.py
index 60a9b061..be70d8e7 100644
--- a/stix/incident/total_loss_estimation.py
+++ b/stix/incident/total_loss_estimation.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# internal
import stix
import stix.bindings.incident as incident_binding
@@ -14,61 +16,8 @@ class TotalLossEstimation(stix.Entity):
_binding = incident_binding
_binding_class = incident_binding.TotalLossEstimationType
+ initial_reported_total_loss_estimation = fields.TypedField("Initial_Reported_Total_Loss_Estimation", LossEstimation)
+ actual_total_loss_estimation = fields.TypedField("Actual_Total_Loss_Estimation", LossEstimation)
+
def __init__(self):
super(TotalLossEstimation, self).__init__()
- self.initial_reported_total_loss_estimation = None
- self.actual_total_loss_estimation = None
-
- @property
- def initial_reported_total_loss_estimation(self):
- return self._initial_reported_total_loss_estimation
-
- @initial_reported_total_loss_estimation.setter
- def initial_reported_total_loss_estimation(self, value):
- self._set_var(LossEstimation, initial_reported_total_loss_estimation=value)
-
- @property
- def actual_total_loss_estimation(self):
- return self._actual_total_loss_estimation
-
- @actual_total_loss_estimation.setter
- def actual_total_loss_estimation(self, value):
- self._set_var(LossEstimation, actual_total_loss_estimation=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(TotalLossEstimation, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- obj = self._binding_class()
- if self.initial_reported_total_loss_estimation:
- obj.Initial_Reported_Total_Loss_Estimation = self.initial_reported_total_loss_estimation.to_obj(ns_info=ns_info)
- if self.actual_total_loss_estimation:
- obj.Actual_Total_Loss_Estimation = self.actual_total_loss_estimation.to_obj(ns_info=ns_info)
- return obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.initial_reported_total_loss_estimation = LossEstimation.from_obj(obj.Initial_Reported_Total_Loss_Estimation)
- return_obj.actual_total_loss_estimation = LossEstimation.from_obj(obj.Actual_Total_Loss_Estimation)
- return return_obj
-
- def to_dict(self):
- return super(TotalLossEstimation, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_, return_obj=None):
- if not dict_:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.initial_reported_total_loss_estimation = LossEstimation.from_dict(dict_.get('initial_reported_total_loss_estimation'))
- return_obj.actual_total_loss_estimation = LossEstimation.from_dict(dict_.get('actual_total_loss_estimation'))
-
- return return_obj
diff --git a/stix/indicator/__init__.py b/stix/indicator/__init__.py
index a3116185..65d34942 100644
--- a/stix/indicator/__init__.py
+++ b/stix/indicator/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-from indicator import * # noqa
+from .indicator import * # noqa
diff --git a/stix/indicator/indicator.py b/stix/indicator/indicator.py
index 3b202e47..06cb0933 100644
--- a/stix/indicator/indicator.py
+++ b/stix/indicator/indicator.py
@@ -1,30 +1,31 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# external
+# mixbox
+from mixbox import fields
+from mixbox import entities
+from mixbox import typedlist
+
+# cybox
from cybox.core import Observable, ObservableComposition
from cybox.common import Time
# internal
import stix
-import stix.utils as utils
-from stix.common import (
- Identity, InformationSource, VocabString, Confidence,
- RelatedTTP, Statement, CampaignRef
-)
-from stix.common.related import (
- GenericRelationshipList, RelatedCOA, RelatedIndicator, RelatedCampaignRef,
- RelatedPackageRefs
-)
-from stix.data_marking import Marking
-from stix.common.vocabs import IndicatorType
+from stix.common.identity import Identity
+from stix.common import (InformationSource, VocabString, Confidence, RelatedTTP,
+ Statement, CampaignRef)
+from stix.common.related import (GenericRelationshipList, RelatedCOA,
+ RelatedIndicator, RelatedCampaignRef, RelatedPackageRefs)
+from stix.common.vocabs import VocabField, IndicatorType
from stix.common.kill_chains import KillChainPhasesReference
+from stix import utils
import stix.bindings.indicator as indicator_binding
# relative
from .test_mechanism import TestMechanisms
from .sightings import Sightings
-from .valid_time import _ValidTimePositions
+from .valid_time import ValidTime
class SuggestedCOAs(GenericRelationshipList):
@@ -55,7 +56,7 @@ class SuggestedCOAs(GenericRelationshipList):
>>> coa = CourseOfAction()
>>> indicator = Indicator()
>>> indicator.suggested_coas.append(coa)
- >>> print type(indicator.suggested_coas[0])
+ >>> print(type(indicator.suggested_coas[0]))
Iterate over the ``suggested_coas`` property of an :class:`Indicator`
@@ -63,7 +64,7 @@ class SuggestedCOAs(GenericRelationshipList):
:class:`stix.coa.CourseOfAction` instance.
>>> for related_coa in indicator.suggested_coas:
- >>> print related_coa.item.id_
+ >>> print(related_coa.item.id_)
Args:
suggested_coas(list): A list of :class:`stix.coa.CourseOfAction`
@@ -78,14 +79,13 @@ class SuggestedCOAs(GenericRelationshipList):
or ``"exclusive"``. See
:class:`stix.common.related.GenericRelationshipList` documentation
for more information.
-
"""
+
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = indicator_binding.SuggestedCOAsType
- _binding_var = "Suggested_COA"
- _contained_type = RelatedCOA
- _inner_name = "suggested_coas"
+
+ suggested_coa = fields.TypedField("Suggested_COA", RelatedCOA, multiple=True, key_name="suggested_coas")
def __init__(self, suggested_coas=None, scope=None):
super(SuggestedCOAs, self).__init__(scope, suggested_coas)
@@ -119,7 +119,7 @@ class RelatedIndicators(GenericRelationshipList):
>>> related = Indicator()
>>> parent_indicator = Indicator()
>>> parent_indicator.related_indicators.append(related)
- >>> print type(indicator.related_indicators[0])
+ >>> print(type(indicator.related_indicators[0]))
Iterate over the ``related_indicators`` property of an
@@ -127,7 +127,7 @@ class RelatedIndicators(GenericRelationshipList):
:class:`Indicator`` instance:
>>> for related in indicator.related_indicators:
- >>> print related.item.id_
+ >>> print(related.item.id_)
Args:
related_indicators (list, optional): A list of :class:`Indicator` or
@@ -147,20 +147,19 @@ class RelatedIndicators(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = indicator_binding.RelatedIndicatorsType
- _binding_var = "Related_Indicator"
- _contained_type = RelatedIndicator
- _inner_name = "related_indicators"
+
+ related_indicator = fields.TypedField("Related_Indicator", RelatedIndicator, multiple=True, key_name="related_indicators")
def __init__(self, related_indicators=None, scope=None):
super(RelatedIndicators, self).__init__(scope, related_indicators)
class Indicator(stix.BaseCoreComponent):
- """Implementation of the STIX ``IndicatorType``.
+ """Implementation of the STIX Indicator.
Args:
id_ (optional): An identifier. If ``None``, a value will be generated
- via ``stix.utils.create_id()``. If set, this will unset the
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
``idref`` property.
idref (optional): An identifier reference. If set this will unset the
``id_`` property.
@@ -178,6 +177,25 @@ class Indicator(stix.BaseCoreComponent):
_ALL_VERSIONS = ("2.0", "2.0.1", "2.1", "2.1.1")
_ALLOWED_COMPOSITION_OPERATORS = ('AND', 'OR')
_ID_PREFIX = "indicator"
+ _try_cast = False
+
+ producer = fields.TypedField("Producer", InformationSource)
+ observable = fields.TypedField("Observable", Observable)
+ indicator_types = VocabField("Type", IndicatorType, multiple=True, key_name="indicator_types")
+ confidence = fields.TypedField("Confidence", Confidence)
+ indicated_ttps = fields.TypedField("Indicated_TTP", RelatedTTP, multiple=True, key_name="indicated_ttps")
+ test_mechanisms = fields.TypedField("Test_Mechanisms", TestMechanisms)
+ alternative_id = fields.TypedField("Alternative_ID", multiple=True)
+ suggested_coas = fields.TypedField("Suggested_COAs", SuggestedCOAs)
+ sightings = fields.TypedField("Sightings", Sightings)
+ composite_indicator_expression = fields.TypedField("Composite_Indicator_Expression", "stix.indicator.CompositeIndicatorExpression")
+ kill_chain_phases = fields.TypedField("Kill_Chain_Phases", KillChainPhasesReference)
+ valid_time_positions = fields.TypedField("Valid_Time_Position", ValidTime, multiple=True, key_name="valid_time_positions")
+ related_indicators = fields.TypedField("Related_Indicators", RelatedIndicators)
+ related_campaigns = fields.TypedField("Related_Campaigns", type_="stix.indicator.RelatedCampaignRefs")
+ likely_impact = fields.TypedField("Likely_Impact", Statement)
+ negate = fields.TypedField("negate")
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -191,124 +209,115 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.producer = None
- self.observables = None
+ self.observable = None
self.indicator_types = IndicatorTypes()
- self.confidence = None
- self.indicated_ttps = _IndicatedTTPs()
self.test_mechanisms = TestMechanisms()
self.alternative_id = None
self.suggested_coas = SuggestedCOAs()
self.sightings = Sightings()
self.composite_indicator_expression = None
- self.handling = None
self.kill_chain_phases = KillChainPhasesReference()
- self.valid_time_positions = _ValidTimePositions()
- self.related_indicators = None
+ self.related_indicators = RelatedIndicators()
self.related_campaigns = RelatedCampaignRefs()
self.observable_composition_operator = "OR"
- self.likely_impact = None
- self.negate = None
self.related_packages = RelatedPackageRefs()
@property
- def producer(self):
- """Contains information about the source of the :class:`Indicator`.
+ def observables(self):
+ """A list of ``cybox.core.Observable`` instances. This can be set to
+ a single object instance or a list of objects.
- Default Value: ``None``
+ Note:
+ If only one Observable is set, this property will return a list
+ with the ``observable`` property.
- Returns:
- An instance of
- :class:`stix.common.information_source.InformationSource`
+ If multiple ``cybox.core.Observable`` this property will return
+ Observables under the ``cybox.core.ObservableComposition``.
- Raises:
- ValueError: If set to a value that is not ``None`` and not an
- instance of
- :class:`stix.common.information_source.InformationSource`
+ Access to the top level ``cybox.core.Observable`` is made via
+ ``observable`` property.
- """
- return self._producer
+ Default Value:
+ Empty ``list``.
- @producer.setter
- def producer(self, value):
- self._set_var(InformationSource, try_cast=False, producer=value)
+ Returns:
+ A ``list`` of ``cybox.core.Observable`` instances.
- @property
- def observable(self):
- """A convenience property for accessing or setting the only
- ``cybox.core.Observable`` instance held by this Indicator.
+ """
+ if not self.observable:
+ return []
+ elif self.observable.observable_composition:
+ return self.observable.observable_composition.observables
- Default Value: Empty ``list``.
+ # self.observable is defined and not a composition.
+ return [self.observable]
- Setting this property results in the ``observables`` property being
- reinitialized to an empty ``list`` and appending the input value,
- resulting in a ``list`` containing one value.
+ @observables.setter
+ def observables(self, value):
+ """
+ The method will automatically create a top ``cybox.core.Observable`` and
+ append all ``cybox.core.Observable`` using ``observable_composition``
+ property when a ``list`` is given with length greater than 1.
Note:
- If the ``observables`` list contains more than one item, this
- property will only return the first item in the list.
+ The top level ``cybox.core.Observable`` will set the ``operator``
+ property for the ``cybox.core.ObservableComposition`` via the
+ ``observable_composition_operator`` property. The value of
+ ``operator`` can be changed via ``observable_composition_operator``
+ property. By default, the composition layer will be set to ``"OR"``.
- Returns:
- An instance of ``cybox.core.Observable``.
+ Args:
+ value: A ``list`` of ``cybox.core.Observable`` instances or a single
+ ``cybox.core.Observable`` instance.
Raises:
ValueError: If set to a value that cannot be converted to an
instance of ``cybox.core.Observable``.
-
-
"""
- if self.observables:
- return self.observables[0]
- else:
- return None
-
- @observable.setter
- def observable(self, observable):
- self._observables = _Observables(observable)
+ if not value:
+ return
- @property
- def observables(self):
- """A list of ``cybox.core.Observable`` instances. This can be set to
- a single object instance or a list of objects.
+ if isinstance(value, Observable):
+ self.observable = value
- Note:
- If the input value or values are not instance(s) of
- ``cybox.core.Observable``, an attempt will be made to
- convert the value to an instance of ``cybox.core.Observable``.
+ elif utils.is_sequence(value):
+ if len(value) == 1:
+ self.add_observable(value[0])
+ return
- Default Value: Empty ``list``
+ observable_comp = ObservableComposition()
+ observable_comp.operator = self.observable_composition_operator
- Returns:
- A ``list`` of ``cybox.core.Observable`` instances.
+ for element in value:
+ observable_comp.add(element)
- Raises:
- ValueError: If set to a value that cannot be converted to an
- instance of ``cybox.core.Observable``.
+ self.observable = Observable()
+ self.observable.observable_composition = observable_comp
- """
- return self._observables
-
- @observables.setter
- def observables(self, value):
- self._observables = _Observables(value)
+ def set_observables(self, value):
+ self.observables = value
def add_observable(self, observable):
- """Adds an observable to the ``observables`` list property of the
+ """Adds an observable to the ``observable`` property of the
:class:`Indicator`.
If the `observable` parameter is ``None``, no item will be added
- to the ``observables`` list.
+ to the ``observable`` property.
Note:
The STIX Language dictates that an :class:`Indicator` can have only
- one ``Observable`` under it. Because of this, the ``to_xml()``
- method will convert the ``observables`` list into an
- ``cybox.core.ObservableComposition`` instance, in which each item
- in the ``observables`` list will be added to the composition. By
+ one ``Observable`` under it. Because of this, when a user adds
+ another ``Observable`` a new, empty ``Observable`` will be crated
+ and append the existing and new ``observable`` using the
+ ``ObservableComposition`` property. To access the top level
+ ``Observable`` can be achieved by the ``observable`` property .By
default, the ``operator`` of the composition layer will be set to
``"OR"``. The ``operator`` value can be changed via the
``observable_composition_operator`` property.
+ Setting ``observable`` or ``observables`` with re-initialize the
+ property and lose all ``Observable`` in the composition layer.
+
Args:
observable: An instance of ``cybox.core.Observable`` or an object
type that can be converted into one.
@@ -319,33 +328,28 @@ def add_observable(self, observable):
instance of ``cybox.core.Observable``.
"""
- self.observables.append(observable)
-
- @property
- def alternative_id(self):
- """An alternative identifi er for this :class:`Indicator`
+ if not observable:
+ return
- This property can be set to a single string identifier or a list of
- identifiers. If set to a single object, the object will be inserted
- into an empty list internally.
+ # Sets the first observable.
+ elif not self.observable:
+ self.observable = observable
- Default Value: Empty ``list``
+ # When another is inserted. A "root" Observable is created and the
+ # user's Observables are appended to the composition.
+ elif not self.observable.observable_composition:
+ observable_comp = ObservableComposition()
+ observable_comp.operator = self.observable_composition_operator
- Returns:
- A list of alternative ids.
+ observable_comp.add(self.observable)
+ observable_comp.add(observable)
- """
- return self._alternative_id
+ self.observable = Observable()
+ self.observable.observable_composition = observable_comp
- @alternative_id.setter
- def alternative_id(self, value):
- self._alternative_id = []
- if not value:
- return
- elif utils.is_sequence(value):
- self._alternative_id.extend(x for x in value if x)
+ # Keep appending to "root" Observable.
else:
- self._alternative_id.append(value)
+ self.observable.observable_composition.add(observable)
def add_alternative_id(self, value):
"""Adds an alternative id to the ``alternative_id`` list property.
@@ -362,28 +366,6 @@ def add_alternative_id(self, value):
return
self.alternative_id.append(value)
-
- @property
- def valid_time_positions(self):
- """A list of valid time positions for this :class:`Indicator`.
-
- This property can be set to a single instance or a list of
- :class:`stix.indicator.valid_time.ValidTime` instances. If set to a
- single instance, that object is converted into a list containing
- one item.
-
- Default Value: Empty ``list``
-
- Returns:
- A list of
- :class:`stix.indicator.valid_time.ValidTime` instances.
-
- """
- return self._valid_time_positions
-
- @valid_time_positions.setter
- def valid_time_positions(self, value):
- self._valid_time_positions = _ValidTimePositions(value)
def add_valid_time_position(self, value):
"""Adds an valid time position to the ``valid_time_positions`` property
@@ -398,36 +380,9 @@ def add_valid_time_position(self, value):
Raises:
ValueError: If the `value` argument is not an instance of
:class:`stix.indicator.valid_time.ValidTime`.
- """
- self.valid_time_positions.append(value)
-
- @property
- def indicator_types(self):
- """A list of indicator types for this :class:`Indicator`.
-
- This property can be set to lists or single instances of ``str``
- or :class:`stix.common.vocabs.VocabString` or an instance
- of :class:`IndicatorTypes`.
-
- Note:
- If an instance of ``str`` is passed in (or a ``list`` containing
- ``str`` values) an attempt will be made to convert that string
- value to an instance of :class:`stix.common.vocabs.IndicatorType`.
-
- Default Value: An empty ``IndicatorTypes`` instance.
-
- See Also:
- Documentation for :class:`IndicatorTypes`.
-
- Returns:
- An instance of ``IndicatorTypes``.
"""
- return self._indicator_types
-
- @indicator_types.setter
- def indicator_types(self, value):
- self._indicator_types = IndicatorTypes(value)
+ self.valid_time_positions.append(value)
def add_indicator_type(self, value):
"""Adds a value to the ``indicator_types`` list property.
@@ -451,45 +406,6 @@ def add_indicator_type(self, value):
"""
self.indicator_types.append(value)
- @property
- def confidence(self):
- """The confidence for this :class:`Indicator`.
-
- This property can be set to an instance of ``str``,
- :class:`stix.common.vocabs.VocabString`, or
- :class:`stix.common.confidence.Confidence`.
-
- Default Value: ``None``
-
- Note:
- If set to an instance of ``str`` or
- :class:`stix.common.vocabs.VocabString`, that value will be wrapped
- in an instance of
- :class:`stix.common.confidence.Confidence`.
-
- Returns:
- An instance of of
- :class:`stix.common.confidence.Confidence`.
-
- Raises:
- ValueError: If set to a ``str`` value that cannot be converted into
- an instance of :class:`stix.common.confidence.Confidence`.
-
- """
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._set_var(Confidence, confidence=value)
-
- @property
- def indicated_ttps(self):
- return self._indicated_ttps
-
- @indicated_ttps.setter
- def indicated_ttps(self, value):
- self._indicated_ttps = _IndicatedTTPs(value)
-
def add_indicated_ttp(self, v):
"""Adds an Indicated TTP to the ``indicated_ttps`` list property
of this :class:`Indicator`.
@@ -516,14 +432,6 @@ def add_indicated_ttp(self, v):
"""
self.indicated_ttps.append(v)
- @property
- def test_mechanisms(self):
- return self._test_mechanisms
-
- @test_mechanisms.setter
- def test_mechanisms(self, value):
- self._test_mechanisms = TestMechanisms(value)
-
def add_test_mechanism(self, tm):
"""Adds an Test Mechanism to the ``test_mechanisms`` list property
of this :class:`Indicator`.
@@ -551,25 +459,6 @@ def add_test_mechanism(self, tm):
"""
self.test_mechanisms.append(tm)
- @property
- def handling(self):
- return self._handling
-
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, handling=value)
-
- @property
- def related_indicators(self):
- return self._related_indicators
-
- @related_indicators.setter
- def related_indicators(self, value):
- if isinstance(value, RelatedIndicators):
- self._related_indicators = value
- else:
- self._related_indicators = RelatedIndicators(value)
-
def add_related_indicator(self, indicator):
"""Adds an Related Indicator to the ``related_indicators`` list
property of this :class:`Indicator`.
@@ -603,18 +492,35 @@ def add_related_indicator(self, indicator):
"""
self.related_indicators.append(indicator)
- @property
- def related_campaigns(self):
- return self._related_campaigns
+ def add_related_campaign(self, value):
+ """Adds a Related Campaign to this Indicator.
- @related_campaigns.setter
- def related_campaigns(self, value):
- if isinstance(value, RelatedCampaignRefs):
- self._related_campaigns = value
- else:
- self._related_campaigns = RelatedCampaignRefs(value)
+ The `value` parameter must be an instance of :class:`.RelatedCampaignRef`
+ or :class:`.CampaignRef`.
- def add_related_campaign(self, value):
+ If the `value` parameter is ``None``, no item wil be added to the
+ ``related_campaigns`` collection.
+
+ Calling this method is the same as calling ``append()`` on the
+ ``related_campaigns`` property.
+
+ See Also:
+ The :class:`.RelatedCampaignRef` documentation.
+
+ Note:
+ If the `value` parameter is not an instance of
+ :class:`.RelatedCampaignRef` an attempt will be made to convert it
+ to one.
+
+ Args:
+ value: An instance of :class:`.RelatedCampaignRef` or
+ :class:`.Campaign`.
+
+ Raises:
+ ValueError: If the `value` parameter cannot be converted into
+ an instance of :class:`.RelatedCampaignRef`
+
+ """
self.related_campaigns.append(value)
@property
@@ -625,36 +531,16 @@ def observable_composition_operator(self):
def observable_composition_operator(self, value):
if value in self._ALLOWED_COMPOSITION_OPERATORS:
self._observable_composition_operator = value
+
+ if self.observable and self.observable.observable_composition:
+ self.observable.observable_composition.operator = value
+
return
error = "observable_composition_operator must one of {0}"
error = error.format(self._ALLOWED_COMPOSITION_OPERATORS)
raise ValueError(error)
- @property
- def likely_impact(self):
- return self._likely_impact
-
- @likely_impact.setter
- def likely_impact(self, value):
- self._set_var(Statement, likely_impact=value)
-
- @property
- def negate(self):
- return self._negate
-
- @negate.setter
- def negate(self, value):
- self._negate = utils.xml_bool(value)
-
- @property
- def kill_chain_phases(self):
- return self._kill_chain_phases
-
- @kill_chain_phases.setter
- def kill_chain_phases(self, value):
- self._kill_chain_phases = KillChainPhasesReference(value)
-
def add_kill_chain_phase(self, value):
"""Add a new Kill Chain Phase reference to this Indicator.
@@ -666,14 +552,6 @@ def add_kill_chain_phase(self, value):
"""
self.kill_chain_phases.append(value)
- @property
- def related_packages(self):
- return self._related_packages
-
- @related_packages.setter
- def related_packages(self, value):
- self._related_packages = RelatedPackageRefs(value)
-
def add_related_package(self, value):
self.related_packages.append(value)
@@ -846,135 +724,35 @@ def add_object(self, object_):
observable = Observable(object_)
self.add_observable(observable)
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(Indicator, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- return_obj.negate = True if self.negate else None
-
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.indicator_types:
- return_obj.Type = self.indicator_types.to_obj(ns_info=ns_info)
- if self.indicated_ttps:
- return_obj.Indicated_TTP = self.indicated_ttps.to_obj(ns_info=ns_info)
- if self.producer:
- return_obj.Producer = self.producer.to_obj(ns_info=ns_info)
- if self.test_mechanisms:
- return_obj.Test_Mechanisms = self.test_mechanisms.to_obj(ns_info=ns_info)
- if self.likely_impact:
- return_obj.Likely_Impact = self.likely_impact.to_obj(ns_info=ns_info)
- if self.alternative_id:
- return_obj.Alternative_ID = self.alternative_id
- if self.valid_time_positions:
- return_obj.Valid_Time_Position = self.valid_time_positions.to_obj(ns_info=ns_info)
- if self.suggested_coas:
- return_obj.Suggested_COAs = self.suggested_coas.to_obj(ns_info=ns_info)
- if self.sightings:
- return_obj.Sightings = self.sightings.to_obj(ns_info=ns_info)
- if self.composite_indicator_expression:
- return_obj.Composite_Indicator_Expression = self.composite_indicator_expression.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.kill_chain_phases:
- return_obj.Kill_Chain_Phases = self.kill_chain_phases.to_obj(ns_info=ns_info)
- if self.related_indicators:
- return_obj.Related_Indicators = self.related_indicators.to_obj(ns_info=ns_info)
- if self.related_campaigns:
- return_obj.Related_Campaigns = self.related_campaigns.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
- if self.observables:
- if len(self.observables) > 1:
- root_observable = self._merge_observables(self.observables)
- else:
- root_observable = self.observables[0]
- return_obj.Observable = root_observable.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(Indicator, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class):
- return_obj.negate = obj.negate
- return_obj.producer = InformationSource.from_obj(obj.Producer)
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.sightings = Sightings.from_obj(obj.Sightings)
- return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.Composite_Indicator_Expression)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.Kill_Chain_Phases)
- return_obj.related_indicators = RelatedIndicators.from_obj(obj.Related_Indicators)
- return_obj.likely_impact = Statement.from_obj(obj.Likely_Impact)
- return_obj.indicator_types = IndicatorTypes.from_obj(obj.Type)
- return_obj.test_mechanisms = TestMechanisms.from_obj(obj.Test_Mechanisms)
- return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.Suggested_COAs)
- return_obj.alternative_id = obj.Alternative_ID
- return_obj.indicated_ttps = _IndicatedTTPs.from_obj(obj.Indicated_TTP)
- return_obj.valid_time_positions = _ValidTimePositions.from_obj(obj.Valid_Time_Position)
- return_obj.observable = Observable.from_obj(obj.Observable)
- return_obj.related_campaigns = RelatedCampaignRefs.from_obj(obj.Related_Campaigns)
- return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages)
-
- return return_obj
-
- def to_dict(self):
- skip = ('observables', 'observable_composition_operator', 'negate')
- d = utils.to_dict(self, skip=skip)
+ def _finalize_obj(self, entity_obj):
+ """Omits the `negate` field if it is not equal to True.
+ """
+ if self.negate:
+ entity_obj.negate = True
+ elif hasattr(entity_obj, 'negate'):
+ entity_obj.negate = None
+ def _finalize_dict(self, entity_dict):
+ """Omits the `negate` field if it is not equal to True.
+ """
if self.negate:
- d['negate'] = True
+ entity_dict['negate'] = True
+ elif 'negate' in entity_dict:
+ del entity_dict['negate']
- if self.observables:
- if len(self.observables) == 1:
- d['observable'] = self.observables[0].to_dict()
- else:
- composite_observable = self._merge_observables(self.observables)
- d['observable'] = composite_observable.to_dict()
- return d
+def check_operator(composite_indicator_exp, value):
+ allowed = CompositeIndicatorExpression.OPERATORS
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(Indicator, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get
- return_obj.negate = get('negate')
- return_obj.alternative_id = get('alternative_id')
- return_obj.indicated_ttps = _IndicatedTTPs.from_dict(get('indicated_ttps'))
- return_obj.test_mechanisms = TestMechanisms.from_list(get('test_mechanisms'))
- return_obj.suggested_coas = SuggestedCOAs.from_dict(get('suggested_coas'))
- return_obj.sightings = Sightings.from_dict(get('sightings'))
- return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(get('composite_indicator_expression'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(get('kill_chain_phases'))
- return_obj.related_indicators = RelatedIndicators.from_dict(get('related_indicators'))
- return_obj.likely_impact = Statement.from_dict(get('likely_impact'))
- return_obj.indicator_types = IndicatorTypes.from_list(get('indicator_types'))
- return_obj.confidence = Confidence.from_dict(get('confidence'))
- return_obj.valid_time_positions = _ValidTimePositions.from_dict(get('valid_time_positions'))
- return_obj.observable = Observable.from_dict(get('observable'))
- return_obj.producer = InformationSource.from_dict(get('producer'))
- return_obj.related_campaigns = RelatedCampaignRefs.from_dict(get('related_campaigns'))
- return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages'))
-
- return return_obj
-
-
-class CompositeIndicatorExpression(stix.EntityList):
+ if not value:
+ raise ValueError("operator must not be None or empty")
+ elif value not in allowed:
+ raise ValueError("operator must be one of: %s" % allowed)
+ else:
+ return
+
+
+class CompositeIndicatorExpression(entities.EntityList):
"""Implementation of the STIX ``CompositeIndicatorExpressionType``.
The ``CompositeIndicatorExpression`` class implements methods found on
@@ -1016,87 +794,58 @@ class CompositeIndicatorExpression(stix.EntityList):
_binding = indicator_binding
_binding_class = indicator_binding.CompositeIndicatorExpressionType
_namespace = 'http://stix.mitre.org/Indicator-2'
- _contained_type = Indicator
- _binding_var = "Indicator"
- _inner_name = "indicators"
-
+
OP_AND = "AND"
OP_OR = "OR"
OPERATORS = (OP_AND, OP_OR)
-
+ operator = fields.TypedField("operator", preset_hook=check_operator)
+ indicator = fields.TypedField(
+ name="Indicator",
+ type_=Indicator,
+ multiple=True,
+ key_name="indicators"
+ )
+
+ # TODO (bworrell): Change this to *args, **kwargs to get around the weirdness
+ # that occurs when creating with kwarg and arglist.
+ # E.g, CompositeIndicatorExpression(operator="AND", arg1, arg2, arg3)
+ # will raise an error.
def __init__(self, operator="OR", *args):
super(CompositeIndicatorExpression, self).__init__(*args)
self.operator = operator
- @property
- def operator(self):
- return self._operator
-
- @operator.setter
- def operator(self, value):
- if not value:
- raise ValueError("operator must not be None or empty")
- elif value not in self.OPERATORS:
- raise ValueError("operator must be one of: %s" % (self.OPERATORS,))
- else:
- self._operator = value
-
- def __nonzero__(self):
- return super(CompositeIndicatorExpression, self).__nonzero__()
-
- def to_obj(self, return_obj=None, ns_info=None):
- list_obj = super(CompositeIndicatorExpression, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- list_obj.operator = self.operator
- return list_obj
-
- def to_dict(self):
- d = super(CompositeIndicatorExpression, self).to_dict()
- if self.operator:
- d['operator'] = self.operator
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if return_obj is None:
- return_obj = cls()
- super(CompositeIndicatorExpression, cls).from_obj(obj, return_obj=return_obj)
- return_obj.operator = obj.operator
- return return_obj
+class _RelatedCampaignRefList(typedlist.TypedList):
+ def __init__(self, *args):
+ super(_RelatedCampaignRefList, self).__init__(type=RelatedCampaignRef, *args)
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if return_obj is None:
- return_obj = cls()
+ def _fix_value(self, value):
+ from stix.campaign import Campaign
- super(CompositeIndicatorExpression, cls).from_dict(dict_repr, return_obj=return_obj)
- return_obj.operator = dict_repr.get('operator')
- return return_obj
+ if isinstance(value, Campaign) and value.id_:
+ return RelatedCampaignRef(CampaignRef(idref=value.id_))
+
+ msg = "Cannot insert object of type '%s' into '%s'"
+ msg = msg % (type(value), self.__class__.__name__)
+ raise TypeError(msg)
class RelatedCampaignRefs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = _binding.RelatedCampaignReferencesType
- _binding_var = 'Related_Campaign'
- _contained_type = RelatedCampaignRef
- _inner_name = "related_campaigns"
+
+ related_campaign = fields.TypedField(
+ name="Related_Campaign",
+ type_=RelatedCampaignRef,
+ multiple=True,
+ key_name="related_campaigns",
+ listfunc=_RelatedCampaignRefList
+ )
def __init__(self, related_campaign_refs=None, scope=None):
super(RelatedCampaignRefs, self).__init__(scope, related_campaign_refs)
- def _fix_value(self, value):
- from stix.campaign import Campaign
-
- if isinstance(value, Campaign) and value.id_:
- return RelatedCampaignRef(CampaignRef(idref=value.id_))
- else:
- return super(RelatedCampaignRefs, self)._fix_value(value)
-
# NOT ACTUAL STIX TYPES!
class IndicatorTypes(stix.TypedList):
@@ -1118,7 +867,7 @@ class IndicatorTypes(stix.TypedList):
>>> itypes = IndicatorTypes()
>>> type_ = IndicatorType(IndicatorType.TERM_IP_WATCHLIST)
>>> itypes.append(type_)
- >>> print len(itypes)
+ >>> print(len(itypes))
1
Add a string value:
@@ -1128,7 +877,7 @@ class IndicatorTypes(stix.TypedList):
>>> type(IndicatorType.TERM_IP_WATCHLIST)
>>> itypes.append(IndicatorType.TERM_IP_WATCHLIST)
- >>> print len(itypes)
+ >>> print(len(itypes))
1
Args:
@@ -1141,11 +890,3 @@ class IndicatorTypes(stix.TypedList):
def _fix_value(self, value):
return IndicatorType(value)
-
-
-class _IndicatedTTPs(stix.TypedList):
- _contained_type = RelatedTTP
-
-
-class _Observables(stix.TypedList):
- _contained_type = Observable
diff --git a/stix/indicator/sightings.py b/stix/indicator/sightings.py
index 7af12240..c110513c 100644
--- a/stix/indicator/sightings.py
+++ b/stix/indicator/sightings.py
@@ -1,12 +1,14 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
-import stix.utils as utils
-from stix.common import (
- GenericRelationshipList, RelatedObservable, StructuredText, Confidence,
- InformationSource
-)
+from stix import utils
+from stix.common import (GenericRelationshipList, RelatedObservable,
+ StructuredText, Confidence, InformationSource)
+from stix.common.datetimewithprecision import validate_precision
+
import stix.bindings.indicator as indicator_binding
@@ -15,166 +17,49 @@ class Sighting(stix.Entity):
_binding = indicator_binding
_binding_class = _binding.SightingType
+ timestamp = fields.DateTimeField("timestamp")
+ timestamp_precision = fields.TypedField("timestamp_precision", preset_hook=validate_precision)
+ description = fields.TypedField("Description", StructuredText)
+ source = fields.TypedField("Source", InformationSource)
+ reference = fields.TypedField("Reference")
+ confidence = fields.TypedField("Confidence", Confidence)
+ related_observables = fields.TypedField("Related_Observables", type_="stix.indicator.sightings.RelatedObservables")
+
def __init__(self, timestamp=None, timestamp_precision=None, description=None):
+ super(Sighting, self).__init__()
+
self.timestamp = timestamp or utils.dates.now()
self.timestamp_precision = timestamp_precision
self.description = description
self.source = None
self.reference = None
self.confidence = None
- self.related_observables = RelatedObservables()
-
- @property
- def timestamp(self):
- return self._timestamp
-
- @timestamp.setter
- def timestamp(self, value):
- self._timestamp = utils.dates.parse_value(value)
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def source(self):
- return self._source
-
- @source.setter
- def source(self, value):
- self._set_var(InformationSource, try_cast=False, source=value)
-
- @property
- def confidence(self):
- return self._confidence
-
- @confidence.setter
- def confidence(self, value):
- self._set_var(Confidence, confidence=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Sighting, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.timestamp = utils.dates.serialize_value(self.timestamp)
- return_obj.timestamp_precision = self.timestamp_precision
- return_obj.Reference = self.reference
-
- if self.source:
- return_obj.Source = self.source.to_obj(ns_info=ns_info)
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.related_observables:
- return_obj.Related_Observables = self.related_observables.to_obj(ns_info=ns_info)
-
- return return_obj
-
- def to_dict(self):
- return super(Sighting, self).to_dict()
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if return_obj is None:
- return_obj = cls()
-
- return_obj.timestamp = obj.timestamp
- return_obj.timestamp_precision = obj.timestamp_precision
- return_obj.source = InformationSource.from_obj(obj.Source)
- return_obj.reference = obj.Reference
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.related_observables = RelatedObservables.from_obj(obj.Related_Observables)
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if return_obj is None:
- return_obj = cls()
-
- return_obj.timestamp = d.get('timestamp')
- return_obj.timestamp_precision = d.get('timestamp_precision')
- return_obj.source = InformationSource.from_dict(d.get('source'))
- return_obj.reference = d.get('reference')
- return_obj.confidence = Confidence.from_dict(d.get('confidence'))
- return_obj.description = StructuredText.from_dict(d.get('description'))
- return_obj.related_observables = RelatedObservables.from_dict(d.get('related_observables'))
- return return_obj
class Sightings(stix.EntityList):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = _binding.SightingsType
- _contained_type = Sighting
- _binding_var = "Sighting"
- _inner_name = "sightings"
-
+
+ sightings_count = fields.TypedField("sightings_count")
+ sighting = fields.TypedField("Sighting", Sighting, multiple=True, key_name="sightings")
+
def __init__(self, sightings_count=None, *args):
super(Sightings, self).__init__(*args)
self.sightings_count = sightings_count
def __nonzero__(self):
- return super(Sightings, self).__nonzero__() or bool(self.sightings_count)
-
- @property
- def sightings_count(self):
- return self._sightings_count
-
- @sightings_count.setter
- def sightings_count(self, value):
- self._set_var(int, sightings_count=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- list_obj = super(Sightings, self).to_obj(return_obj=return_obj, ns_info=ns_info)
- list_obj.sightings_count = self.sightings_count
- return list_obj
-
- def to_dict(self):
- d = super(Sightings, self).to_dict()
- if self.sightings_count:
- d['sightings_count'] = self.sightings_count
- return d
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if return_obj is None:
- return_obj = cls()
-
- super(Sightings, cls).from_obj(obj, return_obj=return_obj)
- return_obj.sightings_count = obj.sightings_count
- return return_obj
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if return_obj is None:
- return_obj = cls()
-
- super(Sightings, cls).from_dict(dict_repr, return_obj=return_obj)
- return_obj.sightings_count = dict_repr.get('sightings_count')
- return return_obj
+ return super(Sightings, self).__nonzero__() or (self.sightings_count is not None)
class RelatedObservables(GenericRelationshipList):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = _binding.RelatedObservablesType
- _binding_var = "Related_Observable"
- _contained_type = RelatedObservable
- _inner_name = "observables"
+
+ observable = fields.TypedField(
+ name="Related_Observable",
+ type_=RelatedObservable,
+ multiple=True,
+ key_name="observables"
+ )
diff --git a/stix/indicator/test_mechanism.py b/stix/indicator/test_mechanism.py
index f339b21c..1f09b6ea 100644
--- a/stix/indicator/test_mechanism.py
+++ b/stix/indicator/test_mechanism.py
@@ -1,128 +1,69 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# external
+from mixbox import fields, entities
+
+# internal
import stix
from stix.common import InformationSource, Statement
+
+# bindings
import stix.bindings.indicator as indicator_binding
class _BaseTestMechanism(stix.Entity):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
- _binding_class = indicator_binding.TestMechanismType()
-
+ _binding_class = indicator_binding.TestMechanismType
+
+ id_ = fields.IdField("id")
+ idref = fields.IdField("idref")
+ efficacy = fields.TypedField("Efficacy", Statement)
+ producer = fields.TypedField("Producer", InformationSource)
+
def __init__(self, id_=None, idref=None):
+ super(_BaseTestMechanism, self).__init__()
+
self.id_ = id_
self.idref = idref
self.efficacy = None
self.producer = None
-
- @property
- def efficacy(self):
- return self._efficacy
-
- @efficacy.setter
- def efficacy(self, value):
- self._set_var(Statement, efficacy=value)
-
- @property
- def producer(self):
- return self._producer
-
- @producer.setter
- def producer(self, value):
- self._set_var(InformationSource, try_cast=False, producer=value)
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- from stix.extensions.test_mechanism.snort_test_mechanism import SnortTestMechanism # noqa
- from stix.extensions.test_mechanism.open_ioc_2010_test_mechanism import OpenIOCTestMechanism # noqa
- from stix.extensions.test_mechanism.yara_test_mechanism import YaraTestMechanism # noqa
- from stix.extensions.test_mechanism.generic_test_mechanism import GenericTestMechanism # noqa
-
- if not return_obj:
- klass = _BaseTestMechanism.lookup_class(obj.xml_type)
- return_obj = klass.from_obj(obj)
- else:
- return_obj.id_ = obj.id
- return_obj.idref = obj.idref
- return_obj.efficacy = Statement.from_obj(obj.Efficacy)
- return_obj.producer = InformationSource.from_obj(obj.Producer)
-
- return return_obj
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(_BaseTestMechanism, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.idref = self.idref
- return_obj.xsi_type = self._XSI_TYPE
-
- if self.efficacy:
- return_obj.Efficacy = self.efficacy.to_obj(ns_info=ns_info)
- if self.producer:
- return_obj.Producer = self.producer.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @staticmethod
- def lookup_class(xsi_type):
- if not xsi_type:
- raise ValueError("xsi:type is required")
- for (k, v) in _EXTENSION_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- raise ValueError("Unregistered xsi:type %s" % xsi_type)
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
-
- from stix.extensions.test_mechanism.snort_test_mechanism import SnortTestMechanism # noqa
- from stix.extensions.test_mechanism.open_ioc_2010_test_mechanism import OpenIOCTestMechanism # noqa
- from stix.extensions.test_mechanism.yara_test_mechanism import YaraTestMechanism # noqa
- from stix.extensions.test_mechanism.generic_test_mechanism import GenericTestMechanism # noqa
-
- if not return_obj:
- klass = _BaseTestMechanism.lookup_class(d.get('xsi:type'))
- return_obj = klass.from_dict(d)
- else:
- return_obj.id_ = d.get('id')
- return_obj.idref = d.get('idref')
- return_obj.efficacy = Statement.from_dict(d.get('efficacy'))
- return_obj.producer = InformationSource.from_dict(d.get('producer'))
-
- return return_obj
-
+ def to_obj(self, ns_info=None):
+ obj = super(_BaseTestMechanism, self).to_obj(ns_info=ns_info)
+ obj.xsi_type = self._XSI_TYPE
+ return obj
+
def to_dict(self):
d = super(_BaseTestMechanism, self).to_dict()
d['xsi:type'] = self._XSI_TYPE # added by subclass
return d
+class TestMechanismFactory(entities.EntityFactory):
+ @classmethod
+ def entity_class(self, key):
+ import stix.extensions.test_mechanism.snort_test_mechanism # noqa
+ import stix.extensions.test_mechanism.open_ioc_2010_test_mechanism # noqa
+ import stix.extensions.test_mechanism.yara_test_mechanism # noqa
+ import stix.extensions.test_mechanism.generic_test_mechanism # noqa
+ return stix.lookup_extension(key)
+
+
class TestMechanisms(stix.EntityList):
_binding = indicator_binding
_namespace = 'http://stix.mitre.org/Indicator-2'
_binding_class = _binding.TestMechanismsType
- _contained_type = _BaseTestMechanism
- _binding_var = "Test_Mechanism"
- _inner_name = "test_mechanisms"
- _dict_as_list = True
+ test_mechanism = fields.TypedField(
+ name="Test_Mechanism",
+ type_=_BaseTestMechanism,
+ factory=TestMechanismFactory,
+ multiple=True
+ )
-#: Mapping of test mechanism extension types to classes
-_EXTENSION_MAP = {}
-def add_extension(cls):
- _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+# Backwards compatibility
+add_extension = stix.add_extension
diff --git a/stix/indicator/valid_time.py b/stix/indicator/valid_time.py
index c8348a5c..2514e4c9 100644
--- a/stix/indicator/valid_time.py
+++ b/stix/indicator/valid_time.py
@@ -1,76 +1,23 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix
from stix.common import DateTimeWithPrecision
import stix.bindings.indicator as indicator_binding
+from mixbox.entities import Entity
-class ValidTime(stix.Entity):
+class ValidTime(Entity):
_namespace = "http://stix.mitre.org/Indicator-2"
_binding = indicator_binding
_binding_class = _binding.ValidTimeType
-
+
+ start_time = fields.TypedField("Start_Time", DateTimeWithPrecision)
+ end_time = fields.TypedField("End_Time", DateTimeWithPrecision)
+
def __init__(self, start_time=None, end_time=None):
+ super(ValidTime, self).__init__()
self.start_time = start_time
self.end_time = end_time
-
- @property
- def start_time(self):
- return self._start_time
-
- @start_time.setter
- def start_time(self, value):
- self._set_var(DateTimeWithPrecision, start_time=value)
-
- @property
- def end_time(self):
- return self._end_time
-
- @end_time.setter
- def end_time(self, value):
- self._set_var(DateTimeWithPrecision, end_time=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(ValidTime, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.start_time:
- return_obj.Start_Time = self.start_time.to_obj(ns_info=ns_info)
- if self.end_time:
- return_obj.End_Time = self.end_time.to_obj(ns_info=ns_info)
-
- return return_obj
-
- def to_dict(self):
- return super(ValidTime, self).to_dict()
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if return_obj is None:
- return_obj = cls()
-
- return_obj.start_time = DateTimeWithPrecision.from_obj(obj.Start_Time)
- return_obj.end_time = DateTimeWithPrecision.from_obj(obj.End_Time)
- return return_obj
-
- @classmethod
- def from_dict(cls, d, return_obj=None):
- if not d:
- return None
- if return_obj is None:
- return_obj = cls()
-
- return_obj.start_time = DateTimeWithPrecision.from_dict(d.get('start_time'))
- return_obj.end_time = DateTimeWithPrecision.from_dict(d.get('end_time'))
-
- return return_obj
-
-
-# NOT AN ACTUAL STIX TYPE
-class _ValidTimePositions(stix.TypedList):
- _contained_type = ValidTime
diff --git a/stix/test/__init__.py b/stix/test/__init__.py
index b43ebb6d..94a03ffd 100644
--- a/stix/test/__init__.py
+++ b/stix/test/__init__.py
@@ -1,21 +1,60 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-import json
+import contextlib
+import functools
import itertools
+import json
+import warnings
import cybox.utils
+from mixbox.binding_utils import ExternalEncoding
+from mixbox.entities import NamespaceCollector
+from mixbox.vendor.six import iteritems, text_type
+
+from stix.utils import silence_warnings
+
+
+@contextlib.contextmanager
+def ctx_assert_warnings(self):
+ """Context manager for verifying that a block of code has raised a
+ warning.
-import stix.bindings as bindings
-from stix.utils import NamespaceInfo
+ """
+ with warnings.catch_warnings(record=True) as w:
+ # Raise all warnings
+ warnings.simplefilter('always')
+
+ # Return to caller
+ yield
+
+ # Assert that a warning was raised.
+ self.assertTrue(len(w) > 0)
+
+
+def assert_warnings(func):
+ """Test function decorator which asserts that a warning has been raised
+ during the execution of the test.
+
+ """
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ self = args[0]
+ with ctx_assert_warnings(self):
+ return func(*args, **kwargs)
+
+ return inner
def round_trip_dict(cls, dict_):
obj = cls.object_from_dict(dict_)
dict2 = cls.dict_from_object(obj)
+ api_obj = cls.from_dict(dict_)
+ dict2 = cls.to_dict(api_obj)
return dict2
+
def round_trip(o, output=False, list_=False):
""" Performs all eight conversions to verify import/export functionality.
@@ -34,8 +73,8 @@ def round_trip(o, output=False, list_=False):
klass = o.__class__
if output:
- print "Class: ", klass
- print "-" * 40
+ print("Class: ", klass)
+ print("-" * 40)
# 1. cybox.Entity -> dict/list
if list_:
@@ -48,7 +87,7 @@ def round_trip(o, output=False, list_=False):
if output:
print(json_string)
- print "-" * 40
+ print("-" * 40)
# Before parsing the JSON, make sure the cache is clear
cybox.utils.cache_clear()
@@ -63,30 +102,30 @@ def round_trip(o, output=False, list_=False):
o2 = klass.from_dict(d2)
# 5. Entity -> Bindings Object
- ns_info = NamespaceInfo()
+ ns_info = NamespaceCollector()
xobj = o2.to_obj(ns_info=ns_info)
try:
# 6. Bindings Object -> XML String
- xml_string = o2.to_xml(encoding=bindings.ExternalEncoding)
+ xml_string = o2.to_xml(encoding=ExternalEncoding)
- if not isinstance(xml_string, unicode):
- xml_string = xml_string.decode(bindings.ExternalEncoding)
+ if not isinstance(xml_string, text_type):
+ xml_string = xml_string.decode(ExternalEncoding)
except KeyError as ex:
- print str(ex)
+ print(str(ex))
ns_info.finalize()
- print ns_info.finalized_namespaces
+ print(ns_info.binding_namespaces)
raise ex
if output:
print(xml_string)
- print "-" * 40
+ print("-" * 40)
# Before parsing the XML, make sure the cache is clear
cybox.utils.cache_clear()
- #7. XML String -> Bindings Object
+ # 7. XML String -> Bindings Object
xobj2 = klass._binding.parseString(xml_string)
# 8. Bindings object -> cybox.Entity
@@ -94,6 +133,7 @@ def round_trip(o, output=False, list_=False):
return o3
+
class EntityTestCase(object):
"""A base class for testing STIX Entities"""
@@ -101,9 +141,10 @@ def setUp(self):
self.assertNotEqual(self.klass, None)
self.assertNotEqual(self._full_dict, None)
+ @silence_warnings
def test_round_trip_full_dict(self):
# Don't run this test on the base class
- if type(self) == type(EntityTestCase):
+ if type(self) is EntityTestCase:
return
dict2 = round_trip_dict(self.klass, self._full_dict)
@@ -112,39 +153,40 @@ def test_round_trip_full_dict(self):
def _combine(self, d):
items = itertools.chain(
- self._full_dict.iteritems(),
- d.iteritems()
+ iteritems(self._full_dict),
+ iteritems(d)
)
return dict(items)
+ @silence_warnings
def test_round_trip_full(self):
# Don't run this test on the base class
- if type(self) == type(EntityTestCase):
+ if type(self) is EntityTestCase:
return
ent = self.klass.from_dict(self._full_dict)
ent2 = round_trip(ent, output=True)
- #TODO: eventually we want to test the objects are the same, but for
- # now, just make sure there aren't any errors.
-
+ @silence_warnings
def _test_round_trip_dict(self, input):
dict2 = round_trip_dict(self.klass, input)
-
self.maxDiff = None
self.assertEqual(input, dict2)
+ @silence_warnings
def _test_partial_dict(self, partial):
d = self._combine(partial)
self._test_round_trip_dict(d)
class TypedListTestCase(object):
+
+ @silence_warnings
def test_round_trip_rt(self):
- if type(self) == type(TypedListTestCase):
+ if type(self) is TypedListTestCase:
return
obj = self.klass.from_dict(self._full_dict)
dict2 = obj.to_dict()
- self.assertEqual(self._full_dict, dict2)
\ No newline at end of file
+ self.assertEqual(self._full_dict, dict2)
diff --git a/stix/test/campaign_test.py b/stix/test/campaign_test.py
index 19f8a019..b7d29c96 100644
--- a/stix/test/campaign_test.py
+++ b/stix/test/campaign_test.py
@@ -1,9 +1,10 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import unittest
-from stix.test import EntityTestCase, TypedListTestCase, data_marking_test
+from stix.test import EntityTestCase, TypedListTestCase
+import stix.test.data_marking_test as data_marking_test
from stix.test.common import (
confidence_test, information_source_test, statement_test, related_test,
activity_test
@@ -21,18 +22,23 @@ class NamesTests(EntityTestCase, unittest.TestCase):
"Crazy Squirrels",
{
'value': "Medium",
- 'xsi:type':'stixVocabs:HighMediumLowVocab-1.0'
+ 'xsi:type': 'stixVocabs:HighMediumLowVocab-1.0'
}
]
}
+
class IntendedEffectsTests(TypedListTestCase, unittest.TestCase):
- klass = campaign._IntendedEffects
+ klass = campaign.Campaign
- _full_dict = [
+ _partial_dict = [
statement_test.StatementTests._full_dict
]
+ _full_dict = {
+ 'intended_effects': _partial_dict,
+ }
+
class RelatedTTPsTest(EntityTestCase, unittest.TestCase):
klass = campaign.RelatedTTPs
@@ -64,6 +70,7 @@ class RelatedIndicatorsTests(EntityTestCase, unittest.TestCase):
]
}
+
class AttributionTests(EntityTestCase, unittest.TestCase):
klass = campaign.Attribution
@@ -76,11 +83,13 @@ class AttributionTests(EntityTestCase, unittest.TestCase):
class AttributionListTests(TypedListTestCase, unittest.TestCase):
- klass = campaign._AttributionList
+ klass = campaign.Campaign
- _full_dict = [
- AttributionTests._full_dict
- ]
+ _full_dict = {
+ 'attribution': [
+ AttributionTests._full_dict
+ ]
+ }
class AssociatedCampaignsTests(EntityTestCase, unittest.TestCase):
@@ -94,12 +103,10 @@ class AssociatedCampaignsTests(EntityTestCase, unittest.TestCase):
}
-class ActivitiesTests(TypedListTestCase, unittest.TestCase):
- klass = campaign._Activities
+class ActivityTests(TypedListTestCase, unittest.TestCase):
+ klass = campaign.Activity
- _full_dict = [
- activity_test.ActivityTests._full_dict
- ]
+ _full_dict = activity_test.ActivityTests._full_dict
class CampaignTest(EntityTestCase, unittest.TestCase):
@@ -112,18 +119,18 @@ class CampaignTest(EntityTestCase, unittest.TestCase):
'description': 'A pretty novice set of actors.',
'short_description': 'novices',
'names': NamesTests._full_dict,
- 'intended_effects': IntendedEffectsTests._full_dict,
+ 'intended_effects': IntendedEffectsTests._partial_dict,
'status': {
'value': "Ongoing",
- 'xsi:type':'stixVocabs:CampaignStatusVocab-1.0'
+ 'xsi:type': 'stixVocabs:CampaignStatusVocab-1.0'
},
'related_ttps': RelatedTTPsTest._full_dict,
'related_incidents': RelatedIncidentsTests._full_dict,
'related_indicators': RelatedIndicatorsTests._full_dict,
- 'attribution': AttributionListTests._full_dict,
+ 'attribution': [AttributionTests._full_dict],
'associated_campaigns': AssociatedCampaignsTests._full_dict,
'confidence': confidence_test.ConfidenceTests._full_dict,
- 'activity': ActivitiesTests._full_dict,
+ 'activity': [ActivityTests._full_dict],
'information_source': information_source_test.InformationSourceTests._full_dict,
'handling': data_marking_test.MarkingTests._full_dict,
'related_packages': related_test.RelatedPackageRefsTests._full_dict
diff --git a/stix/test/coa_test.py b/stix/test/coa_test.py
index 7ade2353..98861537 100644
--- a/stix/test/coa_test.py
+++ b/stix/test/coa_test.py
@@ -3,10 +3,10 @@
import unittest
-from stix.test import EntityTestCase, data_marking_test
-from stix.test.common import (
- confidence_test, information_source_test, statement_test, related_test,
-)
+from stix.test import EntityTestCase
+from stix.test import data_marking_test
+from stix.test.common import (confidence_test, information_source_test,
+ statement_test, related_test)
from stix.test.extensions.structured_coa import generic_test
import stix.coa as coa
import stix.coa.objective as objective
@@ -21,6 +21,7 @@ class RelatedCOAsTests(EntityTestCase, unittest.TestCase):
]
}
+
class ObjectiveTests(EntityTestCase, unittest.TestCase):
klass = objective.Objective
@@ -50,9 +51,9 @@ class COATests(EntityTestCase, unittest.TestCase):
},
'objective': ObjectiveTests._full_dict,
'parameter_observables': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
@@ -70,16 +71,12 @@ class COATests(EntityTestCase, unittest.TestCase):
}
-
def test_structured_coa(self):
coa_ = coa.CourseOfAction()
- def should_fail():
- coa_.structured_coa = "ERROR"
-
self.assertRaises(
TypeError,
- should_fail
+ setattr(coa_, "structured_coa", "ERROR")
)
from stix.extensions.structured_coa.generic_structured_coa import GenericStructuredCOA
diff --git a/stix/test/common/tools_tests.py b/stix/test/common/tools_tests.py
index 40fe4c9f..b9795de6 100644
--- a/stix/test/common/tools_tests.py
+++ b/stix/test/common/tools_tests.py
@@ -1,4 +1,5 @@
-__author__ = 'bworrell'
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
import unittest
from stix.test import EntityTestCase
diff --git a/stix/test/core/stix_package_test.py b/stix/test/core/stix_package_test.py
index f63edf21..6261cb9d 100644
--- a/stix/test/core/stix_package_test.py
+++ b/stix/test/core/stix_package_test.py
@@ -1,12 +1,13 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import copy
-import StringIO
import unittest
+from mixbox.vendor.six import BytesIO
+
from stix.test import EntityTestCase
-from stix.test.common import kill_chains_test
+from stix.test.common import kill_chains_test, related_test
from . import stix_header_test
@@ -29,6 +30,7 @@ class COAsTests(EntityTestCase, unittest.TestCase):
{'idref': 'example:test-1'}
]
+
class ExploitTargetsTests(EntityTestCase, unittest.TestCase):
klass = stix_package.ExploitTargets
@@ -36,6 +38,7 @@ class ExploitTargetsTests(EntityTestCase, unittest.TestCase):
{'idref': 'example:test-1'}
]
+
class IncidentsTests(EntityTestCase, unittest.TestCase):
klass = stix_package.Incidents
@@ -43,6 +46,7 @@ class IncidentsTests(EntityTestCase, unittest.TestCase):
{'idref': 'example:test-1'}
]
+
class IndicatorsTests(EntityTestCase, unittest.TestCase):
klass = stix_package.Indicators
@@ -58,6 +62,7 @@ class ThreatActorsTests(EntityTestCase, unittest.TestCase):
{'idref': 'example:test-1'}
]
+
class TTPsTests(EntityTestCase, unittest.TestCase):
klass = stix_package.TTPs
@@ -79,9 +84,9 @@ class STIXPackageTests(EntityTestCase, unittest.TestCase):
'incidents': IncidentsTests._full_dict,
'indicators': IndicatorsTests._full_dict,
'observables': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
@@ -90,10 +95,10 @@ class STIXPackageTests(EntityTestCase, unittest.TestCase):
},
'threat_actors': ThreatActorsTests._full_dict,
'ttps': TTPsTests._full_dict,
+ 'related_packages': related_test.RelatedPackagesTests._full_dict,
'version': "1.1.1"
}
-
def test_deepcopy(self):
"""Test copy.deepcopy() against parsed document.
@@ -106,7 +111,7 @@ def test_deepcopy(self):
"""
package = core.STIXPackage.from_xml(
- StringIO.StringIO(
+ BytesIO(
core.STIXPackage().to_xml()
)
)
diff --git a/stix/test/data_marking_test.py b/stix/test/data_marking_test.py
index 381a6e64..9833ad76 100644
--- a/stix/test/data_marking_test.py
+++ b/stix/test/data_marking_test.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import unittest
@@ -12,7 +12,7 @@ class MarkingSpecificationTests(EntityTestCase, unittest.TestCase):
klass = dm.MarkingSpecification
_full_dict = {
'id': "foo",
- 'idref': "foo_ref",
+ # 'idref': "foo_ref", # Cannot have both @id and @idref set at the same time.
'version': "1234",
'controlled_structure': "some xpath",
'marking_structures': [
@@ -26,21 +26,13 @@ class MarkingSpecificationTests(EntityTestCase, unittest.TestCase):
class MarkingStructureTests(unittest.TestCase):
- def test_xsi_type_required(self):
- d = {
- 'marking_model_name': 'TLP',
- }
-
- # If there's not an xsi:type in the dict, this will raise an error.
- self.assertRaises(ValueError, dm.MarkingStructure.from_dict, d)
-
- def test_xsi_type_required(self):
+ def test_bad_xsi_type(self):
d = {
'marking_model_name': 'TLP',
'xsi:type': "UNKNOWN_XSI_TYPE",
}
- self.assertRaises(ValueError, dm.MarkingStructure.from_dict, d)
+ self.assertRaises(ValueError, dm.MarkingStructureFactory.from_dict, d)
class MarkingTests(EntityTestCase, unittest.TestCase):
diff --git a/stix/test/encoding_test.py b/stix/test/encoding_test.py
index 9797c262..f8311534 100644
--- a/stix/test/encoding_test.py
+++ b/stix/test/encoding_test.py
@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
"""Tests for various encoding issues throughout the library"""
import unittest
-from StringIO import StringIO
+from mixbox.vendor.six import BytesIO, text_type
+from mixbox import binding_utils
-import stix.bindings as bindings
from stix.core import STIXHeader, STIXPackage
from stix.campaign import Campaign
from stix.indicator import Indicator
@@ -40,12 +40,12 @@ class EncodingTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
- cls.orig_encoding = bindings.ExternalEncoding
- bindings.ExternalEncoding = 'utf-16'
+ cls.orig_encoding = binding_utils.ExternalEncoding
+ binding_utils.ExternalEncoding = 'utf-16'
@classmethod
def tearDownClass(cls):
- bindings.ExternalEncoding = cls.orig_encoding
+ binding_utils.ExternalEncoding = cls.orig_encoding
def _test_equal(self, obj1, obj2):
self.assertEqual(obj1.title, obj2.title)
@@ -119,90 +119,12 @@ def test_campaign(self):
c2 = round_trip(c)
self._test_equal(c, c2)
- def test_quote_xml(self):
- s = bindings.quote_xml(UNICODE_STR)
- self.assertEqual(s, UNICODE_STR)
-
- def test_quote_attrib(self):
- """Tests that the stix.bindings.quote_attrib method works properly
- on unicode inputs.
-
- Note:
- The quote_attrib method (more specifically, saxutils.quoteattr())
- adds quotation marks around the input data, so we need to strip
- the leading and trailing chars to test effectively
- """
- s = bindings.quote_attrib(UNICODE_STR)
- s = s[1:-1]
- self.assertEqual(s, UNICODE_STR)
-
- def test_quote_attrib_int(self):
- i = 65536
- s = bindings.quote_attrib(i)
- self.assertEqual(u'"65536"', s)
-
- def test_quote_attrib_bool(self):
- b = True
- s = bindings.quote_attrib(b)
- self.assertEqual(u'"True"', s)
-
- def test_quote_xml_int(self):
- i = 65536
- s = bindings.quote_xml(i)
- self.assertEqual(unicode(i), s)
-
- def test_quote_xml_bool(self):
- b = True
- s = bindings.quote_xml(b)
- self.assertEqual(unicode(b), s)
-
- def test_quote_xml_encoded(self):
- encoding = bindings.ExternalEncoding
- encoded = UNICODE_STR.encode(encoding)
- quoted = bindings.quote_xml(encoded)
- self.assertEqual(UNICODE_STR, quoted)
-
- def test_quote_attrib_encoded(self):
- encoding = bindings.ExternalEncoding
- encoded = UNICODE_STR.encode(encoding)
- quoted = bindings.quote_attrib(encoded)[1:-1]
- self.assertEqual(UNICODE_STR, quoted)
-
- def test_quote_xml_zero(self):
- i = 0
- s = bindings.quote_xml(i)
- self.assertEqual(unicode(i), s)
-
- def test_quote_attrib_zero(self):
- i = 0
- s = bindings.quote_attrib(i)
- self.assertEqual(u'"0"', s)
-
- def test_quote_xml_none(self):
- i = None
- s = bindings.quote_xml(i)
- self.assertEqual(u'', s)
-
- def test_quote_attrib_none(self):
- i = None
- s = bindings.quote_attrib(i)
- self.assertEqual(u'""', s)
-
- def test_quote_attrib_empty(self):
- i = ''
- s = bindings.quote_attrib(i)
- self.assertEqual(u'""', s)
-
- def test_quote_xml_empty(self):
- i = ''
- s = bindings.quote_xml(i)
- self.assertEqual(u'', s)
-
def test_to_xml_utf16_encoded(self):
encoding = 'utf-16'
s = STIXHeader()
s.title = UNICODE_STR
xml = s.to_xml(encoding=encoding)
+ print(xml)
self.assertTrue(UNICODE_STR in xml.decode(encoding))
def test_to_xml_default_encoded(self):
@@ -215,24 +137,23 @@ def test_to_xml_no_encoding(self):
s = STIXHeader()
s.title = UNICODE_STR
xml = s.to_xml(encoding=None)
- self.assertTrue(isinstance(xml, unicode))
+ self.assertTrue(isinstance(xml, text_type))
self.assertTrue(UNICODE_STR in xml)
def test_from_xml_utf16_encoded(self):
utf16_xml = XML.encode('utf-16')
- sio = StringIO(utf16_xml)
+ sio = BytesIO(utf16_xml)
sp = STIXPackage.from_xml(sio, encoding='utf-16')
header = sp.stix_header
self.assertEqual(header.title, UNICODE_STR)
def test_from_xml_default_encoded(self):
utf8_xml = XML.encode('utf-8')
- sio = StringIO(utf8_xml)
+ sio = BytesIO(utf8_xml)
sp = STIXPackage.from_xml(sio)
header = sp.stix_header
self.assertEqual(header.title, UNICODE_STR)
-
def test_utf16_roundtrip(self):
sh = STIXHeader()
sh.title = UNICODE_STR
@@ -243,7 +164,7 @@ def test_utf16_roundtrip(self):
xml16 = sp.to_xml(encoding='utf-16')
# deserialize as utf-16
- sp2 = STIXPackage.from_xml(StringIO(xml16), encoding='utf-16')
+ sp2 = STIXPackage.from_xml(BytesIO(xml16), encoding='utf-16')
sh2 = sp2.stix_header
# check that the titles align
diff --git a/stix/test/exploit_target_test.py b/stix/test/exploit_target_test.py
index 2965fd17..4ebc4e22 100644
--- a/stix/test/exploit_target_test.py
+++ b/stix/test/exploit_target_test.py
@@ -9,6 +9,7 @@
import stix.exploit_target as et
from stix.exploit_target import weakness, vulnerability, configuration
+
class CVSSVectorTests(EntityTestCase, unittest.TestCase):
klass = vulnerability.CVSSVector
@@ -86,6 +87,7 @@ class RelatedExploitTargetsTests(EntityTestCase, unittest.TestCase):
]
}
+
class WeaknessTests(EntityTestCase, unittest.TestCase):
klass = weakness.Weakness
@@ -103,7 +105,6 @@ class WeaknessesTests(TypedListTestCase, unittest.TestCase):
]
-
class ConfigurationTests(EntityTestCase, unittest.TestCase):
klass = configuration.Configuration
@@ -115,14 +116,6 @@ class ConfigurationTests(EntityTestCase, unittest.TestCase):
}
-class ConfigurationsTests(TypedListTestCase, unittest.TestCase):
- klass = configuration._Configurations
-
- _full_dict = [
- ConfigurationTests._full_dict
- ]
-
-
class ExploitTargetTests(EntityTestCase, unittest.TestCase):
klass = et.ExploitTarget
_full_dict = {
@@ -135,7 +128,7 @@ class ExploitTargetTests(EntityTestCase, unittest.TestCase):
'short_description': "an ExploitTarget",
'vulnerabilities': VulnerabilitiesTests._full_dict,
'weaknesses': WeaknessesTests._full_dict,
- 'configuration': ConfigurationsTests._full_dict,
+ 'configuration': [ConfigurationTests._full_dict],
'potential_coas': PotentialCOAsTests._full_dict,
'information_source': information_source_test.InformationSourceTests._full_dict,
'handling': data_marking_test.MarkingTests._full_dict,
diff --git a/stix/test/extensions/identity/ciq_identity_3_0_test.py b/stix/test/extensions/identity/ciq_identity_3_0_test.py
index f56bb6f2..507fc3bf 100644
--- a/stix/test/extensions/identity/ciq_identity_3_0_test.py
+++ b/stix/test/extensions/identity/ciq_identity_3_0_test.py
@@ -36,8 +36,16 @@ class CIQIdentity3_0InstanceTests(EntityTestCase, unittest.TestCase):
],
'person_names': [
{
+ 'type': 'LegalName',
'name_elements': [
- {'value': 'John Smith'}
+ {
+ 'element_type': 'FirstName',
+ 'value': 'John',
+ },
+ {
+ 'element_type': 'LastName',
+ 'value': 'Smith',
+ }
]
},
{
@@ -57,8 +65,17 @@ class CIQIdentity3_0InstanceTests(EntityTestCase, unittest.TestCase):
},
'country': {
'name_elements': [
- {'value': 'name 1'},
- {'value': 'name 2'}
+ {
+ 'value': 'name 1',
+ 'name_code': 'US',
+ 'name_code_type': 'ISO 3166-1 alpha-2'
+ },
+ {
+ 'value': 'name 2',
+ 'name_code': 'BZ',
+ 'name_code_type': 'ISO 3166-1 alpha-2',
+ 'name_type': 'ISO'
+ }
]
},
'administrative_area': {
@@ -99,9 +116,12 @@ class CIQIdentity3_0InstanceTests(EntityTestCase, unittest.TestCase):
{'value': 'name 2'}
]
}
- ]
+ ],
+ 'organisation_info': {
+ 'industry_type': 'SECTOR 1 | SECTOR 2',
+ }
},
- 'xsi:type': 'ciqIdentity:CIQIdentity3.0InstanceType'
+ 'xsi:type': 'stix-ciqidentity:CIQIdentity3.0InstanceType'
}
diff --git a/stix/test/extensions/malware/__init__.py b/stix/test/extensions/malware/__init__.py
index e69de29b..9b80d3dd 100644
--- a/stix/test/extensions/malware/__init__.py
+++ b/stix/test/extensions/malware/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
diff --git a/stix/test/extensions/malware/maec_4_1_malware_test.py b/stix/test/extensions/malware/maec_4_1_malware_test.py
index 66f19d63..b79a3ab8 100644
--- a/stix/test/extensions/malware/maec_4_1_malware_test.py
+++ b/stix/test/extensions/malware/maec_4_1_malware_test.py
@@ -1,11 +1,21 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
import unittest
-from StringIO import StringIO
-from lxml import etree
+from stix.core import STIXPackage
+from mixbox.vendor.six import StringIO, text_type
-import stix.utils.parser
from stix.test import EntityTestCase
from stix.extensions.malware.maec_4_1_malware import MAECInstance
+try:
+ import maec
+ maec_present = True
+except ImportError:
+ maec_present = False
+
+
+@unittest.skipIf(condition=maec_present is False, reason="These tests require the 'maec' library.")
class PythonMAECTests(EntityTestCase, unittest.TestCase):
klass = MAECInstance
@@ -14,104 +24,152 @@ class PythonMAECTests(EntityTestCase, unittest.TestCase):
'maec': {
'malware_subjects':
[
- {'malware_instance_object_attributes':
- {'id': 'maec-tst-obj-1',
- 'properties': {
- 'hashes':
- [
- {
- 'simple_hash_value': '9d7006e30fdf15e9c8e03e62534b3a3e',
- 'type': 'MD5'
- }
- ],
- 'xsi:type': 'FileObjectType'}
- }
+ {
+ 'malware_instance_object_attributes': {
+ 'id': 'maec-tst-obj-1',
+ 'properties': {
+ 'hashes':
+ [
+ {
+ 'simple_hash_value': '9d7006e30fdf15e9c8e03e62534b3a3e',
+ 'type': 'MD5'
+ }
+ ],
+ 'xsi:type': 'FileObjectType'
+ }
+ }
}
]
}
}
-class PythonMAECEtreeTests(unittest.TestCase):
- XML = (
+ def test_add_name_type(self):
+ maec_malware_instance = MAECInstance()
+ maec_malware_instance.add_name("Poison Ivy Variant v4392-acc")
+ maec_malware_instance.add_type("Remote Access Trojan")
+ maec_xml = text_type(maec_malware_instance.to_xml())
+ self.assertTrue("Poison Ivy Variant v4392-acc" in maec_xml)
+ self.assertTrue("Remote Access Trojan" in maec_xml)
+
+
+@unittest.skipIf(condition=maec_present is False, reason="These tests require the 'maec' library.")
+class PythonMAECInPackageTests(unittest.TestCase):
+ XML = StringIO(
"""
-
+
+
+ Poison Ivy Variant v4392-acc
+
+
+
+ Remote Access Trojan
+ Poison Ivy Variant v4392-acc
+
+
+
+
+
+
+ """
+ )
+ XML_MAEC = StringIO(
+ """
+
-
-
-
-
-
-
- MD5
- 9d7006e30fdf15e9c8e03e62534b3a3e
-
-
-
-
-
-
-
+ http://stix.mitre.org/TTP-1 http://stix.mitre.org/XMLSchema/ttp/1.2/ttp.xsd
+ http://stix.mitre.org/common-1 http://stix.mitre.org/XMLSchema/common/1.2/stix_common.xsd
+ http://stix.mitre.org/default_vocabularies-1 http://stix.mitre.org/XMLSchema/default_vocabularies/1.2.0/stix_default_vocabularies.xsd
+ http://stix.mitre.org/stix-1 http://stix.mitre.org/XMLSchema/core/1.2/stix_core.xsd
+ http://stix.mitre.org/extensions/Malware#MAEC4.1-1 http://stix.mitre.org/XMLSchema/extensions/malware/maec_4.1/1.0/maec_4.1_malware.xsd
+ http://maec.mitre.org/XMLSchema/maec-package-2 http://maec.mitre.org/language/version4.1/maec_package_schema.xsd"
+ id="example:Package-2b8fb66f-b6b3-4d40-865a-33e4a5ee1246"
+ version="1.1.1"
+ >
+
+
+ Poison Ivy Variant v4392-acc
+
+
+
+ Remote Access Trojan
+ Poison Ivy Variant v4392-acc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
"""
)
- def _test_xml(self, obj):
- xml = obj.to_xml()
- parser = stix.utils.parser.get_xml_parser()
- tree = etree.parse(StringIO(xml), parser=parser)
- root = tree.getroot()
-
- xpath = "//cyboxCommon:Type"
- nodes = root.xpath(xpath, namespaces={'cyboxCommon': 'http://cybox.mitre.org/common-2'})
-
- self.assertTrue(nodes is not None)
- self.assertEqual(len(nodes), 1)
- self.assertEqual(nodes[0].text, "MD5")
+ def test_parse_malware(self):
+ """Test parsing a normal MalwareInstance from XML
+ """
+ stix_pkg = STIXPackage.from_xml(self.XML)
+ mw = stix_pkg.ttps.ttp[0].behavior.malware_instances[0].to_dict()
+ self.assertTrue('names' in mw)
+ def test_parse_malware_maec(self):
+ """Test parsing a MaecInstance from XML
+ """
+ stix_pkg = STIXPackage.from_xml(self.XML_MAEC)
+ mw = stix_pkg.ttps.ttp[0].behavior.malware_instances[0].to_dict()
+ self.assertTrue('names' in mw)
- def test_etree(self):
- parser = stix.utils.parser.get_xml_parser()
- tree = etree.parse(StringIO(self.XML), parser=parser)
- ext = MAECInstance()
- ext.maec = tree
- self._test_xml(ext)
+@unittest.skipIf(condition=maec_present is True, reason="These tests require the 'maec' library to be missing.")
+class PythonMAECNotInstalledTest(unittest.TestCase):
+ def test_parsing_maec_fails(self):
+ try:
+ STIXPackage.from_xml(PythonMAECInPackageTests.XML_MAEC)
+ except ImportError as e:
+ self.assertTrue(all(x in str(e) for x in ("No module named", "maec")))
- def test_etree_dict(self):
- parser = stix.utils.parser.get_xml_parser()
- tree = etree.parse(StringIO(self.XML), parser=parser)
- ext = MAECInstance()
- ext.maec = tree
+ def test_handling_maec_object_fails(self):
+ try:
+ MAECInstance().from_dict(PythonMAECTests._full_dict)
+ except ImportError as e:
+ self.assertTrue(all(x in str(e) for x in ("No module named", "maec")))
- d = ext.to_dict()
- ext2 = MAECInstance.from_dict(d)
- self._test_xml(ext2)
+ def test_setting_maec_property_fails(self):
+ try:
+ m = MAECInstance()
+ m.maec = "foo"
+ except ImportError as e:
+ self.assertTrue(all(x in str(e) for x in ("No module named", "maec")))
if __name__ == "__main__":
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/stix/test/extensions/marking/__init__.py b/stix/test/extensions/marking/__init__.py
index e69de29b..9b80d3dd 100644
--- a/stix/test/extensions/marking/__init__.py
+++ b/stix/test/extensions/marking/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
diff --git a/stix/test/extensions/marking/ais.py b/stix/test/extensions/marking/ais.py
new file mode 100644
index 00000000..7f7a8327
--- /dev/null
+++ b/stix/test/extensions/marking/ais.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
+import unittest
+
+from stix.test import EntityTestCase
+
+from stix.core import STIXPackage
+from stix.extensions.marking import ais
+
+
+class AISMarkingStructureNotProprietaryTests(EntityTestCase, unittest.TestCase):
+ klass = ais.AISMarkingStructure
+ _full_dict = {
+ 'not_proprietary':
+ {
+ 'cisa_proprietary': 'false',
+ 'ais_consent': {'consent': 'NONE'},
+ 'tlp_marking': {'color': 'GREEN'}
+ },
+ 'xsi:type': 'AIS:AISMarkingStructure'
+ }
+
+
+class AISMarkingStructureIsProprietaryTests(EntityTestCase, unittest.TestCase):
+ klass = ais.AISMarkingStructure
+ _full_dict = {
+ 'is_proprietary':
+ {
+ 'cisa_proprietary': 'true',
+ 'ais_consent': {'consent': 'EVERYONE'},
+ 'tlp_marking': {'color': 'AMBER'}
+ },
+ 'xsi:type': 'AIS:AISMarkingStructure'
+ }
+
+
+class AISMarkingGeneralTests(unittest.TestCase):
+ """General tests for ais module helpers."""
+
+ @classmethod
+ def setUpClass(cls):
+ cls.INDUSTRY_SECTORS = (ais.CHEMICAL_SECTOR, ais.COMMERCIAL_FACILITIES_SECTOR,
+ ais.COMMUNICATIONS_SECTOR,
+ ais.CRITICAL_MANUFACTURING_SECTOR,
+ ais.DAMS_SECTOR, ais.DEFENSE_INDUSTRIAL_BASE_SECTOR,
+ ais.EMERGENCY_SERVICES_SECTOR, ais.ENERGY_SECTOR,
+ ais.FINANCIAL_SERVICES_SECTOR,
+ ais.FOOD_AND_AGRICULTURE_SECTOR,
+ ais.GOVERNMENT_FACILITIES_SECTOR,
+ ais.HEALTH_CARE_AND_PUBLIC_HEALTH_SECTOR,
+ ais.INFORMATION_TECHNOLOGY_SECTOR,
+ ais.NUCLEAR_REACTORS_MATERIALS_AND_WASTE_SECTOR,
+ ais.TRANSPORTATION_SYSTEMS_SECTOR, ais.OTHER,
+ ais.WATER_AND_WASTEWATER_SYSTEMS_SECTOR)
+
+ def test_validate_and_create_industry_type(self):
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, [])
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, "")
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, [""])
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, ["Energy Sector", "Others", "Dams Sector"])
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, "Energy Sector| Others|Dams Sector")
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, 3)
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, "|")
+ self.assertRaises(ValueError, ais._validate_and_create_industry_type, ["Energy Sector|Dams Sector"])
+
+ self.assertEqual(ais._validate_and_create_industry_type("eNergY sectOr"), ais.ENERGY_SECTOR)
+ self.assertEqual(ais._validate_and_create_industry_type("eNergY sectOr |Dams sector"), "Energy Sector|Dams Sector")
+ self.assertEqual(ais._validate_and_create_industry_type(["eNergY sectOr ", " Dams sectOr "]), "Energy Sector|Dams Sector")
+ self.assertEqual(ais._validate_and_create_industry_type([ais.ENERGY_SECTOR, ais.DAMS_SECTOR]), "Energy Sector|Dams Sector")
+ self.assertEqual(ais._validate_and_create_industry_type("Energy Sector|Dams Sector"), "Energy Sector|Dams Sector")
+
+ for idx, x in enumerate(self.INDUSTRY_SECTORS):
+ self.assertEqual(ais._validate_and_create_industry_type(x), self.INDUSTRY_SECTORS[idx])
+
+ def test_add_ais_marking(self):
+ PACKAGE = STIXPackage()
+
+ # Missing kwarg.
+ self.assertRaises(ValueError, ais.add_ais_marking, PACKAGE, True, 'NONE', 'GREEN',
+ country_name_code='US',
+ country_name_code_type='ISO 3166-1 alpha-2',
+ admin_area_name_code='US-DC',
+ admin_area_name_code_type='ISO 3166-2',
+ organisation_name='NCCIC')
+
+ def test_bad_values_raises_error(self):
+ self.assertRaises(ValueError, ais.TLPMarkingType, "ORANGE")
+ self.assertRaises(ValueError, ais.AISConsentType, "WHAT?")
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/stix/test/extensions/marking/simple_marking_test.py b/stix/test/extensions/marking/simple_marking_test.py
index 755a76c8..7e434099 100644
--- a/stix/test/extensions/marking/simple_marking_test.py
+++ b/stix/test/extensions/marking/simple_marking_test.py
@@ -1,3 +1,6 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
import unittest
from stix.test import EntityTestCase
diff --git a/stix/test/extensions/marking/tlp_test.py b/stix/test/extensions/marking/tlp_test.py
index 5ba879b4..8388908c 100644
--- a/stix/test/extensions/marking/tlp_test.py
+++ b/stix/test/extensions/marking/tlp_test.py
@@ -1,3 +1,6 @@
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
+# See LICENSE.txt for complete terms.
+
import unittest
from stix.test import EntityTestCase
diff --git a/stix/test/extensions/structured_coa/__init__.py b/stix/test/extensions/structured_coa/__init__.py
index 462a1719..9a9569c5 100644
--- a/stix/test/extensions/structured_coa/__init__.py
+++ b/stix/test/extensions/structured_coa/__init__.py
@@ -1,2 +1,2 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
-# See LICENSE.txt for complete terms.
\ No newline at end of file
+# See LICENSE.txt for complete terms.
diff --git a/stix/test/extensions/structured_coa/generic_test.py b/stix/test/extensions/structured_coa/generic_test.py
index 155409b2..bcd6ac63 100644
--- a/stix/test/extensions/structured_coa/generic_test.py
+++ b/stix/test/extensions/structured_coa/generic_test.py
@@ -5,6 +5,7 @@
from stix.extensions.structured_coa.generic_structured_coa import GenericStructuredCOA
from stix.test import EntityTestCase
+
class GenericStructuredCOATests(EntityTestCase, unittest.TestCase):
klass = GenericStructuredCOA
_full_dict = {
diff --git a/stix/test/extensions/test_mechanisms/__init__.py b/stix/test/extensions/test_mechanisms/__init__.py
index 462a1719..9a9569c5 100644
--- a/stix/test/extensions/test_mechanisms/__init__.py
+++ b/stix/test/extensions/test_mechanisms/__init__.py
@@ -1,2 +1,2 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
-# See LICENSE.txt for complete terms.
\ No newline at end of file
+# See LICENSE.txt for complete terms.
diff --git a/stix/test/extensions/test_mechanisms/openioc_test.py b/stix/test/extensions/test_mechanisms/openioc_test.py
index 36fc19dc..8edaa213 100644
--- a/stix/test/extensions/test_mechanisms/openioc_test.py
+++ b/stix/test/extensions/test_mechanisms/openioc_test.py
@@ -1,12 +1,15 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import unittest
-import StringIO
import lxml
-from stix import utils
+from mixbox import idgen
+from mixbox.namespaces import Namespace
+from mixbox.vendor.six import StringIO, BytesIO
+import mixbox.xml
+
from stix.test import EntityTestCase
from stix.extensions.test_mechanism.open_ioc_2010_test_mechanism import OpenIOCTestMechanism
@@ -38,12 +41,11 @@ class OpenIOCTestMechanismTests(EntityTestCase, unittest.TestCase):
class OpenIOCEtreeTests(unittest.TestCase):
DESCRIPTION = "Finds Zeus variants, twexts, sdra64, ntos"
XML = (
- """
+ r"""
Zeus
@@ -117,35 +119,37 @@ class OpenIOCEtreeTests(unittest.TestCase):
)
def setUp(self):
- utils.set_id_namespace({"http://schemas.mandiant.com/2010/ioc": "mandiant-openioc"})
+ ioc_ns = Namespace("http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1",
+ "stix-openioc", '')
+ idgen.set_id_namespace(ioc_ns)
def tearDown(self):
- utils.set_id_namespace(utils.EXAMPLE_NAMESPACE)
+ idgen.set_id_namespace(idgen.EXAMPLE_NAMESPACE)
def _test_xml(self, obj):
xml = obj.to_xml()
- parser = utils.parser.get_xml_parser()
- tree = lxml.etree.parse(StringIO.StringIO(xml), parser=parser)
+ parser = mixbox.xml.get_xml_parser()
+ tree = lxml.etree.parse(BytesIO(xml), parser=parser)
root = tree.getroot()
- xpath = "//openioc:description"
- nodes = root.xpath(xpath, namespaces={'openioc': 'http://schemas.mandiant.com/2010/ioc'})
+ xpath = "//stix-openioc:ioc//description"
+ nodes = root.xpath(xpath, namespaces={'stix-openioc': 'http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1'})
self.assertTrue(nodes is not None)
self.assertEqual(len(nodes), 1)
self.assertEqual(nodes[0].text, self.DESCRIPTION)
def test_etree(self):
- parser = utils.parser.get_xml_parser()
- tree = lxml.etree.parse(StringIO.StringIO(self.XML), parser=parser)
+ parser = mixbox.xml.get_xml_parser()
+ tree = lxml.etree.parse(StringIO(self.XML), parser=parser)
ext = OpenIOCTestMechanism()
ext.ioc = tree
self._test_xml(ext)
def test_etree_dict(self):
- parser = utils.parser.get_xml_parser()
- tree = lxml.etree.parse(StringIO.StringIO(self.XML), parser=parser)
+ parser = mixbox.xml.get_xml_parser()
+ tree = lxml.etree.parse(StringIO(self.XML), parser=parser)
ext = OpenIOCTestMechanism()
ext.ioc = tree
diff --git a/stix/test/incident_test.py b/stix/test/incident_test.py
index 90bdd57d..55209a28 100644
--- a/stix/test/incident_test.py
+++ b/stix/test/incident_test.py
@@ -1,14 +1,17 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import unittest
-import StringIO
+
+from mixbox.vendor.six import StringIO
from cybox.common import StructuredText
-from stix.test import EntityTestCase, TypedListTestCase, data_marking_test
+from stix.test import EntityTestCase
+from stix.test import data_marking_test
from stix.test.common import (
- confidence_test, information_source_test, statement_test, related_test
+ confidence_test, information_source_test, related_test, identity_test,
+ statement_test
)
import stix.common.vocabs as vocabs
@@ -64,14 +67,6 @@ class COATakenTest(EntityTestCase, unittest.TestCase):
}
-class COAsTakenTest(TypedListTestCase, unittest.TestCase):
- klass = incident._COAsTaken
-
- _full_dict = [
- COATakenTest._full_dict,
- ]
-
-
class COARequestedTest(EntityTestCase, unittest.TestCase):
klass = incident.COARequested
@@ -89,15 +84,6 @@ class COARequestedTest(EntityTestCase, unittest.TestCase):
}
-class COAsRequestedTest(TypedListTestCase, unittest.TestCase):
- klass = incident._COAsRequested
-
- _full_dict = [
- COARequestedTest._full_dict,
- ]
-
-
-
class JournalEntryTest(EntityTestCase, unittest.TestCase):
klass = history.JournalEntry
@@ -161,28 +147,13 @@ class LeveragedTTPsTest(EntityTestCase, unittest.TestCase):
}
-class ExternalIDsTest(TypedListTestCase, unittest.TestCase):
- klass = incident._ExternalIDs
+class ExternalIDTest(EntityTestCase, unittest.TestCase):
+ klass = incident.ExternalID
- _full_dict = [
- {
- 'source': 'foo',
- 'value': '478392-feb3ca-98a9ef-984392742'
- },
- {
- 'source': 'bar',
- 'value': '478392-feb3ca-98a9ef-984392742'
- },
- ]
-
-
-class VictimsTest(TypedListTestCase, unittest.TestCase):
- klass = incident._Victims
-
- _full_dict = [
- {'name': 'Spooderman'},
- {'name': 'Spooderman'}
- ]
+ _full_dict = {
+ 'source': 'foo',
+ 'value': '478392-feb3ca-98a9ef-984392742'
+ }
class TimeTest(EntityTestCase, unittest.TestCase):
@@ -212,19 +183,6 @@ class CategoriesTest(EntityTestCase, unittest.TestCase):
]
-class InformationSourcesTest(TypedListTestCase, unittest.TestCase):
- klass = incident._InformationSources
-
- _full_dict = [
- {
- 'description': 'Test',
- 'identity': {
- 'name': 'Spooderman'
- }
- },
- ]
-
-
class TotalLossEstimationTest(EntityTestCase, unittest.TestCase):
klass = impact_assessment.TotalLossEstimation
@@ -360,6 +318,8 @@ class AffectedAssetTest(EntityTestCase, unittest.TestCase):
_full_dict = {
'type': AssetTypeTest._full_dict,
+ 'description': 'Foo',
+ 'business_function_or_role': 'Bar',
'nature_of_security_effect': NatureOfSecurityEffectTest._full_dict,
'ownership_class': {
'value': 'Unknown',
@@ -405,25 +365,6 @@ class RelatedIncidentsTests(EntityTestCase, unittest.TestCase):
}
-class IntendedEffectsTests(TypedListTestCase, unittest.TestCase):
- klass = incident._IntendedEffects
-
- _full_dict = [
- statement_test.StatementTests._full_dict
- ]
-
-
-class DiscoveryMethodsTests(TypedListTestCase, unittest.TestCase):
- klass = incident.DiscoveryMethods
-
- _full_dict = [
- {
- 'value': 'Unknown',
- 'xsi:type': 'stixVocabs:LocationClassVocab-1.0'
- }
- ]
-
-
class IncidentTest(EntityTestCase, unittest.TestCase):
klass = incident.Incident
_full_dict = {
@@ -434,19 +375,19 @@ class IncidentTest(EntityTestCase, unittest.TestCase):
'description': 'The Datacenter was broken into.',
'short_description': 'Short Description Title',
'handling': data_marking_test.MarkingTests._full_dict,
- 'external_ids': ExternalIDsTest._full_dict,
+ 'external_ids': [ExternalIDTest._full_dict],
'attributed_threat_actors': AttributedThreatActorsTest._full_dict,
'categories': CategoriesTest._full_dict,
- 'coa_taken': COAsTakenTest._full_dict,
- 'coa_requested': COAsRequestedTest._full_dict,
- 'coordinators': InformationSourcesTest._full_dict,
+ 'coa_taken': [COATakenTest._full_dict],
+ 'coa_requested': [COARequestedTest._full_dict],
+ 'coordinators': [information_source_test.InformationSourceTests._full_dict],
'impact_assessment': ImpactAssessmentTest._full_dict,
'leveraged_ttps': LeveragedTTPsTest._full_dict,
'related_indicators': RelatedIndicatorsTest._full_dict,
'reporter': information_source_test.InformationSourceTests._full_dict,
- 'responders': InformationSourcesTest._full_dict,
+ 'responders': [information_source_test.InformationSourceTests._full_dict],
'time': TimeTest._full_dict,
- 'victims': VictimsTest._full_dict,
+ 'victims': [identity_test.IdentityTests._full_dict],
'information_source': information_source_test.InformationSourceTests._full_dict,
'security_compromise': {
"value": "Suspected",
@@ -460,9 +401,15 @@ class IncidentTest(EntityTestCase, unittest.TestCase):
'affected_assets': AffectedAssetsTest._full_dict,
'related_observables': RelatedObservablesTest._full_dict,
'related_incidents': RelatedIncidentsTests._full_dict,
- 'intended_effects': IntendedEffectsTests._full_dict,
- 'discovery_methods': DiscoveryMethodsTests._full_dict,
- 'confidence': confidence_test.ConfidenceTests._full_dict
+ 'intended_effects': [statement_test.StatementTests._full_dict],
+ 'discovery_methods': [{
+ "value": "Security Alarm",
+ "xsi:type": "stixVocabs:DiscoveryMethodVocab-2.0"
+ }],
+ 'confidence': confidence_test.ConfidenceTests._full_dict,
+ 'related_packages': related_test.RelatedPackageRefsTests._full_dict,
+ 'contacts': [information_source_test.InformationSourceTests._full_dict],
+ 'url': 'http://www.example.com/'
}
def test_parse_category(self):
@@ -486,7 +433,7 @@ def test_description_output(self):
assets.add_Affected_Asset(asset)
incident.Affected_Assets = assets
- s = StringIO.StringIO()
+ s = StringIO()
incident.export(s.write, 0, {'http://stix.mitre.org/Incident-1': 'incident'})
xml = s.getvalue()
@@ -509,7 +456,7 @@ def test_add_related_observable(self):
# Test that this fails
self.assertRaises(
- ValueError,
+ TypeError,
i.add_related_observable,
"THIS SHOULD FAIL"
)
@@ -530,7 +477,7 @@ def test_add_related_indicator(self):
# Test that this fails
self.assertRaises(
- ValueError,
+ TypeError,
i.add_related_indicator,
"THIS SHOULD FAIL"
)
diff --git a/stix/test/indicator_test.py b/stix/test/indicator_test.py
index c8dc3e55..daf4bb1a 100644
--- a/stix/test/indicator_test.py
+++ b/stix/test/indicator_test.py
@@ -1,10 +1,20 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from datetime import datetime
import unittest
-from stix.indicator import Indicator
-from stix.test import EntityTestCase, round_trip, round_trip_dict
+from cybox.core import Observable, ObservableComposition
+from cybox.objects.file_object import File
+import mixbox.typedlist
+from mixbox.vendor.six import text_type
+
+from stix.common.vocabs import IndicatorType, VocabString
+from stix.indicator import Indicator, RelatedCampaignRefs, ValidTime
+
+from stix.test import EntityTestCase
+from stix.test.common import related_test
+
class IndicatorTest(EntityTestCase, unittest.TestCase):
klass = Indicator
@@ -25,7 +35,6 @@ class IndicatorTest(EntityTestCase, unittest.TestCase):
def test_base(self):
self._test_partial_dict(self._base_dict)
-
def test_negate(self):
d = dict(self._base_dict.items())
d['negate'] = False
@@ -33,6 +42,8 @@ def test_negate(self):
d2 = self.klass.from_dict(d).to_dict()
self.assertTrue('negate' not in d2)
+ o2 = self.klass.from_dict(d).to_obj()
+ self.assertTrue(o2.negate is None)
def test_indicator_types(self):
d = {
@@ -179,7 +190,7 @@ def test_producer(self):
]
}
},
- 'xsi:type': 'ciqIdentity:CIQIdentity3.0InstanceType'
+ 'xsi:type': 'stix-ciqidentity:CIQIdentity3.0InstanceType'
},
'time': {'produced_time': '2014-02-21T10:16:14.947201'}
}
@@ -409,5 +420,110 @@ def test_related_packages(self):
self._test_partial_dict(d)
+ def test_indicator_type_hashing(self):
+ # https://github.com/STIXProject/python-stix/issues/338
+ vocab_str = IndicatorType(value=IndicatorType.TERM_C2)
+ indicator_set = set([vocab_str])
+
+ def test_datetime_format(self):
+ indicator = Indicator(title="title")
+ valid_time = ValidTime(start_time=datetime.strptime("2010-03-05",
+ "%Y-%m-%d"))
+ indicator.add_valid_time_position(valid_time)
+
+ ixml = indicator.to_xml()
+ self.assertTrue("2010-03-05T" in text_type(ixml))
+
+ def test_observables_property_empty(self):
+ ind = Indicator()
+ ind2 = Indicator.from_dict(ind.to_dict())
+
+ self.assertEqual([], ind2.observables)
+
+ def test_observables_property_composition(self):
+ f1 = File()
+ f1.file_name = "README.txt"
+ f2 = File()
+ f2.file_name = "README2.txt"
+ obs1 = Observable(f1)
+ obs2 = Observable(f2)
+
+ comp = Observable(ObservableComposition('AND', [obs1, obs2]))
+
+ ind = Indicator()
+ ind.observable = comp
+ ind2 = Indicator.from_dict(ind.to_dict())
+ self.assertEqual([obs1.to_dict(), obs2.to_dict()],
+ [x.to_dict() for x in ind2.observables])
+
+ def test_observables_property_standard(self):
+ f = File()
+ f.file_name = "README.txt"
+ obs = Observable(f)
+ ind = Indicator()
+ ind.observable = obs
+
+ ind2 = Indicator.from_dict(ind.to_dict())
+
+ self.assertEqual([obs.to_dict()],
+ [x.to_dict() for x in ind2.observables])
+
+ def test_set_indicator_observables_to_single_observable(self):
+ # https://github.com/STIXProject/python-stix/issues/325
+ i = Indicator()
+ o1 = Observable()
+ o2 = Observable()
+
+ i.observables = o1
+ self.assertEqual(type([]), type(i.observables))
+ self.assertEqual(1, len(i.observables))
+
+ def test_set_indicator_observables_to_list_of_two_observables(self):
+ # https://github.com/STIXProject/python-stix/issues/325
+ i = Indicator()
+ o1 = Observable()
+ o2 = Observable()
+
+ i.observables = [o1, o2]
+ self.assertEqual(mixbox.typedlist.TypedList, type(i.observables))
+ self.assertEqual(2, len(i.observables))
+
+ def test_set_indicator_observables_to_list_of_one_observable(self):
+ # https://github.com/STIXProject/python-stix/issues/325
+ i = Indicator()
+ o1 = Observable()
+ o2 = Observable()
+
+ i.observables = [o1]
+ self.assertEqual(type([]), type(i.observables))
+ self.assertEqual(1, len(i.observables))
+
+
+class RelatedCampaignReferencesTests(unittest.TestCase, EntityTestCase):
+ klass = RelatedCampaignRefs
+ _full_dict = {
+ 'related_campaigns': [
+ related_test.RelatedCampaignRefTests._full_dict
+ ]
+ }
+
+ def test_add_campaign(self):
+ from stix.campaign import Campaign
+
+ l = RelatedCampaignRefs()
+ l.append(Campaign())
+
+ self.assertEqual(1, len(l))
+
+ def test_append_bad_type(self):
+ l = RelatedCampaignRefs()
+
+ self.assertRaises(
+ TypeError,
+ l.append,
+ Indicator()
+ )
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/stix/test/threat_actor_test.py b/stix/test/threat_actor_test.py
index c61d26e9..73a3e93d 100644
--- a/stix/test/threat_actor_test.py
+++ b/stix/test/threat_actor_test.py
@@ -1,9 +1,10 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
import unittest
-from stix.test import EntityTestCase, TypedListTestCase, data_marking_test
+from stix.test import EntityTestCase, TypedListTestCase
+from stix.test import data_marking_test
from stix.test.common import (
confidence_test, information_source_test, related_test,identity_test
)
@@ -12,69 +13,87 @@
class TypesTests(TypedListTestCase, unittest.TestCase):
- klass = ta._Types
+ klass = ta.ThreatActor
- _full_dict = [
+ _partial_dict = [
{
'value': {
- "value" : "Hacker",
- "xsi:type" : "stixVocabs:ThreatActorTypeVocab-1.0"
+ "value": "Hacker",
+ "xsi:type": "stixVocabs:ThreatActorTypeVocab-1.0"
}
},
]
+ _full_dict = {
+ "types": _partial_dict
+ }
+
class MotivationsTests(TypedListTestCase, unittest.TestCase):
- klass = ta._Motivations
+ klass = ta.ThreatActor
- _full_dict = [
- {
+ _partial_dict = [{
'value': {
"value" : "Ego",
"xsi:type" : "stixVocabs:MotivationVocab-1.1"
}
- },
- ]
+ }]
+
+ _full_dict = {
+ "motivations": _partial_dict
+ }
class SophisticationTests(TypedListTestCase, unittest.TestCase):
- klass = ta._Sophistications
+ klass = ta.ThreatActor
- _full_dict = [
- {
- 'value': {
- "value" : "Novice",
- "xsi:type" : "stixVocabs:ThreatActorSophisticationVocab-1.0"
- }
- },
+ _partial_dict = [
+ {
+ 'value': {
+ "value": "Novice",
+ "xsi:type": "stixVocabs:ThreatActorSophisticationVocab-1.0"
+ }
+ }
]
+ _full_dict = {
+ "sophistications": _partial_dict
+ }
+
class IntendedEffectsTests(TypedListTestCase, unittest.TestCase):
- klass = ta._IntendedEffects
+ klass = ta.ThreatActor
- _full_dict = [
+ _partial_dict = [
{
'value': {
- "value" : "Destruction",
- "xsi:type" : "stixVocabs:IntendedEffectVocab-1.0"
+ "value": "Destruction",
+ "xsi:type": "stixVocabs:IntendedEffectVocab-1.0"
}
}
]
+ _full_dict = {
+ "intended_effects": _partial_dict
+ }
+
class PlanningAndOperationalSupportTests(TypedListTestCase, unittest.TestCase):
- klass = ta._PlanningAndOperationalSupports
+ klass = ta.ThreatActor
- _full_dict = [
+ _partial_dict = [
{
'value': {
- "value" : "Data Exploitation",
- "xsi:type" : 'stixVocabs:PlanningAndOperationalSupportVocab-1.0.1'
+ "value": "Data Exploitation",
+ "xsi:type": 'stixVocabs:PlanningAndOperationalSupportVocab-1.0.1'
}
- },
+ }
]
+ _full_dict = {
+ "planning_and_operational_supports": _partial_dict
+ }
+
class ObservedTTPsTests(EntityTestCase, unittest.TestCase):
klass = ta.ObservedTTPs
@@ -114,16 +133,16 @@ class ThreatActorTests(EntityTestCase, unittest.TestCase):
_full_dict = {
'id': 'example:ThreatActor-1',
'timestamp': "2014-01-31T06:14:46",
- 'version': '1.1',
+ 'version': '1.1.1',
'title': "BadGuy1",
'description': "This is a long description about a threat actor.",
'short_description': "A bad guy",
'identity': identity_test.IdentityTests._full_dict,
- 'types': TypesTests._full_dict,
- 'motivations': MotivationsTests._full_dict,
- 'sophistications': SophisticationTests._full_dict,
- 'intended_effects': IntendedEffectsTests._full_dict,
- 'planning_and_operational_supports': PlanningAndOperationalSupportTests._full_dict,
+ 'types': TypesTests._partial_dict,
+ 'motivations': MotivationsTests._partial_dict,
+ 'sophistications': SophisticationTests._partial_dict,
+ 'intended_effects': IntendedEffectsTests._partial_dict,
+ 'planning_and_operational_supports': PlanningAndOperationalSupportTests._partial_dict,
'observed_ttps': ObservedTTPsTests._full_dict,
'associated_campaigns': AssocaitedCampaignsTests._full_dict,
'associated_actors': AssociatedActorsTests._full_dict,
diff --git a/stix/test/ttp_test.py b/stix/test/ttp_test.py
index 73808775..624e38de 100644
--- a/stix/test/ttp_test.py
+++ b/stix/test/ttp_test.py
@@ -9,7 +9,7 @@
import stix.ttp as ttp
from stix.ttp import (
resource, infrastructure, exploit_targets, malware_instance, exploit,
- attack_pattern, behavior
+ attack_pattern, behavior, victim_targeting
)
@@ -41,9 +41,9 @@ class InfrastructureTests(EntityTestCase, unittest.TestCase):
'short_description': 'Short Description',
'types': ['foo', 'bar'],
'observable_characterization': {
- 'major_version': 2,
- 'minor_version': 1,
- 'update_version': 0,
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
'observables': [
{
'idref': "example:Observable-1"
@@ -60,7 +60,13 @@ class ResourcesTests(EntityTestCase, unittest.TestCase):
'personas': PersonasTests._full_dict,
'tools': [
{
- 'title': "Tool"
+ 'title': "Tool",
+ 'type': [
+ {
+ 'value': 'Malware',
+ 'xsi:type': 'stixVocabs:AttackerToolTypeVocab-1.0'
+ }
+ ]
}
],
'infrastructure': InfrastructureTests._full_dict
@@ -70,7 +76,7 @@ class ResourcesTests(EntityTestCase, unittest.TestCase):
class MalwareInstanceTests(EntityTestCase, unittest.TestCase):
klass = malware_instance.MalwareInstance
- _full_dict = _full_dict = {
+ _full_dict = {
'id': 'example:test-1',
'title': 'Title',
'description': 'Description',
@@ -135,6 +141,44 @@ class BehaviorTests(EntityTestCase, unittest.TestCase):
'attack_patterns': AttackPatternsTests._full_dict
}
+
+class VictimTargetingTests(EntityTestCase, unittest.TestCase):
+ klass = victim_targeting.VictimTargeting
+
+ _full_dict = {
+ 'identity': {
+ 'specification': {
+ 'organisation_info': {
+ 'industry_type': 'Electricity, Industrial Control Systems'
+ }
+ },
+ 'xsi:type': 'stix-ciqidentity:CIQIdentity3.0InstanceType'
+ },
+ 'targeted_systems': [
+ {
+ 'value': 'Industrial Control Systems',
+ 'xsi:type': 'stixVocabs:SystemTypeVocab-1.0'
+ }
+ ],
+ 'targeted_information': [
+ {
+ 'value': 'Information Assets - Intellectual Property',
+ 'xsi:type': 'stixVocabs:InformationTypeVocab-1.0'
+ }
+ ],
+ 'targeted_technical_details': {
+ 'cybox_major_version': '2',
+ 'cybox_minor_version': '1',
+ 'cybox_update_version': '0',
+ 'observables': [
+ {
+ 'idref': "example:Observable-2"
+ }
+ ]
+ }
+ }
+
+
class TTPTests(EntityTestCase, unittest.TestCase):
klass = ttp.TTP
_full_dict = {
@@ -146,8 +190,10 @@ class TTPTests(EntityTestCase, unittest.TestCase):
'resources': ResourcesTests._full_dict,
'handling': data_marking_test.MarkingTests._full_dict,
'exploit_targets': ExploitTargetsTests._full_dict,
- 'behavior': BehaviorTests._full_dict
+ 'behavior': BehaviorTests._full_dict,
+ 'victim_targeting': VictimTargetingTests._full_dict
}
+
if __name__ == "__main__":
unittest.main()
diff --git a/stix/test/utils/nsparser_test.py b/stix/test/utils/nsparser_test.py
index d3f7452d..0e5c14fe 100644
--- a/stix/test/utils/nsparser_test.py
+++ b/stix/test/utils/nsparser_test.py
@@ -1,90 +1,27 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# stdlib
-import StringIO
import unittest
-import warnings
# external
import lxml.etree
+from mixbox.vendor.six import StringIO
# internal
-import stix
+import mixbox.namespaces
from stix.core import STIXPackage
-from stix.utils import nsparser
-
-
-NSMAP = {
- "test:a": "a",
- "test:b": "b",
- "test:c": "c"
-}
-
-
-SCHEMALOCS = {
- "test:a": "/dev/null",
- "test:b": "/dev/null",
- "test:c": "/dev/null"
-}
-
-
-class A(stix.Entity):
- _namespace = "test:a"
- _XSI_TYPE = "a:AType"
-
-
-class B(A):
- _namespace = "test:b"
- _XSI_TYPE = "b:BType"
-
-
-class C(B):
- _namespace = "test:c"
- _XSI_TYPE = "c:CType"
+from stix.utils import silence_warnings
class NamespaceInfoTests(unittest.TestCase):
- def test_nsinfo_collect(self):
- """Tests that the NamespaceInfo.collect() method correctly ascends the MRO
- of input objects.
-
- """
- nsinfo = nsparser.NamespaceInfo()
-
- # Collect classes
- nsinfo.collect(C())
-
- # Parse collected classes
- nsinfo._parse_collected_classes()
-
- self.assertEqual(len(nsinfo._collected_namespaces), 4) # noqa
-
- def test_namespace_collect(self):
- """Test that NamespaceInfo correctly pulls namespaces from all classes
- in an objects MRO.
-
- """
- nsinfo = nsparser.NamespaceInfo()
-
- # Collect classes
- nsinfo.collect(C())
-
- # finalize the namespace dictionary
- nsinfo.finalize(ns_dict=NSMAP, schemaloc_dict=SCHEMALOCS)
- namespaces = nsinfo.finalized_namespaces.values()
-
- self.assertTrue(all(ns in namespaces for ns in NSMAP.iterkeys()))
+ @silence_warnings
def test_user_provided_ns(self):
"""Test that user-provided namespaces are serialized.
"""
p = STIXPackage()
- nsinfo = nsparser.NamespaceInfo()
-
- # Collect classes
- nsinfo.collect(p)
TEST_PREFIX = 'test'
TEST_NS = 'a:unit:test'
@@ -96,22 +33,14 @@ def test_user_provided_ns(self):
NEW_STIX_NS: NEW_STIX_PREFIX
}
- finalized = nsinfo._finalize_namespaces(ns_dict=test_dict)
- nsinfo.finalized_namespaces
-
- self.assertEqual(finalized.get(TEST_PREFIX), TEST_NS)
- self.assertEqual(finalized.get(NEW_STIX_PREFIX), NEW_STIX_NS)
-
- with warnings.catch_warnings():
- warnings.simplefilter('ignore')
- xml = p.to_xml(ns_dict=test_dict)
-
# Parse the exported document and make sure that the namespaces
# made it through the serialization process.
+ xml = p.to_xml(ns_dict=test_dict)
e = lxml.etree.XML(xml)
self.assertEqual(e.nsmap.get(TEST_PREFIX), TEST_NS)
self.assertEqual(e.nsmap.get(NEW_STIX_PREFIX), NEW_STIX_NS)
+ @silence_warnings
def test_duplicate_ns_prefix(self):
"""Test that duplicate namespace prefix mappings raise errors.
@@ -120,30 +49,36 @@ def test_duplicate_ns_prefix(self):
bad = {'bad:ns': 'stix'} # 'stix' is already default ns prefix
self.assertRaises(
- nsparser.DuplicatePrefixError,
+ mixbox.namespaces.DuplicatePrefixError,
p.to_xml,
ns_dict=bad
)
# Build a valid stix document that has a default namespace remapped
- # to another namespace. We remap 'cybox' to a bogus ns here.
+ # to another namespace. We remap 'stixCommon' to a bogus ns here.
xml = (
""""""
+ timestamp="2015-04-09T14:22:25.620831">
+
+ A unit test
+
+ """
)
- sio = StringIO.StringIO(xml)
+ sio = StringIO(xml)
p = STIXPackage.from_xml(sio)
# Exporting should raise an error.
self.assertRaises(
- nsparser.DuplicatePrefixError,
+ mixbox.namespaces.DuplicatePrefixError,
p.to_xml
)
+ @silence_warnings
def test_parsed_namespaces(self):
"""Test that non-default namespaces make it through the parse-serialize
process.
@@ -164,16 +99,13 @@ def test_parsed_namespaces(self):
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="example:Package-e2454ee8-e59c-43ac-a085-46ae4516fd6e"
version="1.1.1"
- timestamp="2015-04-09T14:22:25.620831+00:00"/>"""
+ timestamp="2015-04-09T14:22:25.620831"/>"""
)
- sio = StringIO.StringIO(xml)
+ sio = StringIO(xml)
p = STIXPackage.from_xml(sio)
- with warnings.catch_warnings():
- warnings.simplefilter('ignore')
- serialized = p.to_xml()
-
+ serialized = p.to_xml()
e = lxml.etree.XML(serialized)
self.assertEqual(e.nsmap.get('TEST'), 'a:test')
self.assertEqual(e.nsmap.get('FOO'), 'a:foo')
@@ -181,4 +113,4 @@ def test_parsed_namespaces(self):
if __name__ == "__main__":
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/stix/threat_actor/__init__.py b/stix/threat_actor/__init__.py
index 53346b94..8ee721af 100644
--- a/stix/threat_actor/__init__.py
+++ b/stix/threat_actor/__init__.py
@@ -1,44 +1,64 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# mixbox
+from mixbox import fields
+
+# internal
import stix
-from stix.data_marking import Marking
import stix.bindings.threat_actor as threat_actor_binding
-from stix.common import vocabs, Confidence, Identity, Statement
+from stix.common import vocabs, Confidence, Statement
+from stix.common.identity import Identity, IdentityFactory
from stix.common.related import (
GenericRelationshipList, RelatedCampaign, RelatedPackageRefs, RelatedTTP,
RelatedThreatActor
)
+from stix.common.statement import StatementField
+from stix.common.information_source import InformationSource
+
class ObservedTTPs(GenericRelationshipList):
_namespace = 'http://stix.mitre.org/ThreatActor-1'
_binding = threat_actor_binding
_binding_class = threat_actor_binding.ObservedTTPsType
- _binding_var = "Observed_TTP"
- _contained_type = RelatedTTP
- _inner_name = "ttps"
+
+ observed_ttp = fields.TypedField("Observed_TTP", RelatedTTP, multiple=True, key_name="ttps")
class AssociatedActors(GenericRelationshipList):
_namespace = 'http://stix.mitre.org/ThreatActor-1'
_binding = threat_actor_binding
_binding_class = threat_actor_binding.AssociatedActorsType
- _binding_var = "Associated_Actor"
- _contained_type = RelatedThreatActor
- _inner_name = "threat_actors"
+
+ associated_actor = fields.TypedField("Associated_Actor", RelatedThreatActor, multiple=True, key_name="threat_actors")
class AssociatedCampaigns(GenericRelationshipList):
_namespace = 'http://stix.mitre.org/ThreatActor-1'
_binding = threat_actor_binding
_binding_class = threat_actor_binding.AssociatedCampaignsType
- _binding_var = "Associated_Campaign"
- _contained_type = RelatedCampaign
- _inner_name = "campaigns"
+
+ associated_campaign = fields.TypedField("Associated_Campaign", RelatedCampaign, multiple=True, key_name="campaigns")
class ThreatActor(stix.BaseCoreComponent):
+ """Implementation of the STIX Threat Actor.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref (optional): An identifier reference. If set this will unset the
+ ``id_`` property.
+ timestamp (optional): A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ description: A description of the purpose or intent of this object.
+ short_description: A short description of the intent
+ or purpose of this object.
+ title: The title of this object.
+
+ """
_binding = threat_actor_binding
_binding_class = threat_actor_binding.ThreatActorType
_namespace = 'http://stix.mitre.org/ThreatActor-1'
@@ -46,6 +66,19 @@ class ThreatActor(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = 'threatactor'
+ identity = fields.TypedField("Identity", Identity, factory=IdentityFactory)
+ types = StatementField("Type", Statement, vocab_type=vocabs.ThreatActorType, multiple=True, key_name="types")
+ motivations = StatementField("Motivation", Statement, vocab_type=vocabs.Motivation, multiple=True, key_name="motivations")
+ sophistications = StatementField("Sophistication", Statement, vocab_type=vocabs.ThreatActorSophistication, multiple=True, key_name="sophistications")
+ intended_effects = StatementField("Intended_Effect", Statement, vocab_type=vocabs.IntendedEffect, multiple=True, key_name="intended_effects")
+ planning_and_operational_supports = StatementField("Planning_And_Operational_Support", Statement, vocab_type=vocabs.PlanningAndOperationalSupport, multiple=True, key_name="planning_and_operational_supports")
+ confidence = fields.TypedField("Confidence", Confidence)
+ observed_ttps = fields.TypedField("Observed_TTPs", ObservedTTPs)
+ associated_campaigns = fields.TypedField("Associated_Campaigns", AssociatedCampaigns)
+ associated_actors = fields.TypedField("Associated_Actors", AssociatedActors)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -58,209 +91,53 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.identity = None
- self.types = None
- self.motivations = None
- self.sophistications = None
- self.intended_effects = None
- self.planning_and_operational_supports = None
- self.handling = None
- self.confidence = None
self.observed_ttps = ObservedTTPs()
self.associated_campaigns = AssociatedCampaigns()
self.associated_actors = AssociatedActors()
self.related_packages = RelatedPackageRefs()
-
- @property
- def identity(self):
- return self._identity
-
- @identity.setter
- def identity(self, value):
- self._set_var(Identity, try_cast=False, identity=value)
-
- @property
- def types(self):
- return self._types
-
- @types.setter
- def types(self, value):
- self._types = _Types(value)
def add_type(self, value):
- self.types.append(value)
+ """Adds a :class:`.VocabString` object to the :attr:`types` collection.
- @property
- def motivations(self):
- return self._motivations
-
- @motivations.setter
- def motivations(self, value):
- self._motivations = _Motivations(value)
+ If set to a string, an attempt will be made to convert it into an
+ instance of :class:`.ThreatActorType`.
+
+ """
+ self.types.append(value)
def add_motivation(self, value):
+ """Adds a :class:`.Motivation` object to the :attr:`motivations`
+ collection.
+
+ """
self.motivations.append(value)
- @property
- def sophistications(self):
- return self._sophistications
-
- @sophistications.setter
- def sophistications(self, value):
- self._sophistications = _Sophistications(value)
-
def add_sophistication(self, value):
- self._sophistications.append(value)
+ """Adds a :class:`.VocabString` object to the :attr:`sophistications`
+ collection.
- @property
- def intended_effects(self):
- return self._intended_effects
-
- @intended_effects.setter
- def intended_effects(self, value):
- self._intended_effects = _IntendedEffects(value)
-
- def add_intended_effect(self, value):
- self.intended_effects.append(value)
+ If `value` is a string, an attempt will be made to convert it to an
+ instance of :class:`.ThreatActorSophistication`.
- @property
- def planning_and_operational_supports(self):
- return self._planning_and_operational_supports
-
- @planning_and_operational_supports.setter
- def planning_and_operational_supports(self, value):
- self._planning_and_operational_supports = _PlanningAndOperationalSupports(value)
+ """
+ self.sophistications.append(value)
- def add_planning_and_operational_support(self, value):
- self.planning_and_operational_supports.append(value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
-
- super(ThreatActor, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if self.identity:
- return_obj.Identity = self.identity.to_obj(ns_info=ns_info)
- if self.types:
- return_obj.Type = self.types.to_obj(ns_info=ns_info)
- if self.motivations:
- return_obj.Motivation = self.motivations.to_obj(ns_info=ns_info)
- if self.sophistications:
- return_obj.Sophistication = self.sophistications.to_obj(ns_info=ns_info)
- if self.intended_effects:
- return_obj.Intended_Effect = self.intended_effects.to_obj(ns_info=ns_info)
- if self.planning_and_operational_supports:
- return_obj.Planning_And_Operational_Support = \
- self.planning_and_operational_supports.to_obj(ns_info=ns_info)
- if self.observed_ttps:
- return_obj.Observed_TTPs = self.observed_ttps.to_obj(ns_info=ns_info)
- if self.associated_campaigns:
- return_obj.Associated_Campaigns = self.associated_campaigns.to_obj(ns_info=ns_info)
- if self.associated_actors:
- return_obj.Associated_Actors = self.associated_actors.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
- if self.confidence:
- return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info)
- if self.related_packages:
- return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- super(ThreatActor, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class): # ThreatActorType properties
- return_obj.identity = Identity.from_obj(obj.Identity)
- return_obj.types = _Types.from_obj(obj.Type)
- return_obj.motivations = _Motivations.from_obj(obj.Motivation)
- return_obj.sophistications = _Sophistications.from_obj(obj.Sophistication)
- return_obj.intended_effects = _IntendedEffects.from_obj(obj.Intended_Effect)
- return_obj.planning_and_operational_supports = \
- _PlanningAndOperationalSupports.from_obj(obj.Planning_And_Operational_Support)
- return_obj.observed_ttps = ObservedTTPs.from_obj(obj.Observed_TTPs)
- return_obj.associated_campaigns = AssociatedCampaigns.from_obj(obj.Associated_Campaigns)
- return_obj.associated_actors = AssociatedActors.from_obj(obj.Associated_Actors)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.confidence = Confidence.from_obj(obj.Confidence)
- return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages)
-
- return return_obj
-
- def to_dict(self):
- return super(ThreatActor, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(ThreatActor, cls).from_dict(dict_repr, return_obj=return_obj)
-
- get = dict_repr.get
- return_obj.identity = Identity.from_dict(get('identity'))
- return_obj.types = _Types.from_dict(get('types'))
- return_obj.motivations = _Motivations.from_dict(get('motivations'))
- return_obj.sophistications = _Sophistications.from_dict(get('sophistications'))
- return_obj.intended_effects = _IntendedEffects.from_dict(get('intended_effects'))
- return_obj.planning_and_operational_supports = \
- _PlanningAndOperationalSupports.from_dict(get('planning_and_operational_supports'))
- return_obj.observed_ttps = ObservedTTPs.from_dict(get('observed_ttps'))
- return_obj.associated_campaigns = AssociatedCampaigns.from_dict(get('associated_campaigns'))
- return_obj.associated_actors = AssociatedActors.from_dict(get('associated_actors'))
- return_obj.handling = Marking.from_dict(get('handling'))
- return_obj.confidence = Confidence.from_dict(get('confidence'))
- return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages'))
-
- return return_obj
-
-
-# NOT ACTUAL STIX TYPES!
-class _Sophistications(stix.TypedList):
- _contained_type = Statement
-
- def _fix_value(self, value):
- sophistication = vocabs.ThreatActorSophistication(value)
- return Statement(value=sophistication)
-
-
-class _Motivations(stix.TypedList):
- _contained_type = Statement
-
- def _fix_value(self, value):
- motivation = vocabs.Motivation(value)
- return Statement(value=motivation)
-
-
-class _IntendedEffects(stix.TypedList):
- _contained_type = Statement
-
- def _fix_value(self, value):
- intended_effect = vocabs.IntendedEffect(value)
- return Statement(value=intended_effect)
-
+ def add_intended_effect(self, value):
+ """Adds a :class:`.Statement` object to the :attr:`intended_effects`
+ collection.
-class _PlanningAndOperationalSupports(stix.TypedList):
- _contained_type = Statement
+ If `value` is a string, an attempt will be made to convert it into an
+ instance of :class:`.Statement`.
- def _fix_value(self, value):
- pos = vocabs.PlanningAndOperationalSupport(value)
- return Statement(value=pos)
+ """
+ self.intended_effects.append(value)
+ def add_planning_and_operational_support(self, value):
+ """Adds a :class:`.VocabString` object to the
+ :attr:`planning_and_operational_supports` collection.
-class _Types(stix.TypedList):
- _contained_type = Statement
+ If `value` is a string, an attempt will be made to convert it to an
+ instance of :class:`.PlanningAndOperationalSupport`.
- def _fix_value(self, value):
- type_ = vocabs.ThreatActorType(value)
- return Statement(value=type_)
+ """
+ self.planning_and_operational_supports.append(value)
diff --git a/stix/ttp/__init__.py b/stix/ttp/__init__.py
index 19656ffa..d019545c 100644
--- a/stix/ttp/__init__.py
+++ b/stix/ttp/__init__.py
@@ -1,19 +1,43 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
# internal
import stix
import stix.bindings.ttp as ttp_binding
-from stix.common import vocabs, Statement
-from stix.data_marking import Marking
+from stix.common import vocabs
+from stix.common import Statement
+from stix.common.kill_chains import KillChainPhasesReference
+from stix.common.related import RelatedPackageRefs
+from stix.common.statement import StatementField
+from stix.ttp.related_ttps import RelatedTTPs
+from stix.ttp.exploit_targets import ExploitTargets
# relative
from .behavior import Behavior
from .resource import Resource
from .victim_targeting import VictimTargeting
+from stix.common.information_source import InformationSource
class TTP(stix.BaseCoreComponent):
+ """Implementation of the STIX TTP.
+
+ Args:
+ id_ (optional): An identifier. If ``None``, a value will be generated
+ via ``mixbox.idgen.create_id()``. If set, this will unset the
+ ``idref`` property.
+ idref (optional): An identifier reference. If set this will unset the
+ ``id_`` property.
+ timestamp (optional): A timestamp value. Can be an instance of
+ ``datetime.datetime`` or ``str``.
+ description: A description of the purpose or intent of this object.
+ short_description: A short description of the intent
+ or purpose of this object.
+ title: The title of this object.
+
+ """
_binding = ttp_binding
_binding_class = _binding.TTPType
_namespace = "http://stix.mitre.org/TTP-1"
@@ -21,6 +45,16 @@ class TTP(stix.BaseCoreComponent):
_ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1")
_ID_PREFIX = "ttp"
+ behavior = fields.TypedField("Behavior", Behavior)
+ related_ttps = fields.TypedField("Related_TTPs", RelatedTTPs)
+ intended_effects = StatementField("Intended_Effect", Statement, vocab_type=vocabs.IntendedEffect, multiple=True)
+ resources = fields.TypedField("Resources", Resource)
+ victim_targeting = fields.TypedField("Victim_Targeting", VictimTargeting)
+ exploit_targets = fields.TypedField("Exploit_Targets", ExploitTargets)
+ related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs)
+ kill_chain_phases = fields.TypedField("Kill_Chain_Phases", KillChainPhasesReference)
+ information_source = fields.TypedField("Information_Source", InformationSource)
+
def __init__(self, id_=None, idref=None, timestamp=None, title=None,
description=None, short_description=None):
@@ -33,156 +67,82 @@ def __init__(self, id_=None, idref=None, timestamp=None, title=None,
short_description=short_description
)
- self.behavior = None
- self.related_ttps = None
- self.intended_effects = None
- self.resources = None
- self.victim_targeting = None
- self.handling = None
+ self.related_packages = RelatedPackageRefs()
self.exploit_targets = ExploitTargets()
+ self.related_ttps = RelatedTTPs()
+ self.kill_chain_phases = KillChainPhasesReference()
- @property
- def behavior(self):
- return self._behavior
-
- @behavior.setter
- def behavior(self, value):
- self._set_var(Behavior, try_cast=False, behavior=value)
-
- @property
- def related_ttps(self):
- return self._related_ttps
-
- @related_ttps.setter
- def related_ttps(self, value):
- if isinstance(value, RelatedTTPs):
- self._related_ttps = value
- else:
- self._related_ttps = RelatedTTPs(value)
-
- @property
- def exploit_targets(self):
- return self._exploit_targets
+ def add_related_ttp(self, value):
+ """Adds an Related TTP to the :attr:`related_ttps` list
+ property of this :class:`TTP`.
- @exploit_targets.setter
- def exploit_targets(self, value):
- if isinstance(value, ExploitTargets):
- self._exploit_targets = value
- else:
- self._exploit_targets = ExploitTargets(value)
-
- @property
- def intended_effects(self):
- return self._intended_effects
-
- @intended_effects.setter
- def intended_effects(self, value):
- self._intended_effects = _IntendedEffects(value)
-
- def add_intended_effect(self, value):
- self.intended_effects.append(value)
+ The `TTP` parameter must be an instance of
+ :class:`.RelatedTTP` or :class:`TTP`.
- @property
- def resources(self):
- return self._resources
+ If the `TTP` parameter is ``None``, no item wil be added to the
+ ``related_ttps`` list property.
- @resources.setter
- def resources(self, value):
- self._set_var(Resource, resources=value)
+ Calling this method is the same as calling ``append()`` on the
+ ``related_ttps`` property.
- @property
- def victim_targeting(self):
- return self._victim_targeting
+ See Also:
+ The :class:`RelatedTTPs` documentation.
- @victim_targeting.setter
- def victim_targeting(self, value):
- self._set_var(VictimTargeting, try_cast=False, victim_targeting=value)
+ Note:
+ If the `TTP` parameter is not an instance of
+ :class:`.RelatedTTP` an attempt will be
+ made to convert it to one.
- @property
- def handling(self):
- return self._handling
+ Args:
+ value: An instance of :class:`TTP` or
+ :class:`.RelatedTTP`.
- @handling.setter
- def handling(self, value):
- self._set_var(Marking, try_cast=False, handling=value)
+ Raises:
+ ValueError: If the `TTP` parameter cannot be converted into
+ an instance of :class:`.RelatedTTP`
- def to_obj(self, return_obj=None, ns_info=None):
- if not return_obj:
- return_obj = self._binding_class()
+ """
+ self.related_ttps.append(value)
- super(TTP, self).to_obj(return_obj=return_obj, ns_info=ns_info)
+ def add_exploit_target(self, value):
+ """Adds a :class:`.ExploitTarget` object to the :attr:`exploit_targets`
+ collection.
- if self.behavior:
- return_obj.Behavior = self.behavior.to_obj(ns_info=ns_info)
- if self.related_ttps:
- return_obj.Related_TTPs = self.related_ttps.to_obj(ns_info=ns_info)
- if self.exploit_targets:
- return_obj.Exploit_Targets = self.exploit_targets.to_obj(ns_info=ns_info)
- if self.intended_effects:
- return_obj.Intended_Effect = self.intended_effects.to_obj(ns_info=ns_info)
- if self.resources:
- return_obj.Resources = self.resources.to_obj(ns_info=ns_info)
- if self.victim_targeting:
- return_obj.Victim_Targeting = self.victim_targeting.to_obj(ns_info=ns_info)
- if self.handling:
- return_obj.Handling = self.handling.to_obj(ns_info=ns_info)
+ """
+ self.exploit_targets.append(value)
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- super(TTP, cls).from_obj(obj, return_obj=return_obj)
-
- if isinstance(obj, cls._binding_class):
- return_obj.behavior = Behavior.from_obj(obj.Behavior)
- return_obj.related_ttps = RelatedTTPs.from_obj(obj.Related_TTPs)
- return_obj.exploit_targets = ExploitTargets.from_obj(obj.Exploit_Targets)
- return_obj.resources = Resource.from_obj(obj.Resources)
- return_obj.victim_targeting = VictimTargeting.from_obj(obj.Victim_Targeting)
- return_obj.handling = Marking.from_obj(obj.Handling)
- return_obj.intended_effects = _IntendedEffects.from_obj(obj.Intended_Effect)
-
- return return_obj
-
- def to_dict(self):
- return super(TTP, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
+ def add_intended_effect(self, value):
+ """Adds a :class:`.Statement` object to the :attr:`intended_effects`
+ collection.
- super(TTP, cls).from_dict(dict_repr, return_obj=return_obj)
+ If `value` is a string, an attempt will be made to convert it into an
+ instance of :class:`.Statement`.
- get = dict_repr.get
- return_obj.behavior = Behavior.from_dict(get('behavior'))
- return_obj.related_ttps = RelatedTTPs.from_dict(get('related_ttps'))
- return_obj.exploit_targets = ExploitTargets.from_dict(get('exploit_targets'))
- return_obj.intended_effects = _IntendedEffects.from_dict(get('intended_effects'))
- return_obj.resources = Resource.from_dict(get('resources'))
- return_obj.victim_targeting = VictimTargeting.from_dict(get('victim_targeting'))
- return_obj.handling = Marking.from_dict(get('handling'))
+ """
+ self.intended_effects.append(value)
- return return_obj
+ def add_kill_chain_phase(self, value):
+ """Adds a :class:`.KillChainPhaseReference` to the
+ :attr:`kill_chain_phases` collection.
+ Args:
+ value: A :class:`.KillChainPhase`, :class:`.KillChainPhaseReference`
+ or a ``str`` representing the phase_id of. Note that you if you
+ are defining a custom Kill Chain, you need to add it to the
+ STIX package separately.
+ """
+ self.kill_chain_phases.append(value)
-# NOT ACTUAL STIX TYPE
-class _IntendedEffects(stix.TypedList):
- _contained_type = Statement
+ def add_related_package(self, value):
+ """Adds a :class:`.RelatedPackageRef` object to the
+ :attr:`related_packages` collection.
- def _fix_value(self, value):
- intended_effect = vocabs.IntendedEffect(value)
- return Statement(value=intended_effect)
+ Args:
+ value: A :class:`.RelatedPackageRef` or a :class:`.STIXPackage`
+ object.
+ """
+ self.related_packages.append(value)
# Avoid circular imports
from .related_ttps import RelatedTTPs
diff --git a/stix/ttp/attack_pattern.py b/stix/ttp/attack_pattern.py
index eef1b585..cf950086 100644
--- a/stix/ttp/attack_pattern.py
+++ b/stix/ttp/attack_pattern.py
@@ -1,93 +1,33 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# internal
import stix
from stix.common import StructuredText
+
+# bindings
import stix.bindings.ttp as ttp_binding
+from mixbox import fields
+
class AttackPattern(stix.Entity):
_binding = ttp_binding
_binding_class = _binding.AttackPatternType
_namespace = "http://stix.mitre.org/TTP-1"
- def __init__(self, id_=None, title=None, description=None, short_description=None):
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ title = fields.TypedField("Title")
+ capec_id = fields.TypedField("capec_id")
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+
+ def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None):
+ super(AttackPattern, self).__init__()
+
self.id_ = id_
- self.capec_id = None
+ self.idref = idref
self.title = title
self.description = description
self.short_description = short_description
-
- @property
- def title(self):
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(AttackPattern, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.capec_id = self.capec_id
- return_obj.Title = self.title
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.capec_id = obj.capec_id
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
-
- return return_obj
-
- def to_dict(self):
- return super(AttackPattern, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = dict_repr.get('id')
- return_obj.capec_id = dict_repr.get('capec_id')
- return_obj.title = dict_repr.get('title')
- return_obj.description = StructuredText.from_dict(dict_repr.get('description'))
- return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description'))
-
- return return_obj
diff --git a/stix/ttp/behavior.py b/stix/ttp/behavior.py
index f564c5b9..35861e53 100644
--- a/stix/ttp/behavior.py
+++ b/stix/ttp/behavior.py
@@ -1,9 +1,14 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+
+# mixbox
+from mixbox import fields
+
+# stix
import stix
import stix.bindings.ttp as ttp_binding
-from .malware_instance import MalwareInstance
+from .malware_instance import MalwareInstance, MalwareInstanceFactory
from .exploit import Exploit
from .attack_pattern import AttackPattern
@@ -13,117 +18,47 @@ class Behavior(stix.Entity):
_binding_class = _binding.BehaviorType
_namespace = "http://stix.mitre.org/TTP-1"
- def __init__(self, malware_instances=None, attack_patterns=None, exploits=None):
- self.malware_instances = malware_instances
- self.attack_patterns = attack_patterns
- self.exploits = exploits
+ malware_instances = fields.TypedField("Malware", type_="stix.ttp.behavior.MalwareInstances", key_name="malware_instances")
+ attack_patterns = fields.TypedField("Attack_Patterns", type_="stix.ttp.behavior.AttackPatterns")
+ exploits = fields.TypedField("Exploits", type_="stix.ttp.behavior.Exploits")
- @property
- def malware_instances(self):
- return self._malware_instances
+ def __init__(self, malware_instances=None, attack_patterns=None, exploits=None):
+ super(Behavior, self).__init__()
+ self.malware_instances = malware_instances or MalwareInstances()
+ self.attack_patterns = attack_patterns or AttackPatterns()
+ self.exploits = exploits or Exploits()
- @malware_instances.setter
- def malware_instances(self, value):
- self._malware_instances = MalwareInstances(value)
def add_malware_instance(self, malware):
self.malware_instances.append(malware)
- @property
- def attack_patterns(self):
- return self._attack_patterns
-
- @attack_patterns.setter
- def attack_patterns(self, value):
- self._attack_patterns = AttackPatterns(value)
-
def add_attack_pattern(self, attack_pattern):
self.attack_patterns.append(attack_pattern)
- @property
- def exploits(self):
- return self._exploits
-
- @exploits.setter
- def exploits(self, value):
- self._exploits = Exploits(value)
-
def add_exploit(self, exploit):
self.exploits.append(exploit)
- def to_obj(self, return_obj=None, ns_info=None):
- super(Behavior, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.malware_instances:
- return_obj.Malware = self.malware_instances.to_obj(ns_info=ns_info)
- if self.exploits:
- return_obj.Exploits = self.exploits.to_obj(ns_info=ns_info)
- if self.attack_patterns:
- return_obj.Attack_Patterns = self.attack_patterns.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.malware_instances = MalwareInstances.from_obj(obj.Malware)
- return_obj.exploits = Exploits.from_obj(obj.Exploits)
- return_obj.attack_patterns = AttackPatterns.from_obj(obj.Attack_Patterns)
-
- return return_obj
-
- def to_dict(self):
- return super(Behavior, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
-
- return_obj.malware_instances = MalwareInstances.from_dict(get('malware_instances'))
- return_obj.exploits = Exploits.from_dict(get('exploits'))
- return_obj.attack_patterns = AttackPatterns.from_dict(get('attack_patterns'))
-
- return return_obj
-
class Exploits(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
_contained_type = Exploit
_binding = ttp_binding
_binding_class = _binding.ExploitsType
- _binding_var = "Exploit"
- _inner_name = "exploits"
- _dict_as_list = True
+
+ exploit = fields.TypedField("Exploit", Exploit, multiple=True, key_name="exploits")
class MalwareInstances(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
- _contained_type = MalwareInstance
_binding = ttp_binding
_binding_class = _binding.MalwareType
- _binding_var = "Malware_Instance"
- _inner_name = "malware_instances"
- _dict_as_list = True
+
+ malware_instance = fields.TypedField("Malware_Instance", MalwareInstance, multiple=True, factory=MalwareInstanceFactory, key_name="malware_instances")
class AttackPatterns(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
- _contained_type = AttackPattern
_binding = ttp_binding
_binding_class = _binding.AttackPatternsType
- _binding_var = "Attack_Pattern"
- _inner_name = "attack_patterns"
- _dict_as_list = True
+
+ attack_pattern = fields.TypedField("Attack_Pattern", AttackPattern, multiple=True, key_name="attack_patterns")
diff --git a/stix/ttp/exploit.py b/stix/ttp/exploit.py
index 0d55aaf7..dbd36944 100644
--- a/stix/ttp/exploit.py
+++ b/stix/ttp/exploit.py
@@ -1,90 +1,31 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# internal
import stix
-import stix.utils
from stix.common import StructuredText
+
+# bindings
import stix.bindings.ttp as ttp_binding
+from mixbox import fields
+
class Exploit(stix.Entity):
_binding = ttp_binding
_binding_class = _binding.ExploitType
_namespace = "http://stix.mitre.org/TTP-1"
- def __init__(self, id_=None, title=None, description=None, short_description=None):
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ title = fields.TypedField("Title")
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+
+ def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None):
+ super(Exploit, self).__init__()
self.id_ = id_
+ self.idref = idref
self.title = title
self.description = description
self.short_description = short_description
-
- @property
- def title(self):
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Exploit, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.Title = self.title
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
-
- return return_obj
-
- def to_dict(self):
- return super(Exploit, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = dict_repr.get('id')
- return_obj.title = dict_repr.get('title')
- return_obj.description = StructuredText.from_dict(dict_repr.get('description'))
- return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description'))
-
- return return_obj
diff --git a/stix/ttp/exploit_targets.py b/stix/ttp/exploit_targets.py
index 3caf4206..24b165f6 100644
--- a/stix/ttp/exploit_targets.py
+++ b/stix/ttp/exploit_targets.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix.bindings.ttp as ttp_binding
from stix.common.related import GenericRelationshipList, RelatedExploitTarget
@@ -9,6 +11,5 @@ class ExploitTargets(GenericRelationshipList):
_namespace = "http://stix.mitre.org/TTP-1"
_binding = ttp_binding
_binding_class = _binding.ExploitTargetsType
- _binding_var = "Exploit_Target"
- _contained_type = RelatedExploitTarget
- _inner_name = "exploit_targets"
+
+ exploit_target = fields.TypedField("Exploit_Target", RelatedExploitTarget, multiple=True, key_name="exploit_targets")
diff --git a/stix/ttp/infrastructure.py b/stix/ttp/infrastructure.py
index d067ce01..d43428d0 100644
--- a/stix/ttp/infrastructure.py
+++ b/stix/ttp/infrastructure.py
@@ -1,7 +1,10 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# external
+# mixbox
+from mixbox import fields
+
+# cybox
from cybox.core import Observables
# internal
@@ -16,119 +19,36 @@ class Infrastructure(stix.Entity):
_binding_class = _binding.InfrastructureType
_namespace = "http://stix.mitre.org/TTP-1"
- def __init__(self, id_=None, title=None, description=None, short_description=None):
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ title = fields.TypedField("Title")
+ description = fields.TypedField("Description", StructuredText)
+ short_description = fields.TypedField("Short_Description", StructuredText)
+ types = fields.TypedField("Type", VocabString, multiple=True, key_name="types")
+ observable_characterization = fields.TypedField("Observable_Characterization", Observables)
+
+ def __init__(self, id_=None, idref=None, title=None, description=None,
+ short_description=None):
+
+ super(Infrastructure, self).__init__()
+
self.id_ = id_
+ self.idref = idref
self.title = title
self.description = description
self.short_description = short_description
- self.types = None
- self.observable_characterization = None
-
- @property
- def title(self):
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- @property
- def types(self):
- return self._types
-
- @types.setter
- def types(self, value):
- self._types = InfraStructureTypes(value)
def add_type(self, type_):
self.types.append(type_)
- @property
- def observable_characterization(self):
- return self._observable_characterization
-
- @observable_characterization.setter
- def observable_characterization(self, value):
- self._set_var(Observables, observable_characterization=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Infrastructure, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- return_obj.id = self.id_
- return_obj.Title = self.title
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.types:
- return_obj.Type = [x.to_obj(ns_info=ns_info) for x in self.types]
- if self.observable_characterization:
- return_obj.Observable_Characterization = self.observable_characterization.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = obj.id
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.observable_characterization = Observables.from_obj(obj.Observable_Characterization)
-
- if obj.Type:
- return_obj.types = [VocabString.from_obj(x) for x in obj.Type]
-
- return return_obj
-
- def to_dict(self):
- return super(Infrastructure, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.id_ = dict_repr.get('id')
- return_obj.title = dict_repr.get('title')
- return_obj.description = StructuredText.from_dict(dict_repr.get('description'))
- return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description'))
- return_obj.types = [VocabString.from_dict(x) for x in dict_repr.get('types', [])]
- return_obj.observable_characterization = Observables.from_dict(dict_repr.get('observable_characterization'))
-
- return return_obj
-
class InfraStructureTypes(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
_contained_type = VocabString
- _dict_as_list = True
+
+ @classmethod
+ def _dict_as_list(cls):
+ return True
def _fix_value(self, value):
return AttackerInfrastructureType(value)
diff --git a/stix/ttp/malware_instance.py b/stix/ttp/malware_instance.py
index fc921471..14c301ea 100644
--- a/stix/ttp/malware_instance.py
+++ b/stix/ttp/malware_instance.py
@@ -1,175 +1,67 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# internal
import stix
-import stix.utils as utils
-from stix.common import vocabs, StructuredText, VocabString
+from stix.common import vocabs
+from stix.common import StructuredText, VocabString
+
+# bindings
import stix.bindings.ttp as ttp_binding
+from mixbox import fields, entities
+
class MalwareInstance(stix.Entity):
_binding = ttp_binding
_binding_class = _binding.MalwareInstanceType
_namespace = "http://stix.mitre.org/TTP-1"
-
- def __init__(self, id_=None, title=None, description=None, short_description=None):
+ _XSI_TYPE = None # defined by subclasses
+
+ id_ = fields.IdField("id")
+ idref = fields.IdrefField("idref")
+ title = fields.TypedField("Title")
+ description = fields.TypedField("Description", type_="stix.common.StructuredText")
+ short_description = fields.TypedField("Short_Description", type_="stix.common.StructuredText")
+ names = vocabs.VocabField("Name", type_=VocabString, multiple=True, key_name="names")
+ types = vocabs.VocabField("Type", type_=vocabs.MalwareType, multiple=True, key_name="types")
+
+ def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None):
+ super(MalwareInstance, self).__init__()
self.id_ = id_
+ self.idref = idref
self.title = title
self.description = description
self.short_description = short_description
- self.names = None
- self.types = None
-
- @property
- def title(self):
- return self._title
-
- @title.setter
- def title(self, value):
- self._title = value
-
- @property
- def description(self):
- return self._description
-
- @description.setter
- def description(self, value):
- self._set_var(StructuredText, description=value)
-
- @property
- def short_description(self):
- return self._short_description
-
- @short_description.setter
- def short_description(self, value):
- self._set_var(StructuredText, short_description=value)
-
- @property
- def names(self):
- return self._names
-
- @names.setter
- def names(self, value):
- self._names = MalwareNames(value)
def add_name(self, name):
- self._names.append(name)
-
- @property
- def types(self):
- return self._types
-
- @types.setter
- def types(self, value):
- self._types = MalwareTypes(value)
+ self.names.append(name)
def add_type(self, type_):
- self._types.append(type_)
+ self.types.append(type_)
@staticmethod
def lookup_class(xsi_type):
if not xsi_type:
raise ValueError("xsi:type is required")
- for (k, v) in _EXTENSION_MAP.iteritems():
- # TODO: for now we ignore the prefix and just check for
- # a partial match
- if xsi_type in k:
- return v
-
- raise ValueError("Unregistered xsi:type %s" % xsi_type)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(MalwareInstance, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
- return_obj.id = self.id_
- return_obj.Title = self.title
-
- if self.description:
- return_obj.Description = self.description.to_obj(ns_info=ns_info)
- if self.short_description:
- return_obj.Short_Description = self.short_description.to_obj(ns_info=ns_info)
- if self.names:
- return_obj.Name = self.names.to_obj(ns_info=ns_info)
- if self.types:
- return_obj.Type = self.types.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- from stix.extensions.malware import maec_4_1_malware # noqa
-
- if not obj:
- return None
-
- if not return_obj:
- try:
- klass = MalwareInstance.lookup_class(obj.xml_type)
- return_obj = klass.from_obj(obj)
- except AttributeError:
- return_obj = MalwareInstance.from_obj(obj, cls())
- else:
- return_obj.id_ = obj.id
- return_obj.title = obj.Title
- return_obj.description = StructuredText.from_obj(obj.Description)
- return_obj.short_description = StructuredText.from_obj(obj.Short_Description)
- return_obj.names = MalwareNames.from_obj(obj.Name)
- return_obj.types = MalwareTypes.from_obj(obj.Type)
-
- return return_obj
+ return stix.lookup_extension(xsi_type)
def to_dict(self):
- d = utils.to_dict(self)
+ d = super(MalwareInstance, self).to_dict()
- if getattr(self, '_XSI_TYPE', None):
- d['xsi:type'] = self._XSI_TYPE
+ if self._XSI_TYPE:
+ d["xsi:type"] = self._XSI_TYPE
return d
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- from stix.extensions.malware import maec_4_1_malware # noqa
-
- if not dict_repr:
- return None
-
- get = dict_repr.get
-
- if not return_obj:
- xsi_type = get('xsi:type')
- if xsi_type:
- klass = MalwareInstance.lookup_class(get('xsi:type'))
- return_obj = klass.from_dict(dict_repr)
- else:
- return_obj = MalwareInstance.from_dict(dict_repr, cls())
- else:
- return_obj.id_ = get('id')
- return_obj.title = get('title')
- return_obj.description = StructuredText.from_dict(get('description'))
- return_obj.short_description = StructuredText.from_dict(get('short_description'))
- return_obj.names = MalwareNames.from_dict(get('names'))
- return_obj.types = MalwareTypes.from_dict(get('types'))
-
- return return_obj
-
-class MalwareNames(stix.TypedList):
- _contained_type = VocabString
-
-
-class MalwareTypes(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.MalwareType(value)
-
-
-#: Mapping of malware instance extension types to classes
-_EXTENSION_MAP = {}
+class MalwareInstanceFactory(entities.EntityFactory):
+ @classmethod
+ def entity_class(cls, key):
+ from stix.extensions.malware.maec_4_1_malware import MAECInstance # noqa
+ return stix.lookup_extension(key, default=MalwareInstance)
-def add_extension(cls):
- _EXTENSION_MAP[cls._XSI_TYPE] = cls # noqa
+# Backwards compatibility
+add_extension = stix.add_extension
diff --git a/stix/ttp/related_ttps.py b/stix/ttp/related_ttps.py
index 2dda8cfe..29164739 100644
--- a/stix/ttp/related_ttps.py
+++ b/stix/ttp/related_ttps.py
@@ -1,6 +1,8 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+from mixbox import fields
+
import stix.bindings.ttp as ttp_binding
from stix.common.related import GenericRelationshipList, RelatedTTP
@@ -9,6 +11,6 @@ class RelatedTTPs(GenericRelationshipList):
_namespace = "http://stix.mitre.org/TTP-1"
_binding = ttp_binding
_binding_class = _binding.RelatedTTPsType
- _binding_var = "Related_TTP"
- _contained_type = RelatedTTP
- _inner_name = "ttps"
+
+ related_ttp = fields.TypedField("Related_TTP", RelatedTTP, multiple=True, key_name="ttps")
+
diff --git a/stix/ttp/resource.py b/stix/ttp/resource.py
index ce63576e..3722355a 100644
--- a/stix/ttp/resource.py
+++ b/stix/ttp/resource.py
@@ -1,122 +1,59 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
+# mixbox
+from mixbox import fields
+from mixbox import typedlist
+
# internal
import stix
-from stix.common import ToolInformation, Identity
+from stix.common import ToolInformation
+from stix.common.identity import Identity, IdentityFactory
import stix.bindings.ttp as ttp_binding
# relative
from .infrastructure import Infrastructure
-class Resource(stix.Entity):
- _binding = ttp_binding
- _binding_class = _binding.ResourceType
- _namespace = "http://stix.mitre.org/TTP-1"
-
- def __init__(self, tools=None, infrastructure=None, personas=None):
- self.tools = tools
- self.infrastructure = infrastructure
- self.personas = personas
-
- @property
- def tools(self):
- return self._tools
-
- @tools.setter
- def tools(self, value):
- self._tools = Tools(value)
-
- def add_tool(self, tool):
- self.tools.append(tool)
-
- @property
- def infrastructure(self):
- return self._infrastructure
-
- @infrastructure.setter
- def infrastructure(self, value):
- self._infrastructure = value
-
- @property
- def personas(self):
- return self._personas
-
- @personas.setter
- def personas(self, value):
- self._personas = Personas(value)
-
- def add_persona(self, persona):
- self.personas.append(persona)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(Resource, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.tools:
- return_obj.Tools = self.tools.to_obj(ns_info=ns_info)
- if self.infrastructure:
- return_obj.Infrastructure = self.infrastructure.to_obj(ns_info=ns_info)
- if self.personas:
- return_obj.Personas = self.personas.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- return_obj.infrastructure = Infrastructure.from_obj(obj.Infrastructure)
- return_obj.tools = Tools.from_obj(obj.Tools)
- return_obj.personas = Personas.from_obj(obj.Personas)
+class _IdentityList(typedlist.TypedList):
+ def __init__(self, *args):
+ super(_IdentityList, self).__init__(type=Identity, *args)
- return return_obj
-
- def to_dict(self):
- return super(Resource, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
-
- return_obj.tools = Tools.from_dict(get('tools'))
- return_obj.infrastructure = Infrastructure.from_dict(get('infrastructure'))
- return_obj.personas = Personas.from_dict(get('personas'))
-
- return return_obj
+ def _fix_value(self, value):
+ return Identity(name=value)
class Personas(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
- _contained_type = Identity
_binding = ttp_binding
_binding_class = _binding.PersonasType
- _binding_var = "Persona"
- _inner_name = "personas"
- _dict_as_list = True
- def _fix_value(self, value):
- return Identity(name=value)
+ persona = fields.TypedField("Persona", Identity, multiple=True, factory=IdentityFactory, listfunc=_IdentityList)
class Tools(stix.EntityList):
_namespace = "http://stix.mitre.org/TTP-1"
- _contained_type = ToolInformation
_binding = ttp_binding
_binding_class = _binding.ToolsType
- _binding_var = "Tool"
- _inner_name = "tools"
- _dict_as_list = True
+
+ tool = fields.TypedField("Tool", ToolInformation, multiple=True)
+
+ @classmethod
+ def _dict_as_list(cls):
+ return True
+
+
+class Resource(stix.Entity):
+ _binding = ttp_binding
+ _binding_class = _binding.ResourceType
+ _namespace = "http://stix.mitre.org/TTP-1"
+
+ tools = fields.TypedField("Tools", Tools)
+ infrastructure = fields.TypedField("Infrastructure", Infrastructure)
+ personas = fields.TypedField("Personas", Personas)
+
+ def __init__(self, tools=None, infrastructure=None, personas=None):
+ super(Resource, self).__init__()
+ self.tools = tools
+ self.infrastructure = infrastructure
+ self.personas = personas
diff --git a/stix/ttp/victim_targeting.py b/stix/ttp/victim_targeting.py
index 738d7e6c..5e3a03d0 100644
--- a/stix/ttp/victim_targeting.py
+++ b/stix/ttp/victim_targeting.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# external
@@ -6,8 +6,10 @@
# internal
import stix
-from stix.common import vocabs, VocabString, Identity
import stix.bindings.ttp as ttp_binding
+from stix.common import vocabs
+from stix.common.identity import Identity, IdentityFactory
+from mixbox import fields
class VictimTargeting(stix.Entity):
@@ -15,102 +17,16 @@ class VictimTargeting(stix.Entity):
_binding_class = _binding.VictimTargetingType
_namespace = "http://stix.mitre.org/TTP-1"
- def __init__(self):
- self.identity = None
- self.targeted_systems = None
- self.targeted_information = None
- self.targeted_technical_details = None
-
- @property
- def targeted_systems(self):
- return self._targeted_systems
+ identity = fields.TypedField("Identity", Identity, factory=IdentityFactory)
+ targeted_systems = vocabs.VocabField("Targeted_Systems", vocabs.SystemType, multiple=True)
+ targeted_information = vocabs.VocabField("Targeted_Information", vocabs.InformationType, multiple=True)
+ targeted_technical_details = fields.TypedField("Targeted_Technical_Details", Observables)
- @targeted_systems.setter
- def targeted_systems(self, value):
- self._targeted_systems = TargetedSystems(value)
+ def __init__(self):
+ super(VictimTargeting, self).__init__()
def add_targeted_system(self, system):
- self._targeted_systems.append(system)
-
- @property
- def targeted_information(self):
- return self._targeted_information
-
- @targeted_information.setter
- def targeted_information(self, value):
- self._targeted_information = TargetedInformation(value)
+ self.targeted_systems.append(system)
def add_targeted_information(self, targeted_information):
- self._targeted_information.append(targeted_information)
-
- @property
- def targeted_technical_details(self):
- return self._targeted_technical_details
-
- @targeted_technical_details.setter
- def targeted_technical_details(self, value):
- self._set_var(Observables, targeted_technical_details=value)
-
- def to_obj(self, return_obj=None, ns_info=None):
- super(VictimTargeting, self).to_obj(return_obj=return_obj, ns_info=ns_info)
-
- if not return_obj:
- return_obj = self._binding_class()
-
- if self.identity:
- return_obj.Identity = self.identity.to_obj(ns_info=ns_info)
- if self.targeted_information:
- return_obj.Targeted_Information = self.targeted_information.to_obj(ns_info=ns_info)
- if self.targeted_systems:
- return_obj.Targeted_Systems = self.targeted_systems.to_obj(ns_info=ns_info)
- if self.targeted_technical_details:
- return_obj.Targeted_Technical_Details = self.targeted_technical_details.to_obj(ns_info=ns_info)
-
- return return_obj
-
- @classmethod
- def from_obj(cls, obj, return_obj=None):
- if not obj:
- return None
- if not return_obj:
- return_obj = cls()
-
- return_obj.identity = Identity.from_obj(obj.Identity)
- return_obj.targeted_technical_details = Observables.from_obj(obj.Targeted_Technical_Details)
- return_obj.targeted_systems = TargetedSystems.from_obj(obj.Targeted_Systems)
- return_obj.targeted_information = TargetedInformation.from_obj(obj.Targeted_Information)
-
- return return_obj
-
- def to_dict(self):
- return super(VictimTargeting, self).to_dict()
-
- @classmethod
- def from_dict(cls, dict_repr, return_obj=None):
- if not dict_repr:
- return None
-
- if not return_obj:
- return_obj = cls()
-
- get = dict_repr.get
- return_obj.identity = Identity.from_dict(get('identity'))
- return_obj.targeted_systems = TargetedSystems.from_dict(get('targeted_systems'))
- return_obj.targeted_information = TargetedInformation.from_dict(get('targeted_information'))
- return_obj.targeted_technical_details = Observables.from_dict(get('targeted_technical_details'))
-
- return return_obj
-
-
-class TargetedSystems(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.SystemType(value)
-
-
-class TargetedInformation(stix.TypedList):
- _contained_type = VocabString
-
- def _fix_value(self, value):
- return vocabs.InformationType(value)
+ self.targeted_information.append(targeted_information)
diff --git a/stix/utils/__init__.py b/stix/utils/__init__.py
index 1422f2ee..bc20610b 100644
--- a/stix/utils/__init__.py
+++ b/stix/utils/__init__.py
@@ -1,19 +1,18 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# stdlib
-import collections
import contextlib
+import functools
import keyword
import warnings
-# external
-import cybox
import lxml.etree
-# internal
+from mixbox.entities import Entity, EntityList
+import mixbox.xml
+from mixbox.vendor.six import iteritems, string_types
+
import stix
-import stix.xmlconst as xmlconst
# relative
from . import dates
@@ -36,7 +35,52 @@ def ignored(*exceptions):
pass
+def raise_warnings(func):
+ """Function decorator that causes all Python warnings to be raised as
+ exceptions in the wrapped function.
+
+ Example:
+ >>> @raise_warnings
+ >>> def foo():
+ >>> warnings.warn("this will raise an exception")
+
+ """
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ with warnings.catch_warnings():
+ warnings.simplefilter('error')
+ return func(*args, **kwargs)
+ return inner
+
+
+def silence_warnings(func):
+ """Function decorator that silences/ignores all Python warnings in the
+ wrapped function.
+
+ Example:
+ >>> @silence_warnings
+ >>> def foo():
+ >>> warnings.warn("this will not appear")
+
+ """
+ @functools.wraps(func)
+ def inner(*args, **kwargs):
+ with warnings.catch_warnings(record=True):
+ warnings.simplefilter('always')
+ return func(*args, **kwargs)
+ return inner
+
+
def is_cdata(text):
+ """Returns ``True`` if `text` contains a CDATA block.
+
+ Example:
+ >>> is_cdata("")
+ True
+ >>> is_cdata("NOPE")
+ False
+
+ """
if not text:
return False
@@ -66,7 +110,7 @@ def strip_cdata(text):
def cdata(text):
- """Wraps the input `text` in a block.
+ """Wraps the input `text` in a ```` block.
If the text contains CDATA sections already, they are stripped and replaced
by the application of an outer-most CDATA block.
@@ -75,7 +119,7 @@ def cdata(text):
text: A string to wrap in a CDATA block.
Returns:
- The `text` value wrapped in
+ The `text` value wrapped in ````
"""
if not text:
@@ -94,24 +138,26 @@ def is_stix(entity):
def is_cybox(entity):
- """Returns true if `entity` is an instance of :class:`cybox.Entity`."""
- return isinstance(entity, cybox.Entity)
+ """Returns true if `entity` is a Cybox object"""
+ try:
+ return entity.__module__.startswith("cybox.")
+ except AttributeError:
+ return False
def is_entity(entity):
"""Returns true if `entity` is an instance of :class:`.Entity` or
- :class:`cybox.Entity`.
-
+ :class:`mixbox.Entity`.
"""
- return isinstance(entity, (cybox.Entity, stix.Entity))
+ return isinstance(entity, (Entity, stix.Entity))
def is_entitylist(entity):
"""Returns true if `entity` is an instance of :class:`.EntityList`
- or :class:`cybox.EntityList`.
+ or :class:`mixbox.entities.EntityList`.
"""
- return isinstance(entity, (cybox.EntityList, stix.EntityList))
+ return isinstance(entity, (EntityList, stix.EntityList))
def is_typedlist(entity):
@@ -176,7 +222,7 @@ def is_sequence(item):
``tuple``). String types will return ``False``.
"""
- return hasattr(item, "__iter__")
+ return hasattr(item, "__iter__") and not isinstance(item, string_types)
def check_version(expected, found):
@@ -207,7 +253,7 @@ def iter_vars(obj):
def check(name):
return name not in ('__input_namespaces__', '__input_schemalocations__')
- instance_vars = obj.__dict__.iteritems()
+ instance_vars = iteritems(vars(obj))
return ((attr_name(name), val) for name, val in instance_vars if check(name))
@@ -231,16 +277,6 @@ def is_bool(obj):
return isinstance(obj, bool)
-def is_element(obj):
- """Returns ``True`` if `obj` is an lxml ``Element``."""
- return isinstance(obj, lxml.etree._Element) # noqa
-
-
-def is_etree(obj):
- """Returns ``True`` if `obj` is an lxml ``ElementTree``."""
- return isinstance(obj, lxml.etree._ElementTree) # noqa
-
-
def has_value(var):
"""Returns ``True`` if `var` is not ``None`` and not empty."""
if var is None:
@@ -249,6 +285,7 @@ def has_value(var):
return bool(var) or (var in (False, 0))
+@silence_warnings
def to_dict(entity, skip=()):
"""Returns a dictionary representation of `entity`. This will iterate over
the instance vars of `entity` and construct keys and values from those
@@ -267,33 +304,26 @@ def to_dict(entity, skip=()):
def dict_iter(items):
return [x.to_dict() if is_dictable(x) else x for x in items]
- def dictify(entity):
- d = {}
- for name, field in iter_vars(entity):
- key = key_name(name)
-
- if key in skip or not has_value(field):
- continue
-
- if is_dictable(field):
- d[key] = field.to_dict()
- elif is_timestamp(field):
- d[key] = dates.serialize_value(field)
- elif is_date(field):
- d[key] = dates.serialize_date(field)
- elif is_element(field) or is_etree(field):
- d[key] = lxml.etree.tostring(field)
- elif is_sequence(field):
- d[key] = dict_iter(field)
- else:
- d[key] = field
-
- return d
d = {}
- with warnings.catch_warnings():
- warnings.simplefilter("ignore")
- d.update(dictify(entity))
+ for name, field in iter_vars(entity):
+ key = key_name(name)
+
+ if key in skip or not has_value(field):
+ continue
+
+ if is_dictable(field):
+ d[key] = field.to_dict()
+ elif is_timestamp(field):
+ d[key] = dates.serialize_value(field)
+ elif is_date(field):
+ d[key] = dates.serialize_date(field)
+ elif mixbox.xml.is_element(field) or mixbox.xml.is_etree(field):
+ d[key] = lxml.etree.tostring(field)
+ elif is_sequence(field):
+ d[key] = dict_iter(field)
+ else:
+ d[key] = field
return d
@@ -307,10 +337,10 @@ def xml_bool(value):
if value is None:
return None
- if value in xmlconst.FALSE:
+ if value in mixbox.xml.FALSE:
return False
- if value in xmlconst.TRUE:
+ if value in mixbox.xml.TRUE:
return True
error = "Unable to determine the xml boolean value of '{0}'".format(value)
@@ -334,9 +364,20 @@ def cast_var(item, klass, arg=None):
return klass(**kwarg) # klass(value='foobar')
+def remove_entries(d, keys):
+ """Removes all the `keys` from the dictionary `d`.
+
+ Args:
+ d: A dictionary.
+ keys: An iterable collection of dictionary keys to remove.
+
+ """
+ for key in keys:
+ d.pop(key, None)
+
+
# Namespace flattening
from .nsparser import * # noqa
from .dates import * # noqa
-from .idgen import * # noqa
-from .nsparser import * # noqa
+from .parser import * # noqa
from .walk import * # noqa
diff --git a/stix/utils/dates.py b/stix/utils/dates.py
index 55fc4cf9..4195cf10 100644
--- a/stix/utils/dates.py
+++ b/stix/utils/dates.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# stdlib
@@ -83,5 +83,5 @@ def serialize_date(value):
def now():
- """Returns the current UTC datetime.datetime."""
+ """Returns the current UTC ``datetime.datetime`` timestamp."""
return datetime.datetime.now(tz=dateutil.tz.tzutc())
diff --git a/stix/utils/nsparser.py b/stix/utils/nsparser.py
index eb4050ec..482bdb50 100644
--- a/stix/utils/nsparser.py
+++ b/stix/utils/nsparser.py
@@ -1,542 +1,52 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-
-# stdlib
-import collections
-import warnings
-import itertools
-
-# external
-import cybox
-import cybox.core
-import cybox.common
-import cybox.utils
-
-# internal
-import stix
-
-# relative
-from . import ignored, idgen
-from .walk import iterwalk
-
-
-class DuplicatePrefixError(Exception):
- def __init__(self, message, prefix, namespaces):
- super(DuplicatePrefixError, self).__init__(message)
- self.prefix = prefix
- self.namespaces = namespaces
-
-
-class NamespaceInfo(object):
- # These appear in every exported document
-
- _BASELINE_NAMESPACES = {
- 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
- 'stix': 'http://stix.mitre.org/stix-1',
- 'stixCommon': 'http://stix.mitre.org/common-1',
- 'stixVocabs': 'http://stix.mitre.org/default_vocabularies-1',
- 'cybox': 'http://cybox.mitre.org/cybox-2',
- 'cyboxCommon': 'http://cybox.mitre.org/common-2',
- 'cyboxVocabs': 'http://cybox.mitre.org/default_vocabularies-2'
- }
-
- def __init__(self):
- # Namespaces that are "collected" from the Python objects during
- # serialization. Key is the namespace alias/prefix. Value is the
- # namespace. There are many classes without a defined prefix, so
- # the ``None`` prefix is predefined as a ``set()``.
- self._collected_namespaces = {None: set()}
-
- # Namespaces and schemalocations that are attached to STIX/CybOX
- # entities when parsed from an external source.
- self._input_namespaces = {}
- self._input_schemalocs = {}
-
- # A list of classes that have been visited/seen during the namespace
- # collection process. This speeds up the collect() method.
- self._collected_classes = set()
-
- # Namespaces and schemalocations that will appear in the output
- # XML document.
- self.finalized_namespaces = None
- self.finalized_schemalocs = None
-
- # Namespace dictionary that gets passed to the bindings.
- self.binding_namespaces = None
-
- def update(self, ns_info):
- self._collected_namespaces.update(ns_info._collected_namespaces) # noqa
- self._input_namespaces.update(ns_info._input_namespaces) # noqa
- self._input_schemalocs.update(ns_info._input_schemalocs) # noqa
-
- def _parse_collected_classes(self):
- collected = self._collected_classes
- entity_klasses = (stix.Entity, cybox.Entity)
-
- # Generator which yields all stix.Entity and cybox.Entity subclasses
- # that were collected.
- entity_subclasses = (
- klass for klass in collected if issubclass(klass, entity_klasses)
- )
-
- # Local function for adding namespaces that have no defined prefix
- # mapping at the class-level. These will be resolved in the
- # self._finalize_namespaces() function.
- no_alias = self._collected_namespaces[None].add
-
- for klass in entity_subclasses:
- # Prevents exception being raised if/when
- # collections.MutableSequence or another base class appears in the
- # MRO.
- ns = getattr(klass, "_namespace", None)
- if not ns:
- continue
-
- # cybox.objects.* ObjectProperties derivations have an _XSI_NS
- # class-level attribute which holds the namespace alias to be
- # used for its namespace.
- alias = getattr(klass, "_XSI_NS", None)
- if alias:
- self._collected_namespaces[alias] = ns
- continue
-
- # Many stix/cybox entity classes have an _XSI_TYPE attribute that
- # contains a `prefix:namespace` formatted QNAME for the
- # associated xsi:type.
- xsi_type = getattr(klass, "_XSI_TYPE", None)
- if not xsi_type:
- no_alias(ns)
- continue
-
- # Attempt to split the xsi:type attribute value into the ns alias
- # and the typename.
- typeinfo = xsi_type.split(":")
- if len(typeinfo) == 2:
- self._collected_namespaces[typeinfo[0]] = ns
- else:
- no_alias(ns)
-
- def _fix_example_namespace(self):
- """Attempts to resolve issues where our samples use
- 'http://example.com/' for our example namespace but python-stix uses
- 'http://example.com' by removing the former.
-
- """
- ex_api_ns = idgen.EXAMPLE_NAMESPACE.keys()[0]
- ex_prefix = 'example' # Example ns prefix
- id_alias = idgen.get_id_namespace_alias()
-
- # If the ID namespace alias doesn't match the example alias, return.
- if id_alias != ex_prefix:
- return
-
- # If the example namespace prefix isn't in the parsed namespace
- # prefixes, return.
- if ex_prefix not in self._input_namespaces:
- return
-
- self._input_namespaces[ex_prefix] = ex_api_ns
-
- def _check_namespaces(self, ns_dict):
- """Check that all the prefixes in `ns_dict` are mapped to only
- one namespace.
-
- Args:
- ns_dict: A ``prefix: [namespaces]`` dictionary.
-
- Raises:
- ` .DuplicatePrefixError: If a prefix is mapped to more than one
- namespace.
-
- """
- for prefix, namespaces in ns_dict.iteritems():
- if len(namespaces) == 1:
- continue
-
- error = "Namespace prefix '{0}' mapped to multiple namespaces: {1}"
- error = error.format(prefix, namespaces)
-
- raise DuplicatePrefixError(
- message=error,
- prefix=prefix,
- namespaces=tuple(namespaces)
- )
-
- def _resolve_unprefixed(self, no_prefix):
- """Resolve namespace aliases for the unprefixed namespaces found on
- collected python-stix objects.
-
- Args:
- A collection of namespaces that were not mapped to a namespace
- prefix by a python Object.
-
- """
- collected_unprefixed = {}
-
- for ns in no_prefix:
- alias = DEFAULT_STIX_NAMESPACES[ns]
- collected_unprefixed[alias] = ns
-
- return collected_unprefixed
-
- def _finalize_namespaces(self, ns_dict=None):
- """Returns a dictionary of namespaces to be exported with an XML
- document.
-
- This loops over all the namespaces that were discovered and built
- during the execution of ``collect()`` and
- ``_parse_collected_classes()`` and attempts to merge them all.
-
- Returns:
- An ``alias: namespace`` dictionary containing all namespaces
- required to be present on an exported document.
-
- Raises:
- .DuplicatePrefixError: If namespace prefix was mapped to more than
- one namespace.
-
- """
- if not ns_dict:
- ns_dict = {}
-
- # Copy and flip the input dictionary from ns=>alias to alias=>ns
- user_namespaces = {}
- for ns, alias in ns_dict.iteritems():
- user_namespaces[alias] = ns
-
- # Our return value
- ns_dict = collections.defaultdict(set)
-
- # Add the ID namespaces
- id_alias = idgen.get_id_namespace_alias()
- id_ns = idgen.get_id_namespace()
- ns_dict[id_alias].add(id_ns)
-
- # Build namespace dictionaries from the collected Entity objects.
- collected_prefixed = dict(self._collected_namespaces.iteritems())
-
- # Pop the unprefixed entries.
- no_prefix = collected_prefixed.pop(None, ())
-
- # Resolve namespace aliases for the unprefixed namespaces.
- collected_unprefixed = self._resolve_unprefixed(no_prefix)
-
- # Remap the example namespace to the one expected by the APIs if the
- # sample example namespace is found.
- self._fix_example_namespace()
-
- # All the namespaces dictionaries we need to merge and export.
- namespace_dicts = itertools.chain(
- self._BASELINE_NAMESPACES.iteritems(),
- self._input_namespaces.iteritems(),
- collected_prefixed.iteritems(),
- collected_unprefixed.iteritems(),
- user_namespaces.iteritems()
- )
-
- # Build our merged namespace dictionary. It will be inspected for
- # duplicate ns prefix mappings.
- for alias, ns in namespace_dicts:
- ns_dict[alias].add(ns)
-
- # Check that all the prefixes are mapped to only one namespace
- self._check_namespaces(ns_dict)
-
- # Flatten the dictionary by popping the namespace from the namespace
- # set values in ns_dict.
- flattened = {}
- for alias, ns_set in ns_dict.iteritems():
- flattened[alias] = ns_set.pop()
-
- # Return the flattened dictionary
- return flattened
-
- def _finalize_schemalocs(self, schemaloc_dict=None):
- # If schemaloc_dict was passed in, make a copy so we don't mistakenly
- # modify the original.
- if schemaloc_dict:
- schemaloc_dict = dict(schemaloc_dict.iteritems())
- else:
- schemaloc_dict = {}
-
- # Get our id namespace
- id_ns = idgen.get_id_namespace()
-
- # Build our schemalocation dictionary!
- #
- # Initialize it from values found in the parsed, input schemalocations
- # (if there are any) and the schemaloc_dict parameter values (if there
- # are any).
- #
- # If there is a schemalocation found in both the parsed schemalocs and
- # the schema_loc dict, use the schemaloc_dict value.
- for ns, loc in self._input_schemalocs.iteritems():
- if ns in schemaloc_dict:
- continue
- schemaloc_dict[ns] = loc
-
- # Iterate over the finalized namespaces for a document and attempt
- # to map them to schemalocations. Warn if the namespace should have a
- # schemalocation and we can't find it anywhere.
- nsset = set(self.finalized_namespaces.itervalues())
- for ns in nsset:
- if ns in DEFAULT_STIX_SCHEMALOCATIONS:
- schemaloc_dict[ns] = DEFAULT_STIX_SCHEMALOCATIONS[ns]
- elif ns in schemaloc_dict:
- continue
- elif (ns == id_ns) or (ns in XML_NAMESPACES):
- continue
- else:
- error = "Unable to map namespace '{0}' to schemaLocation"
- warnings.warn(error.format(ns))
-
- return schemaloc_dict
-
- def _finalize_binding_namespaces(self):
- """Returns a namespace-to-prefix dictionary view of the
- finalized_namespaces (which are mapped prefix-to-namespace).
-
- The bindings expect an NS-to-prefix mapping, while our ns processing
- code builds dictionaries that map prefix-to-Namespace(s). Because of
- this, we need to flip our dictionaries before handing them off to the
- bindings for serialization.
-
- """
- if not self.finalized_namespaces:
- return {} # TODO: Should this return the DEFAULT_STIX_NAMESPACES?
-
- binding_namespaces = {}
- for alias, ns in self.finalized_namespaces.iteritems():
- binding_namespaces[ns] = alias
-
- # Always use the default STIX prefixes for STIX namespaces.
- # This is because of xsi:type prefixes used by the STIX/CybOX user-level
- # API classes.
- binding_namespaces.update(DEFAULT_STIX_NAMESPACES)
-
- return binding_namespaces
-
- def finalize(self, ns_dict=None, schemaloc_dict=None):
- self._parse_collected_classes()
- self.finalized_namespaces = self._finalize_namespaces(ns_dict)
- self.finalized_schemalocs = self._finalize_schemalocs(schemaloc_dict)
- self.binding_namespaces = self._finalize_binding_namespaces()
-
- def collect(self, entity):
- # Collect all the classes we need to inspect for namespace information
- self._collected_classes.update(entity.__class__.__mro__)
-
- # Collect the input namespaces if this entity came from some external
- # source.
- if hasattr(entity, "__input_namespaces__"):
- self._input_namespaces.update(entity.__input_namespaces__)
-
- # Collect the input schemalocation information if this entity came
- # from some external source.
- if hasattr(entity, "__input_schemalocations__"):
- self._input_schemalocs.update(entity.__input_schemalocations__)
-
-
-class NamespaceParser(object):
- def __init__(self):
- pass
-
- def get_namespaces(self, entity, ns_dict=None):
- ns_info = NamespaceInfo()
-
- for node in iterwalk(entity):
- ns_info.collect(node)
-
- ns_info.finalize(ns_dict=ns_dict)
- return ns_info.finalized_namespaces
-
- def get_namespace_schemalocation_dict(self, entity, ns_dict=None, schemaloc_dict=None):
- ns_info = NamespaceInfo()
-
- for node in iterwalk(entity):
- ns_info.collect(node)
-
- ns_info.finalize(ns_dict=ns_dict, schemaloc_dict=schemaloc_dict)
- return ns_info.finalized_schemalocs
-
- def get_xmlns_str(self, ns_dict):
- pairs = sorted(ns_dict.iteritems())
- return "\n\t".join(
- 'xmlns:%s="%s"' % (alias, ns) for alias, ns in pairs
- )
-
- def get_schemaloc_str(self, schemaloc_dict):
- if not schemaloc_dict:
- return ""
-
- schemaloc_str_start = 'xsi:schemaLocation="\n\t'
- schemaloc_str_end = '"'
-
- pairs = sorted(schemaloc_dict.iteritems())
- schemaloc_str_content = "\n\t".join(
- "%s %s" % (ns, loc) for ns, loc in pairs
- )
-
- return schemaloc_str_start + schemaloc_str_content + schemaloc_str_end
-
- def get_namespace_def_str(self, namespaces, schemaloc_dict):
- if not any((namespaces, schemaloc_dict)):
- return ""
-
- parts = (
- self.get_xmlns_str(namespaces),
- self.get_schemaloc_str(schemaloc_dict)
- )
-
- return "\n\t".join(parts)
-
-
-#: Schema locations for standard XML namespaces
-XML_NAMESPACES = {
- 'http://www.w3.org/2001/XMLSchema-instance': 'xsi',
- 'http://www.w3.org/2001/XMLSchema': 'xs',
- 'http://www.w3.org/1999/xlink': 'xlink',
- 'http://www.w3.org/2000/09/xmldsig#': 'ds'
-}
-
-#: Schema locations for namespaces defined by the STIX language
-STIX_NS_TO_SCHEMALOCATION = {
- 'http://data-marking.mitre.org/Marking-1': 'http://stix.mitre.org/XMLSchema/data_marking/1.1.1/data_marking.xsd',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#Simple-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/simple/1.1.1/simple_marking.xsd',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/tlp/1.1.1/tlp_marking.xsd',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#Terms_Of_Use-1': 'http://stix.mitre.org/XMLSchema/extensions/marking/terms_of_use/1.0.1/terms_of_use_marking.xsd',
- 'http://stix.mitre.org/Campaign-1': 'http://stix.mitre.org/XMLSchema/campaign/1.1.1/campaign.xsd',
- 'http://stix.mitre.org/CourseOfAction-1': 'http://stix.mitre.org/XMLSchema/course_of_action/1.1.1/course_of_action.xsd',
- 'http://stix.mitre.org/ExploitTarget-1': 'http://stix.mitre.org/XMLSchema/exploit_target/1.1.1/exploit_target.xsd',
- 'http://stix.mitre.org/Incident-1': 'http://stix.mitre.org/XMLSchema/incident/1.1.1/incident.xsd',
- 'http://stix.mitre.org/Indicator-2': 'http://stix.mitre.org/XMLSchema/indicator/2.1.1/indicator.xsd',
- 'http://stix.mitre.org/TTP-1': 'http://stix.mitre.org/XMLSchema/ttp/1.1.1/ttp.xsd',
- 'http://stix.mitre.org/ThreatActor-1': 'http://stix.mitre.org/XMLSchema/threat_actor/1.1.1/threat_actor.xsd',
- 'http://stix.mitre.org/common-1': 'http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd',
- 'http://stix.mitre.org/default_vocabularies-1': 'http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd',
- 'http://stix.mitre.org/extensions/AP#CAPEC2.7-1': 'http://stix.mitre.org/XMLSchema/extensions/attack_pattern/capec_2.7/1.0.1/capec_2.7_attack_pattern.xsd',
- 'http://stix.mitre.org/extensions/Address#CIQAddress3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/address/ciq_3.0/1.1.1/ciq_3.0_address.xsd',
- 'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd',
- 'http://stix.mitre.org/extensions/Malware#MAEC4.1-1': 'http://stix.mitre.org/XMLSchema/extensions/malware/maec_4.1/1.0.1/maec_4.1_malware.xsd',
- 'http://stix.mitre.org/extensions/StructuredCOA#Generic-1': 'http://stix.mitre.org/XMLSchema/extensions/structured_coa/generic/1.1.1/generic_structured_coa.xsd',
- 'http://stix.mitre.org/extensions/TestMechanism#Generic-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/generic/1.1.1/generic_test_mechanism.xsd',
- 'http://stix.mitre.org/extensions/TestMechanism#OVAL5.10-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/oval_5.10/1.1.1/oval_5.10_test_mechanism.xsd',
- 'http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/open_ioc_2010/1.1.1/open_ioc_2010_test_mechanism.xsd',
- 'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd',
- 'http://stix.mitre.org/extensions/TestMechanism#YARA-1': 'http://stix.mitre.org/XMLSchema/extensions/test_mechanism/yara/1.1.1/yara_test_mechanism.xsd',
- 'http://stix.mitre.org/extensions/Vulnerability#CVRF-1': 'http://stix.mitre.org/XMLSchema/extensions/vulnerability/cvrf_1.1/1.1.1/cvrf_1.1_vulnerability.xsd',
- 'http://stix.mitre.org/stix-1': 'http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd'
-}
-
-#: Schema locations for namespaces defined by the CybOX language
-CYBOX_NS_TO_SCHEMALOCATION = dict(
- (ns, loc) for ns, _, loc in cybox.utils.nsparser.NS_LIST if loc
-)
-
-#: Schema locations for namespaces not defined by STIX, but hosted on the STIX website
-EXT_NS_TO_SCHEMALOCATION = {
- 'urn:oasis:names:tc:ciq:xal:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd',
- 'urn:oasis:names:tc:ciq:xpil:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd',
- 'urn:oasis:names:tc:ciq:xnl:3': 'http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd'
-}
-
-#: Default namespace->alias mappings. These can be overriden by user-provided dictionaries on export.
-DEFAULT_STIX_NS_TO_PREFIX = {
- 'http://cybox.mitre.org/common-2': 'cyboxCommon',
- 'http://cybox.mitre.org/cybox-2': 'cybox',
- 'http://data-marking.mitre.org/Marking-1': 'marking',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#Simple-1': 'simpleMarking',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1': 'tlpMarking',
- 'http://data-marking.mitre.org/extensions/MarkingStructure#Terms_Of_Use-1': 'TOUMarking',
- 'http://stix.mitre.org/Campaign-1': 'campaign',
- 'http://stix.mitre.org/CourseOfAction-1': 'coa',
- 'http://stix.mitre.org/ExploitTarget-1': 'et',
- 'http://stix.mitre.org/Incident-1': 'incident',
- 'http://stix.mitre.org/Indicator-2': 'indicator',
- 'http://stix.mitre.org/TTP-1': 'ttp',
- 'http://stix.mitre.org/ThreatActor-1': 'ta',
- 'http://stix.mitre.org/stix-1': 'stix',
- 'http://stix.mitre.org/common-1': 'stixCommon',
- 'http://stix.mitre.org/default_vocabularies-1': 'stixVocabs',
- 'http://stix.mitre.org/extensions/AP#CAPEC2.7-1': 'stix-capec',
- 'http://stix.mitre.org/extensions/Address#CIQAddress3.0-1': 'stix-ciqaddress',
- 'http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1': 'ciqIdentity',
- 'http://stix.mitre.org/extensions/Malware#MAEC4.1-1': 'stix-maec',
- 'http://stix.mitre.org/extensions/StructuredCOA#Generic-1': 'genericStructuredCOA',
- 'http://stix.mitre.org/extensions/TestMechanism#Generic-1': 'genericTM',
- 'http://stix.mitre.org/extensions/TestMechanism#OVAL5.10-1': 'stix-oval',
- 'http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1': 'stix-openioc',
- 'http://stix.mitre.org/extensions/TestMechanism#Snort-1': 'snortTM',
- 'http://stix.mitre.org/extensions/TestMechanism#YARA-1': 'yaraTM',
- 'http://stix.mitre.org/extensions/Vulnerability#CVRF-1': 'stix-cvrf'
-}
-
-#: Mapping of extension namespaces to their (typical) prefixes.
-DEFAULT_EXT_TO_PREFIX = {
- 'http://capec.mitre.org/capec-2': 'capec',
- 'http://maec.mitre.org/XMLSchema/maec-package-2': 'maecPackage',
- 'http://oval.mitre.org/XMLSchema/oval-definitions-5': 'oval-def',
- 'http://oval.mitre.org/XMLSchema/oval-variables-5': 'oval-var',
- 'http://schemas.mandiant.com/2010/ioc': 'ioc',
- 'http://schemas.mandiant.com/2010/ioc/TR/': 'ioc-tr',
- 'http://www.icasi.org/CVRF/schema/cvrf/1.1': 'cvrf',
- 'urn:oasis:names:tc:ciq:xal:3': 'xal',
- 'urn:oasis:names:tc:ciq:xpil:3': 'xpil',
- 'urn:oasis:names:tc:ciq:xnl:3': 'xnl'
-}
-
-#: Mapping of CybOX namespaces to default aliases
-DEFAULT_CYBOX_NAMESPACES = dict(
- (ns, alias) for (ns, alias, _) in cybox.utils.nsparser.NS_LIST
-)
-
-
-#: Mapping of all STIX/STIX Extension/CybOX/XML namespaces
-DEFAULT_STIX_NAMESPACES = dict(
- itertools.chain(
- DEFAULT_CYBOX_NAMESPACES.iteritems(),
- XML_NAMESPACES.iteritems(),
- DEFAULT_STIX_NS_TO_PREFIX.iteritems(),
- DEFAULT_EXT_TO_PREFIX.iteritems()
- )
-)
-
-#: Prefix-to-namespace mapping of the `DEFAULT_STIX_NAMESPACES` mapping
-DEFAULT_STIX_PREFIX_TO_NAMESPACE = dict(
- (alias, ns) for ns, alias in DEFAULT_STIX_NAMESPACES.iteritems()
-)
-
-#: Tuple of all keys found in `DEFAULT_STIX_NAMESPACES` mapping.
-DEFAULT_STIX_NAMESPACES_TUPLE = tuple(DEFAULT_STIX_NAMESPACES.keys())
-
-#: Mapping of STIX/CybOX/STIX Extension namespaces to canonical schema locations
-DEFAULT_STIX_SCHEMALOCATIONS = dict(
- itertools.chain(
- STIX_NS_TO_SCHEMALOCATION.iteritems(),
- EXT_NS_TO_SCHEMALOCATION.iteritems(),
- CYBOX_NS_TO_SCHEMALOCATION.iteritems(),
- )
-)
-
-# python-maec support code
-with ignored(ImportError):
- from maec.utils.nsparser import NS_LIST
-
- ns_to_prefix = dict(
- (ns, prefix) for (ns, prefix, _) in NS_LIST
- )
-
- del ns_to_prefix['http://maec.mitre.org/default_vocabularies-1']
-
- prefix_to_ns = dict(
- (prefix, ns) for (ns, prefix) in ns_to_prefix.iteritems()
- )
-
- ns_to_schemalocation = dict(
- (ns, schemaloc) for ns, _, schemaloc in NS_LIST if schemaloc
- )
-
- DEFAULT_STIX_NAMESPACES.update(ns_to_prefix)
- DEFAULT_STIX_PREFIX_TO_NAMESPACE.update(prefix_to_ns)
- DEFAULT_STIX_NAMESPACES_TUPLE = tuple(DEFAULT_STIX_NAMESPACES.iterkeys())
- DEFAULT_STIX_SCHEMALOCATIONS.update(ns_to_schemalocation)
+"""
+This module automatically registers all STIX namespaces into mixbox.
+"""
+
+import mixbox.namespaces
+
+Namespace = mixbox.namespaces.Namespace
+
+NS_CAMPAIGN_OBJECT = Namespace("http://stix.mitre.org/Campaign-1", "campaign", "http://stix.mitre.org/XMLSchema/campaign/1.1.1/campaign.xsd")
+NS_CAPEC_OBJECT = Namespace("http://capec.mitre.org/capec-2", "capec", "")
+NS_CIQIDENTITY_OBJECT = Namespace("http://stix.mitre.org/extensions/Identity#CIQIdentity3.0-1", "stix-ciqidentity", "http://stix.mitre.org/XMLSchema/extensions/identity/ciq_3.0/1.1.1/ciq_3.0_identity.xsd")
+NS_COA_OBJECT = Namespace("http://stix.mitre.org/CourseOfAction-1", "coa", "http://stix.mitre.org/XMLSchema/course_of_action/1.1.1/course_of_action.xsd")
+NS_CVRF_OBJECT = Namespace("http://www.icasi.org/CVRF/schema/cvrf/1.1", "cvrf", "")
+NS_ET_OBJECT = Namespace("http://stix.mitre.org/ExploitTarget-1", "et", "http://stix.mitre.org/XMLSchema/exploit_target/1.1.1/exploit_target.xsd")
+NS_GENERICSTRUCTUREDCOA_OBJECT = Namespace("http://stix.mitre.org/extensions/StructuredCOA#Generic-1", "genericStructuredCOA", "http://stix.mitre.org/XMLSchema/extensions/structured_coa/generic/1.1.1/generic_structured_coa.xsd")
+NS_GENERICTM_OBJECT = Namespace("http://stix.mitre.org/extensions/TestMechanism#Generic-1", "genericTM", "http://stix.mitre.org/XMLSchema/extensions/test_mechanism/generic/1.1.1/generic_test_mechanism.xsd")
+NS_INCIDENT_OBJECT = Namespace("http://stix.mitre.org/Incident-1", "incident", "http://stix.mitre.org/XMLSchema/incident/1.1.1/incident.xsd")
+NS_INDICATOR_OBJECT = Namespace("http://stix.mitre.org/Indicator-2", "indicator", "http://stix.mitre.org/XMLSchema/indicator/2.1.1/indicator.xsd")
+NS_IOC_OBJECT = Namespace("http://schemas.mandiant.com/2010/ioc", "ioc", "")
+NS_IOCTR_OBJECT = Namespace("http://schemas.mandiant.com/2010/ioc/TR/", "ioc-tr", "")
+NS_MARKING_OBJECT = Namespace("http://data-marking.mitre.org/Marking-1", "marking", "http://stix.mitre.org/XMLSchema/data_marking/1.1.1/data_marking.xsd")
+NS_OVALDEF_OBJECT = Namespace("http://oval.mitre.org/XMLSchema/oval-definitions-5", "oval-def", "")
+NS_OVALVAR_OBJECT = Namespace("http://oval.mitre.org/XMLSchema/oval-variables-5", "oval-var", "")
+NS_SIMPLEMARKING_OBJECT = Namespace("http://data-marking.mitre.org/extensions/MarkingStructure#Simple-1", "simpleMarking", "http://stix.mitre.org/XMLSchema/extensions/marking/simple/1.1.1/simple_marking.xsd")
+NS_SNORTTM_OBJECT = Namespace("http://stix.mitre.org/extensions/TestMechanism#Snort-1", "snortTM", "http://stix.mitre.org/XMLSchema/extensions/test_mechanism/snort/1.1.1/snort_test_mechanism.xsd")
+NS_STIX_OBJECT = Namespace("http://stix.mitre.org/stix-1", "stix", "http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd")
+NS_STIXCAPEC_OBJECT = Namespace("http://stix.mitre.org/extensions/AP#CAPEC2.7-1", "stix-capec", "http://stix.mitre.org/XMLSchema/extensions/attack_pattern/capec_2.7/1.0.1/capec_2.7_attack_pattern.xsd")
+NS_STIXCIQADDRESS_OBJECT = Namespace("http://stix.mitre.org/extensions/Address#CIQAddress3.0-1", "stix-ciqaddress", "http://stix.mitre.org/XMLSchema/extensions/address/ciq_3.0/1.1.1/ciq_3.0_address.xsd")
+NS_STIXCVRF_OBJECT = Namespace("http://stix.mitre.org/extensions/Vulnerability#CVRF-1", "stix-cvrf", "http://stix.mitre.org/XMLSchema/extensions/vulnerability/cvrf_1.1/1.1.1/cvrf_1.1_vulnerability.xsd")
+NS_STIXMAEC_OBJECT = Namespace("http://stix.mitre.org/extensions/Malware#MAEC4.1-1", "stix-maec", "http://stix.mitre.org/XMLSchema/extensions/malware/maec_4.1/1.0.1/maec_4.1_malware.xsd")
+NS_STIXOPENIOC_OBJECT = Namespace("http://stix.mitre.org/extensions/TestMechanism#OpenIOC2010-1", "stix-openioc", "http://stix.mitre.org/XMLSchema/extensions/test_mechanism/open_ioc_2010/1.1.1/open_ioc_2010_test_mechanism.xsd")
+NS_STIXOVAL_OBJECT = Namespace("http://stix.mitre.org/extensions/TestMechanism#OVAL5.10-1", "stix-oval", "http://stix.mitre.org/XMLSchema/extensions/test_mechanism/oval_5.10/1.1.1/oval_5.10_test_mechanism.xsd")
+NS_STIXCOMMON_OBJECT = Namespace("http://stix.mitre.org/common-1", "stixCommon", "http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd")
+NS_STIXVOCABS_OBJECT = Namespace("http://stix.mitre.org/default_vocabularies-1", "stixVocabs", "http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd")
+NS_TA_OBJECT = Namespace("http://stix.mitre.org/ThreatActor-1", "ta", "http://stix.mitre.org/XMLSchema/threat_actor/1.1.1/threat_actor.xsd")
+NS_TLPMARKING_OBJECT = Namespace("http://data-marking.mitre.org/extensions/MarkingStructure#TLP-1", "tlpMarking", "http://stix.mitre.org/XMLSchema/extensions/marking/tlp/1.1.1/tlp_marking.xsd")
+NS_TOUMARKING_OBJECT = Namespace("http://data-marking.mitre.org/extensions/MarkingStructure#Terms_Of_Use-1", "TOUMarking", "http://stix.mitre.org/XMLSchema/extensions/marking/terms_of_use/1.0.1/terms_of_use_marking.xsd")
+NS_TTP_OBJECT = Namespace("http://stix.mitre.org/TTP-1", "ttp", "http://stix.mitre.org/XMLSchema/ttp/1.1.1/ttp.xsd")
+NS_XAL_OBJECT = Namespace("urn:oasis:names:tc:ciq:xal:3", "xal", "http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xAL.xsd")
+NS_XNL_OBJECT = Namespace("urn:oasis:names:tc:ciq:xnl:3", "xnl", "http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xNL.xsd")
+NS_XPIL_OBJECT = Namespace("urn:oasis:names:tc:ciq:xpil:3", "xpil", "http://stix.mitre.org/XMLSchema/external/oasis_ciq_3.0/xPIL.xsd")
+NS_YARATM_OBJECT = Namespace("http://stix.mitre.org/extensions/TestMechanism#YARA-1", "yaraTM", "http://stix.mitre.org/XMLSchema/extensions/test_mechanism/yara/1.1.1/yara_test_mechanism.xsd")
+
+STIX_NAMESPACES = mixbox.namespaces.NamespaceSet()
+
+# Magic to automatically register all Namespaces defined in this module.
+for k, v in list(globals().items()):
+ if k.startswith('NS_'):
+ mixbox.namespaces.register_namespace(v)
+ STIX_NAMESPACES.add_namespace(v)
diff --git a/stix/utils/parser.py b/stix/utils/parser.py
index f79365a6..698aad56 100644
--- a/stix/utils/parser.py
+++ b/stix/utils/parser.py
@@ -1,261 +1,28 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-# stdlib
-from distutils.version import StrictVersion
-
-# external
-from lxml import etree
-
-# internal
import stix
-import stix.xmlconst as xmlconst
-
-# relative
-from . import ignored, is_etree, is_element
-
-
-class UnknownVersionError(Exception):
- """Raised when a parsed STIX document contains no version information."""
- pass
-
-
-class UnsupportedVersionError(Exception):
- """Raised when a parsed STIX document contains a version that is
- not supported by this verison of python-stix.
-
- """
- def __init__(self, message, expected=None, found=None):
- super(UnsupportedVersionError, self).__init__(message)
- self.expected = expected
- self.found = found
-
-
-class UnsupportedRootElementError(Exception):
- """Raised when an input STIX document does not contain a supported root-
- level element.
-
- """
- def __init__(self, message, expected=None, found=None):
- super(UnsupportedRootElementError, self).__init__(message)
- self.expected = expected
- self.found = found
+from stix.xmlconst import TAG_STIX_PACKAGE
+import mixbox.parser
+# Import these from mixbox for backward compatibility
+from mixbox.parser import (UnknownVersionError, UnsupportedVersionError,
+ UnsupportedRootElementError)
# Alias for backwards compatibility
UnsupportedRootElement = UnsupportedRootElementError
-def get_xml_parser(encoding=None):
- """Returns an ``etree.ETCompatXMLParser`` instance."""
- parser = etree.ETCompatXMLParser(
- huge_tree=True,
- remove_comments=True,
- strip_cdata=False,
- remove_blank_text=True,
- resolve_entities=False,
- encoding=encoding
- )
-
- return parser
-
-
-def get_etree(doc, encoding=None):
- if is_etree(doc):
- return doc
- elif is_element(doc):
- return etree.ElementTree(doc)
- else:
- parser = get_xml_parser(encoding=encoding)
- return etree.parse(doc, parser=parser)
-
-
-def get_etree_root(doc, encoding=None):
- """Returns an instance of lxml.etree._Element for the given `doc` input.
-
- Args:
- doc: The input XML document. Can be an instance of
- ``lxml.etree._Element``, ``lxml.etree._ElementTree``, a file-like
- object, or a string filename.
- encoding: The character encoding of `doc`. If ``None``, an attempt
- will be made to determine the character encoding by the XML
- parser.
-
- Returns:
- An ``lxml.etree._Element`` instance for `doc`.
-
- Raises:
- IOError: If `doc` cannot be found.
- lxml.ParseError: If `doc` is a malformed XML document.
-
- """
- tree = get_etree(doc, encoding)
- root = tree.getroot()
-
- return root
-
-
-def get_schemaloc_pairs(node):
- """Parses the xsi:schemaLocation attribute on `node`.
-
- Returns:
- A list of (ns, schemaLocation) tuples for the node.
-
- Raises:
- KeyError: If `node` does not have an xsi:schemaLocation attribute.
-
- """
- schemalocs = node.attrib[xmlconst.TAG_SCHEMALOCATION]
- l = schemalocs.split()
- return zip(l[::2], l[1::2])
-
-
-def get_document_version(doc):
- root = get_etree_root(doc)
-
- if 'version' in root.attrib:
- return root.attrib['version']
-
- raise UnknownVersionError(
- "Unable to determine the version if the input STIX document: no "
- "version attribute found on the root element."
- )
-
-
-def root_tag(doc):
- root = get_etree_root(doc)
- return root.tag
-
-
-def is_stix(doc):
- root = root_tag(doc)
- return root == xmlconst.TAG_STIX_PACKAGE
-
-
-class EntityParser(object):
- def __init__(self):
- pass
-
- def _check_version(self, tree):
- """Returns true of the instance document @tree is a version supported
- by python-stix.
-
- """
- document_version = get_document_version(tree)
- supported = stix.supported_stix_version()
-
- if StrictVersion(supported) == StrictVersion(document_version):
- return
-
- error = (
- "Your python-stix library supports STIX %s. Document version was "
- "%s" % (supported, document_version)
- )
-
- raise UnsupportedVersionError(
- message=error,
- expected=supported,
- found=document_version
- )
-
- def _check_root(self, tree):
- if is_stix(tree):
- return
-
- error = "Document root element must be an instance of STIX_Package"
- raise UnsupportedRootElement(
- message=error,
- expected=xmlconst.TAG_STIX_PACKAGE,
- found=root_tag(tree),
- )
-
- def _apply_input_namespaces(self, tree, entity):
- root = get_etree_root(tree)
- entity.__input_namespaces__ = dict(root.nsmap.iteritems())
-
- def _apply_input_schemalocations(self, tree, entity):
- """Attaches an __input_schemalocations__ dictionary to the input entity.
-
- Args:
- tree: The input etree instance
- entity: The entity to attach the schemlocation dictionary to
-
- """
- root = get_etree_root(tree)
-
- with ignored(KeyError):
- pairs = get_schemaloc_pairs(root)
- entity.__input_schemalocations__ = dict(pairs)
-
- def parse_xml_to_obj(self, xml_file, check_version=True, check_root=True,
- encoding=None):
- """Creates a STIX binding object from the supplied xml file.
-
- Args:
- xml_file: A filename/path or a file-like object representing a STIX
- instance document
- check_version: Inspect the version before parsing.
- check_root: Inspect the root element before parsing.
- encoding: The character encoding of the input `xml_file`.
-
- Raises:
- .UnknownVersionError: If `check_version` is ``True`` and `xml_file`
- does not contain STIX version information.
- .UnsupportedVersionError: If `check_version` is ``False`` and
- `xml_file` contains an unsupported STIX version.
- .UnsupportedRootElement: If `check_root` is ``True`` and `xml_file`
- contains an invalid root element.
-
- """
- root = get_etree_root(xml_file, encoding=encoding)
-
- if check_version:
- self._check_version(root)
-
- if check_root:
- self._check_root(root)
-
- import stix.bindings.stix_core as stix_core_binding
- stix_package_obj = stix_core_binding.STIXType().factory()
- stix_package_obj.build(root)
-
- return stix_package_obj
-
- def parse_xml(self, xml_file, check_version=True, check_root=True,
- encoding=None):
- """Creates a python-stix STIXPackage object from the supplied xml_file.
-
- Args:
- xml_file: A filename/path or a file-like object representing a STIX
- instance document
- check_version: Inspect the version before parsing.
- check_root: Inspect the root element before parsing.
- encoding: The character encoding of the input `xml_file`. If
- ``None``, an attempt will be made to determine the input
- character encoding.
+class EntityParser(mixbox.parser.EntityParser):
- Raises:
- .UnknownVersionError: If `check_version` is ``True`` and `xml_file`
- does not contain STIX version information.
- .UnsupportedVersionError: If `check_version` is ``False`` and
- `xml_file` contains an unsupported STIX version.
- .UnsupportedRootElement: If `check_root` is ``True`` and `xml_file`
- contains an invalid root element.
+ def supported_tags(self):
+ return [TAG_STIX_PACKAGE]
- """
- root = get_etree_root(xml_file, encoding=encoding)
+ def get_version(self, root):
+ return root.attrib.get('version')
- stix_package_obj = self.parse_xml_to_obj(
- xml_file=root,
- check_version=check_version,
- check_root=check_root,
- encoding=encoding
- )
-
- from stix.core import STIXPackage # resolve circular dependencies
- stix_package = STIXPackage().from_obj(stix_package_obj)
+ def supported_versions(self, tag=TAG_STIX_PACKAGE):
+ return stix.supported_stix_version()
- self._apply_input_namespaces(root, stix_package)
- self._apply_input_schemalocations(root, stix_package)
-
- return stix_package
+ def get_entity_class(self, tag=TAG_STIX_PACKAGE):
+ return stix.core.STIXPackage
diff --git a/stix/utils/walk.py b/stix/utils/walk.py
index 6965a20f..f995677f 100644
--- a/stix/utils/walk.py
+++ b/stix/utils/walk.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# stdlib
@@ -6,6 +6,7 @@
# external
from cybox.common import ObjectProperties
+from mixbox.vendor.six import iteritems
# internal
from . import is_entity, is_entitylist, attr_name, is_sequence
@@ -25,9 +26,15 @@ def _is_skippable(owner, varname, varobj):
def _iter_vars(obj):
- instance_vars = getattr(obj, "__dict__", {}).iteritems()
- typed_fields = getattr(obj, "_fields", {}).iteritems()
- return itertools.chain(instance_vars, typed_fields)
+ attrs = []
+
+ if hasattr(obj, "__dict__"):
+ attrs.append(iteritems(vars(obj)))
+
+ if hasattr(obj, "_fields"):
+ attrs.append(iteritems(obj._fields))
+
+ return itertools.chain.from_iterable(attrs)
def iterwalk(obj):
diff --git a/stix/version.py b/stix/version.py
index e4f82811..9eb1b590 100644
--- a/stix/version.py
+++ b/stix/version.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
-__version__ = "1.1.1.6.dev0"
+__version__ = "1.1.1.19"
diff --git a/stix/xmlconst.py b/stix/xmlconst.py
index e508eeb2..bffe65c5 100644
--- a/stix/xmlconst.py
+++ b/stix/xmlconst.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
+# Copyright (c) 2016, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
# XML NAMESPACES
diff --git a/tox.ini b/tox.ini
index 59c9179a..275e8bdf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,24 +1,49 @@
[tox]
-envlist = py26, py27, lxml23
+envlist = py27, py34, py35, py36, py37, py38, lxml23, docs, no-maec, packaging
[testenv]
commands =
nosetests stix
# NOTE: python-stix does not have any doctests
# sphinx-build -b doctest docs docs/_build/doctest
- sphinx-build -b html docs docs/_build/html
deps =
-rrequirements.txt
# We call this "lxml23" instead of "rhel6", since RHEL6 ships with LXML 2.2.3.
# python-stix requires at least 2.3.
[testenv:lxml23]
-basepython=python2.6
+basepython=python2.7
commands =
nosetests stix
deps =
+ # Pin specific versions of LXML and python-dateutil
lxml==2.3
python-dateutil==1.4.1
- cybox
- maec
- nose
+ -rrequirements.txt
+
+# Test the behavior when MAEC is not installed in the environment.
+[testenv:no-maec]
+commands =
+ nosetests stix
+deps =
+ nose==1.3.7
+ tox==2.7.0
+
+[testenv:docs]
+commands =
+ sphinx-build -W -b html -d {envtmpdir}/doctrees docs {envtmpdir}/html
+
+[testenv:packaging]
+deps =
+ readme_renderer
+commands =
+ python setup.py check -r -s
+
+[travis]
+python =
+ 2.7: py27, docs, lxml23, no-maec, packaging
+ 3.4: py34, no-maec
+ 3.5: py35, no-maec
+ 3.6: py36, no-maec, packaging
+ 3.7: py37, no-maec
+ 3.8: py38, no-maec