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([