In [1]:
# Delete this cell to re-enable tracebacks
import sys
ipython = get_ipython()

def hide_traceback(exc_tuple=None, filename=None, tb_offset=None,
                   exception_only=False, running_compiled_code=False):
    etype, value, tb = sys.exc_info()
    value.__cause__ = None  # suppress chained exceptions
    return ipython._showtraceback(etype, value, ipython.InteractiveTB.get_exception_only(etype, value))

ipython.showtraceback = hide_traceback

In [2]:
# JSON output syntax highlighting
from __future__ import print_function
from pygments import highlight
from pygments.lexers import JsonLexer, TextLexer
from pygments.formatters import HtmlFormatter
from IPython.display import display, HTML
from IPython.core.interactiveshell import InteractiveShell

InteractiveShell.ast_node_interactivity = "all"

def json_print(inpt):
    string = str(inpt)
    formatter = HtmlFormatter()
    if string[0] == '{':
        lexer = JsonLexer()
    else:
        lexer = TextLexer()
    return HTML('<style type="text/css">{}</style>{}'.format(
                formatter.get_style_defs('.highlight'),
                highlight(string, lexer, formatter)))

globals()['print'] = json_print

Using The Workbench

The Workbench API hides most of the complexity of the rest of the library to make it easy to interact with STIX data. To use it, just import everything from stix2.workbench:


In [3]:
from stix2.workbench import *

Retrieving STIX Data

To get some STIX data to work with, let's set up a DataSource and add it to our workbench.


In [4]:
from taxii2client import Collection

collection = Collection("http://127.0.0.1:5000/trustgroup1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/", user="admin", password="Password0")
tc_source = TAXIICollectionSource(collection)
add_data_source(tc_source)

Now we can get all of the indicators from the data source.


In [5]:
response = indicators()

Similar functions are available for the other STIX Object types. See the full list here.

If you want to only retrieve some indicators, you can pass in one or more Filters. This example finds all the indicators created by a specific identity:


In [6]:
response = indicators(filters=Filter('created_by_ref', '=', 'identity--adede3e8-bf44-4e6f-b3c9-1958cbc3b188'))

The objects returned let you easily traverse their relationships. Get all Relationship objects involving that object with .relationships(), all other objects related to this object with .related(), and the Identity object for the creator of the object (if one exists) with .created_by(). For full details on these methods and their arguments, see the Workbench API documentation.


In [7]:
for i in indicators():
    for rel in i.relationships():
        print(rel.source_ref)
        print(rel.relationship_type)
        print(rel.target_ref)


Out[7]:
indicator--cd981c25-8042-4166-8945-51178443bdac
Out[7]:
indicates
Out[7]:
malware--c0931cc6-c75e-47e5-9036-78fabc95d4ec

In [8]:
for i in indicators():
    for obj in i.related():
        print(obj)


Out[8]:
{
    "type": "malware",
    "spec_version": "2.1",
    "id": "malware--c0931cc6-c75e-47e5-9036-78fabc95d4ec",
    "created": "2017-01-27T13:49:53.997Z",
    "modified": "2017-01-27T13:49:53.997Z",
    "name": "Poison Ivy",
    "description": "Poison Ivy",
    "malware_types": [
        "remote-access-trojan"
    ],
    "is_family": true
}

If there are a lot of related objects, you can narrow it down by passing in one or more Filters just as before. For example, if we want to get only the indicators related to a specific piece of malware (and not any entities that use it or are targeted by it):


In [10]:
malware = get('malware--c0931cc6-c75e-47e5-9036-78fabc95d4ec')
indicator = malware.related(filters=Filter('type', '=', 'indicator'))
print(indicator[0])


Out[10]:
{
    "type": "indicator",
    "spec_version": "2.1",
    "id": "indicator--cd981c25-8042-4166-8945-51178443bdac",
    "created": "2014-05-08T09:00:00.000Z",
    "modified": "2014-05-08T09:00:00.000Z",
    "name": "File hash for Poison Ivy variant",
    "indicator_types": [
        "file-hash-watchlist"
    ],
    "pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
    "pattern_type": "stix",
    "pattern_version": "2.1",
    "valid_from": "2014-05-08T09:00:00Z"
}

Creating STIX Data

To create a STIX object, just use that object's class constructor. Once it's created, add it to the workbench with save().


In [11]:
identity = Identity(name="ACME Threat Intel Co.", identity_class="organization")
save(identity)

You can also set defaults for certain properties when creating objects. For example, let's set the default creator to be the identity object we just created:


In [12]:
set_default_creator(identity)

Now when we create an indicator (or any other STIX Domain Object), it will automatically have the right create_by_ref value.


In [14]:
indicator = Indicator(pattern_type="stix", pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']")
save(indicator)

indicator_creator = get(indicator.created_by_ref)
print(indicator_creator.name)


Out[14]:
ACME Threat Intel Co.

Defaults can also be set for the created timestamp, external references and object marking references.

**Warning** The workbench layer replaces STIX Object classes with special versions of them that use "wrappers" to provide extra functionality. Because of this, we recommend that you **either use the workbench layer or the rest of the library, but not both**. In other words, don't import from both ``stix2.workbench`` and any other submodules of ``stix2``.