diff --git a/.isort.cfg b/.isort.cfg
index d535851..0fadb83 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -8,6 +8,7 @@ known_third_party =
requests,
simplejson
six,
+ sphinx,
stix2patterns,
taxii2client,
known_first_party = stix2
diff --git a/docs/api_ref.rst b/docs/api_ref.rst
index bb60081..ffc328c 100644
--- a/docs/api_ref.rst
+++ b/docs/api_ref.rst
@@ -7,6 +7,6 @@ functions in the ``stix2`` API, as given by the package's docstrings.
.. note::
All the classes and functions detailed in the pages below are importable
directly from `stix2`. See also:
- :ref:`How imports will work `.
+ :ref:`How imports will work `.
.. automodule:: stix2
diff --git a/docs/conf.py b/docs/conf.py
index c337e79..dbed6a3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,6 +1,12 @@
import os
+import re
import sys
+from six import class_types
+from sphinx.ext.autodoc import ClassDocumenter
+
+from stix2.base import _STIXBase
+
sys.path.insert(0, os.path.abspath('..'))
extensions = [
@@ -50,3 +56,57 @@ latex_elements = {}
latex_documents = [
(master_doc, 'stix2.tex', 'stix2 Documentation', 'OASIS', 'manual'),
]
+
+
+def get_property_type(prop):
+ """Convert property classname into pretty string name of property.
+
+ """
+ try:
+ prop_class = prop.__name__
+ except AttributeError:
+ prop_class = prop.__class__.__name__
+ # Remove 'Property' from the string
+ prop_class = prop_class.split('Property')[0]
+ # Split camelcase with spaces
+ split_camelcase = re.sub('(?!^)([A-Z][a-z]+)', r' \1', prop_class).split()
+ prop_class = ' '.join(split_camelcase)
+ return prop_class
+
+
+class STIXAttributeDocumenter(ClassDocumenter):
+ """Custom Sphinx extension to auto-document STIX properties.
+
+ Needed because descendants of _STIXBase use `_properties` dictionaries
+ instead of instance variables for STIX 2 objects' properties.
+
+ """
+ objtype = 'stixattr'
+ directivetype = 'class'
+ priority = 999
+
+ @classmethod
+ def can_document_member(cls, member, membername, isattr, parent):
+ return isinstance(member, class_types) and \
+ issubclass(member, _STIXBase) and \
+ hasattr(member, '_properties')
+
+ def add_content(self, more_content, no_docstring=False):
+ ClassDocumenter.add_content(self, more_content, no_docstring)
+
+ obj = self.object
+ self.add_line(':Properties:', '')
+ for prop_name, prop in obj._properties.items():
+ # Add metadata about the property
+ prop_type = get_property_type(prop)
+ if prop_type == 'List':
+ prop_type = 'List of %ss' % get_property_type(prop.contained)
+ if prop.required:
+ prop_type += ', required'
+ prop_str = '**%s** (*%s*)' % (prop_name, prop_type)
+ self.add_line(' - %s' % prop_str, '')
+ self.add_line('', '')
+
+
+def setup(app):
+ app.add_autodocumenter(STIXAttributeDocumenter)
diff --git a/docs/guide/creating.ipynb b/docs/guide/creating.ipynb
index 5836d1d..3e22061 100644
--- a/docs/guide/creating.ipynb
+++ b/docs/guide/creating.ipynb
@@ -381,7 +381,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "To update the properties of an object, see the [Versioning](versioning.ipynb) section."
+ "To update the properties of an object, see the [Versioning](guide/versioning.ipynb) section."
]
},
{
diff --git a/requirements.txt b/requirements.txt
index 0de31a7..d6abb63 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
bumpversion
-nbsphinx>=0.2.15
+ipython
+nbsphinx>=0.3.0
pre-commit
pytest
pytest-cov
diff --git a/stix2/core.py b/stix2/core.py
index 658bb47..b6d295d 100644
--- a/stix2/core.py
+++ b/stix2/core.py
@@ -41,6 +41,9 @@ class STIXObjectProperty(Property):
class Bundle(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'bundle'
_properties = OrderedDict()
diff --git a/stix2/v20/common.py b/stix2/v20/common.py
index ef45060..e915df6 100644
--- a/stix2/v20/common.py
+++ b/stix2/v20/common.py
@@ -11,6 +11,10 @@ from ..utils import NOW, get_dict
class ExternalReference(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_properties = OrderedDict()
_properties.update([
('source_name', StringProperty(required=True)),
@@ -26,6 +30,10 @@ class ExternalReference(_STIXBase):
class KillChainPhase(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_properties = OrderedDict()
_properties.update([
('kill_chain_name', StringProperty(required=True)),
@@ -34,6 +42,10 @@ class KillChainPhase(_STIXBase):
class GranularMarking(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_properties = OrderedDict()
_properties.update([
('marking_ref', ReferenceProperty(required=True, type="marking-definition")),
@@ -42,15 +54,23 @@ class GranularMarking(_STIXBase):
class TLPMarking(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
# TODO: don't allow the creation of any other TLPMarkings than the ones below
_type = 'tlp'
_properties = OrderedDict()
_properties.update([
- ('tlp', Property(required=True))
+ ('tlp', StringProperty(required=True))
])
class StatementMarking(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_type = 'statement'
_properties = OrderedDict()
_properties.update([
@@ -78,6 +98,10 @@ class MarkingProperty(Property):
class MarkingDefinition(_STIXBase, _MarkingsMixin):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_type = 'marking-definition'
_properties = OrderedDict()
_properties.update([
diff --git a/stix2/v20/observables.py b/stix2/v20/observables.py
index a874df9..83600b0 100644
--- a/stix2/v20/observables.py
+++ b/stix2/v20/observables.py
@@ -74,6 +74,9 @@ class ExtensionsProperty(DictionaryProperty):
class Artifact(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'artifact'
_properties = OrderedDict()
@@ -93,6 +96,9 @@ class Artifact(_Observable):
class AutonomousSystem(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'autonomous-system'
_properties = OrderedDict()
@@ -106,6 +112,9 @@ class AutonomousSystem(_Observable):
class Directory(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'directory'
_properties = OrderedDict()
@@ -123,6 +132,9 @@ class Directory(_Observable):
class DomainName(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'domain-name'
_properties = OrderedDict()
@@ -135,6 +147,9 @@ class DomainName(_Observable):
class EmailAddress(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'email-addr'
_properties = OrderedDict()
@@ -148,6 +163,9 @@ class EmailAddress(_Observable):
class EmailMIMEComponent(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_properties = OrderedDict()
_properties.update([
@@ -163,6 +181,9 @@ class EmailMIMEComponent(_STIXBase):
class EmailMessage(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'email-message'
_properties = OrderedDict()
@@ -194,6 +215,9 @@ class EmailMessage(_Observable):
class ArchiveExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'archive-ext'
_properties = OrderedDict()
@@ -205,6 +229,9 @@ class ArchiveExt(_Extension):
class AlternateDataStream(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_properties = OrderedDict()
_properties.update([
@@ -215,6 +242,9 @@ class AlternateDataStream(_STIXBase):
class NTFSExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'ntfs-ext'
_properties = OrderedDict()
@@ -225,6 +255,9 @@ class NTFSExt(_Extension):
class PDFExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'pdf-ext'
_properties = OrderedDict()
@@ -238,6 +271,9 @@ class PDFExt(_Extension):
class RasterImageExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'raster-image-ext'
_properties = OrderedDict()
@@ -251,6 +287,9 @@ class RasterImageExt(_Extension):
class WindowsPEOptionalHeaderType(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_properties = OrderedDict()
_properties.update([
@@ -293,6 +332,9 @@ class WindowsPEOptionalHeaderType(_STIXBase):
class WindowsPESection(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_properties = OrderedDict()
_properties.update([
@@ -304,6 +346,9 @@ class WindowsPESection(_STIXBase):
class WindowsPEBinaryExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'windows-pebinary-ext'
_properties = OrderedDict()
@@ -324,6 +369,9 @@ class WindowsPEBinaryExt(_Extension):
class File(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'file'
_properties = OrderedDict()
@@ -355,6 +403,9 @@ class File(_Observable):
class IPv4Address(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'ipv4-addr'
_properties = OrderedDict()
@@ -368,6 +419,9 @@ class IPv4Address(_Observable):
class IPv6Address(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'ipv6-addr'
_properties = OrderedDict()
@@ -381,6 +435,9 @@ class IPv6Address(_Observable):
class MACAddress(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'mac-addr'
_properties = OrderedDict()
@@ -392,6 +449,9 @@ class MACAddress(_Observable):
class Mutex(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'mutex'
_properties = OrderedDict()
@@ -403,6 +463,9 @@ class Mutex(_Observable):
class HTTPRequestExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'http-request-ext'
_properties = OrderedDict()
@@ -417,6 +480,9 @@ class HTTPRequestExt(_Extension):
class ICMPExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'icmp-ext'
_properties = OrderedDict()
@@ -427,6 +493,9 @@ class ICMPExt(_Extension):
class SocketExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'socket-ext'
_properties = OrderedDict()
@@ -465,6 +534,9 @@ class SocketExt(_Extension):
class TCPExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'tcp-ext'
_properties = OrderedDict()
@@ -475,6 +547,9 @@ class TCPExt(_Extension):
class NetworkTraffic(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'network-traffic'
_properties = OrderedDict()
@@ -506,6 +581,9 @@ class NetworkTraffic(_Observable):
class WindowsProcessExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'windows-process-ext'
_properties = OrderedDict()
@@ -520,6 +598,9 @@ class WindowsProcessExt(_Extension):
class WindowsServiceExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'windows-service-ext'
_properties = OrderedDict()
@@ -555,6 +636,9 @@ class WindowsServiceExt(_Extension):
class Process(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'process'
_properties = OrderedDict()
@@ -593,6 +677,9 @@ class Process(_Observable):
class Software(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'software'
_properties = OrderedDict()
@@ -608,6 +695,9 @@ class Software(_Observable):
class URL(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'url'
_properties = OrderedDict()
@@ -619,6 +709,9 @@ class URL(_Observable):
class UNIXAccountExt(_Extension):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'unix-account-ext'
_properties = OrderedDict()
@@ -631,6 +724,9 @@ class UNIXAccountExt(_Extension):
class UserAccount(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'user-account'
_properties = OrderedDict()
@@ -654,6 +750,9 @@ class UserAccount(_Observable):
class WindowsRegistryValueType(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'windows-registry-value-type'
_properties = OrderedDict()
@@ -679,6 +778,9 @@ class WindowsRegistryValueType(_STIXBase):
class WindowsRegistryKey(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'windows-registry-key'
_properties = OrderedDict()
@@ -700,6 +802,9 @@ class WindowsRegistryKey(_Observable):
class X509V3ExtenstionsType(_STIXBase):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'x509-v3-extensions-type'
_properties = OrderedDict()
@@ -724,6 +829,9 @@ class X509V3ExtenstionsType(_STIXBase):
class X509Certificate(_Observable):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """ # noqa
_type = 'x509-certificate'
_properties = OrderedDict()
diff --git a/stix2/v20/sdo.py b/stix2/v20/sdo.py
index 2d36aaf..7ccc3e3 100644
--- a/stix2/v20/sdo.py
+++ b/stix2/v20/sdo.py
@@ -19,6 +19,9 @@ class STIXDomainObject(_STIXBase, _MarkingsMixin):
class AttackPattern(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'attack-pattern'
_properties = OrderedDict()
@@ -40,6 +43,9 @@ class AttackPattern(STIXDomainObject):
class Campaign(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'campaign'
_properties = OrderedDict()
@@ -64,6 +70,9 @@ class Campaign(STIXDomainObject):
class CourseOfAction(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'course-of-action'
_properties = OrderedDict()
@@ -84,6 +93,9 @@ class CourseOfAction(STIXDomainObject):
class Identity(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'identity'
_properties = OrderedDict()
@@ -107,6 +119,9 @@ class Identity(STIXDomainObject):
class Indicator(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'indicator'
_properties = OrderedDict()
@@ -131,6 +146,9 @@ class Indicator(STIXDomainObject):
class IntrusionSet(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'intrusion-set'
_properties = OrderedDict()
@@ -158,6 +176,9 @@ class IntrusionSet(STIXDomainObject):
class Malware(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'malware'
_properties = OrderedDict()
@@ -179,6 +200,9 @@ class Malware(STIXDomainObject):
class ObservedData(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'observed-data'
_properties = OrderedDict()
@@ -201,6 +225,9 @@ class ObservedData(STIXDomainObject):
class Report(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'report'
_properties = OrderedDict()
@@ -223,6 +250,9 @@ class Report(STIXDomainObject):
class ThreatActor(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'threat-actor'
_properties = OrderedDict()
@@ -251,6 +281,9 @@ class ThreatActor(STIXDomainObject):
class Tool(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'tool'
_properties = OrderedDict()
@@ -273,6 +306,9 @@ class Tool(STIXDomainObject):
class Vulnerability(STIXDomainObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'vulnerability'
_properties = OrderedDict()
diff --git a/stix2/v20/sro.py b/stix2/v20/sro.py
index 7f05f5e..7d7d3ae 100644
--- a/stix2/v20/sro.py
+++ b/stix2/v20/sro.py
@@ -16,6 +16,9 @@ class STIXRelationshipObject(_STIXBase, _MarkingsMixin):
class Relationship(STIXRelationshipObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
_type = 'relationship'
_properties = OrderedDict()
@@ -51,6 +54,10 @@ class Relationship(STIXRelationshipObject):
class Sighting(STIXRelationshipObject):
+ """For more detailed information on this object's properties, see
+ `the STIX 2.0 specification `__.
+ """
+
_type = 'sighting'
_properties = OrderedDict()
_properties.update([