WIP: Merge branch 'master' into stix2.1
commit
3e159abd4d
|
@ -43,6 +43,7 @@ htmlcov/
|
|||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
[settings]
|
||||
skip = workbench.py
|
||||
not_skip = __init__.py
|
||||
known_third_party =
|
||||
dateutil,
|
||||
ordereddict,
|
||||
medallion,
|
||||
pytest,
|
||||
pytz,
|
||||
requests,
|
||||
simplejson
|
||||
simplejson,
|
||||
six,
|
||||
sphinx,
|
||||
stix2patterns,
|
||||
taxii2client,
|
||||
known_first_party = stix2
|
||||
|
|
|
@ -5,13 +5,7 @@ python:
|
|||
- "2.7"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.5-dev"
|
||||
- "3.6"
|
||||
- "3.6-dev"
|
||||
- "nightly"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: "nightly"
|
||||
install:
|
||||
- pip install -U pip setuptools
|
||||
- pip install tox-travis pre-commit
|
||||
|
|
39
CHANGELOG
39
CHANGELOG
|
@ -1,6 +1,45 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
1.0.2 - 2018-05-18
|
||||
|
||||
* Fixes bugs when using allow_custom (#176, #179).
|
||||
|
||||
1.0.1 - 2018-04-27
|
||||
|
||||
* Fixes bug with incorrect TAXII parameters (#169).
|
||||
* Fixes bug with constructing patterns (#171).
|
||||
|
||||
1.0.0 - 2018-04-16
|
||||
|
||||
* Adds the Workbench layer API.
|
||||
* Adds checks to ensure valid type names are provided.
|
||||
* Supports parsing generic custom STIX 2 content without needing to create classes for them.
|
||||
* Fixes "Not JSON serializable" error in TAXIICollectionStore.
|
||||
* Fixes bug with parsing JSON files in FileSystemStore.
|
||||
* Fixes bug with Filters in TAXIICollectionStore.
|
||||
* Fixes minor bugs in the patterning API.
|
||||
* Fixes bug with ListProperty containing DictionaryProperty.
|
||||
* Fixes bug with parsing observables.
|
||||
* Fixes bug involving optional properties with default values.
|
||||
* Changes custom observable extensions to require properties to be defined as a list of tuples rather than a dictionary.
|
||||
* Changes Filters to allow passing a dictionary as a filter value.
|
||||
* Changes `get_dict` to a private function.
|
||||
* `taxii2-client` is now an optional dependency.
|
||||
|
||||
0.5.1 - 2018-03-06
|
||||
|
||||
* Fixes issue with PyPI.
|
||||
|
||||
0.5.0 - 2018-03-06
|
||||
|
||||
* Adds functions to dereference relationships.
|
||||
* Adds a function to get an object's type from its ID.
|
||||
* Reorganizes DataStore api, renaming: stix2.sources to stix2.datastore.
|
||||
* Fixes various bugs involving CustomMarking, creating new versions of objects
|
||||
with custom properties, and a missing IntrusionSet property.
|
||||
* Drops Python 3.3 support.
|
||||
|
||||
0.4.0 - 2017-11-13
|
||||
|
||||
* Adds `creator_of` function to easily get the Identity that created an object,
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<div>
|
||||
<h2><a id="openParticipation">Public Participation Invited</a></h2>
|
||||
|
||||
<p>This <a href="https://www.oasis-open.org/resources/open-repositories">OASIS Open Repository</a> ( <b><a href="https://github.com/oasis-open/cti-python-stix2">github.com/oasis-open/cti-python-stix2</a></b> ) is a community public repository that supports participation by anyone, whether affiliated with OASIS or not. Substantive contributions (repository "code") and related feedback is invited from all parties, following the common conventions for participation in GitHub public repository projects. Participation is expected to be consistent with the <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">OASIS Open Repository Guidelines and Procedures</a>, the <a href="https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt">LICENSE</a> designated for this particular repository (BSD-3-Clause License), and the requirement for an <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement</a>. Please see the repository <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/README.md">README</a> document for other details.</p>
|
||||
<p>This <a href="https://www.oasis-open.org/resources/open-repositories">OASIS TC Open Repository</a> ( <b><a href="https://github.com/oasis-open/cti-python-stix2">github.com/oasis-open/cti-python-stix2</a></b> ) is a community public repository that supports participation by anyone, whether affiliated with OASIS or not. Substantive contributions (repository "code") and related feedback is invited from all parties, following the common conventions for participation in GitHub public repository projects. Participation is expected to be consistent with the <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">OASIS TC Open Repository Guidelines and Procedures</a>, the <a href="https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt">LICENSE</a> designated for this particular repository (BSD-3-Clause License), and the requirement for an <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement</a>. Please see the repository <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/README.md">README</a> document for other details.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2><a id="distinctRules">Governance Distinct from OASIS TC Process</a></h2>
|
||||
<p>Content accepted as "contributions" to this Open Repository, as <a href="#openRepoContribution">defined</a> below, are distinct from any <a href="https://www.oasis-open.org/policies-guidelines/ipr#contributions">Contributions</a> made to the associated <a href="https://www.oasis-open.org/committees/cti/">OASIS Cyber Threat Intelligence (CTI) TC</a> itself. Participation in the associated Technical Committee is governed by the <a href="https://www.oasis-open.org/policies-guidelines/bylaws">OASIS Bylaws</a>, <a href="https://www.oasis-open.org/policies-guidelines/tc-process">OASIS TC Process</a>, <a href="https://www.oasis-open.org/policies-guidelines/ipr">IPR Policy</a>, and related <a href="https://www.oasis-open.org/policies-guidelines/">policies</a>. This Open Repository is not subject to the OASIS TC-related policies. Open Repository governance is defined by separate <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">participation and contribution guidelines</a> as referenced in the <a href="https://www.oasis-open.org/resources/open-repositories/">OASIS Open Repositories Overview</a>.</p>
|
||||
<p>Content accepted as "contributions" to this TC Open Repository, as <a href="#openRepoContribution">defined</a> below, are distinct from any <a href="https://www.oasis-open.org/policies-guidelines/ipr#contributions">Contributions</a> made to the associated <a href="https://www.oasis-open.org/committees/cti/">OASIS Cyber Threat Intelligence (CTI) TC</a> itself. Participation in the associated Technical Committee is governed by the <a href="https://www.oasis-open.org/policies-guidelines/bylaws">OASIS Bylaws</a>, <a href="https://www.oasis-open.org/policies-guidelines/tc-process">OASIS TC Process</a>, <a href="https://www.oasis-open.org/policies-guidelines/ipr">IPR Policy</a>, and related <a href="https://www.oasis-open.org/policies-guidelines/">policies</a>. This TC Open Repository is not subject to the OASIS TC-related policies. TC Open Repository governance is defined by separate <a href="https://www.oasis-open.org/policies-guidelines/open-repositories">participation and contribution guidelines</a> as referenced in the <a href="https://www.oasis-open.org/resources/open-repositories/">OASIS TC Open Repositories Overview</a>.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2><a id="distinctLicenses">Licensing Distinct from OASIS IPR Policy</a></h2>
|
||||
<p>Because different licenses apply to the OASIS TC's specification work, and this Open Repository, there is no guarantee that the licensure of specific repository material will be compatible with licensing requirements of an implementation of a TC's specification. Please refer to the <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/LICENSE">LICENSE file</a> for the terms of this material, and to the OASIS IPR Policy for <a href="https://www.oasis-open.org/policies-guidelines/ipr#Non-Assertion-Mode">the terms applicable to the TC's specifications</a>, including any applicable <a href="https://www.oasis-open.org/committees/cti/ipr.php">declarations</a>.</p>
|
||||
<p>Because different licenses apply to the OASIS TC's specification work, and this TC Open Repository, there is no guarantee that the licensure of specific repository material will be compatible with licensing requirements of an implementation of a TC's specification. Please refer to the <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/LICENSE">LICENSE file</a> for the terms of this material, and to the OASIS IPR Policy for <a href="https://www.oasis-open.org/policies-guidelines/ipr#Non-Assertion-Mode">the terms applicable to the TC's specifications</a>, including any applicable <a href="https://www.oasis-open.org/committees/cti/ipr.php">declarations</a>.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2><a id="contributionDefined">Contributions Subject to Individual CLA</a></h2>
|
||||
|
||||
<p>Formally, <a id="openRepoContribution">"contribution"</a> to this Open Repository refers to content merged into the "Code" repository (repository changes represented by code <a href="https://github.com/oasis-open/cti-python-stix2/commits/master">commits</a>), following the GitHub definition of <i><a href="https://help.github.com/articles/github-glossary/#contributor">contributor</a></i>: "someone who has contributed to a project by having a pull request merged but does not have collaborator [<i>i.e.</i>, direct write] access." Anyone who signs the Open Repository <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement (CLA)</a>, signifying agreement with the licensing requirement, may contribute substantive content — subject to evaluation of a GitHub pull request. The main web page for this repository, as with any GitHub public repository, displays a link to a document listing contributions to the repository's default branch (filtered by Commits, Additions, and Deletions).</p>
|
||||
<p>Formally, <a id="openRepoContribution">"contribution"</a> to this TC Open Repository refers to content merged into the "Code" repository (repository changes represented by code <a href="https://github.com/oasis-open/cti-python-stix2/commits/master">commits</a>), following the GitHub definition of <i><a href="https://help.github.com/articles/github-glossary/#contributor">contributor</a></i>: "someone who has contributed to a project by having a pull request merged but does not have collaborator [<i>i.e.</i>, direct write] access." Anyone who signs the TC Open Repository <a href="https://www.oasis-open.org/resources/open-repositories/cla/individual-cla">Individual Contributor License Agreement (CLA)</a>, signifying agreement with the licensing requirement, may contribute substantive content — subject to evaluation of a GitHub pull request. The main web page for this repository, as with any GitHub public repository, displays a link to a document listing contributions to the repository's default branch (filtered by Commits, Additions, and Deletions).</p>
|
||||
|
||||
<p>This Open Repository, as with GitHub public repositories generally, also accepts public feedback from any GitHub user. Public feedback includes opening issues, authoring and editing comments, participating in conversations, making wiki edits, creating repository stars, and making suggestions via pull requests. Such feedback does not constitute an OASIS Open Repository <a href="#openRepoContribution">contribution</a>. Some details are presented under "Read permissions" in the table of <a href="https://help.github.com/articles/repository-permission-levels-for-an-organization/">permission levels</a> for a GitHub organization. Technical content intended as a substantive contribution (repository "Code") to an Open Repository is subject to evaluation, and requires a signed Individual CLA.</p>
|
||||
<p>This TC Open Repository, as with GitHub public repositories generally, also accepts public feedback from any GitHub user. Public feedback includes opening issues, authoring and editing comments, participating in conversations, making wiki edits, creating repository stars, and making suggestions via pull requests. Such feedback does not constitute an OASIS TC Open Repository <a href="#openRepoContribution">contribution</a>. Some details are presented under "Read permissions" in the table of <a href="https://help.github.com/articles/repository-permission-levels-for-an-organization/">permission levels</a> for a GitHub organization. Technical content intended as a substantive contribution (repository "Code") to an TC Open Repository is subject to evaluation, and requires a signed Individual CLA.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -27,12 +27,12 @@
|
|||
<div>
|
||||
<h2><a id="fork-and-pull-model">Fork-and-Pull Collaboration Model</a></h2>
|
||||
|
||||
<p>OASIS Open Repositories use the familiar <a href="https://help.github.com/articles/using-pull-requests/#fork--pull">fork-and-pull</a> collaboration model supported by GitHub and other distributed version-control systems. Any GitHub user wishing to contribute should <a href="https://help.github.com/articles/github-glossary/#fork">fork</a> the repository, make additions or other modifications, and then submit a pull request. GitHub pull requests should be accompanied by supporting <a href="https://help.github.com/articles/commenting-on-the-diff-of-a-pull-request/">comments</a> and/or <a href="https://help.github.com/articles/about-issues/">issues</a>. Community conversations about pull requests, supported by GitHub <a href="https://help.github.com/articles/about-notifications/">notifications</a>, will provide the basis for a consensus determination to merge, modify, close, or take other action, as communicated by the repository <a href="https://www.oasis-open.org/resources/open-repositories/maintainers-guide">Maintainers</a>.</p>
|
||||
<p>OASIS TC Open Repositories use the familiar <a href="https://help.github.com/articles/using-pull-requests/#fork--pull">fork-and-pull</a> collaboration model supported by GitHub and other distributed version-control systems. Any GitHub user wishing to contribute should <a href="https://help.github.com/articles/github-glossary/#fork">fork</a> the repository, make additions or other modifications, and then submit a pull request. GitHub pull requests should be accompanied by supporting <a href="https://help.github.com/articles/commenting-on-the-diff-of-a-pull-request/">comments</a> and/or <a href="https://help.github.com/articles/about-issues/">issues</a>. Community conversations about pull requests, supported by GitHub <a href="https://help.github.com/articles/about-notifications/">notifications</a>, will provide the basis for a consensus determination to merge, modify, close, or take other action, as communicated by the repository <a href="https://www.oasis-open.org/resources/open-repositories/maintainers-guide">Maintainers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2><a id="feedback">Feedback</a></h2>
|
||||
|
||||
<p>Questions or comments about this Open Repository's activities should be composed as GitHub issues or comments. If use of an issue/comment is not possible or appropriate, questions may be directed by email to the <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/README.md#maintainers">repository Maintainer(s)</a>. Please send general questions about Open Repository participation to OASIS Staff at <a href="mailto:repository-admin@oasis-open.org">repository-admin@oasis-open.org</a> and any specific CLA-related questions to <a href="mailto:repository-cla@oasis-open.org">repository-cla@oasis-open.org</a>.</p>
|
||||
<p>Questions or comments about this TC Open Repository's activities should be composed as GitHub issues or comments. If use of an issue/comment is not possible or appropriate, questions may be directed by email to the <a href="https://github.com/oasis-open/cti-python-stix2/blob/master/README.md#maintainers">repository Maintainer(s)</a>. Please send general questions about TC Open Repository participation to OASIS Staff at <a href="mailto:repository-admin@oasis-open.org">repository-admin@oasis-open.org</a> and any specific CLA-related questions to <a href="mailto:repository-cla@oasis-open.org">repository-cla@oasis-open.org</a>.</p>
|
||||
|
||||
</div></div>
|
||||
|
|
124
README.rst
124
README.rst
|
@ -3,11 +3,13 @@
|
|||
cti-python-stix2
|
||||
================
|
||||
|
||||
This is an `OASIS Open
|
||||
Repository <https://www.oasis-open.org/resources/open-repositories/>`__.
|
||||
This is an `OASIS TC Open
|
||||
Repository <https://www.oasis-open.org/resources/open-
|
||||
repositories/>`__.
|
||||
See the `Governance <#governance>`__ section for more information.
|
||||
|
||||
This repository provides Python APIs for serializing and de-serializing
|
||||
This repository provides Python APIs for serializing and de-
|
||||
serializing
|
||||
STIX 2 JSON content, along with higher-level APIs for common tasks,
|
||||
including data markings, versioning, and for resolving STIX IDs across
|
||||
multiple data sources.
|
||||
|
@ -29,8 +31,10 @@ Usage
|
|||
-----
|
||||
|
||||
To create a STIX object, provide keyword arguments to the type's
|
||||
constructor. Certain required attributes of all objects, such as ``type`` or
|
||||
``id``, will be set automatically if not provided as keyword arguments.
|
||||
constructor. Certain required attributes of all objects, such as
|
||||
``type`` or
|
||||
``id``, will be set automatically if not provided as keyword
|
||||
arguments.
|
||||
|
||||
.. code:: python
|
||||
|
||||
|
@ -40,7 +44,8 @@ constructor. Certain required attributes of all objects, such as ``type`` or
|
|||
labels=["malicious-activity"],
|
||||
pattern="[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']")
|
||||
|
||||
To parse a STIX JSON string into a Python STIX object, use ``parse()``:
|
||||
To parse a STIX JSON string into a Python STIX object, use
|
||||
``parse()``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
|
@ -55,12 +60,14 @@ To parse a STIX JSON string into a Python STIX object, use ``parse()``:
|
|||
"malicious-activity"
|
||||
],
|
||||
"name": "File hash for malware variant",
|
||||
"pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",
|
||||
"pattern": "[file:hashes.md5 =
|
||||
'd41d8cd98f00b204e9800998ecf8427e']",
|
||||
"valid_from": "2017-09-26T23:33:39.829952Z"
|
||||
}""")
|
||||
print(indicator)
|
||||
|
||||
For more in-depth documentation, please see `https://stix2.readthedocs.io/ <https://stix2.readthedocs.io/>`__.
|
||||
For more in-depth documentation, please see
|
||||
`https://stix2.readthedocs.io/ <https://stix2.readthedocs.io/>`__.
|
||||
|
||||
STIX 2.X Technical Specification Support
|
||||
----------------------------------------
|
||||
|
@ -77,66 +84,87 @@ Governance
|
|||
|
||||
This GitHub public repository (
|
||||
**https://github.com/oasis-open/cti-python-stix2** ) was
|
||||
`proposed <https://lists.oasis-open.org/archives/cti/201702/msg00008.html>`__
|
||||
`proposed <https://lists.oasis-
|
||||
open.org/archives/cti/201702/msg00008.html>`__
|
||||
and
|
||||
`approved <https://www.oasis-open.org/committees/download.php/60009/>`__
|
||||
`approved <https://www.oasis-
|
||||
open.org/committees/download.php/60009/>`__
|
||||
[`bis <https://issues.oasis-open.org/browse/TCADMIN-2549>`__] by the
|
||||
`OASIS Cyber Threat Intelligence (CTI)
|
||||
TC <https://www.oasis-open.org/committees/cti/>`__ as an `OASIS Open
|
||||
Repository <https://www.oasis-open.org/resources/open-repositories/>`__
|
||||
TC <https://www.oasis-open.org/committees/cti/>`__ as an `OASIS TC
|
||||
Open
|
||||
Repository <https://www.oasis-open.org/resources/open-
|
||||
repositories/>`__
|
||||
to support development of open source resources related to Technical
|
||||
Committee work.
|
||||
|
||||
While this Open Repository remains associated with the sponsor TC, its
|
||||
While this TC Open Repository remains associated with the sponsor TC,
|
||||
its
|
||||
development priorities, leadership, intellectual property terms,
|
||||
participation rules, and other matters of governance are `separate and
|
||||
distinct <https://github.com/oasis-open/cti-python-stix2/blob/master/CONTRIBUTING.md#governance-distinct-from-oasis-tc-process>`__
|
||||
distinct <https://github.com/oasis-open/cti-python-
|
||||
stix2/blob/master/CONTRIBUTING.md#governance-distinct-from-oasis-tc-
|
||||
process>`__
|
||||
from the OASIS TC Process and related policies.
|
||||
|
||||
All contributions made to this Open Repository are subject to open
|
||||
All contributions made to this TC Open Repository are subject to open
|
||||
source license terms expressed in the `BSD-3-Clause
|
||||
License <https://www.oasis-open.org/sites/www.oasis-open.org/files/BSD-3-Clause.txt>`__.
|
||||
License <https://www.oasis-open.org/sites/www.oasis-
|
||||
open.org/files/BSD-3-Clause.txt>`__.
|
||||
That license was selected as the declared `"Applicable
|
||||
License" <https://www.oasis-open.org/resources/open-repositories/licenses>`__
|
||||
when the Open Repository was created.
|
||||
License" <https://www.oasis-open.org/resources/open-
|
||||
repositories/licenses>`__
|
||||
when the TC Open Repository was created.
|
||||
|
||||
As documented in `"Public Participation
|
||||
Invited <https://github.com/oasis-open/cti-python-stix2/blob/master/CONTRIBUTING.md#public-participation-invited>`__",
|
||||
contributions to this OASIS Open Repository are invited from all
|
||||
parties, whether affiliated with OASIS or not. Participants must have a
|
||||
Invited <https://github.com/oasis-open/cti-python-
|
||||
stix2/blob/master/CONTRIBUTING.md#public-participation-invited>`__",
|
||||
contributions to this OASIS TC Open Repository are invited from all
|
||||
parties, whether affiliated with OASIS or not. Participants must have
|
||||
a
|
||||
GitHub account, but no fees or OASIS membership obligations are
|
||||
required. Participation is expected to be consistent with the `OASIS
|
||||
Open Repository Guidelines and
|
||||
Procedures <https://www.oasis-open.org/policies-guidelines/open-repositories>`__,
|
||||
TC Open Repository Guidelines and
|
||||
Procedures <https://www.oasis-open.org/policies-guidelines/open-
|
||||
repositories>`__,
|
||||
the open source
|
||||
`LICENSE <https://github.com/oasis-open/cti-python-stix2/blob/master/LICENSE>`__
|
||||
`LICENSE <https://github.com/oasis-open/cti-python-
|
||||
stix2/blob/master/LICENSE>`__
|
||||
designated for this particular repository, and the requirement for an
|
||||
`Individual Contributor License
|
||||
Agreement <https://www.oasis-open.org/resources/open-repositories/cla/individual-cla>`__
|
||||
Agreement <https://www.oasis-open.org/resources/open-
|
||||
repositories/cla/individual-cla>`__
|
||||
that governs intellectual property.
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
Open Repository
|
||||
`Maintainers <https://www.oasis-open.org/resources/open-repositories/maintainers-guide>`__
|
||||
TC Open Repository
|
||||
`Maintainers <https://www.oasis-open.org/resources/open-
|
||||
repositories/maintainers-guide>`__
|
||||
are responsible for oversight of this project's community development
|
||||
activities, including evaluation of GitHub `pull
|
||||
requests <https://github.com/oasis-open/cti-python-stix2/blob/master/CONTRIBUTING.md#fork-and-pull-collaboration-model>`__
|
||||
requests <https://github.com/oasis-open/cti-python-
|
||||
stix2/blob/master/CONTRIBUTING.md#fork-and-pull-collaboration-
|
||||
model>`__
|
||||
and
|
||||
`preserving <https://www.oasis-open.org/policies-guidelines/open-repositories#repositoryManagement>`__
|
||||
`preserving <https://www.oasis-open.org/policies-guidelines/open-
|
||||
repositories#repositoryManagement>`__
|
||||
open source principles of openness and fairness. Maintainers are
|
||||
recognized and trusted experts who serve to implement community goals
|
||||
and consensus design preferences.
|
||||
|
||||
Initially, the associated TC members have designated one or more persons
|
||||
to serve as Maintainer(s); subsequently, participating community members
|
||||
Initially, the associated TC members have designated one or more
|
||||
persons
|
||||
to serve as Maintainer(s); subsequently, participating community
|
||||
members
|
||||
may select additional or substitute Maintainers, per `consensus
|
||||
agreements <https://www.oasis-open.org/resources/open-repositories/maintainers-guide#additionalMaintainers>`__.
|
||||
agreements <https://www.oasis-open.org/resources/open-
|
||||
repositories/maintainers-guide#additionalMaintainers>`__.
|
||||
|
||||
.. _currentMaintainers:
|
||||
|
||||
**Current Maintainers of this Open Repository**
|
||||
**Current Maintainers of this TC Open Repository**
|
||||
|
||||
- `Greg Back <mailto:gback@mitre.org>`__; GitHub ID:
|
||||
https://github.com/gtback/; WWW: `MITRE
|
||||
|
@ -145,28 +173,36 @@ agreements <https://www.oasis-open.org/resources/open-repositories/maintainers-g
|
|||
https://github.com/clenk/; WWW: `MITRE
|
||||
Corporation <http://www.mitre.org/>`__
|
||||
|
||||
About OASIS Open Repositories
|
||||
-----------------------------
|
||||
About OASIS TC Open Repositories
|
||||
--------------------------------
|
||||
|
||||
- `Open Repositories: Overview and
|
||||
Resources <https://www.oasis-open.org/resources/open-repositories/>`__
|
||||
- `TC Open Repositories: Overview and
|
||||
Resources <https://www.oasis-open.org/resources/open-
|
||||
repositories/>`__
|
||||
- `Frequently Asked
|
||||
Questions <https://www.oasis-open.org/resources/open-repositories/faq>`__
|
||||
Questions <https://www.oasis-open.org/resources/open-
|
||||
repositories/faq>`__
|
||||
- `Open Source
|
||||
Licenses <https://www.oasis-open.org/resources/open-repositories/licenses>`__
|
||||
Licenses <https://www.oasis-open.org/resources/open-
|
||||
repositories/licenses>`__
|
||||
- `Contributor License Agreements
|
||||
(CLAs) <https://www.oasis-open.org/resources/open-repositories/cla>`__
|
||||
(CLAs) <https://www.oasis-open.org/resources/open-
|
||||
repositories/cla>`__
|
||||
- `Maintainers' Guidelines and
|
||||
Agreement <https://www.oasis-open.org/resources/open-repositories/maintainers-guide>`__
|
||||
Agreement <https://www.oasis-open.org/resources/open-
|
||||
repositories/maintainers-guide>`__
|
||||
|
||||
Feedback
|
||||
--------
|
||||
|
||||
Questions or comments about this Open Repository's activities should be
|
||||
composed as GitHub issues or comments. If use of an issue/comment is not
|
||||
Questions or comments about this TC Open Repository's activities
|
||||
should be
|
||||
composed as GitHub issues or comments. If use of an issue/comment is
|
||||
not
|
||||
possible or appropriate, questions may be directed by email to the
|
||||
Maintainer(s) `listed above <#currentmaintainers>`__. Please send
|
||||
general questions about Open Repository participation to OASIS Staff at
|
||||
general questions about TC Open Repository participation to OASIS
|
||||
Staff at
|
||||
repository-admin@oasis-open.org and any specific CLA-related questions
|
||||
to repository-cla@oasis-open.org.
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
filesystem
|
||||
==========================
|
||||
|
||||
.. automodule:: stix2.datastore.filesystem
|
||||
:members:
|
|
@ -0,0 +1,5 @@
|
|||
filters
|
||||
=======================
|
||||
|
||||
.. automodule:: stix2.datastore.filters
|
||||
:members:
|
|
@ -0,0 +1,5 @@
|
|||
memory
|
||||
======================
|
||||
|
||||
.. automodule:: stix2.datastore.memory
|
||||
:members:
|
|
@ -0,0 +1,5 @@
|
|||
taxii
|
||||
=====================
|
||||
|
||||
.. automodule:: stix2.datastore.taxii
|
||||
:members:
|
|
@ -1,5 +0,0 @@
|
|||
filesystem
|
||||
========================
|
||||
|
||||
.. automodule:: stix2.sources.filesystem
|
||||
:members:
|
|
@ -1,5 +0,0 @@
|
|||
filters
|
||||
=====================
|
||||
|
||||
.. automodule:: stix2.sources.filters
|
||||
:members:
|
|
@ -1,5 +0,0 @@
|
|||
memory
|
||||
====================
|
||||
|
||||
.. automodule:: stix2.sources.memory
|
||||
:members:
|
|
@ -1,5 +0,0 @@
|
|||
taxii
|
||||
===================
|
||||
|
||||
.. automodule:: stix2.sources.taxii
|
||||
:members:
|
|
@ -0,0 +1,5 @@
|
|||
datastore
|
||||
===============
|
||||
|
||||
.. automodule:: stix2.datastore
|
||||
:members:
|
|
@ -1,5 +0,0 @@
|
|||
sources
|
||||
=============
|
||||
|
||||
.. automodule:: stix2.sources
|
||||
:members:
|
|
@ -0,0 +1,5 @@
|
|||
workbench
|
||||
===============
|
||||
|
||||
.. automodule:: stix2.workbench
|
||||
:members:
|
|
@ -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 <guide/ts_support.ipynb#How-imports-will-work>`.
|
||||
:ref:`How imports work </guide/ts_support.ipynb#How-imports-work>`.
|
||||
|
||||
.. automodule:: stix2
|
||||
|
|
82
docs/conf.py
82
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 = [
|
||||
|
@ -28,8 +34,8 @@ project = 'stix2'
|
|||
copyright = '2017, OASIS Open'
|
||||
author = 'OASIS Open'
|
||||
|
||||
version = '0.4.0'
|
||||
release = '0.4.0'
|
||||
version = '1.0.2'
|
||||
release = '1.0.2'
|
||||
|
||||
language = None
|
||||
exclude_patterns = ['_build', '_templates', 'Thumbs.db', '.DS_Store', 'guide/.ipynb_checkpoints']
|
||||
|
@ -50,3 +56,75 @@ 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 STIXPropertyDocumenter(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:', '<stixattr>')
|
||||
for prop_name, prop in obj._properties.items():
|
||||
# Skip 'type'
|
||||
if prop_name == 'type':
|
||||
continue
|
||||
|
||||
# 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'
|
||||
if 'Timestamp' in prop_type and hasattr(prop, 'default'):
|
||||
prop_type += ', default: current date/time'
|
||||
prop_str = '**%s** (*%s*)' % (prop_name, prop_type)
|
||||
self.add_line(' - %s' % prop_str, '<stixattr>')
|
||||
|
||||
self.add_line('', '<stixattr>')
|
||||
|
||||
|
||||
def autodoc_skipper(app, what, name, obj, skip, options):
|
||||
"""Customize Sphinx to skip some member we don't want documented.
|
||||
|
||||
Skips anything containing ':autodoc-skip:' in its docstring.
|
||||
"""
|
||||
if obj.__doc__ and ':autodoc-skip:' in obj.__doc__:
|
||||
return skip or True
|
||||
return skip
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_autodocumenter(STIXPropertyDocumenter)
|
||||
app.connect('autodoc-skip-member', autodoc_skipper)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
.. _datastore_api:
|
||||
|
||||
DataStore API
|
||||
=============
|
||||
|
||||
.. warning::
|
||||
|
||||
The DataStore API is still in the planning stages and may be subject to
|
||||
major changes. We encourage anyone with feedback to contact the maintainers
|
||||
to help ensure the API meets a large variety of use cases.
|
||||
|
||||
One prominent feature of python-stix2 will be an interface for connecting
|
||||
different backend data stores containing STIX content. This will allow a uniform
|
||||
interface for querying and saving STIX content, and allow higher level code to
|
||||
be written without regard to the underlying data storage format. python-stix2
|
||||
will define the API and contain some default implementations of this API, but
|
||||
developers are encouraged to write their own implementations.
|
||||
|
||||
Potential functions of the API include:
|
||||
|
||||
* get a STIX Object by ID (returns the most recent version).
|
||||
* get all versions of a STIX object by ID.
|
||||
* get all relationships involving a given object, and all related objects.
|
||||
* save an object.
|
||||
* query for objects that match certain criteria (query syntax TBD).
|
||||
|
||||
For all queries, the API will include a "filter" interface that can be used to
|
||||
either explicitly include or exclude results with certain criteria. For example,
|
||||
|
||||
* only trust content from a set of object creators.
|
||||
* exclude content from certain (untrusted) object creators.
|
||||
* only include content with a confidence above a certain threshold (once
|
||||
confidence is added to STIX).
|
||||
* only return content that can be shared with external parties (in other words,
|
||||
that has TLP:GREEN markings).
|
||||
|
||||
Additionally, the python-stix2 library will contain a "composite" data store,
|
||||
which implements the DataStore API while delegating functionality to one or more
|
||||
"child" data stores.
|
|
@ -1,6 +1,9 @@
|
|||
User's Guide
|
||||
============
|
||||
|
||||
This section of documentation contains guides and tutorials on how to use the
|
||||
``stix2`` library.
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -25,7 +24,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -146,15 +144,15 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dbcbd659-c927-4f9a-994f-0a2632274394"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829952Z"</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193659Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -188,9 +186,7 @@
|
|||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"indicator2 = Indicator(type='indicator',\n",
|
||||
|
@ -295,7 +291,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"u'File hash for malware variant'"
|
||||
"'File hash for malware variant'"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
|
@ -322,7 +318,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"u'File hash for malware variant'"
|
||||
"'File hash for malware variant'"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
|
@ -469,9 +465,9 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--d7fd675d-94eb-4d95-b0bc-b3c5e28e8ed2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:56.908Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:56.908Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:46.584Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:46.584Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Poison Ivy"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"remote-access-trojan"</span>\n",
|
||||
|
@ -592,12 +588,12 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--637aa3b1-d4b8-4bc4-85e7-77cc82b198a3"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:01.765Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:01.765Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--34ddc7b4-4965-4615-b286-1c8bbaa1e7db"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:49.474Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:49.474Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"relationship_type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicates"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dbcbd659-c927-4f9a-994f-0a2632274394"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--d7fd675d-94eb-4d95-b0bc-b3c5e28e8ed2"</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -704,12 +700,12 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--70fe77c2-ab00-4181-a2dc-fe5567d971ca"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:03.923Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:03.923Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--0a646403-f7e7-4cfd-b945-cab5cde05857"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:51.417Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:51.417Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"relationship_type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicates"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dbcbd659-c927-4f9a-994f-0a2632274394"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--d7fd675d-94eb-4d95-b0bc-b3c5e28e8ed2"</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -814,26 +810,26 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"bundle"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"bundle--2536c43d-c874-418e-886c-20a22120d8cb"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"bundle--f83477e5-f853-47e1-a267-43f3aa1bd5b0"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"spec_version"</span><span class=\"p\">:</span> <span class=\"s2\">"2.0"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"objects"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dbcbd659-c927-4f9a-994f-0a2632274394"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:39.829952Z"</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:24.193659Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
" <span class=\"p\">},</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--d7fd675d-94eb-4d95-b0bc-b3c5e28e8ed2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:56.908Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:33:56.908Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:46.584Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:46.584Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Poison Ivy"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"remote-access-trojan"</span>\n",
|
||||
|
@ -841,12 +837,12 @@
|
|||
" <span class=\"p\">},</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--637aa3b1-d4b8-4bc4-85e7-77cc82b198a3"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:01.765Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:34:01.765Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"relationship--34ddc7b4-4965-4615-b286-1c8bbaa1e7db"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:49.474Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:32:49.474Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"relationship_type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicates"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dbcbd659-c927-4f9a-994f-0a2632274394"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--d7fd675d-94eb-4d95-b0bc-b3c5e28e8ed2"</span>\n",
|
||||
" <span class=\"nt\">"source_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"target_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
|
@ -871,21 +867,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -23,9 +22,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -70,7 +70,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -99,7 +99,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -175,9 +175,9 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--00c5743f-2d5e-4d66-88f1-1842584f4519"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T16:17:44.596Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T16:17:44.596Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--87aac643-341b-413a-b702-ea5820416155"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:10.269Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:10.269Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"John Smith"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"x_foo"</span><span class=\"p\">:</span> <span class=\"s2\">"bar"</span>\n",
|
||||
|
@ -188,7 +188,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -211,6 +211,117 @@
|
|||
"Alternatively, setting ``allow_custom`` to ``True`` will allow custom properties without requiring a ``custom_properties`` dictionary."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--a1ad0a6f-39ab-4642-9a72-aaa198b1eee2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:12.270Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:12.270Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"John Smith"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"x_foo"</span><span class=\"p\">:</span> <span class=\"s2\">"bar"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"identity2 = Identity(name=\"John Smith\",\n",
|
||||
" identity_class=\"individual\",\n",
|
||||
" x_foo=\"bar\",\n",
|
||||
" allow_custom=True)\n",
|
||||
"print(identity2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Likewise, when parsing STIX content with custom properties, pass ``allow_custom=True`` to [parse()](../api/stix2.core.rst#stix2.core.parse):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
|
@ -287,15 +398,7 @@
|
|||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"x_foo"</span><span class=\"p\">:</span> <span class=\"s2\">"bar"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--1e8188eb-245f-400b-839d-7f612169c514"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T21:02:22.708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T21:02:22.708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"John Smith"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>bar\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
|
@ -307,34 +410,6 @@
|
|||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"identity2 = Identity(name=\"John Smith\",\n",
|
||||
" identity_class=\"individual\",\n",
|
||||
" x_foo=\"bar\",\n",
|
||||
" allow_custom=True)\n",
|
||||
"print(identity2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Likewise, when parsing STIX content with custom properties, pass ``allow_custom=True`` to [parse()](../api/stix2.core.rst#stix2.core.parse):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"bar\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from stix2 import parse\n",
|
||||
"\n",
|
||||
|
@ -364,10 +439,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import CustomObject, properties\n",
|
||||
|
@ -391,7 +464,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -467,9 +540,9 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"x-animal"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-animal--caebdf17-9d2a-4c84-8864-7406326618f0"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T21:02:34.724Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T21:02:34.724Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-animal--b1e4fe7f-7985-451d-855c-6ba5c265b22a"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:19.790Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T18:38:19.790Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"species"</span><span class=\"p\">:</span> <span class=\"s2\">"lion"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"animal_class"</span><span class=\"p\">:</span> <span class=\"s2\">"mammal"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
|
@ -479,7 +552,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -499,7 +572,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -525,15 +598,90 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"shark\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>shark\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -558,7 +706,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -593,7 +741,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -678,7 +826,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -709,16 +857,172 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"foobaz\n",
|
||||
"5\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>foobaz\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>5\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -759,7 +1063,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -843,7 +1147,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -872,16 +1176,172 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"bla\n",
|
||||
"50\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>bla\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>50\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -918,21 +1378,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 40,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
|
@ -33,23 +33,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -58,9 +60,9 @@
|
|||
"source": [
|
||||
"# DataStore API\n",
|
||||
"\n",
|
||||
"CTI Python STIX2 features a new interface for pulling and pushing STIX2 content. The new interface consists of [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore), [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource) and [DataSink](../api/stix2.sources.rst#stix2.sources.DataSink) constructs: a [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource) for pulling STIX2 content, a [DataSink](../api/stix2.sources.rst#stix2.sources.DataSink) for pushing STIX2 content, and a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) for both pulling and pushing.\n",
|
||||
"The ``stix2`` library features an interface for pulling and pushing STIX 2 content. This interface consists of [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin), [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource) and [DataSink](../api/stix2.datastore.rst#stix2.datastore.DataSink) constructs: a [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource) for pulling STIX 2 content, a [DataSink](../api/stix2.datastore.rst#stix2.datastore.DataSink) for pushing STIX 2 content, and a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) for both pulling and pushing.\n",
|
||||
"\n",
|
||||
"The DataStore, [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource), [DataSink](../api/stix2.sources.rst#stix2.sources.DataSink) (collectively referred to as the \"DataStore suite\") APIs are not referenced directly by a user but are used as base classes, which are then subclassed by real DataStore suites. CTI Python STIX2 provides the DataStore suites of [FileSystem](../api/sources/stix2.sources.filesystem.rst), [Memory](../api/sources/stix2.sources.memory.rst), and [TAXII](../api/sources/stix2.sources.taxii.rst). Users are also encouraged to subclass the base classes and create their own custom DataStore suites."
|
||||
"The DataStore, [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource), [DataSink](../api/stix2.datastore.rst#stix2.datastore.DataSink) (collectively referred to as the \"DataStore suite\") APIs are not referenced directly by a user but are used as base classes, which are then subclassed by real DataStore suites. The ``stix2`` library provides the DataStore suites of [FileSystem](../api/datastore/stix2.datastore.filesystem.rst), [Memory](../api/datastore/stix2.datastore.memory.rst), and [TAXII](../api/datastore/stix2.datastore.taxii.rst). Users are also encouraged to subclass the base classes and create their own custom DataStore suites."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -69,13 +71,13 @@
|
|||
"source": [
|
||||
"## CompositeDataSource\n",
|
||||
"\n",
|
||||
"[CompositeDataSource](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) is an available controller that can be used as a single interface to a set of defined [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource). The purpose of this controller is allow for the grouping of [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource) and making `get()`/`query()` calls to a set of DataSources in one API call. [CompositeDataSources](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) can be used to organize/group [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource), federate `get()`/`all_versions()`/`query()` calls, and reduce user code.\n",
|
||||
"[CompositeDataSource](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) is an available controller that can be used as a single interface to a set of defined [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource). The purpose of this controller is allow for the grouping of [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource) and making `get()`/`query()` calls to a set of DataSources in one API call. [CompositeDataSources](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) can be used to organize/group [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource), federate `get()`/`all_versions()`/`query()` calls, and reduce user code.\n",
|
||||
"\n",
|
||||
"[CompositeDataSource](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) is just a wrapper around a set of defined [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource) (e.g. [FileSystemSource](../api/sources/stix2.sources.filesystem.rst#stix2.sources.filesystem.FileSystemSource)) that federates `get()`/`all_versions()`/`query()` calls individually to each of the attached [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource) , collects the results from each [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource) and returns them.\n",
|
||||
"[CompositeDataSource](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) is just a wrapper around a set of defined [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource) (e.g. [FileSystemSource](../api/datastore/stix2.datastore.filesystem.rst#stix2.datastore.filesystem.FileSystemSource)) that federates `get()`/`all_versions()`/`query()` calls individually to each of the attached [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource) , collects the results from each [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource) and returns them.\n",
|
||||
"\n",
|
||||
"Filters can be attached to [CompositeDataSources](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) just as they can be done to [DataStores](../api/stix2.sources.rst#stix2.sources.DataStore) and [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource). When `get()`/`all_versions()`/`query()` calls are made to the [CompositeDataSource](../api/stix2.sources.rst#stix2.sources.CompositeDataSource), it will pass along any query filters from the call and any of its own filters to the attached [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource). In addition, those [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource) may have their own attached filters as well. The effect is that all the filters are eventually combined when the `get()`/`all_versions()`/`query()` call is actually executed within a [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource). \n",
|
||||
"Filters can be attached to [CompositeDataSources](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) just as they can be done to [DataStores](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) and [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource). When `get()`/`all_versions()`/`query()` calls are made to the [CompositeDataSource](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource), it will pass along any query filters from the call and any of its own filters to the attached [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource). In addition, those [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource) may have their own attached filters as well. The effect is that all the filters are eventually combined when the `get()`/`all_versions()`/`query()` call is actually executed within a [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource). \n",
|
||||
"\n",
|
||||
"A [CompositeDataSource](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) can also be attached to a [CompositeDataSource](../api/stix2.sources.rst#stix2.sources.CompositeDataSource) for multiple layers of grouped [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource).\n",
|
||||
"A [CompositeDataSource](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) can also be attached to a [CompositeDataSource](../api/stix2.datastore.rst#stix2.datastore.CompositeDataSource) for multiple layers of grouped [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource).\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"### CompositeDataSource API\n",
|
||||
|
@ -85,50 +87,229 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"type\": \"indicator\",\n",
|
||||
" \"id\": \"indicator--797ae2b5-3f7a-44c5-8ecd-33ba22fdc2b5\",\n",
|
||||
" \"created\": \"2017-10-04T19:27:41.000Z\",\n",
|
||||
" \"modified\": \"2017-10-04T19:27:41.000Z\",\n",
|
||||
" \"labels\": [\n",
|
||||
" \"malicious-activity\"\n",
|
||||
" ],\n",
|
||||
" \"name\": \"Emerging Threats - Block Rules - Compromised IPs\",\n",
|
||||
" \"pattern\": \"[ ipv4-addr:value = '98.138.19.88' ]\",\n",
|
||||
" \"valid_from\": \"2017-10-04T19:27:41Z\",\n",
|
||||
" \"kill_chain_phases\": [\n",
|
||||
" {\n",
|
||||
" \"kill_chain_name\": \"lockheed-martin-cyber-kill-chain\",\n",
|
||||
" \"phase_name\": \"delivery\"\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}\n",
|
||||
"{\n",
|
||||
" \"type\": \"indicator\",\n",
|
||||
" \"id\": \"indicator--11913f42-2d52-4b9d-842f-94bf06819a66\",\n",
|
||||
" \"created\": \"2017-10-04T19:27:41.000Z\",\n",
|
||||
" \"modified\": \"2017-10-04T19:27:41.000Z\",\n",
|
||||
" \"labels\": [\n",
|
||||
" \"malicious-activity\"\n",
|
||||
" ],\n",
|
||||
" \"name\": \"Emerging Threats - Block Rules - Compromised IPs\",\n",
|
||||
" \"pattern\": \"[ ipv4-addr:value = '98.138.19.88' ]\",\n",
|
||||
" \"valid_from\": \"2017-10-04T19:27:41Z\",\n",
|
||||
" \"kill_chain_phases\": [\n",
|
||||
" {\n",
|
||||
" \"kill_chain_name\": \"lockheed-martin-cyber-kill-chain\",\n",
|
||||
" \"phase_name\": \"delivery\"\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"intrusion-set"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-05-31T21:31:53.197Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-05-31T21:31:53.197Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"DragonOK"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"DragonOK is a threat group that has targeted Japanese organizations with phishing emails. Due to overlapping TTPs, including similar custom tools, DragonOK is thought to have a direct or indirect relationship with the threat group Moafee. [[Citation: Operation Quantum Entanglement]][[Citation: Symbiotic APT Groups]] It is known to use a variety of malware, including Sysget/HelloBridge, PlugX, PoisonIvy, FormerFirstRat, NFlog, and NewCT. [[Citation: New DragonOK]]"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"aliases"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"DragonOK"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"external_references"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"source_name"</span><span class=\"p\">:</span> <span class=\"s2\">"mitre-attack"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"url"</span><span class=\"p\">:</span> <span class=\"s2\">"https://attack.mitre.org/wiki/Group/G0017"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"external_id"</span><span class=\"p\">:</span> <span class=\"s2\">"G0017"</span>\n",
|
||||
" <span class=\"p\">},</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"source_name"</span><span class=\"p\">:</span> <span class=\"s2\">"Operation Quantum Entanglement"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Haq, T., Moran, N., Vashisht, S., Scott, M. (2014, September). OPERATION QUANTUM ENTANGLEMENT. Retrieved November 4, 2015."</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"url"</span><span class=\"p\">:</span> <span class=\"s2\">"https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/wp-operation-quantum-entanglement.pdf"</span>\n",
|
||||
" <span class=\"p\">},</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"source_name"</span><span class=\"p\">:</span> <span class=\"s2\">"Symbiotic APT Groups"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Haq, T. (2014, October). An Insight into Symbiotic APT Groups. Retrieved November 4, 2015."</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"url"</span><span class=\"p\">:</span> <span class=\"s2\">"https://dl.mandiant.com/EE/library/MIRcon2014/MIRcon%202014%20R&D%20Track%20Insight%20into%20Symbiotic%20APT.pdf"</span>\n",
|
||||
" <span class=\"p\">},</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"source_name"</span><span class=\"p\">:</span> <span class=\"s2\">"New DragonOK"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Miller-Osborn, J., Grunzweig, J.. (2015, April). Unit 42 Identifies New DragonOK Backdoor Malware Deployed Against Japanese Targets. Retrieved November 4, 2015."</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"url"</span><span class=\"p\">:</span> <span class=\"s2\">"http://researchcenter.paloaltonetworks.com/2015/04/unit-42-identifies-new-dragonok-backdoor-malware-deployed-against-japanese-targets/"</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--02b90f02-a96a-43ee-88f1-1e87297941f2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T07:00:24.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T07:00:24.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Ransomware IP Blocklist"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"IP Blocklist address from abuse.ch"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[ ipv4-addr:value = '91.237.247.24' ]"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T07:00:24Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"Ransomware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"Botnet"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"C&C"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"external_references"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"source_name"</span><span class=\"p\">:</span> <span class=\"s2\">"abuse.ch"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"url"</span><span class=\"p\">:</span> <span class=\"s2\">"https://ransomwaretracker.abuse.ch/blocklist/"</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -136,23 +317,23 @@
|
|||
"from stix2 import CompositeDataSource, FileSystemSource, TAXIICollectionSource\n",
|
||||
"\n",
|
||||
"# create FileSystemStore\n",
|
||||
"fs = FileSystemSource(\"/tmp/stix2_data\")\n",
|
||||
"fs = FileSystemSource(\"/tmp/stix2_source\")\n",
|
||||
"\n",
|
||||
"# create TAXIICollectionSource\n",
|
||||
"colxn = Collection('https://test.freetaxii.com:8000/api1/collections/9cfa669c-ee94-4ece-afd2-f8edac37d8fd/')\n",
|
||||
"colxn = Collection('http://127.0.0.1:5000/trustgroup1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/')\n",
|
||||
"ts = TAXIICollectionSource(colxn)\n",
|
||||
"\n",
|
||||
"# add them both to the CompositeDataSource\n",
|
||||
"cs = CompositeDataSource()\n",
|
||||
"cs.add_data_sources([fs, ts])\n",
|
||||
"cs.add_data_sources([fs,ts])\n",
|
||||
"\n",
|
||||
"# get an object that is only in the filesystem\n",
|
||||
"ta = cs.get('intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a')\n",
|
||||
"print(ta)\n",
|
||||
"intrusion_set = cs.get('intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a')\n",
|
||||
"print(intrusion_set)\n",
|
||||
"\n",
|
||||
"# get an object that is only in the TAXII collection\n",
|
||||
"ind = cs.get('indicator--37a6a5de-a5b9-425a-903a-4ae9cbf1ff3f')\n",
|
||||
"print(ind)\n"
|
||||
"ind = cs.get('indicator--02b90f02-a96a-43ee-88f1-1e87297941f2')\n",
|
||||
"print(ind)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -161,23 +342,30 @@
|
|||
"source": [
|
||||
"## Filters\n",
|
||||
"\n",
|
||||
"The CTI Python STIX2 DataStore suites - [FileSystem](../api/sources/stix2.sources.filesystem.rst), [Memory](../api/sources/stix2.sources.memory.rst), and [TAXII](../api/sources/stix2.sources.taxii.rst) - all use the [Filters](../api/sources/stix2.sources.filters.rst) module to allow for the querying of STIX content. The basic functionality is that filters can be created and supplied everytime to calls to `query()`, and/or attached to a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) so that every future query placed to that [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) is evaluated against the attached filters, supplemented with any further filters supplied with the query call. Attached filters can also be removed from [DataStores](../api/stix2.sources.rst#stix2.sources.DataStore).\n",
|
||||
"The ``stix2`` DataStore suites - [FileSystem](../api/datastore/stix2.datastore.filesystem.rst), [Memory](../api/datastore/stix2.datastore.memory.rst), and [TAXII](../api/datastore/stix2.datastore.taxii.rst) - all use the [Filters](../api/datastore/stix2.datastore.filters.rst) module to allow for the querying of STIX content. Filters can be used to explicitly include or exclude results with certain criteria. For example:\n",
|
||||
"\n",
|
||||
"Filters are very simple, as they consist of a field name, comparison operator and an object property value (i.e. value to compare to). All properties of STIX2 objects can be filtered on. In addition, TAXII2 Filtering parameters for fields can also be used in filters.\n",
|
||||
"* only trust content from a set of object creators\n",
|
||||
"* exclude content from certain (untrusted) object creators\n",
|
||||
"* only include content with a confidence above a certain threshold (once confidence is added to STIX 2)\n",
|
||||
"* only return content that can be shared with external parties (e.g. only content that has TLP:GREEN markings)\n",
|
||||
"\n",
|
||||
"Filters can be created and supplied with every call to `query()`, and/or attached to a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) so that every future query placed to that [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) is evaluated against the attached filters, supplemented with any further filters supplied with the query call. Attached filters can also be removed from [DataStores](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin).\n",
|
||||
"\n",
|
||||
"Filters are very simple, as they consist of a field name, comparison operator and an object property value (i.e. value to compare to). All properties of STIX 2 objects can be filtered on. In addition, TAXII 2 Filtering parameters for fields can also be used in filters.\n",
|
||||
"\n",
|
||||
"TAXII2 filter fields:\n",
|
||||
"\n",
|
||||
"* added_after\n",
|
||||
"* match[id]\n",
|
||||
"* match[type]\n",
|
||||
"* match[version]\n",
|
||||
"* id\n",
|
||||
"* type\n",
|
||||
"* version\n",
|
||||
"\n",
|
||||
"Supported operators:\n",
|
||||
"\n",
|
||||
"* =\n",
|
||||
"* !=\n",
|
||||
"* in\n",
|
||||
"* >\n",
|
||||
"* ```>```\n",
|
||||
"* < \n",
|
||||
"* ```>=```\n",
|
||||
"* <=\n",
|
||||
|
@ -197,7 +385,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
@ -226,31 +414,29 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"For Filters to be applied to a query, they must be either supplied with the query call or attached a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore), more specifically to a [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource) whether that [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource) is a part of a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) or stands by itself. "
|
||||
"For Filters to be applied to a query, they must be either supplied with the query call or attached to a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin), more specifically to a [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource) whether that [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource) is a part of a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) or stands by itself. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import MemoryStore, FileSystemStore, FileSystemSource\n",
|
||||
"\n",
|
||||
"fs = FileSystemStore(\"/home/michael/Desktop/sample_stix2_data\")\n",
|
||||
"fs_source = FileSystemSource(\"/home/michael/Desktop/sample_stix2_data\")\n",
|
||||
"fs = FileSystemStore(\"/tmp/stix2_store\")\n",
|
||||
"fs_source = FileSystemSource(\"/tmp/stix2_source\")\n",
|
||||
"\n",
|
||||
"# attach filter to FileSystemStore\n",
|
||||
"fs.source.filters.add(f)\n",
|
||||
"\n",
|
||||
"# attach multiple filters to FileSystemStore\n",
|
||||
"fs.source.filters.update([f1,f2])\n",
|
||||
"fs.source.filters.add([f1,f2])\n",
|
||||
"\n",
|
||||
"# can also attach filters to a Source\n",
|
||||
"# attach multiple filters to FileSystemSource\n",
|
||||
"fs_source.filters.update([f3, f4])\n",
|
||||
"fs_source.filters.add([f3, f4])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"mem = MemoryStore()\n",
|
||||
|
@ -260,7 +446,7 @@
|
|||
"mem.source.filters.add(f)\n",
|
||||
"\n",
|
||||
"# attach multiple filters to a MemoryStore\n",
|
||||
"mem.source.filters.update([f1,f2])"
|
||||
"mem.source.filters.add([f1,f2])"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -269,13 +455,15 @@
|
|||
"source": [
|
||||
"## De-Referencing Relationships\n",
|
||||
"\n",
|
||||
"Given a STIX object, there are several ways to find other STIX objects related to it. To illustrate this, let's first create a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) and add some objects and relationships."
|
||||
"Given a STIX object, there are several ways to find other STIX objects related to it. To illustrate this, let's first create a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) and add some objects and relationships."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import Campaign, Identity, Indicator, Malware, Relationship\n",
|
||||
|
@ -295,12 +483,12 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If a STIX object has a `created_by_ref` property, you can use the [creator_of()](../api/stix2.sources.rst#stix2.sources.DataSource.creator_of) method to retrieve the [Identity](../api/stix2.v20.sdo.rst#stix2.v20.sdo.Identity) object that created it."
|
||||
"If a STIX object has a `created_by_ref` property, you can use the [creator_of()](../api/stix2.datastore.rst#stix2.datastore.DataSource.creator_of) method to retrieve the [Identity](../api/stix2.v20.sdo.rst#stix2.v20.sdo.Identity) object that created it."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -376,9 +564,9 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--be3baac0-9aba-48a8-81e4-4408b1c379a8"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-21T22:14:45.213Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-21T22:14:45.213Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--b67cf8d4-cc1a-4bb7-9402-fffcff17c9a9"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:43:54.117Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:43:54.117Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"John Doe"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
|
@ -388,7 +576,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -401,12 +589,12 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Use the [relationships()](../api/stix2.sources.rst#stix2.sources.DataSource.relationships) method to retrieve all the relationship objects that reference a STIX object."
|
||||
"Use the [relationships()](../api/stix2.datastore.rst#stix2.datastore.DataSource.relationships) method to retrieve all the relationship objects that reference a STIX object."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -415,7 +603,7 @@
|
|||
"3"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -434,16 +622,16 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Relationship(type='relationship', id='relationship--bd6fd399-c907-4feb-b1da-b90f15942f1d', created='2017-11-21T22:14:45.214Z', modified='2017-11-21T22:14:45.214Z', relationship_type=u'indicates', source_ref='indicator--5ee33ff0-c50d-456b-a8dd-b5d1b69a66e8', target_ref='malware--66c0bc78-4e27-4d80-a565-a07e6eb6fba4')]"
|
||||
"[Relationship(type='relationship', id='relationship--3b9cb248-5c2c-425d-85d0-680bfef6e69d', created='2018-04-05T20:43:54.134Z', modified='2018-04-05T20:43:54.134Z', relationship_type='indicates', source_ref='indicator--61deb2a5-305a-490e-83b3-9839a9677368', target_ref='malware--9fe343d8-edf7-4f4a-bb6c-a221fb75142d')]"
|
||||
]
|
||||
},
|
||||
"execution_count": 27,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -461,16 +649,16 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Relationship(type='relationship', id='relationship--7eb7f5cd-8bf2-4f7c-8756-84c0b5693b9a', created='2017-11-21T22:14:45.215Z', modified='2017-11-21T22:14:45.215Z', relationship_type=u'targets', source_ref='malware--66c0bc78-4e27-4d80-a565-a07e6eb6fba4', target_ref='identity--be3baac0-9aba-48a8-81e4-4408b1c379a8')]"
|
||||
"[Relationship(type='relationship', id='relationship--8d322508-423b-4d51-be85-a95ad083f8af', created='2018-04-05T20:43:54.134Z', modified='2018-04-05T20:43:54.134Z', relationship_type='targets', source_ref='malware--9fe343d8-edf7-4f4a-bb6c-a221fb75142d', target_ref='identity--b67cf8d4-cc1a-4bb7-9402-fffcff17c9a9')]"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -488,17 +676,17 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Relationship(type='relationship', id='relationship--bd6fd399-c907-4feb-b1da-b90f15942f1d', created='2017-11-21T22:14:45.214Z', modified='2017-11-21T22:14:45.214Z', relationship_type=u'indicates', source_ref='indicator--5ee33ff0-c50d-456b-a8dd-b5d1b69a66e8', target_ref='malware--66c0bc78-4e27-4d80-a565-a07e6eb6fba4'),\n",
|
||||
" Relationship(type='relationship', id='relationship--3c759d40-c92a-430e-aab6-77d5c5763302', created='2017-11-21T22:14:45.215Z', modified='2017-11-21T22:14:45.215Z', relationship_type=u'uses', source_ref='campaign--82ab7aa4-d13b-4e99-8a09-ebcba30668a7', target_ref='malware--66c0bc78-4e27-4d80-a565-a07e6eb6fba4')]"
|
||||
"[Relationship(type='relationship', id='relationship--3b9cb248-5c2c-425d-85d0-680bfef6e69d', created='2018-04-05T20:43:54.134Z', modified='2018-04-05T20:43:54.134Z', relationship_type='indicates', source_ref='indicator--61deb2a5-305a-490e-83b3-9839a9677368', target_ref='malware--9fe343d8-edf7-4f4a-bb6c-a221fb75142d'),\n",
|
||||
" Relationship(type='relationship', id='relationship--93e5afe0-d1fb-4315-8d08-10951f7a99b6', created='2018-04-05T20:43:54.134Z', modified='2018-04-05T20:43:54.134Z', relationship_type='uses', source_ref='campaign--edfd885c-bc31-4051-9bc2-08e057542d56', target_ref='malware--9fe343d8-edf7-4f4a-bb6c-a221fb75142d')]"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -511,21 +699,21 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Finally, you can retrieve all STIX objects related to a given STIX object using [related_to()](../api/stix2.sources.rst#stix2.sources.DataSource.related_to). This calls [relationships()](../api/stix2.sources.rst#stix2.sources.DataSource.relationships) but then performs the extra step of getting the objects that these Relationships point to. [related_to()](../api/stix2.sources.rst#stix2.sources.DataSource.related_to) takes all the same arguments that [relationships()](../api/stix2.sources.rst#stix2.sources.DataSource.relationships) does."
|
||||
"Finally, you can retrieve all STIX objects related to a given STIX object using [related_to()](../api/stix2.datastore.rst#stix2.datastore.DataSource.related_to). This calls [relationships()](../api/stix2.datastore.rst#stix2.datastore.DataSource.relationships) but then performs the extra step of getting the objects that these Relationships point to. [related_to()](../api/stix2.datastore.rst#stix2.datastore.DataSource.related_to) takes all the same arguments that [relationships()](../api/stix2.datastore.rst#stix2.datastore.DataSource.relationships) does."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 42,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Campaign(type='campaign', id='campaign--82ab7aa4-d13b-4e99-8a09-ebcba30668a7', created='2017-11-21T22:14:45.213Z', modified='2017-11-21T22:14:45.213Z', name=u'Charge', description=u'Attack!')]"
|
||||
"[Campaign(type='campaign', id='campaign--edfd885c-bc31-4051-9bc2-08e057542d56', created='2018-04-05T20:43:54.117Z', modified='2018-04-05T20:43:54.117Z', name='Charge', description='Attack!')]"
|
||||
]
|
||||
},
|
||||
"execution_count": 42,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -537,9 +725,9 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "cti-python-stix2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "cti-python-stix2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -25,7 +24,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -62,15 +62,13 @@
|
|||
"\n",
|
||||
"### Storing and Retrieving STIX Content\n",
|
||||
"\n",
|
||||
"An [Environment](../api/stix2.environment.rst#stix2.environment.Environment) can be set up with a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore) if you want to store and retrieve STIX content from the same place. "
|
||||
"An [Environment](../api/stix2.environment.rst#stix2.environment.Environment) can be set up with a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin) if you want to store and retrieve STIX content from the same place. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import Environment, MemoryStore\n",
|
||||
|
@ -82,38 +80,34 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If desired, you can instead set up an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with different data sources and sinks. In the following example we set up an environment that retrieves objects from [memory](../api/sources/stix2.sources.memory.rst) and a directory on the [filesystem](../api/sources/stix2.sources.filesystem.rst), and stores objects in a different directory on the filesystem."
|
||||
"If desired, you can instead set up an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with different data sources and sinks. In the following example we set up an environment that retrieves objects from [memory](../api/datastore/stix2.datastore.memory.rst) and a directory on the [filesystem](../api/datastore/stix2.datastore.filesystem.rst), and stores objects in a different directory on the filesystem."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import CompositeDataSource, FileSystemSink, FileSystemSource, MemorySource\n",
|
||||
"\n",
|
||||
"src = CompositeDataSource()\n",
|
||||
"src.add_data_sources([MemorySource(), FileSystemSource(\"/tmp/stix_source\")])\n",
|
||||
"src.add_data_sources([MemorySource(), FileSystemSource(\"/tmp/stix2_source\")])\n",
|
||||
"env2 = Environment(source=src,\n",
|
||||
" sink=FileSystemSink(\"/tmp/stix_sink\"))"
|
||||
" sink=FileSystemSink(\"/tmp/stix2_sink\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Once you have an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) you can store some STIX content in its [DataSinks](../api/stix2.sources.rst#stix2.sources.DataSink) with [add()](../api/stix2.environment.rst#stix2.environment.Environment.add):"
|
||||
"Once you have an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) you can store some STIX content in its [DataSinks](../api/stix2.datastore.rst#stix2.datastore.DataSink) with [add()](../api/stix2.environment.rst#stix2.environment.Environment.add):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import Indicator\n",
|
||||
|
@ -128,140 +122,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can retrieve STIX objects from the [DataSources](../api/stix2.sources.rst#stix2.sources.DataSource) in the [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with [get()](../api/stix2.environment.rst#stix2.environment.Environment.get), [query()](../api/stix2.environment.rst#stix2.environment.Environment.query), [all_versions()](../api/stix2.environment.rst#stix2.environment.Environment.all_versions), [creator_of()](../api/stix2.sources.rst#stix2.sources.DataSource.creator_of), [related_to()](../api/stix2.sources.rst#stix2.sources.DataSource.related_to), and [relationships()](../api/stix2.sources.rst#stix2.sources.DataSource.relationships) just as you would for a [DataSource](../api/stix2.sources.rst#stix2.sources.DataSource)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--01234567-89ab-cdef-0123-456789abcdef"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:20:39.373Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:20:39.373Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:20:39.3737Z"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(env.get(\"indicator--01234567-89ab-cdef-0123-456789abcdef\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Creating STIX Objects With Defaults\n",
|
||||
"\n",
|
||||
"To create STIX objects with default values for certain properties, use an [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory). For instance, say we want all objects we create to have a ``created_by_ref`` property pointing to the ``Identity`` object representing our organization."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import Indicator, ObjectFactory\n",
|
||||
"\n",
|
||||
"factory = ObjectFactory(created_by_ref=\"identity--311b2d2d-f010-5473-83ec-1edf84858f4c\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"Once you've set up the [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory), use its [create()](../api/stix2.environment.rst#stix2.environment.ObjectFactory.create) method, passing in the class for the type of object you wish to create, followed by the other properties and their values for the object."
|
||||
"You can retrieve STIX objects from the [DataSources](../api/stix2.datastore.rst#stix2.datastore.DataSource) in the [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with [get()](../api/stix2.environment.rst#stix2.environment.Environment.get), [query()](../api/stix2.environment.rst#stix2.environment.Environment.query), [all_versions()](../api/stix2.environment.rst#stix2.environment.Environment.all_versions), [creator_of()](../api/stix2.datastore.rst#stix2.datastore.DataSource.creator_of), [related_to()](../api/stix2.datastore.rst#stix2.datastore.DataSource.related_to), and [relationships()](../api/stix2.datastore.rst#stix2.datastore.DataSource.relationships) just as you would for a [DataSource](../api/stix2.datastore.rst#stix2.datastore.DataSource)."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -342,15 +203,14 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--c92ad60d-449d-4adf-86b3-4e5951a8f480"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--311b2d2d-f010-5473-83ec-1edf84858f4c"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:00.607Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:00.607Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--01234567-89ab-cdef-0123-456789abcdef"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:27:53.923Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:27:53.923Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:27:53.923548Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:00.607216Z"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -363,6 +223,138 @@
|
|||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(env.get(\"indicator--01234567-89ab-cdef-0123-456789abcdef\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Creating STIX Objects With Defaults\n",
|
||||
"\n",
|
||||
"To create STIX objects with default values for certain properties, use an [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory). For instance, say we want all objects we create to have a ``created_by_ref`` property pointing to the ``Identity`` object representing our organization."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2 import Indicator, ObjectFactory\n",
|
||||
"\n",
|
||||
"factory = ObjectFactory(created_by_ref=\"identity--311b2d2d-f010-5473-83ec-1edf84858f4c\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"Once you've set up the [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory), use its [create()](../api/stix2.environment.rst#stix2.environment.ObjectFactory.create) method, passing in the class for the type of object you wish to create, followed by the other properties and their values for the object."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--c1b421c0-9c6b-4276-9b73-1b8684a5a0d2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--311b2d2d-f010-5473-83ec-1edf84858f4c"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:28:48.776Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:28:48.776Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:28:48.776442Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ind = factory.create(Indicator,\n",
|
||||
" labels=[\"malicious-activity\"],\n",
|
||||
|
@ -388,7 +380,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -464,14 +456,14 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--ae206b9f-8723-4fcf-beb7-8b1b9a2570ab"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--30a3b39c-5f57-4e7f-9eaf-e1abcb643da4"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-25T18:07:46.255Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-25T18:07:46.255Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:28:53.268567Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:05.790562Z"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -479,7 +471,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -498,7 +490,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -574,15 +566,15 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--a8e2be68-b496-463f-9ff4-f620046e7cf2"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--6c5bbaaf-6dac-44b0-a0df-86c27b3f6ecb"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--962cabe5-f7f3-438a-9169-585a8c971d12"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-25T18:07:46.255Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-25T18:07:46.255Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:29:56.55129Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:08.32424Z"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -590,7 +582,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -609,12 +601,12 @@
|
|||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"For the full power of the Environment layer, create an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with both a [DataStore](../api/stix2.sources.rst#stix2.sources.DataStore)/[Source](../api/stix2.sources.rst#stix2.sources.DataSource)/[Sink](../api/stix2.sources.rst#stix2.sources.DataSink) and an [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory):"
|
||||
"For the full power of the Environment layer, create an [Environment](../api/stix2.environment.rst#stix2.environment.Environment) with both a [DataStore](../api/stix2.datastore.rst#stix2.datastore.DataStoreMixin)/[Source](../api/stix2.datastore.rst#stix2.datastore.DataSource)/[Sink](../api/stix2.datastore.rst#stix2.datastore.DataSink) and an [ObjectFactory](../api/stix2.environment.rst#stix2.environment.ObjectFactory):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -690,15 +682,15 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--89ba04ea-cce9-47a3-acd3-b6379ce51581"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--d1b8c3f6-1de1-44c1-b079-3df307224a0d"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--311b2d2d-f010-5473-83ec-1edf84858f4c"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:29.629Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:29.629Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:29:59.605Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:29:59.605Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:29:59.605463Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-02T13:23:29.629857Z"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -706,7 +698,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -725,21 +717,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,9 +2,8 @@
|
|||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -23,9 +22,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -68,127 +68,127 @@
|
|||
"To create an object with a (predefined) TLP marking to an object, just provide it as a keyword argument to the constructor. The TLP markings can easily be imported from python-stix2."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--65ff0082-bb92-4812-9b74-b144b858297f"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:42:14.641Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:42:14.641Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:42:14.641818Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from stix2 import Indicator, TLP_AMBER\n",
|
||||
"\n",
|
||||
"indicator = Indicator(labels=[\"malicious-activity\"],\n",
|
||||
" pattern=\"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\",\n",
|
||||
" object_marking_refs=TLP_AMBER)\n",
|
||||
"print(indicator)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If you’re creating your own marking (for example, a ``Statement`` marking), first create the statement marking:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--95a71cff-fad0-4ffb-a641-8a6eaa642290"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from stix2 import Indicator, TLP_AMBER\n",
|
||||
"\n",
|
||||
"indicator = Indicator(labels=[\"malicious-activity\"],\n",
|
||||
" pattern=\"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']\",\n",
|
||||
" object_marking_refs=TLP_AMBER)\n",
|
||||
"print(indicator)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If you’re creating your own marking (for example, a ``Statement`` marking), first create the statement marking:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
|
@ -263,8 +263,8 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"marking-definition"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"marking-definition--d16f0975-c5dd-4b25-a41d-af4afcc5da92"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:43:30.558058Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:53.98008Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"definition_type"</span><span class=\"p\">:</span> <span class=\"s2\">"statement"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"definition"</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"statement"</span><span class=\"p\">:</span> <span class=\"s2\">"Copyright 2017, Example Corp"</span>\n",
|
||||
|
@ -276,7 +276,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -300,7 +300,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -376,16 +376,16 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--526cda4e-6745-4cd6-852f-0750c6a79784"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:09.586Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:09.586Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--7caeab49-2472-41bb-a988-2f990aea99bd"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:55.763Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:55.763Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:55.763364Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:09.586133Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
|
@ -394,7 +394,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -408,7 +408,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -484,14 +484,14 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--1505b789-fcd2-48ee-bea9-3b20627a4abd"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:20.049Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:20.049Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--4eb21bbe-b8a9-4348-86cf-1ed52f9abdd7"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:57.248Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:57.248Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:57.248658Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:43:20.049166Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
|
@ -502,7 +502,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -523,7 +523,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -599,9 +599,9 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--f7128008-f6ab-4d43-a8a2-a681651268f8"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:43:34.857Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-13T14:43:34.857Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--ef1eddbb-b5a5-47e0-b607-75b9870d8d91"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:59.103Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:59.103Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Poison Ivy"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"A ransomware related to ..."</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
|
@ -609,7 +609,7 @@
|
|||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"granular_markings"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"marking_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"marking-definition--d16f0975-c5dd-4b25-a41d-af4afcc5da92"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"marking_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"selectors"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"description"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
|
@ -628,7 +628,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -661,7 +661,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -705,7 +705,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -781,17 +781,17 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--409a0b15-1108-4251-8aee-a08995976561"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T15:03:46.599Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--95a71cff-fad0-4ffb-a641-8a6eaa642290"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:03.387Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685184Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
|
@ -800,7 +800,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -819,7 +819,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -895,14 +895,14 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--409a0b15-1108-4251-8aee-a08995976561"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T15:03:54.290Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--95a71cff-fad0-4ffb-a641-8a6eaa642290"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:05.109Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685184Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
|
@ -913,7 +913,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -932,7 +932,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1008,17 +1008,17 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--409a0b15-1108-4251-8aee-a08995976561"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T15:04:04.218Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--95a71cff-fad0-4ffb-a641-8a6eaa642290"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:06.773Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685184Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"object_marking_refs"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"s2\">"marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
|
@ -1027,7 +1027,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1048,7 +1048,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1124,14 +1124,14 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--409a0b15-1108-4251-8aee-a08995976561"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:54:39.331Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--95a71cff-fad0-4ffb-a641-8a6eaa642290"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:08.616Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:49:47.924708Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-10-04T14:42:54.685184Z"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -1139,7 +1139,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1167,17 +1167,17 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da',\n",
|
||||
" 'marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53']"
|
||||
"['marking-definition--13680b12-3d19-4b42-abe6-0d31effe5368',\n",
|
||||
" 'marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da']"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1195,7 +1195,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1204,7 +1204,7 @@
|
|||
"['marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9']"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1224,7 +1224,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1233,7 +1233,7 @@
|
|||
"['marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9']"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1251,7 +1251,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1260,7 +1260,7 @@
|
|||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1271,7 +1271,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -1280,7 +1280,7 @@
|
|||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1291,7 +1291,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
@ -1302,7 +1302,7 @@
|
|||
"False"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -1314,21 +1314,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -25,7 +24,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -58,14 +58,15 @@
|
|||
"source": [
|
||||
"## Memory\n",
|
||||
"\n",
|
||||
"The Memory suite consists of [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore), [MemorySource](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySource), and [MemorySink](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySink). Under the hood, the Memory suite points to an in-memory dictionary. Similarly, the [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore) is a just a wrapper around a paired [MemorySource](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySource) and [MemorySink](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySink); as there is quite limited uses for just a [MemorySource](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySource) or a [MemorySink](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemorySink), it is recommended to always use [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore). The [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore) is intended for retrieving/searching and pushing STIX content to memory. It is important to note that all STIX content in memory is not backed up on the file system (disk), as that functionality is encompassed within the [FileSystemStore](../api/sources/stix2.sources.filesystem.rst#stix2.sources.filesystem.FileSystemStore). However, the Memory suite does provide some utility methods for saving and loading STIX content to disk. [MemoryStore.save_to_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.save_to_file) allows for saving all the STIX content that is in memory to a json file. [MemoryStore.load_from_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.load_from_file) allows for loading STIX content from a JSON-formatted file. \n",
|
||||
"The Memory suite consists of [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore), [MemorySource](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySource), and [MemorySink](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySink). Under the hood, the Memory suite points to an in-memory dictionary. Similarly, the [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore) is a just a wrapper around a paired [MemorySource](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySource) and [MemorySink](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySink); as there is quite limited uses for just a [MemorySource](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySource) or a [MemorySink](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemorySink), it is recommended to always use [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore). The [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore) is intended for retrieving/searching and pushing STIX content to memory. It is important to note that all STIX content in memory is not backed up on the file system (disk), as that functionality is encompassed within the [FileSystemStore](../api/datastore/stix2.datastore.filesystem.rst#stix2.datastore.filesystem.FileSystemStore). However, the Memory suite does provide some utility methods for saving and loading STIX content to disk. [MemoryStore.save_to_file()](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore.save_to_file) allows for saving all the STIX content that is in memory to a json file. [MemoryStore.load_from_file()](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore.load_from_file) allows for loading STIX content from a JSON-formatted file. \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"### Memory API\n",
|
||||
"A note on adding and retreiving STIX content to the Memory suite: As mentioned, under the hood the Memory suite is an internal, in-memory dictionary. STIX content that is to be added can be in the following forms: python-stix2 objects, (Python) dictionaries (of valid STIX objects or Bundles), JSON-encoded strings (of valid STIX objects or Bundles), or a (Python) list of any of the previously listed types. [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore) actually stores STIX content either as python-stix2 objects or as (Python) dictionaries, reducing and converting any of the aforementioned types to one of those. Additionally, whatever form the STIX object is stored as, is how it will be returned when retrieved. python-stix2 objects, and json-encoded strings (of STIX content) are stored as python-stix2 objects, while (Python) dictionaries (of STIX objects) are stored as (Python) dictionaries.\n",
|
||||
"\n",
|
||||
"A note on [load_from_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.load_from_file) and [save_to_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.save_to_file). These methods both add STIX content to an internal dictionary (maintained by [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore)). STIX content that is to be added can be in the following forms: Python STIX objects, Python dictionaries (of valid STIX objects or Bundles), JSON-encoded strings (of valid STIX objects or Bundles), or a (Python) list of any of the previously listed types. [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore) actually stores STIX content either as python STIX objects or as python dictionaries, reducing and converting any of the aforementioned types to one of those; and whatever form the STIX object is stored as, is how it will be returned as when queried or retrieved. Python STIX objects, and json-encoded strings (of STIX content) are stored as python STIX objects. Python dictionaries (of STIX objects) are stored as Python dictionaries. This is done, as can be efficiently supported, in order to return STIX content in the form it was added to the [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore). Also, for [load_from_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.load_from_file), STIX content is assumed to be in JSON form within the file, individually or in a Bundle. \n",
|
||||
"A note on [load_from_file()](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore.load_from_file): For [load_from_file()](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore.load_from_file), STIX content is assumed to be in JSON form within the file, as an individual STIX object or in a Bundle. When the JSON is loaded, the STIX objects are parsed into python-stix2 objects before being stored in the in-memory dictionary.\n",
|
||||
"\n",
|
||||
"A note on [save_to_file()](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore.save_to_file). This method dumps all STIX content that is in [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore) to the specified file. The file format will be JSON, and the STIX content will be within a STIX Bundle. Note also that the the output form will be a JSON STIX Bundle regardless of the form that the individual STIX objects are stored (i.e. supplied) to the [MemoryStore](../api/sources/stix2.sources.memory.rst#stix2.sources.memory.MemoryStore). \n",
|
||||
"A note on [save_to_file()](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore.save_to_file): This method dumps all STIX content that is in the [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore) to the specified file. The file format will be JSON, and the STIX content will be within a STIX Bundle. Note also that the output form will be a JSON STIX Bundle regardless of the form that the individual STIX objects are stored in (i.e. supplied to) the [MemoryStore](../api/datastore/stix2.datastore.memory.rst#stix2.datastore.memory.MemoryStore). \n",
|
||||
"\n",
|
||||
"### Memory Examples\n",
|
||||
"\n",
|
||||
|
@ -74,26 +75,101 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"type\": \"indicator\",\n",
|
||||
" \"id\": \"indicator--d91ef175-8a82-470a-a610-bbd2ee8a1516\",\n",
|
||||
" \"created\": \"2017-09-29T19:52:16.930Z\",\n",
|
||||
" \"modified\": \"2017-09-29T19:52:16.930Z\",\n",
|
||||
" \"labels\": [\n",
|
||||
" \"malicious-activity\"\n",
|
||||
" ],\n",
|
||||
" \"description\": \"Crusades C2 implant\",\n",
|
||||
" \"pattern\": \"[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']\",\n",
|
||||
" \"valid_from\": \"2017-09-29T19:52:16.930909Z\"\n",
|
||||
"}\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--41a960c7-a6d4-406d-9156-0069cb3bd40d"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:41.222Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:41.222Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Crusades C2 implant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:41.222522Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -115,26 +191,101 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"type\": \"indicator\",\n",
|
||||
" \"id\": \"indicator--79fdaad7-c461-49bb-ad1d-caa5e9c51c90\",\n",
|
||||
" \"created\": \"2017-09-29T19:52:17.021Z\",\n",
|
||||
" \"modified\": \"2017-09-29T19:52:17.021Z\",\n",
|
||||
" \"labels\": [\n",
|
||||
" \"malicious-activity\"\n",
|
||||
" ],\n",
|
||||
" \"description\": \"Crusades stage 2 implant variant\",\n",
|
||||
" \"pattern\": \"[file:hashes.'SHA-256' = '31a45e777e4d58b97f4c43e38006f8cd6580ddabc4037905b2fad734712b582c']\",\n",
|
||||
" \"valid_from\": \"2017-09-29T19:52:17.021728Z\"\n",
|
||||
"}\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--ba2a7acb-a3ac-420b-9288-09988aa99408"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.343Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.343Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Crusades stage 2 implant variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.'SHA-256' = '31a45e777e4d58b97f4c43e38006f8cd6580ddabc4037905b2fad734712b582c']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.343298Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -157,95 +308,108 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"-----------------------\n",
|
||||
"{'name': 'Urban2', 'created': '2017-09-12T13:26:18.023Z', 'labels': ['rootkit'], 'modified': '2017-09-12T13:26:18.023Z', 'type': 'malware', 'id': 'malware--2daa14d6-cbf3-4308-bb8e-226d324a08e4'}\n",
|
||||
"-----------------------\n",
|
||||
"{\n",
|
||||
" \"type\": \"malware\",\n",
|
||||
" \"id\": \"malware--2b3dd412-18a5-4e81-8742-4977068eb3eb\",\n",
|
||||
" \"created\": \"2017-09-29T19:52:17.028Z\",\n",
|
||||
" \"modified\": \"2017-09-29T19:52:17.028Z\",\n",
|
||||
" \"name\": \"Alexios\",\n",
|
||||
" \"labels\": [\n",
|
||||
" \"rootkit\"\n",
|
||||
" ]\n",
|
||||
"}\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--9e9b87ce-2b2b-455a-8d5b-26384ccc8d52"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.346Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.346Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Alexios"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"rootkit"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from stix2 import Filter\n",
|
||||
"\n",
|
||||
"# add dictionary (of STIX object) to MemoryStore\n",
|
||||
"# (this dict would assumably come from output of another source,\n",
|
||||
"# i.e. a loaded json file, NOT manually created as done here for sample purposes)\n",
|
||||
"\n",
|
||||
"malware = {\n",
|
||||
" \"type\": \"malware\",\n",
|
||||
" \"id\" : \"malware--2daa14d6-cbf3-4308-bb8e-226d324a08e4\",\n",
|
||||
" \"labels\": [\"rootkit\"],\n",
|
||||
" \"name\": \"Urban2\",\n",
|
||||
" \"created\": \"2017-09-12T13:26:18.023Z\",\n",
|
||||
" \"modified\": \"2017-09-12T13:26:18.023Z\"\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"mem.add(malware)\n",
|
||||
"\n",
|
||||
"results = mem.query([Filter(\"labels\",\"=\", \"rootkit\")])\n",
|
||||
"for r in results:\n",
|
||||
" # note that python STIX objects are pretty-printed\n",
|
||||
" # due to some python dunder method magic, but normal\n",
|
||||
" # python dictionaries are not by default. Thus the\n",
|
||||
" # python STIX objects and python STIX dictionaries\n",
|
||||
" # that match the above query can be easily identified visually\n",
|
||||
" print(\"-----------------------\")\n",
|
||||
" print(r)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"type\": \"report\",\n",
|
||||
" \"id\": \"report--2add14d6-bbf3-4308-bb8e-226d314a08e4\",\n",
|
||||
" \"created\": \"2017-05-08T18:34:08.042Z\",\n",
|
||||
" \"modified\": \"2017-05-08T18:34:08.042Z\",\n",
|
||||
" \"name\": \"The Crusades: Looking into the relentless infiltration of Israels digital infrastructure.\",\n",
|
||||
" \"published\": \"2017-05-08T10:24:11.011Z\",\n",
|
||||
" \"object_refs\": [\n",
|
||||
" \"malware--2daa14d6-cbf3-4308-bb8e-226d324a08e4\"\n",
|
||||
" ],\n",
|
||||
" \"labels\": [\n",
|
||||
" \"threat-report\"\n",
|
||||
" ]\n",
|
||||
"}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from stix2 import Filter\n",
|
||||
"\n",
|
||||
"# add json formatted string to MemoryStore\n",
|
||||
"# Again, would NOT manual create json-formatted string\n",
|
||||
"# but taken as an output form from another source\n",
|
||||
"report = '{\"type\": \"report\",\"id\": \"report--2add14d6-bbf3-4308-bb8e-226d314a08e4\",\"labels\": [\"threat-report\"], \"name\": \"The Crusades: Looking into the relentless infiltration of Israels digital infrastructure.\", \"published\": \"2017-05-08T10:24:11.011Z\", \"object_refs\":[\"malware--2daa14d6-cbf3-4308-bb8e-226d324a08e4\"], \"created\": \"2017-05-08T18:34:08.042Z\", \"modified\": \"2017-05-08T18:34:08.042Z\"}'\n",
|
||||
"\n",
|
||||
"mem.add(report)\n",
|
||||
"\n",
|
||||
"print(mem.get(\"report--2add14d6-bbf3-4308-bb8e-226d314a08e4\"))"
|
||||
"mal = mem.query([Filter(\"labels\",\"=\", \"rootkit\")])[0]\n",
|
||||
"print(mal)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -257,15 +421,99 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{u'name': u'The Crusades: Looking into the relentless infiltration of Israels digital infrastructure.', u'created': u'2017-05-08T18:34:08.042Z', u'labels': [u'threat-report'], u'modified': u'2017-05-08T18:34:08.042Z', u'object_refs': [u'malware--2daa14d6-cbf3-4308-bb8e-226d324a08e4'], u'published': u'2017-05-08T10:24:11.011Z', u'type': u'report', u'id': u'report--2add14d6-bbf3-4308-bb8e-226d314a08e4'}\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--9e9b87ce-2b2b-455a-8d5b-26384ccc8d52"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.346Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T19:50:43.346Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Alexios"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"rootkit"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -277,32 +525,30 @@
|
|||
"# load(add) STIX content from json file into MemoryStore\n",
|
||||
"mem_2.load_from_file(\"path_to_target_file.json\")\n",
|
||||
"\n",
|
||||
"report = mem_2.get(\"report--2add14d6-bbf3-4308-bb8e-226d314a08e4\")\n",
|
||||
"report = mem_2.get(\"malware--9e9b87ce-2b2b-455a-8d5b-26384ccc8d52\")\n",
|
||||
"\n",
|
||||
"# for visualpurposes\n",
|
||||
"# Note: Since STIX content was added to MemoryStore as json,\n",
|
||||
"# it is maintained as python dictionaries ( as opposed to STIX objects)\n",
|
||||
"# for visual purposes\n",
|
||||
"print(report)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -25,7 +24,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -63,7 +63,9 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Parsing STIX content is as easy as calling the [parse()](../api/stix2.core.rst#stix2.core.parse) function on a JSON string. It will automatically determine the type of the object. The STIX objects within `bundle` objects, and the cyber observables contained within `observed-data` objects will be parsed as well."
|
||||
"Parsing STIX content is as easy as calling the [parse()](../api/stix2.core.rst#stix2.core.parse) function on a JSON string, dictionary, or file-like object. It will automatically determine the type of the object. The STIX objects within `bundle` objects, and the cyber observables contained within `observed-data` objects will be parsed as well.\n",
|
||||
"\n",
|
||||
"**Parsing a string**"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -72,12 +74,184 @@
|
|||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"observed-data\n",
|
||||
"0969de02ecf8a5f003e3f6d063d848c8a193aada092623f8ce408c15bcb5f038\n"
|
||||
]
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><class 'stix2.v20.sdo.ObservedData'>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"observed-data"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2016-04-06T19:58:16.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2016-04-06T19:58:16.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"first_observed"</span><span class=\"p\">:</span> <span class=\"s2\">"2015-12-21T19:00:00Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"last_observed"</span><span class=\"p\">:</span> <span class=\"s2\">"2015-12-21T19:00:00Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"number_observed"</span><span class=\"p\">:</span> <span class=\"mi\">50</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"objects"</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"0"</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"file"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"hashes"</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"SHA-256"</span><span class=\"p\">:</span> <span class=\"s2\">"0969de02ecf8a5f003e3f6d063d848c8a193aada092623f8ce408c15bcb5f038"</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
" <span class=\"p\">}</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -102,28 +276,462 @@
|
|||
"}\"\"\"\n",
|
||||
"\n",
|
||||
"obj = parse(input_string)\n",
|
||||
"print(obj.type)\n",
|
||||
"print(obj.objects[\"0\"].hashes['SHA-256'])"
|
||||
"print(type(obj))\n",
|
||||
"print(obj)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Parsing a dictionary**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><class 'stix2.v20.sdo.Identity'>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--311b2d2d-f010-5473-83ec-1edf84858f4c"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2015-12-21T19:59:11.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2015-12-21T19:59:11.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Cole Powers"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"input_dict = {\n",
|
||||
" \"type\": \"identity\",\n",
|
||||
" \"id\": \"identity--311b2d2d-f010-5473-83ec-1edf84858f4c\",\n",
|
||||
" \"created\": \"2015-12-21T19:59:11Z\",\n",
|
||||
" \"modified\": \"2015-12-21T19:59:11Z\",\n",
|
||||
" \"name\": \"Cole Powers\",\n",
|
||||
" \"identity_class\": \"individual\"\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"obj = parse(input_dict)\n",
|
||||
"print(type(obj))\n",
|
||||
"print(obj)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**Parsing a file-like object**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><class 'stix2.v20.sdo.CourseOfAction'>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"course-of-action"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"course-of-action--d9727aee-48b8-4fdb-89e2-4c49746ba4dd"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created_by_ref"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-05-31T21:30:41.022Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-05-31T21:30:41.022Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Data from Network Shared Drive Mitigation"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Identify unnecessary system utilities or potentially malicious software that may be used to collect data from a network share, and audit and/or block them by using whitelisting[[CiteRef::Beechey 2010]] tools, like AppLocker,[[CiteRef::Windows Commands JPCERT]][[CiteRef::NSA MS AppLocker]] or Software Restriction Policies[[CiteRef::Corio 2008]] where appropriate.[[CiteRef::TechNet Applocker vs SRP]]"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"file_handle = open(\"/tmp/stix2_store/course-of-action/course-of-action--d9727aee-48b8-4fdb-89e2-4c49746ba4dd.json\")\n",
|
||||
"\n",
|
||||
"obj = parse(file_handle)\n",
|
||||
"print(type(obj))\n",
|
||||
"print(obj)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Parsing Custom STIX Content"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Parsing custom STIX objects and/or STIX objects with custom properties is also completed easily with [parse()](../api/stix2.core.rst#stix2.core.parse). Just supply the keyword argument ``allow_custom=True``. When ``allow_custom`` is specified, [parse()](../api/stix2.core.rst#stix2.core.parse) will attempt to convert the supplied STIX content to known STIX 2 domain objects and/or previously defined [custom STIX 2 objects](custom.ipynb). If the conversion cannot be completed (and ``allow_custom`` is specified), [parse()](../api/stix2.core.rst#stix2.core.parse) will treat the supplied STIX 2 content as valid STIX 2 objects and return them. **Warning: Specifying allow_custom may lead to critical errors if further processing (searching, filtering, modifying etc...) of the custom content occurs where the custom content supplied is not valid STIX 2**. This is an axiomatic possibility as the ``stix2`` library cannot guarantee proper processing of unknown custom STIX 2 objects that were explicitly flagged to be allowed, and thus may not be valid.\n",
|
||||
"\n",
|
||||
"For examples of parsing STIX 2 objects with custom STIX properties, see [Custom STIX Content: Custom Properties](custom.ipynb#Custom-Properties)\n",
|
||||
"\n",
|
||||
"For examples of parsing defined custom STIX 2 objects, see [Custom STIX Content: Custom STIX Object Types](custom.ipynb#Custom-STIX-Object-Types)\n",
|
||||
"\n",
|
||||
"For retrieving STIX 2 content from a source (e.g. file system, TAXII) that may possibly have custom STIX 2 content unknown to the user, the user can create a STIX 2 DataStore/Source with the flag ``allow_custom=True``. As mentioned, this will configure the DataStore/Source to allow for unknown STIX 2 content to be returned (albeit not converted to full STIX 2 domain objects and properties); the ``stix2`` library may preclude processing the unknown content, if the content is not valid or actual STIX 2 domain objects and properties."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from taxii2client import Collection\n",
|
||||
"from stix2 import CompositeDataSource, FileSystemSource, TAXIICollectionSource\n",
|
||||
"\n",
|
||||
"# to allow for the retrieval of unknown custom STIX2 content,\n",
|
||||
"# just create *Stores/*Sources with the 'allow_custom' flag\n",
|
||||
"\n",
|
||||
"# create FileSystemStore\n",
|
||||
"fs = FileSystemSource(\"/path/to/stix2_data/\", allow_custom=True)\n",
|
||||
"\n",
|
||||
"# create TAXIICollectionSource\n",
|
||||
"colxn = Collection('http://taxii_url')\n",
|
||||
"ts = TAXIICollectionSource(colxn, allow_custom=True)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -23,9 +22,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -68,7 +68,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -144,12 +144,12 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--5eac4517-6539-4e48-ab51-7d499f599674"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--4336ace8-d985-413a-8e32-f749ba268dc3"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285451Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012209Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
|
@ -160,7 +160,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -179,12 +179,12 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"However, the string representation can be slow, as it sorts properties to be in a more readable order. If you need performance and don't care about the human-readability of the output, use the object's serialize() function:"
|
||||
"However, the string representation can be slow, as it sorts properties to be in a more readable order. If you need performance and don't care about the human-readability of the output, use the object's `serialize()` function:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -258,14 +258,14 @@
|
|||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span><span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285451Z"</span><span class=\"p\">,</span> <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span> <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285Z"</span><span class=\"p\">,</span> <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span> <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">"malicious-activity"</span><span class=\"p\">],</span> <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-11-09T19:21:06.285Z"</span><span class=\"p\">,</span> <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span> <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--5eac4517-6539-4e48-ab51-7d499f599674"</span><span class=\"p\">}</span>\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span><span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span> <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">"malicious-activity"</span><span class=\"p\">],</span> <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span> <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span> <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--4336ace8-d985-413a-8e32-f749ba268dc3"</span><span class=\"p\">,</span> <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span> <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span> <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012209Z"</span><span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -273,25 +273,142 @@
|
|||
"source": [
|
||||
"print(indicator.serialize())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If you need performance but also need human-readable output, you can pass the `indent` keyword argument to `serialize()`:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for malware variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--4336ace8-d985-413a-8e32-f749ba268dc3"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:01:20.012209Z"</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(indicator.serialize(indent=4))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The only difference between this and the string representation from using `str()` is that this will not sort the keys. This works because the keyword arguments are passed to `json.dumps()` internally."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -33,23 +33,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -58,9 +60,9 @@
|
|||
"source": [
|
||||
"## TAXIICollection\n",
|
||||
"\n",
|
||||
"The TAXIICollection suite contains [TAXIICollectionStore](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionStore), [TAXIICollectionSource](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionSource), and [TAXIICollectionSink](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionSink). [TAXIICollectionStore](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionStore) for pushing and retrieving STIX content to local/remote TAXII Collection(s). [TAXIICollectionSource](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionSource) for retrieving STIX content to local/remote TAXII Collection(s). [TAXIICollectionSink](../api/sources/stix2.sources.taxii.rst#stix2.sources.taxii.TAXIICollectionSink) for pushing STIX content to local/remote TAXII Collection(s). Each of the interfaces is designed to be bound to a Collection from the [taxii2client](https://github.com/oasis-open/cti-taxii-client) library (taxii2client.Collection), where all [TAXIICollection](../api/sources/stix2.sources.taxii.rst) API calls will be executed through that Collection instance.\n",
|
||||
"The TAXIICollection suite contains [TAXIICollectionStore](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionStore), [TAXIICollectionSource](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionSource), and [TAXIICollectionSink](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionSink). [TAXIICollectionStore](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionStore) pushes and retrieves STIX content to local/remote TAXII Collection(s). [TAXIICollectionSource](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionSource) retrieves STIX content from local/remote TAXII Collection(s). [TAXIICollectionSink](../api/datastore/stix2.datastore.taxii.rst#stix2.datastore.taxii.TAXIICollectionSink) pushes STIX content to local/remote TAXII Collection(s). Each of the interfaces is designed to be bound to a Collection from the [taxii2client](https://github.com/oasis-open/cti-taxii-client) library (taxii2client.Collection), where all [TAXIICollection](../api/datastore/stix2.datastore.taxii.rst) API calls will be executed through that Collection instance.\n",
|
||||
"\n",
|
||||
"A note on TAXII2 searching/filtering of STIX content. TAXII2 server implementations natively support searching on the STIX2 object properties: id, type and version; API requests made to TAXII2 can contain filter arguments for those 3 properties. However, the [TAXIICollection](../api/sources/stix2.sources.taxii.rst) suite supports searching on all STIX2 common object properties (see [Filters](../api/sources/stix2.sources.filters.rst) documentation for full listing). This works simply by augmenting the filtering that is done remotely at the TAXII2 server instance. [TAXIICollection](../api/sources/stix2.sources.taxii.rst) will seperate any supplied queries into TAXII supported filters and non-supported filters. During a [TAXIICollection](../api/sources/stix2.sources.taxii.rst) API call, TAXII2 supported filters get inserted into the TAXII2 server request (to be evaluated at the server). The rest of the filters are kept locally and then applied to the STIX2 content that is returned from the TAXII2 server, before being returned from the [TAXIICollection](../api/sources/stix2.sources.taxii.rst) API call. \n",
|
||||
"A note on TAXII2 searching/filtering of STIX content: TAXII2 server implementations natively support searching on the STIX2 object properties: id, type and version; API requests made to TAXII2 can contain filter arguments for those 3 properties. However, the [TAXIICollection](../api/datastore/stix2.datastore.taxii.rst) suite supports searching on all STIX2 common object properties (see [Filters](../api/datastore/stix2.datastore.filters.rst) documentation for full listing). This works simply by augmenting the filtering that is done remotely at the TAXII2 server instance. [TAXIICollection](../api/datastore/stix2.datastore.taxii.rst) will seperate any supplied queries into TAXII supported filters and non-supported filters. During a [TAXIICollection](../api/datastore/stix2.datastore.taxii.rst) API call, TAXII2 supported filters get inserted into the TAXII2 server request (to be evaluated at the server). The rest of the filters are kept locally and then applied to the STIX2 content that is returned from the TAXII2 server, before being returned from the [TAXIICollection](../api/datastore/stix2.datastore.taxii.rst) API call. \n",
|
||||
"\n",
|
||||
"### TAXIICollection API\n",
|
||||
"\n",
|
||||
|
@ -261,25 +263,65 @@
|
|||
"\n",
|
||||
"tc_store.add(ind)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Bug and Workaround\n",
|
||||
"\n",
|
||||
"You may get an error similar to the following when adding STIX objects to a TAXIICollectionStore or TAXIICollectionSink:\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"TypeError: Object of type ThreatActor is not JSON serializable\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"This is a known bug and we are working to fix it. For more information, see [this GitHub issue](https://github.com/oasis-open/cti-python-stix2/issues/125) In the meantime, try this workaround:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tc_sink.add(json.loads(Bundle(ta).serialize()))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Or bypass the TAXIICollection altogether and interact with the collection itself:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"collection.add_objects(json.loads(Bundle(ta).serialize()))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +32,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -58,7 +59,7 @@
|
|||
"source": [
|
||||
"## Technical Specification Support\n",
|
||||
"\n",
|
||||
"### How imports will work\n",
|
||||
"### How imports work\n",
|
||||
"\n",
|
||||
"Imports can be used in different ways depending on the use case and support levels.\n",
|
||||
"\n",
|
||||
|
@ -228,7 +229,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### How parsing will work\n",
|
||||
"### How parsing works\n",
|
||||
"If the ``version`` positional argument is not provided. The data will be parsed using the latest version of STIX 2.X supported by the `stix2` library.\n",
|
||||
"\n",
|
||||
"You can lock your [parse()](../api/stix2.core.rst#stix2.core.parse) method to a specific STIX version by:"
|
||||
|
@ -236,7 +237,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -328,7 +329,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -362,7 +363,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### How will custom content work\n",
|
||||
"### How custom content works\n",
|
||||
"\n",
|
||||
"[CustomObject](../api/stix2.v20.sdo.rst#stix2.v20.sdo.CustomObject), [CustomObservable](../api/stix2.v20.observables.rst#stix2.v20.observables.CustomObservable), [CustomMarking](../api/stix2.v20.common.rst#stix2.v20.common.CustomMarking) and [CustomExtension](../api/stix2.v20.observables.rst#stix2.v20.observables.CustomExtension) must be registered explicitly by STIX version. This is a design decision since properties or requirements may change as the STIX Technical Specification advances.\n",
|
||||
"\n",
|
||||
|
@ -396,21 +397,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -23,9 +22,8 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
|
@ -33,23 +31,25 @@
|
|||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import HTML\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"original_print = print\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, JsonLexer(), formatter)))\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" original_print(inpt)\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"print = json_print"
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -68,7 +68,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -144,15 +144,15 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--92bb1ae4-db9c-4d6e-8ded-ef7280b4439a"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dd052ff6-e404-444b-beb9-eae96d1e79ea"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2016-01-01T08:00:00.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:39:07.149Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:02:51.161Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for Foobar malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:39:07.132129Z"</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:02:51.138312Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -160,7 +160,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -187,7 +187,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
|
@ -216,7 +216,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -292,16 +292,16 @@
|
|||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--92bb1ae4-db9c-4d6e-8ded-ef7280b4439a"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--dd052ff6-e404-444b-beb9-eae96d1e79ea"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2016-01-01T08:00:00.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:39:09.463Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">],</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:02:54.704Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for Foobar malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-09-26T23:39:07.132129Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"revoked"</span><span class=\"p\">:</span> <span class=\"kc\">true</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2018-04-05T20:02:51.138312Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"revoked"</span><span class=\"p\">:</span> <span class=\"kc\">true</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"malicious-activity"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
|
@ -309,7 +309,7 @@
|
|||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -322,21 +322,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.12"
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
@ -0,0 +1,801 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Delete this cell to re-enable tracebacks\n",
|
||||
"import sys\n",
|
||||
"ipython = get_ipython()\n",
|
||||
"\n",
|
||||
"def hide_traceback(exc_tuple=None, filename=None, tb_offset=None,\n",
|
||||
" exception_only=False, running_compiled_code=False):\n",
|
||||
" etype, value, tb = sys.exc_info()\n",
|
||||
" return ipython._showtraceback(etype, value, ipython.InteractiveTB.get_exception_only(etype, value))\n",
|
||||
"\n",
|
||||
"ipython.showtraceback = hide_traceback"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"nbsphinx": "hidden"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# JSON output syntax highlighting\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from pygments import highlight\n",
|
||||
"from pygments.lexers import JsonLexer, TextLexer\n",
|
||||
"from pygments.formatters import HtmlFormatter\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"from IPython.core.interactiveshell import InteractiveShell\n",
|
||||
"\n",
|
||||
"InteractiveShell.ast_node_interactivity = \"all\"\n",
|
||||
"\n",
|
||||
"def json_print(inpt):\n",
|
||||
" string = str(inpt)\n",
|
||||
" formatter = HtmlFormatter()\n",
|
||||
" if string[0] == '{':\n",
|
||||
" lexer = JsonLexer()\n",
|
||||
" else:\n",
|
||||
" lexer = TextLexer()\n",
|
||||
" return HTML('<style type=\"text/css\">{}</style>{}'.format(\n",
|
||||
" formatter.get_style_defs('.highlight'),\n",
|
||||
" highlight(string, lexer, formatter)))\n",
|
||||
"\n",
|
||||
"globals()['print'] = json_print"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Using The Workbench"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The [Workbench API](../api/stix2.workbench.rst) 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``:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from stix2.workbench import *"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Retrieving STIX Data\n",
|
||||
"\n",
|
||||
"To get some STIX data to work with, let's set up a DataSource and add it to our workbench."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from taxii2client import Collection\n",
|
||||
"\n",
|
||||
"collection = Collection(\"http://127.0.0.1:5000/trustgroup1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/\", user=\"admin\", password=\"Password0\")\n",
|
||||
"tc_source = TAXIICollectionSource(collection)\n",
|
||||
"add_data_source(tc_source)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"Now we can get all of the indicators from the data source."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"response = indicators()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Similar functions are available for the other STIX Object types. See the full list [here](../api/stix2.workbench.rst#stix2.workbench.attack_patterns).\n",
|
||||
"\n",
|
||||
"If you want to only retrieve *some* indicators, you can pass in one or more [Filters](../api/datastore/stix2.datastore.filters.rst). This example finds all the indicators created by a specific identity:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"response = indicators(filters=Filter('created_by_ref', '=', 'identity--adede3e8-bf44-4e6f-b3c9-1958cbc3b188'))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"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](../api/stix2.workbench.rst) documentation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>indicator--a932fcc6-e032-176c-126f-cb970a5a1ade\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>indicates\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for i in indicators():\n",
|
||||
" for rel in i.relationships():\n",
|
||||
" print(rel.source_ref)\n",
|
||||
" print(rel.relationship_type)\n",
|
||||
" print(rel.target_ref)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"malware"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-01-27T13:49:53.997Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2017-01-27T13:49:53.997Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"Poison Ivy"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"description"</span><span class=\"p\">:</span> <span class=\"s2\">"Poison Ivy"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"remote-access-trojan"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for i in indicators():\n",
|
||||
" for obj in i.related():\n",
|
||||
" print(obj)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If there are a lot of related objects, you can narrow it down by passing in one or more [Filters](../api/datastore/stix2.datastore.filters.rst) 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):"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span><span class=\"p\">{</span>\n",
|
||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"indicator--a932fcc6-e032-176c-126f-cb970a5a1ade"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2014-05-08T09:00:00.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2014-05-08T09:00:00.000Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"name"</span><span class=\"p\">:</span> <span class=\"s2\">"File hash for Poison Ivy variant"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"pattern"</span><span class=\"p\">:</span> <span class=\"s2\">"[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"valid_from"</span><span class=\"p\">:</span> <span class=\"s2\">"2014-05-08T09:00:00Z"</span><span class=\"p\">,</span>\n",
|
||||
" <span class=\"nt\">"labels"</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n",
|
||||
" <span class=\"s2\">"file-hash-watchlist"</span>\n",
|
||||
" <span class=\"p\">]</span>\n",
|
||||
"<span class=\"p\">}</span>\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"malware = get('malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111')\n",
|
||||
"indicator = malware.related(filters=Filter('type', '=', 'indicator'))\n",
|
||||
"print(indicator[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Creating STIX Data\n",
|
||||
"\n",
|
||||
"To create a STIX object, just use that object's class constructor. Once it's created, add it to the workbench with [save()](../api/datastore/stix2.workbench.rst#stix2.workbench.save)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"identity = Identity(name=\"ACME Threat Intel Co.\", identity_class=\"organization\")\n",
|
||||
"save(identity)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"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:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"set_default_creator(identity)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now when we create an indicator (or any other STIX Domain Object), it will automatically have the right ``create_by_ref`` value."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<style type=\"text/css\">.highlight .hll { background-color: #ffffcc }\n",
|
||||
".highlight { background: #f8f8f8; }\n",
|
||||
".highlight .c { color: #408080; font-style: italic } /* Comment */\n",
|
||||
".highlight .err { border: 1px solid #FF0000 } /* Error */\n",
|
||||
".highlight .k { color: #008000; font-weight: bold } /* Keyword */\n",
|
||||
".highlight .o { color: #666666 } /* Operator */\n",
|
||||
".highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
|
||||
".highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
|
||||
".highlight .cp { color: #BC7A00 } /* Comment.Preproc */\n",
|
||||
".highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
|
||||
".highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
|
||||
".highlight .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
|
||||
".highlight .gd { color: #A00000 } /* Generic.Deleted */\n",
|
||||
".highlight .ge { font-style: italic } /* Generic.Emph */\n",
|
||||
".highlight .gr { color: #FF0000 } /* Generic.Error */\n",
|
||||
".highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
|
||||
".highlight .gi { color: #00A000 } /* Generic.Inserted */\n",
|
||||
".highlight .go { color: #888888 } /* Generic.Output */\n",
|
||||
".highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
|
||||
".highlight .gs { font-weight: bold } /* Generic.Strong */\n",
|
||||
".highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
|
||||
".highlight .gt { color: #0044DD } /* Generic.Traceback */\n",
|
||||
".highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
|
||||
".highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
|
||||
".highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
|
||||
".highlight .kp { color: #008000 } /* Keyword.Pseudo */\n",
|
||||
".highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
|
||||
".highlight .kt { color: #B00040 } /* Keyword.Type */\n",
|
||||
".highlight .m { color: #666666 } /* Literal.Number */\n",
|
||||
".highlight .s { color: #BA2121 } /* Literal.String */\n",
|
||||
".highlight .na { color: #7D9029 } /* Name.Attribute */\n",
|
||||
".highlight .nb { color: #008000 } /* Name.Builtin */\n",
|
||||
".highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
|
||||
".highlight .no { color: #880000 } /* Name.Constant */\n",
|
||||
".highlight .nd { color: #AA22FF } /* Name.Decorator */\n",
|
||||
".highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
|
||||
".highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
|
||||
".highlight .nf { color: #0000FF } /* Name.Function */\n",
|
||||
".highlight .nl { color: #A0A000 } /* Name.Label */\n",
|
||||
".highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
|
||||
".highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
|
||||
".highlight .nv { color: #19177C } /* Name.Variable */\n",
|
||||
".highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
|
||||
".highlight .w { color: #bbbbbb } /* Text.Whitespace */\n",
|
||||
".highlight .mb { color: #666666 } /* Literal.Number.Bin */\n",
|
||||
".highlight .mf { color: #666666 } /* Literal.Number.Float */\n",
|
||||
".highlight .mh { color: #666666 } /* Literal.Number.Hex */\n",
|
||||
".highlight .mi { color: #666666 } /* Literal.Number.Integer */\n",
|
||||
".highlight .mo { color: #666666 } /* Literal.Number.Oct */\n",
|
||||
".highlight .sa { color: #BA2121 } /* Literal.String.Affix */\n",
|
||||
".highlight .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
|
||||
".highlight .sc { color: #BA2121 } /* Literal.String.Char */\n",
|
||||
".highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
|
||||
".highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
|
||||
".highlight .s2 { color: #BA2121 } /* Literal.String.Double */\n",
|
||||
".highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
|
||||
".highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
|
||||
".highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
|
||||
".highlight .sx { color: #008000 } /* Literal.String.Other */\n",
|
||||
".highlight .sr { color: #BB6688 } /* Literal.String.Regex */\n",
|
||||
".highlight .s1 { color: #BA2121 } /* Literal.String.Single */\n",
|
||||
".highlight .ss { color: #19177C } /* Literal.String.Symbol */\n",
|
||||
".highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
|
||||
".highlight .fm { color: #0000FF } /* Name.Function.Magic */\n",
|
||||
".highlight .vc { color: #19177C } /* Name.Variable.Class */\n",
|
||||
".highlight .vg { color: #19177C } /* Name.Variable.Global */\n",
|
||||
".highlight .vi { color: #19177C } /* Name.Variable.Instance */\n",
|
||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
|
||||
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */</style><div class=\"highlight\"><pre><span></span>ACME Threat Intel Co.\n",
|
||||
"</pre></div>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"indicator = Indicator(labels=[\"malicious-activity\"], pattern=\"[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']\")\n",
|
||||
"save(indicator)\n",
|
||||
"\n",
|
||||
"indicator_creator = get(indicator.created_by_ref)\n",
|
||||
"print(indicator_creator.name)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Defaults can also be set for the [created timestamp](../api/datastore/stix2.workbench.rst#stix2.workbench.set_default_created), [external references](../api/datastore/stix2.workbench.rst#stix2.workbench.set_default_external_refs) and [object marking references](../api/datastore/stix2.workbench.rst#stix2.workbench.set_default_object_marking_refs)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-warning\">\n",
|
||||
"\n",
|
||||
"**Warning:**\n",
|
||||
"\n",
|
||||
"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``.\n",
|
||||
"\n",
|
||||
"</div>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
|
@ -3,8 +3,17 @@
|
|||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to stix2's documentation!
|
||||
=================================
|
||||
STIX 2 Python API Documentation
|
||||
===============================
|
||||
|
||||
Welcome to the STIX 2 Python API's documentation. This library is designed to
|
||||
help you work with STIX 2 content. For more information about STIX 2, see the
|
||||
`website <http://cti-tc.github.io>`_ of the OASIS Cyber Threat Intelligence
|
||||
Technical Committee.
|
||||
|
||||
Get started with an `overview <overview.rst>`_ of the library, then take a look
|
||||
at the `guides and tutorials <guide.rst>`_ to see how to use it. For information
|
||||
about a specific class or function, see the `API reference <api_ref.rst>`_.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
@ -13,8 +22,6 @@ Welcome to stix2's documentation!
|
|||
overview
|
||||
guide
|
||||
api_ref
|
||||
datastore_api
|
||||
roadmap
|
||||
contributing
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ Overview
|
|||
Goals
|
||||
-----
|
||||
|
||||
High level goals/principles of the python-stix2 library:
|
||||
High level goals/principles of the Python ``stix2`` library:
|
||||
|
||||
1. It should be as easy as possible (but no easier!) to perform common tasks of
|
||||
producing, consuming, and processing STIX 2 content.
|
||||
|
@ -17,22 +17,22 @@ Design Decisions
|
|||
----------------
|
||||
|
||||
To accomplish these goals, and to incorporate lessons learned while developing
|
||||
python-stix (for STIX 1.x), several decisions influenced the design of
|
||||
python-stix2:
|
||||
``python-stix`` (for STIX 1.x), several decisions influenced the design of the
|
||||
``stix2`` library:
|
||||
|
||||
1. All data structures are immutable by default. In contrast to python-stix,
|
||||
where users would create an object and then assign attributes to it, in
|
||||
python-stix2 all properties must be provided when creating the object.
|
||||
``stix2`` all properties must be provided when creating the object.
|
||||
2. Where necessary, library objects should act like ``dict``'s. When treated as
|
||||
a ``str``, the JSON reprentation of the object should be used.
|
||||
3. Core Python data types (including numeric types, ``datetime``) should be used
|
||||
when appropriate, and serialized to the correct format in JSON as specified
|
||||
in the STIX 2.0 spec.
|
||||
in the STIX 2 spec.
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The `stix2` library APIs are divided into three logical layers, representing
|
||||
The ``stix2`` library is divided into three logical layers, representing
|
||||
different levels of abstraction useful in different types of scripts and larger
|
||||
applications. It is possible to combine multiple layers in the same program,
|
||||
and the higher levels build on the layers below.
|
||||
|
@ -41,7 +41,7 @@ and the higher levels build on the layers below.
|
|||
Object Layer
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The lowest layer, **Object Layer**, is where Python objects representing STIX 2
|
||||
The lowest layer, the **Object Layer**, is where Python objects representing STIX 2
|
||||
data types (such as SDOs, SROs, and Cyber Observable Objects, as well as
|
||||
non-top-level objects like External References, Kill Chain phases, and Cyber
|
||||
Observable extensions) are created, and can be serialized and deserialized
|
||||
|
@ -57,8 +57,6 @@ not implemented as references between the Python objects themselves, but by
|
|||
simply having the same values in ``id`` and reference properties. There is no
|
||||
referential integrity maintained by the ``stix2`` library.
|
||||
|
||||
*This layer is mostly complete.*
|
||||
|
||||
Environment Layer
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -79,8 +77,7 @@ intelligence ecosystem.
|
|||
Each of these components can be used individually, or combined as part of an
|
||||
``Environment``. These ``Environment`` objects allow different settings to be
|
||||
used by different users of a multi-user application (such as a web application).
|
||||
|
||||
*This layer is mostly complete.*
|
||||
For more information, check out `this Environment tutorial <guide/environment.ipynb>`_.
|
||||
|
||||
Workbench Layer
|
||||
^^^^^^^^^^^^^^^
|
||||
|
@ -89,9 +86,7 @@ The highest layer of the ``stix2`` APIs is the **Workbench Layer**, designed for
|
|||
a single user in a highly-interactive analytical environment (such as a `Jupyter
|
||||
Notebook <https://jupyter.org/>`_). It builds on the lower layers of the API,
|
||||
while hiding most of their complexity. Unlike the other layers, this layer is
|
||||
designed to be used directly by end users. For users who are comfortable with,
|
||||
designed to be used directly by end users. For users who are comfortable with
|
||||
Python, the Workbench Layer makes it easy to quickly interact with STIX data
|
||||
from a variety of sources without needing to write and run one-off Python
|
||||
scripts.
|
||||
|
||||
*This layer is currently being developed.*
|
||||
scripts. For more information, check out `this Workbench tutorial <guide/workbench.ipynb>`_.
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
Development Roadmap
|
||||
===================
|
||||
|
||||
.. warning::
|
||||
|
||||
Prior to version 1.0, all APIs are considered unstable and subject to
|
||||
change.
|
||||
|
||||
This is a list of (planned) features before version 1.0 is released.
|
||||
|
||||
* Serialization of all STIX and Cyber Observable objects to JSON.
|
||||
* De-serialization (parsing) of all STIX and Cyber Observable objects.
|
||||
* APIs for versioning (revising and revoking) STIX objects.
|
||||
* APIs for marking STIX objects and interpreting markings of STIX objects.
|
||||
* :ref:`datastore_api`, providing a common interface for querying sources
|
||||
of STIX content (such as objects in memory, on a filesystem, in a database, or
|
||||
via a TAXII feed).
|
|
@ -1,54 +1,39 @@
|
|||
import json
|
||||
from taxii2client import Collection
|
||||
|
||||
from stix2.sources.taxii import TAXIIDataSource
|
||||
import stix2
|
||||
|
||||
# Flask TAXII server - developmental
|
||||
ROOT = 'http://localhost:5000'
|
||||
AUTH = {'user': 'mk', 'pass': 'Pass'}
|
||||
# This example is based on the medallion server with default_data.json
|
||||
# See https://github.com/oasis-open/cti-taxii-server for more information
|
||||
|
||||
|
||||
def main():
|
||||
collection = Collection("http://127.0.0.1:5000/trustgroup1/collections/52892447-4d7e-4f70-b94d-d7f22742ff63/",
|
||||
user="admin", password="Password0")
|
||||
|
||||
# instantiate TAXII data source
|
||||
taxii = TAXIIDataSource(api_root=ROOT, auth=AUTH)
|
||||
taxii = stix2.TAXIICollectionSource(collection)
|
||||
|
||||
# get (file watch indicator)
|
||||
indicator_fw = taxii.get(id_="indicator--a932fcc6-e032-176c-126f-cb970a5a1ade")
|
||||
# get (url watch indicator)
|
||||
indicator_fw = taxii.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
print("\n\n-------Queried for Indicator - got:")
|
||||
print(json.dumps(indicator_fw, indent=4))
|
||||
print(indicator_fw.serialize(indent=4))
|
||||
|
||||
# all versions (file watch indicator - currently only 1. maybe Emmanuelle can add a version)
|
||||
indicator_fw_versions = taxii.get(id_="indicator--a932fcc6-e032-176c-126f-cb970a5a1ade")
|
||||
# all versions (url watch indicator - currently two)
|
||||
indicator_fw_versions = taxii.all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
print("\n\n------Queried for indicator (all_versions()) - got:")
|
||||
print(json.dumps(indicator_fw_versions, indent=4))
|
||||
for indicator in indicator_fw_versions:
|
||||
print(indicator.serialize(indent=4))
|
||||
|
||||
# add TAXII filter (ie filter should be passed to TAXII)
|
||||
taxii_filter_ids, status = taxii.add_filter(
|
||||
[
|
||||
{
|
||||
"field": "type",
|
||||
"op": "in",
|
||||
"value": "malware"
|
||||
}
|
||||
])
|
||||
query_filter = stix2.Filter("type", "in", "malware")
|
||||
|
||||
print("\n\n-------Added filter:")
|
||||
print("Filter ID: {0}".format(taxii_filter_ids[0]))
|
||||
print("Filter status: \n")
|
||||
print(json.dumps(status, indent=4))
|
||||
print("filters: \n")
|
||||
print(json.dumps(taxii.get_filters(), indent=4))
|
||||
|
||||
# get() - but with filter attached
|
||||
malware = taxii.query()
|
||||
# query() - but with filter attached. There are no malware objects in this collection
|
||||
malwares = taxii.query(query=query_filter)
|
||||
print("\n\n\n--------Queried for Malware string (with above filter attached) - got:")
|
||||
print(json.dumps(malware, indent=4))
|
||||
|
||||
# remove TAXII filter
|
||||
taxii.remove_filter(taxii_filter_ids)
|
||||
print("\n\n-------Removed filter(TAXII filter):")
|
||||
print("filters: \n")
|
||||
print(json.dumps(taxii.get_filters(), indent=4))
|
||||
for malware in malwares:
|
||||
print(malware.serialize(indent=4))
|
||||
if not malwares:
|
||||
print(malwares)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
bumpversion
|
||||
nbsphinx>=0.2.15
|
||||
ipython
|
||||
nbsphinx==0.3.2
|
||||
pre-commit
|
||||
pytest
|
||||
pytest-cov
|
||||
sphinx
|
||||
sphinx<1.6
|
||||
sphinx-prompt
|
||||
tox
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 0.4.0
|
||||
current_version = 1.0.2
|
||||
commit = True
|
||||
tag = True
|
||||
|
||||
|
|
11
setup.py
11
setup.py
|
@ -4,11 +4,12 @@ import os.path
|
|||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
VERSION_FILE = os.path.join(BASE_DIR, 'stix2', 'version.py')
|
||||
|
||||
|
||||
def get_version():
|
||||
with open('stix2/version.py', encoding="utf-8") as f:
|
||||
with open(VERSION_FILE) as f:
|
||||
for line in f.readlines():
|
||||
if line.startswith("__version__"):
|
||||
version = line.split()[-1].strip('"')
|
||||
|
@ -16,7 +17,7 @@ def get_version():
|
|||
raise AttributeError("Package does not have a __version__")
|
||||
|
||||
|
||||
with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
|
||||
with open('README.rst') as f:
|
||||
long_description = f.read()
|
||||
|
||||
|
||||
|
@ -52,6 +53,8 @@ setup(
|
|||
'simplejson',
|
||||
'six',
|
||||
'stix2-patterns',
|
||||
'taxii2-client',
|
||||
],
|
||||
extras_require={
|
||||
'taxii': ['taxii2-client']
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,32 +3,49 @@
|
|||
.. autosummary::
|
||||
:toctree: api
|
||||
|
||||
v21.common
|
||||
core
|
||||
datastore
|
||||
environment
|
||||
exceptions
|
||||
markings
|
||||
v21.observables
|
||||
patterns
|
||||
properties
|
||||
v21.sdo
|
||||
sources
|
||||
v21.sro
|
||||
utils
|
||||
patterns
|
||||
properties
|
||||
utils
|
||||
workbench
|
||||
v20.common
|
||||
v20.observables
|
||||
v20.sdo
|
||||
v20.sro
|
||||
v21.common
|
||||
v21.observables
|
||||
v21.sdo
|
||||
v21.sro
|
||||
"""
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
from .core import Bundle, _collect_stix2_obj_maps, _register_type, parse
|
||||
from .datastore import CompositeDataSource
|
||||
from .datastore.filesystem import (FileSystemSink, FileSystemSource,
|
||||
FileSystemStore)
|
||||
from .datastore.filters import Filter
|
||||
from .datastore.memory import MemorySink, MemorySource, MemoryStore
|
||||
from .datastore.taxii import (TAXIICollectionSink, TAXIICollectionSource,
|
||||
TAXIICollectionStore)
|
||||
from .environment import Environment, ObjectFactory
|
||||
from .markings import (add_markings, clear_markings, get_markings, is_marked,
|
||||
remove_markings, set_markings)
|
||||
from .patterns import (AndBooleanExpression, AndObservationExpression,
|
||||
BasicObjectPathComponent, EqualityComparisonExpression,
|
||||
BasicObjectPathComponent, BinaryConstant,
|
||||
BooleanConstant, EqualityComparisonExpression,
|
||||
FloatConstant, FollowedByObservationExpression,
|
||||
GreaterThanComparisonExpression,
|
||||
GreaterThanEqualComparisonExpression, HashConstant,
|
||||
HexConstant, IntegerConstant,
|
||||
HexConstant, InComparisonExpression, IntegerConstant,
|
||||
IsSubsetComparisonExpression,
|
||||
IsSupersetComparisonExpression,
|
||||
LessThanComparisonExpression,
|
||||
|
@ -41,14 +58,7 @@ from .patterns import (AndBooleanExpression, AndObservationExpression,
|
|||
ReferenceObjectPathComponent, RepeatQualifier,
|
||||
StartStopQualifier, StringConstant, TimestampConstant,
|
||||
WithinQualifier)
|
||||
from .sources import CompositeDataSource
|
||||
from .sources.filesystem import (FileSystemSink, FileSystemSource,
|
||||
FileSystemStore)
|
||||
from .sources.filters import Filter
|
||||
from .sources.memory import MemorySink, MemorySource, MemoryStore
|
||||
from .sources.taxii import (TAXIICollectionSink, TAXIICollectionSource,
|
||||
TAXIICollectionStore)
|
||||
from .utils import get_dict, new_version, revoke
|
||||
from .utils import new_version, revoke
|
||||
from .v21 import * # This import will always be the latest STIX 2.X version
|
||||
from .version import __version__
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ import datetime as dt
|
|||
|
||||
import simplejson as json
|
||||
|
||||
from .exceptions import (AtLeastOnePropertyError, DependentPropertiesError,
|
||||
ExtraPropertiesError, ImmutableError,
|
||||
InvalidObjRefError, InvalidValueError,
|
||||
from .exceptions import (AtLeastOnePropertyError, CustomContentError,
|
||||
DependentPropertiesError, ExtraPropertiesError,
|
||||
ImmutableError, InvalidObjRefError, InvalidValueError,
|
||||
MissingPropertiesError,
|
||||
MutuallyExclusivePropertiesError)
|
||||
from .markings.utils import validate
|
||||
|
@ -22,6 +22,33 @@ DEFAULT_ERROR = "{type} must have {property}='{expected}'."
|
|||
|
||||
|
||||
class STIXJSONEncoder(json.JSONEncoder):
|
||||
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
||||
|
||||
If an optional property with a default value specified in the STIX 2 spec
|
||||
is set to that default value, it will be left out of the serialized output.
|
||||
|
||||
An example of this type of property include the ``revoked`` common property.
|
||||
"""
|
||||
|
||||
def default(self, obj):
|
||||
if isinstance(obj, (dt.date, dt.datetime)):
|
||||
return format_datetime(obj)
|
||||
elif isinstance(obj, _STIXBase):
|
||||
tmp_obj = dict(copy.deepcopy(obj))
|
||||
for prop_name in obj._defaulted_optional_properties:
|
||||
del tmp_obj[prop_name]
|
||||
return tmp_obj
|
||||
else:
|
||||
return super(STIXJSONEncoder, self).default(obj)
|
||||
|
||||
|
||||
class STIXJSONIncludeOptionalDefaultsEncoder(json.JSONEncoder):
|
||||
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
||||
|
||||
Differs from ``STIXJSONEncoder`` in that if an optional property with a default
|
||||
value specified in the STIX 2 spec is set to that default value, it will be
|
||||
included in the serialized output.
|
||||
"""
|
||||
|
||||
def default(self, obj):
|
||||
if isinstance(obj, (dt.date, dt.datetime)):
|
||||
|
@ -61,6 +88,8 @@ class _STIXBase(collections.Mapping):
|
|||
try:
|
||||
kwargs[prop_name] = prop.clean(kwargs[prop_name])
|
||||
except ValueError as exc:
|
||||
if self.__allow_custom and isinstance(exc, CustomContentError):
|
||||
return
|
||||
raise InvalidValueError(self.__class__, prop_name, reason=str(exc))
|
||||
|
||||
# interproperty constraint methods
|
||||
|
@ -97,6 +126,7 @@ class _STIXBase(collections.Mapping):
|
|||
|
||||
def __init__(self, allow_custom=False, **kwargs):
|
||||
cls = self.__class__
|
||||
self.__allow_custom = allow_custom
|
||||
|
||||
# Use the same timestamp for any auto-generated datetimes
|
||||
self.__now = get_timestamp()
|
||||
|
@ -105,10 +135,12 @@ class _STIXBase(collections.Mapping):
|
|||
custom_props = kwargs.pop('custom_properties', {})
|
||||
if custom_props and not isinstance(custom_props, dict):
|
||||
raise ValueError("'custom_properties' must be a dictionary")
|
||||
if not allow_custom:
|
||||
extra_kwargs = list(set(kwargs) - set(cls._properties))
|
||||
if not self.__allow_custom:
|
||||
extra_kwargs = list(set(kwargs) - set(self._properties))
|
||||
if extra_kwargs:
|
||||
raise ExtraPropertiesError(cls, extra_kwargs)
|
||||
if custom_props:
|
||||
self.__allow_custom = True
|
||||
|
||||
# Remove any keyword arguments whose value is None
|
||||
setting_kwargs = {}
|
||||
|
@ -119,14 +151,25 @@ class _STIXBase(collections.Mapping):
|
|||
setting_kwargs[prop_name] = prop_value
|
||||
|
||||
# Detect any missing required properties
|
||||
required_properties = get_required_properties(cls._properties)
|
||||
missing_kwargs = set(required_properties) - set(setting_kwargs)
|
||||
required_properties = set(get_required_properties(self._properties))
|
||||
missing_kwargs = required_properties - set(setting_kwargs)
|
||||
if missing_kwargs:
|
||||
raise MissingPropertiesError(cls, missing_kwargs)
|
||||
|
||||
for prop_name, prop_metadata in cls._properties.items():
|
||||
for prop_name, prop_metadata in self._properties.items():
|
||||
self._check_property(prop_name, prop_metadata, setting_kwargs)
|
||||
|
||||
# Cache defaulted optional properties for serialization
|
||||
defaulted = []
|
||||
for name, prop in self._properties.items():
|
||||
try:
|
||||
if (not prop.required and not hasattr(prop, '_fixed_value') and
|
||||
prop.default() == setting_kwargs[name]):
|
||||
defaulted.append(name)
|
||||
except (AttributeError, KeyError):
|
||||
continue
|
||||
self._defaulted_optional_properties = defaulted
|
||||
|
||||
self._inner = setting_kwargs
|
||||
|
||||
self._check_object_constraints()
|
||||
|
@ -148,7 +191,7 @@ class _STIXBase(collections.Mapping):
|
|||
(self.__class__.__name__, name))
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name != '_inner' and not name.startswith("_STIXBase__"):
|
||||
if not name.startswith("_"):
|
||||
raise ImmutableError(self.__class__, name)
|
||||
super(_STIXBase, self).__setattr__(name, value)
|
||||
|
||||
|
@ -167,6 +210,7 @@ class _STIXBase(collections.Mapping):
|
|||
if isinstance(self, _Observable):
|
||||
# Assume: valid references in the original object are still valid in the new version
|
||||
new_inner['_valid_refs'] = {'*': '*'}
|
||||
new_inner['allow_custom'] = self.__allow_custom
|
||||
return cls(**new_inner)
|
||||
|
||||
def properties_populated(self):
|
||||
|
@ -180,18 +224,20 @@ class _STIXBase(collections.Mapping):
|
|||
def revoke(self):
|
||||
return _revoke(self)
|
||||
|
||||
def serialize(self, pretty=False, **kwargs):
|
||||
def serialize(self, pretty=False, include_optional_defaults=False, **kwargs):
|
||||
"""
|
||||
Serialize a STIX object.
|
||||
|
||||
Args:
|
||||
pretty (bool): If True, output properties following the STIX specs
|
||||
formatting. This includes indentation. Refer to notes for more
|
||||
details.
|
||||
details. (Default: ``False``)
|
||||
include_optional_defaults (bool): Determines whether to include
|
||||
optional properties set to the default value defined in the spec.
|
||||
**kwargs: The arguments for a json.dumps() call.
|
||||
|
||||
Returns:
|
||||
dict: The serialized JSON object.
|
||||
str: The serialized JSON object.
|
||||
|
||||
Note:
|
||||
The argument ``pretty=True`` will output the STIX object following
|
||||
|
@ -210,17 +256,21 @@ class _STIXBase(collections.Mapping):
|
|||
|
||||
kwargs.update({'indent': 4, 'separators': (",", ": "), 'item_sort_key': sort_by})
|
||||
|
||||
return json.dumps(self, cls=STIXJSONEncoder, **kwargs)
|
||||
if include_optional_defaults:
|
||||
return json.dumps(self, cls=STIXJSONIncludeOptionalDefaultsEncoder, **kwargs)
|
||||
else:
|
||||
return json.dumps(self, cls=STIXJSONEncoder, **kwargs)
|
||||
|
||||
|
||||
class _Observable(_STIXBase):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
# the constructor might be called independently of an observed data object
|
||||
if '_valid_refs' in kwargs:
|
||||
self._STIXBase__valid_refs = kwargs.pop('_valid_refs')
|
||||
else:
|
||||
self._STIXBase__valid_refs = []
|
||||
self._STIXBase__valid_refs = kwargs.pop('_valid_refs', [])
|
||||
|
||||
self.__allow_custom = kwargs.get('allow_custom', False)
|
||||
self._properties['extensions'].allow_custom = kwargs.get('allow_custom', False)
|
||||
|
||||
super(_Observable, self).__init__(**kwargs)
|
||||
|
||||
def _check_ref(self, ref, prop, prop_name):
|
||||
|
|
|
@ -9,14 +9,14 @@ import stix2
|
|||
from . import exceptions
|
||||
from .base import _STIXBase
|
||||
from .properties import IDProperty, ListProperty, Property, TypeProperty
|
||||
from .utils import get_class_hierarchy_names, get_dict
|
||||
from .utils import _get_dict, get_class_hierarchy_names
|
||||
|
||||
|
||||
class STIXObjectProperty(Property):
|
||||
|
||||
def __init__(self, allow_custom=False):
|
||||
def __init__(self, allow_custom=False, *args, **kwargs):
|
||||
self.allow_custom = allow_custom
|
||||
super(STIXObjectProperty, self).__init__()
|
||||
super(STIXObjectProperty, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
# Any STIX Object (SDO, SRO, or Marking Definition) can be added to
|
||||
|
@ -25,7 +25,7 @@ class STIXObjectProperty(Property):
|
|||
for x in get_class_hierarchy_names(value)):
|
||||
return value
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
except ValueError:
|
||||
raise ValueError("This property may only contain a dictionary or object")
|
||||
if dictified == {}:
|
||||
|
@ -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 <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709293>`__.
|
||||
"""
|
||||
|
||||
_type = 'bundle'
|
||||
_properties = OrderedDict()
|
||||
|
@ -59,9 +62,8 @@ class Bundle(_STIXBase):
|
|||
else:
|
||||
kwargs['objects'] = list(args) + kwargs.get('objects', [])
|
||||
|
||||
allow_custom = kwargs.get('allow_custom', False)
|
||||
if allow_custom:
|
||||
self._properties['objects'] = ListProperty(STIXObjectProperty(True))
|
||||
self.__allow_custom = kwargs.get('allow_custom', False)
|
||||
self._properties['objects'].contained.allow_custom = kwargs.get('allow_custom', False)
|
||||
|
||||
super(Bundle, self).__init__(**kwargs)
|
||||
|
||||
|
@ -70,18 +72,57 @@ STIX2_OBJ_MAPS = {}
|
|||
|
||||
|
||||
def parse(data, allow_custom=False, version=None):
|
||||
"""Deserialize a string or file-like object into a STIX object.
|
||||
"""Convert a string, dict or file-like object into a STIX object.
|
||||
|
||||
Args:
|
||||
data (str, dict, file-like object): The STIX 2 content to be parsed.
|
||||
allow_custom (bool): Whether to allow custom properties or not.
|
||||
Default: False.
|
||||
allow_custom (bool): Whether to allow custom properties as well unknown
|
||||
custom objects. Note that unknown custom objects cannot be parsed
|
||||
into STIX objects, and will be returned as is. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
An instantiated Python STIX object.
|
||||
|
||||
WARNING: 'allow_custom=True' will allow for the return of any supplied STIX
|
||||
dict(s) that cannot be found to map to any known STIX object types (both STIX2
|
||||
domain objects or defined custom STIX2 objects); NO validation is done. This is
|
||||
done to allow the processing of possibly unknown custom STIX objects (example
|
||||
scenario: I need to query a third-party TAXII endpoint that could provide custom
|
||||
STIX objects that I dont know about ahead of time)
|
||||
|
||||
"""
|
||||
# convert STIX object to dict, if not already
|
||||
obj = _get_dict(data)
|
||||
|
||||
# convert dict to full python-stix2 obj
|
||||
obj = dict_to_stix2(obj, allow_custom, version)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def dict_to_stix2(stix_dict, allow_custom=False, version=None):
|
||||
"""convert dictionary to full python-stix2 object
|
||||
|
||||
Args:
|
||||
stix_dict (dict): a python dictionary of a STIX object
|
||||
that (presumably) is semantically correct to be parsed
|
||||
into a full python-stix2 obj
|
||||
allow_custom (bool): Whether to allow custom properties as well unknown
|
||||
custom objects. Note that unknown custom objects cannot be parsed
|
||||
into STIX objects, and will be returned as is. Default: False.
|
||||
|
||||
Returns:
|
||||
An instantiated Python STIX object
|
||||
|
||||
WARNING: 'allow_custom=True' will allow for the return of any supplied STIX
|
||||
dict(s) that cannot be found to map to any known STIX object types (both STIX2
|
||||
domain objects or defined custom STIX2 objects); NO validation is done. This is
|
||||
done to allow the processing of possibly unknown custom STIX objects (example
|
||||
scenario: I need to query a third-party TAXII endpoint that could provide custom
|
||||
STIX objects that I dont know about ahead of time)
|
||||
|
||||
"""
|
||||
if not version:
|
||||
# Use latest version
|
||||
|
@ -90,16 +131,20 @@ def parse(data, allow_custom=False, version=None):
|
|||
v = 'v' + version.replace('.', '')
|
||||
|
||||
OBJ_MAP = STIX2_OBJ_MAPS[v]
|
||||
obj = get_dict(data)
|
||||
|
||||
if 'type' not in obj:
|
||||
raise exceptions.ParseError("Can't parse object with no 'type' property: %s" % str(obj))
|
||||
if 'type' not in stix_dict:
|
||||
raise exceptions.ParseError("Can't parse object with no 'type' property: %s" % str(stix_dict))
|
||||
|
||||
try:
|
||||
obj_class = OBJ_MAP[obj['type']]
|
||||
obj_class = OBJ_MAP[stix_dict['type']]
|
||||
except KeyError:
|
||||
raise exceptions.ParseError("Can't parse unknown object type '%s'! For custom types, use the CustomObject decorator." % obj['type'])
|
||||
return obj_class(allow_custom=allow_custom, **obj)
|
||||
if allow_custom:
|
||||
# flag allows for unknown custom objects too, but will not
|
||||
# be parsed into STIX object, returned as is
|
||||
return stix_dict
|
||||
raise exceptions.ParseError("Can't parse unknown object type '%s'! For custom types, use the CustomObject decorator." % stix_dict['type'])
|
||||
|
||||
return obj_class(allow_custom=allow_custom, **stix_dict)
|
||||
|
||||
|
||||
def _register_type(new_type, version=None):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""Python STIX 2.0 Sources
|
||||
"""Python STIX 2.0 DataStore API.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: sources
|
||||
:toctree: datastore
|
||||
|
||||
filesystem
|
||||
filters
|
||||
|
@ -16,7 +16,7 @@ import uuid
|
|||
|
||||
from six import with_metaclass
|
||||
|
||||
from stix2.sources.filters import Filter
|
||||
from stix2.datastore.filters import Filter, FilterSet
|
||||
from stix2.utils import deduplicate
|
||||
|
||||
|
||||
|
@ -24,15 +24,36 @@ def make_id():
|
|||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class DataStore(object):
|
||||
"""An implementer can subclass to create custom behavior from
|
||||
this class for the specific DataStores.
|
||||
class DataSourceError(Exception):
|
||||
"""General DataSource error instance, used primarily for wrapping
|
||||
lower level errors
|
||||
|
||||
Args:
|
||||
message (str): error message
|
||||
root_exception (Exception): Exception instance of root exception
|
||||
in the case that DataSourceError is wrapping a lower level or
|
||||
other exception
|
||||
"""
|
||||
def __init__(self, message, root_exception=None):
|
||||
self.message = message
|
||||
self.root_exception = root_exception
|
||||
|
||||
def __str__(self):
|
||||
if self.root_exception:
|
||||
return "{} \"{}\"".format(self.message, self.root_exception)
|
||||
else:
|
||||
return self.message
|
||||
|
||||
|
||||
class DataStoreMixin(object):
|
||||
"""Provides mechanisms for storing and retrieving STIX data. The specific
|
||||
behavior can be customized by subclasses.
|
||||
|
||||
Args:
|
||||
source (DataSource): An existing DataSource to use
|
||||
as this DataStore's DataSource component
|
||||
as this DataStore's DataSource component
|
||||
sink (DataSink): An existing DataSink to use
|
||||
as this DataStore's DataSink component
|
||||
as this DataStore's DataSink component
|
||||
|
||||
Attributes:
|
||||
id (str): A unique UUIDv4 to identify this DataStore.
|
||||
|
@ -41,7 +62,7 @@ class DataStore(object):
|
|||
|
||||
"""
|
||||
def __init__(self, source=None, sink=None):
|
||||
super(DataStore, self).__init__()
|
||||
super(DataStoreMixin, self).__init__()
|
||||
self.id = make_id()
|
||||
self.source = source
|
||||
self.sink = sink
|
||||
|
@ -73,7 +94,7 @@ class DataStore(object):
|
|||
stix_id (str): the id of the STIX object to retrieve.
|
||||
|
||||
Returns:
|
||||
stix_objs (list): a list of STIX objects
|
||||
list: All versions of the specified STIX object.
|
||||
|
||||
"""
|
||||
try:
|
||||
|
@ -91,7 +112,7 @@ class DataStore(object):
|
|||
to conduct search on.
|
||||
|
||||
Returns:
|
||||
stix_objs (list): a list of STIX objects
|
||||
list: The STIX objects matching the query.
|
||||
|
||||
"""
|
||||
try:
|
||||
|
@ -136,7 +157,7 @@ class DataStore(object):
|
|||
object is the target_ref. Default: False.
|
||||
|
||||
Returns:
|
||||
(list): List of Relationship objects involving the given STIX object.
|
||||
list: The Relationship objects involving the given STIX object.
|
||||
|
||||
"""
|
||||
try:
|
||||
|
@ -162,9 +183,11 @@ class DataStore(object):
|
|||
object is the source_ref. Default: False.
|
||||
target_only (bool): Only examine Relationships for which this
|
||||
object is the target_ref. Default: False.
|
||||
filters (list): list of additional filters the related objects must
|
||||
match.
|
||||
|
||||
Returns:
|
||||
(list): List of STIX objects related to the given STIX object.
|
||||
list: The STIX objects related to the given STIX object.
|
||||
|
||||
"""
|
||||
try:
|
||||
|
@ -175,8 +198,8 @@ class DataStore(object):
|
|||
def add(self, *args, **kwargs):
|
||||
"""Method for storing STIX objects.
|
||||
|
||||
Define custom behavior before storing STIX objects using the associated
|
||||
DataSink. Translates add() to the appropriate DataSink call.
|
||||
Defines custom behavior before storing STIX objects using the
|
||||
appropriate method call on the associated DataSink.
|
||||
|
||||
Args:
|
||||
stix_objs (list): a list of STIX objects
|
||||
|
@ -220,13 +243,13 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
|
||||
Attributes:
|
||||
id (str): A unique UUIDv4 to identify this DataSource.
|
||||
filters (set): A collection of filters attached to this DataSource.
|
||||
filters (FilterSet): A collection of filters attached to this DataSource.
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
super(DataSource, self).__init__()
|
||||
self.id = make_id()
|
||||
self.filters = set()
|
||||
self.filters = FilterSet()
|
||||
|
||||
@abstractmethod
|
||||
def get(self, stix_id):
|
||||
|
@ -240,7 +263,7 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
specified by the "id".
|
||||
|
||||
Returns:
|
||||
stix_obj: the STIX object
|
||||
stix_obj: The STIX object.
|
||||
|
||||
"""
|
||||
|
||||
|
@ -258,7 +281,7 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
specified by the "id".
|
||||
|
||||
Returns:
|
||||
stix_objs (list): a list of STIX objects
|
||||
list: All versions of the specified STIX object.
|
||||
|
||||
"""
|
||||
|
||||
|
@ -273,7 +296,7 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
to conduct search on.
|
||||
|
||||
Returns:
|
||||
stix_objs (list): a list of STIX objects
|
||||
list: The STIX objects that matched the query.
|
||||
|
||||
"""
|
||||
|
||||
|
@ -311,7 +334,7 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
object is the target_ref. Default: False.
|
||||
|
||||
Returns:
|
||||
(list): List of Relationship objects involving the given STIX object.
|
||||
list: The Relationship objects involving the given STIX object.
|
||||
|
||||
"""
|
||||
results = []
|
||||
|
@ -338,7 +361,7 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
|
||||
return results
|
||||
|
||||
def related_to(self, obj, relationship_type=None, source_only=False, target_only=False):
|
||||
def related_to(self, obj, relationship_type=None, source_only=False, target_only=False, filters=None):
|
||||
"""Retrieve STIX Objects that have a Relationship involving the given
|
||||
STIX object.
|
||||
|
||||
|
@ -354,9 +377,11 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
object is the source_ref. Default: False.
|
||||
target_only (bool): Only examine Relationships for which this
|
||||
object is the target_ref. Default: False.
|
||||
filters (list): list of additional filters the related objects must
|
||||
match.
|
||||
|
||||
Returns:
|
||||
(list): List of STIX objects related to the given STIX object.
|
||||
list: The STIX objects related to the given STIX object.
|
||||
|
||||
"""
|
||||
results = []
|
||||
|
@ -372,10 +397,13 @@ class DataSource(with_metaclass(ABCMeta)):
|
|||
ids = set()
|
||||
for r in rels:
|
||||
ids.update((r.source_ref, r.target_ref))
|
||||
ids.remove(obj_id)
|
||||
ids.discard(obj_id)
|
||||
|
||||
# Assemble filters
|
||||
filter_list = FilterSet(filters)
|
||||
|
||||
for i in ids:
|
||||
results.append(self.get(i))
|
||||
results.extend(self.query([f for f in filter_list] + [Filter('id', '=', i)]))
|
||||
|
||||
return results
|
||||
|
||||
|
@ -420,23 +448,24 @@ class CompositeDataSource(DataSource):
|
|||
|
||||
Args:
|
||||
stix_id (str): the id of the STIX object to retrieve.
|
||||
_composite_filters (list): a list of filters passed from a
|
||||
_composite_filters (FilterSet): a collection of filters passed from a
|
||||
CompositeDataSource (i.e. if this CompositeDataSource is attached
|
||||
to another parent CompositeDataSource), not user supplied.
|
||||
|
||||
Returns:
|
||||
stix_obj: the STIX object to be returned.
|
||||
stix_obj: The STIX object to be returned.
|
||||
|
||||
"""
|
||||
if not self.has_data_sources():
|
||||
raise AttributeError('CompositeDataSource has no data sources')
|
||||
|
||||
all_data = []
|
||||
all_filters = set()
|
||||
all_filters.update(self.filters)
|
||||
all_filters = FilterSet()
|
||||
|
||||
all_filters.add(self.filters)
|
||||
|
||||
if _composite_filters:
|
||||
all_filters.update(_composite_filters)
|
||||
all_filters.add(_composite_filters)
|
||||
|
||||
# for every configured Data Source, call its retrieve handler
|
||||
for ds in self.data_sources:
|
||||
|
@ -466,24 +495,24 @@ class CompositeDataSource(DataSource):
|
|||
|
||||
Args:
|
||||
stix_id (str): id of the STIX objects to retrieve.
|
||||
_composite_filters (list): a list of filters passed from a
|
||||
_composite_filters (FilterSet): a collection of filters passed from a
|
||||
CompositeDataSource (i.e. if this CompositeDataSource is
|
||||
attached to a parent CompositeDataSource), not user supplied.
|
||||
|
||||
Returns:
|
||||
all_data (list): list of STIX objects that have the specified id
|
||||
list: The STIX objects that have the specified id.
|
||||
|
||||
"""
|
||||
if not self.has_data_sources():
|
||||
raise AttributeError('CompositeDataSource has no data sources')
|
||||
|
||||
all_data = []
|
||||
all_filters = set()
|
||||
all_filters = FilterSet()
|
||||
|
||||
all_filters.update(self.filters)
|
||||
all_filters.add(self.filters)
|
||||
|
||||
if _composite_filters:
|
||||
all_filters.update(_composite_filters)
|
||||
all_filters.add(_composite_filters)
|
||||
|
||||
# retrieve STIX objects from all configured data sources
|
||||
for ds in self.data_sources:
|
||||
|
@ -505,29 +534,29 @@ class CompositeDataSource(DataSource):
|
|||
|
||||
Args:
|
||||
query (list): list of filters to search on.
|
||||
_composite_filters (list): a list of filters passed from a
|
||||
_composite_filters (FilterSet): a collection of filters passed from a
|
||||
CompositeDataSource (i.e. if this CompositeDataSource is
|
||||
attached to a parent CompositeDataSource), not user supplied.
|
||||
|
||||
Returns:
|
||||
all_data (list): list of STIX objects to be returned
|
||||
list: The STIX objects to be returned.
|
||||
|
||||
"""
|
||||
if not self.has_data_sources():
|
||||
raise AttributeError('CompositeDataSource has no data sources')
|
||||
|
||||
if not query:
|
||||
# don't mess with the query (i.e. convert to a set, as that's done
|
||||
# don't mess with the query (i.e. deduplicate, as that's done
|
||||
# within the specific DataSources that are called)
|
||||
query = []
|
||||
|
||||
all_data = []
|
||||
all_filters = FilterSet()
|
||||
|
||||
all_filters = set()
|
||||
all_filters.update(self.filters)
|
||||
all_filters.add(self.filters)
|
||||
|
||||
if _composite_filters:
|
||||
all_filters.update(_composite_filters)
|
||||
all_filters.add(_composite_filters)
|
||||
|
||||
# federate query to all attached data sources,
|
||||
# pass composite filters to id
|
||||
|
@ -561,7 +590,7 @@ class CompositeDataSource(DataSource):
|
|||
object is the target_ref. Default: False.
|
||||
|
||||
Returns:
|
||||
(list): List of Relationship objects involving the given STIX object.
|
||||
list: The Relationship objects involving the given STIX object.
|
||||
|
||||
"""
|
||||
if not self.has_data_sources():
|
||||
|
@ -597,9 +626,11 @@ class CompositeDataSource(DataSource):
|
|||
object is the source_ref. Default: False.
|
||||
target_only (bool): Only examine Relationships for which this
|
||||
object is the target_ref. Default: False.
|
||||
filters (list): list of additional filters the related objects must
|
||||
match.
|
||||
|
||||
Returns:
|
||||
(list): List of STIX objects related to the given STIX object.
|
||||
list: The STIX objects related to the given STIX object.
|
||||
|
||||
"""
|
||||
if not self.has_data_sources():
|
|
@ -1,20 +1,18 @@
|
|||
"""
|
||||
Python STIX 2.0 FileSystem Source/Sink
|
||||
|
||||
TODO:
|
||||
Test everything
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from stix2.core import Bundle, parse
|
||||
from stix2.sources import DataSink, DataSource, DataStore
|
||||
from stix2.sources.filters import Filter, apply_common_filters
|
||||
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
||||
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||
from stix2.utils import deduplicate, get_class_hierarchy_names
|
||||
|
||||
|
||||
class FileSystemStore(DataStore):
|
||||
class FileSystemStore(DataStoreMixin):
|
||||
"""Interface to a file directory of STIX objects.
|
||||
|
||||
FileSystemStore is a wrapper around a paired FileSystemSink
|
||||
|
@ -22,7 +20,12 @@ class FileSystemStore(DataStore):
|
|||
|
||||
Args:
|
||||
stix_dir (str): path to directory of STIX objects
|
||||
bundlify (bool): Whether to wrap objects in bundles when saving them.
|
||||
allow_custom (bool): whether to allow custom STIX content to be
|
||||
pushed/retrieved. Defaults to True for FileSystemSource side(retrieving data)
|
||||
and False for FileSystemSink side(pushing data). However, when
|
||||
parameter is supplied, it will be applied to both FileSystemSource
|
||||
and FileSystemSink.
|
||||
bundlify (bool): whether to wrap objects in bundles when saving them.
|
||||
Default: False.
|
||||
|
||||
Attributes:
|
||||
|
@ -30,10 +33,16 @@ class FileSystemStore(DataStore):
|
|||
sink (FileSystemSink): FileSystemSink
|
||||
|
||||
"""
|
||||
def __init__(self, stix_dir, bundlify=False):
|
||||
def __init__(self, stix_dir, allow_custom=None, bundlify=False):
|
||||
if allow_custom is None:
|
||||
allow_custom_source = True
|
||||
allow_custom_sink = False
|
||||
else:
|
||||
allow_custom_sink = allow_custom_source = allow_custom
|
||||
|
||||
super(FileSystemStore, self).__init__(
|
||||
source=FileSystemSource(stix_dir=stix_dir),
|
||||
sink=FileSystemSink(stix_dir=stix_dir, bundlify=bundlify)
|
||||
source=FileSystemSource(stix_dir=stix_dir, allow_custom=allow_custom_source),
|
||||
sink=FileSystemSink(stix_dir=stix_dir, allow_custom=allow_custom_sink, bundlify=bundlify)
|
||||
)
|
||||
|
||||
|
||||
|
@ -46,13 +55,16 @@ class FileSystemSink(DataSink):
|
|||
|
||||
Args:
|
||||
stix_dir (str): path to directory of STIX objects.
|
||||
allow_custom (bool): Whether to allow custom STIX content to be
|
||||
added to the FileSystemSource. Default: False
|
||||
bundlify (bool): Whether to wrap objects in bundles when saving them.
|
||||
Default: False.
|
||||
|
||||
"""
|
||||
def __init__(self, stix_dir, bundlify=False):
|
||||
def __init__(self, stix_dir, allow_custom=False, bundlify=False):
|
||||
super(FileSystemSink, self).__init__()
|
||||
self._stix_dir = os.path.abspath(stix_dir)
|
||||
self.allow_custom = allow_custom
|
||||
self.bundlify = bundlify
|
||||
|
||||
if not os.path.exists(self._stix_dir):
|
||||
|
@ -71,20 +83,18 @@ class FileSystemSink(DataSink):
|
|||
os.makedirs(os.path.dirname(path))
|
||||
|
||||
if self.bundlify:
|
||||
stix_obj = Bundle(stix_obj)
|
||||
stix_obj = Bundle(stix_obj, allow_custom=self.allow_custom)
|
||||
|
||||
with open(path, "w") as f:
|
||||
f.write(str(stix_obj))
|
||||
|
||||
def add(self, stix_data=None, allow_custom=False, version=None):
|
||||
def add(self, stix_data=None, version=None):
|
||||
"""Add STIX objects to file directory.
|
||||
|
||||
Args:
|
||||
stix_data (STIX object OR dict OR str OR list): valid STIX 2.0 content
|
||||
in a STIX object (or list of), dict (or list of), or a STIX 2.0
|
||||
json encoded string.
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -100,24 +110,24 @@ class FileSystemSink(DataSink):
|
|||
self._check_path_and_write(stix_data)
|
||||
|
||||
elif isinstance(stix_data, (str, dict)):
|
||||
stix_data = parse(stix_data, allow_custom=allow_custom, version=version)
|
||||
stix_data = parse(stix_data, allow_custom=self.allow_custom, version=version)
|
||||
if stix_data["type"] == "bundle":
|
||||
# extract STIX objects
|
||||
for stix_obj in stix_data.get("objects", []):
|
||||
self.add(stix_obj, allow_custom=allow_custom, version=version)
|
||||
self.add(stix_obj, version=version)
|
||||
else:
|
||||
# adding json-formatted STIX
|
||||
self._check_path_and_write(stix_data)
|
||||
self._check_path_and_write(stix_data,)
|
||||
|
||||
elif isinstance(stix_data, Bundle):
|
||||
# recursively add individual STIX objects
|
||||
for stix_obj in stix_data.get("objects", []):
|
||||
self.add(stix_obj, allow_custom=allow_custom, version=version)
|
||||
self.add(stix_obj, version=version)
|
||||
|
||||
elif isinstance(stix_data, list):
|
||||
# recursively add individual STIX objects
|
||||
for stix_obj in stix_data:
|
||||
self.add(stix_obj, allow_custom=allow_custom, version=version)
|
||||
self.add(stix_obj, version=version)
|
||||
|
||||
else:
|
||||
raise TypeError("stix_data must be a STIX object (or list of), "
|
||||
|
@ -134,11 +144,14 @@ class FileSystemSource(DataSource):
|
|||
|
||||
Args:
|
||||
stix_dir (str): path to directory of STIX objects
|
||||
allow_custom (bool): Whether to allow custom STIX content to be
|
||||
added to the FileSystemSink. Default: True
|
||||
|
||||
"""
|
||||
def __init__(self, stix_dir):
|
||||
def __init__(self, stix_dir, allow_custom=True):
|
||||
super(FileSystemSource, self).__init__()
|
||||
self._stix_dir = os.path.abspath(stix_dir)
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
if not os.path.exists(self._stix_dir):
|
||||
raise ValueError("directory path for STIX data does not exist: %s" % self._stix_dir)
|
||||
|
@ -147,15 +160,13 @@ class FileSystemSource(DataSource):
|
|||
def stix_dir(self):
|
||||
return self._stix_dir
|
||||
|
||||
def get(self, stix_id, allow_custom=False, version=None, _composite_filters=None):
|
||||
def get(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from file directory via STIX ID.
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -167,7 +178,7 @@ class FileSystemSource(DataSource):
|
|||
"""
|
||||
query = [Filter("id", "=", stix_id)]
|
||||
|
||||
all_data = self.query(query=query, allow_custom=allow_custom, version=version, _composite_filters=_composite_filters)
|
||||
all_data = self.query(query=query, version=version, _composite_filters=_composite_filters)
|
||||
|
||||
if all_data:
|
||||
stix_obj = sorted(all_data, key=lambda k: k['modified'])[0]
|
||||
|
@ -176,7 +187,7 @@ class FileSystemSource(DataSource):
|
|||
|
||||
return stix_obj
|
||||
|
||||
def all_versions(self, stix_id, allow_custom=False, version=None, _composite_filters=None):
|
||||
def all_versions(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from file directory via STIX ID, all versions.
|
||||
|
||||
Note: Since FileSystem sources/sinks don't handle multiple versions
|
||||
|
@ -184,10 +195,8 @@ class FileSystemSource(DataSource):
|
|||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -197,9 +206,9 @@ class FileSystemSource(DataSource):
|
|||
a python STIX objects and then returned
|
||||
|
||||
"""
|
||||
return [self.get(stix_id=stix_id, allow_custom=allow_custom, version=version, _composite_filters=_composite_filters)]
|
||||
return [self.get(stix_id=stix_id, version=version, _composite_filters=_composite_filters)]
|
||||
|
||||
def query(self, query=None, allow_custom=False, version=None, _composite_filters=None):
|
||||
def query(self, query=None, version=None, _composite_filters=None):
|
||||
"""Search and retrieve STIX objects based on the complete query.
|
||||
|
||||
A "complete query" includes the filters from the query, the filters
|
||||
|
@ -208,10 +217,8 @@ class FileSystemSource(DataSource):
|
|||
|
||||
Args:
|
||||
query (list): list of filters to search on
|
||||
_composite_filters (set): set of filters passed from the
|
||||
_composite_filters (FilterSet): collection of filters passed from the
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -221,22 +228,16 @@ class FileSystemSource(DataSource):
|
|||
parsed into a python STIX objects and then returned.
|
||||
|
||||
"""
|
||||
|
||||
all_data = []
|
||||
|
||||
if query is None:
|
||||
query = set()
|
||||
else:
|
||||
if not isinstance(query, list):
|
||||
# make sure dont make set from a Filter object,
|
||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
||||
query = [query]
|
||||
query = set(query)
|
||||
query = FilterSet(query)
|
||||
|
||||
# combine all query filters
|
||||
if self.filters:
|
||||
query.update(self.filters)
|
||||
query.add(self.filters)
|
||||
if _composite_filters:
|
||||
query.update(_composite_filters)
|
||||
query.add(_composite_filters)
|
||||
|
||||
# extract any filters that are for "type" or "id" , as we can then do
|
||||
# filtering before reading in the STIX objects. A STIX 'type' filter
|
||||
|
@ -293,18 +294,33 @@ class FileSystemSource(DataSource):
|
|||
for path in include_paths:
|
||||
for root, dirs, files in os.walk(path):
|
||||
for file_ in files:
|
||||
if not file_.endswith(".json"):
|
||||
# skip non '.json' files as more likely to be random non-STIX files
|
||||
continue
|
||||
|
||||
if not id_ or id_ == file_.split(".")[0]:
|
||||
# have to load into memory regardless to evaluate other filters
|
||||
stix_obj = json.load(open(os.path.join(root, file_)))
|
||||
if stix_obj.get('type', '') == 'bundle':
|
||||
stix_obj = stix_obj['objects'][0]
|
||||
try:
|
||||
stix_obj = json.load(open(os.path.join(root, file_)))
|
||||
|
||||
if stix_obj["type"] == "bundle":
|
||||
stix_obj = stix_obj["objects"][0]
|
||||
|
||||
# naive STIX type checking
|
||||
stix_obj["type"]
|
||||
stix_obj["id"]
|
||||
|
||||
except (ValueError, KeyError): # likely not a JSON file
|
||||
raise TypeError("STIX JSON object at '{0}' could either not be parsed to "
|
||||
"JSON or was not valid STIX JSON".format(os.path.join(root, file_)))
|
||||
|
||||
# check against other filters, add if match
|
||||
all_data.extend(apply_common_filters([stix_obj], query))
|
||||
|
||||
all_data = deduplicate(all_data)
|
||||
|
||||
# parse python STIX objects from the STIX object dicts
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=allow_custom, version=version) for stix_obj_dict in all_data]
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=self.allow_custom, version=version) for stix_obj_dict in all_data]
|
||||
|
||||
return stix_objs
|
||||
|
||||
|
@ -320,8 +336,8 @@ class FileSystemSource(DataSource):
|
|||
search space of a FileSystemStore (or FileSystemSink).
|
||||
|
||||
"""
|
||||
file_filters = set()
|
||||
file_filters = []
|
||||
for filter_ in query:
|
||||
if filter_.property == "id" or filter_.property == "type":
|
||||
file_filters.add(filter_)
|
||||
file_filters.append(filter_)
|
||||
return file_filters
|
|
@ -4,6 +4,9 @@ Filters for Python STIX 2.0 DataSources, DataSinks, DataStores
|
|||
"""
|
||||
|
||||
import collections
|
||||
from datetime import datetime
|
||||
|
||||
from stix2.utils import format_datetime
|
||||
|
||||
"""Supported filter operations"""
|
||||
FILTER_OPS = ['=', '!=', 'in', '>', '<', '>=', '<=']
|
||||
|
@ -35,7 +38,11 @@ def _check_filter_components(prop, op, value):
|
|||
|
||||
if type(value) not in FILTER_VALUE_TYPES:
|
||||
# check filter value type is supported
|
||||
raise TypeError("Filter value type '%s' is not supported. The type must be a Python immutable type or dictionary" % type(value))
|
||||
raise TypeError("Filter value of '%s' is not supported. The type must be a Python immutable type or dictionary" % type(value))
|
||||
|
||||
if prop == "type" and "_" in value:
|
||||
# check filter where the property is type, value (type name) cannot have underscores
|
||||
raise ValueError("Filter for property 'type' cannot have its value '%s' include underscores" % value)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -62,6 +69,10 @@ class Filter(collections.namedtuple("Filter", ['property', 'op', 'value'])):
|
|||
if isinstance(value, list):
|
||||
value = tuple(value)
|
||||
|
||||
if isinstance(value, datetime):
|
||||
# if value is a datetime obj, convert to str
|
||||
value = format_datetime(value)
|
||||
|
||||
_check_filter_components(prop, op, value)
|
||||
|
||||
self = super(Filter, cls).__new__(cls, prop, op, value)
|
||||
|
@ -77,6 +88,12 @@ class Filter(collections.namedtuple("Filter", ['property', 'op', 'value'])):
|
|||
True if property matches the filter,
|
||||
False otherwise.
|
||||
"""
|
||||
if isinstance(stix_obj_property, datetime):
|
||||
# if a datetime obj, convert to str format before comparison
|
||||
# NOTE: this check seems like it should be done upstream
|
||||
# but will put here for now
|
||||
stix_obj_property = format_datetime(stix_obj_property)
|
||||
|
||||
if self.op == "=":
|
||||
return stix_obj_property == self.value
|
||||
elif self.op == "!=":
|
||||
|
@ -148,19 +165,94 @@ def _check_filter(filter_, stix_obj):
|
|||
# Check embedded properties, from e.g. granular_markings or external_references
|
||||
sub_property = filter_.property.split(".", 1)[1]
|
||||
sub_filter = filter_._replace(property=sub_property)
|
||||
|
||||
if isinstance(stix_obj[prop], list):
|
||||
for elem in stix_obj[prop]:
|
||||
if _check_filter(sub_filter, elem) is True:
|
||||
return True
|
||||
return False
|
||||
|
||||
else:
|
||||
return _check_filter(sub_filter, stix_obj[prop])
|
||||
|
||||
elif isinstance(stix_obj[prop], list):
|
||||
# Check each item in list property to see if it matches
|
||||
for elem in stix_obj[prop]:
|
||||
if filter_._check_property(elem) is True:
|
||||
return True
|
||||
return False
|
||||
|
||||
else:
|
||||
# Check if property matches
|
||||
return filter_._check_property(stix_obj[prop])
|
||||
|
||||
|
||||
class FilterSet(object):
|
||||
"""Internal STIX2 class to facilitate the grouping of Filters
|
||||
into sets. The primary motivation for this class came from the problem
|
||||
that Filters that had a dict as a value could not be added to a Python
|
||||
set as dicts are not hashable. Thus this class provides set functionality
|
||||
but internally stores filters in a list.
|
||||
"""
|
||||
|
||||
def __init__(self, filters=None):
|
||||
"""
|
||||
Args:
|
||||
filters: see FilterSet.add()
|
||||
"""
|
||||
self._filters = []
|
||||
if filters:
|
||||
self.add(filters)
|
||||
|
||||
def __iter__(self):
|
||||
"""Provide iteration functionality of FilterSet."""
|
||||
for f in self._filters:
|
||||
yield f
|
||||
|
||||
def __len__(self):
|
||||
"""Provide built-in len() utility of FilterSet."""
|
||||
return len(self._filters)
|
||||
|
||||
def add(self, filters=None):
|
||||
"""Add a Filter, FilterSet, or list of Filters to the FilterSet.
|
||||
|
||||
Operates like set, only adding unique stix2.Filters to the FilterSet
|
||||
|
||||
NOTE: method designed to be very accomodating (i.e. even accepting filters=None)
|
||||
as it allows for blind calls (very useful in DataStore)
|
||||
|
||||
Args:
|
||||
filters: stix2.Filter OR list of stix2.Filter OR stix2.FilterSet
|
||||
|
||||
"""
|
||||
if not filters:
|
||||
# so add() can be called blindly, useful for
|
||||
# DataStore/Environment usage of filter operations
|
||||
return
|
||||
|
||||
if not isinstance(filters, (FilterSet, list)):
|
||||
filters = [filters]
|
||||
|
||||
for f in filters:
|
||||
if f not in self._filters:
|
||||
self._filters.append(f)
|
||||
|
||||
def remove(self, filters=None):
|
||||
"""Remove a Filter, list of Filters, or FilterSet from the FilterSet.
|
||||
|
||||
NOTE: method designed to be very accomodating (i.e. even accepting filters=None)
|
||||
as it allows for blind calls (very useful in DataStore)
|
||||
|
||||
Args:
|
||||
filters: stix2.Filter OR list of stix2.Filter or stix2.FilterSet
|
||||
"""
|
||||
if not filters:
|
||||
# so remove() can be called blindly, useful for
|
||||
# DataStore/Environemnt usage of filter ops
|
||||
return
|
||||
|
||||
if not isinstance(filters, (FilterSet, list)):
|
||||
filters = [filters]
|
||||
|
||||
for f in filters:
|
||||
self._filters.remove(f)
|
|
@ -1,9 +1,6 @@
|
|||
"""
|
||||
Python STIX 2.0 Memory Source/Sink
|
||||
|
||||
TODO:
|
||||
Run through tests again, lot of changes.
|
||||
|
||||
TODO:
|
||||
Use deduplicate() calls only when memory corpus is dirty (been added to)
|
||||
can save a lot of time for successive queries
|
||||
|
@ -20,11 +17,11 @@ import os
|
|||
|
||||
from stix2.base import _STIXBase
|
||||
from stix2.core import Bundle, parse
|
||||
from stix2.sources import DataSink, DataSource, DataStore
|
||||
from stix2.sources.filters import Filter, apply_common_filters
|
||||
from stix2.datastore import DataSink, DataSource, DataStoreMixin
|
||||
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||
|
||||
|
||||
def _add(store, stix_data=None, allow_custom=False, version=None):
|
||||
def _add(store, stix_data=None, version=None):
|
||||
"""Add STIX objects to MemoryStore/Sink.
|
||||
|
||||
Adds STIX objects to an in-memory dictionary for fast lookup.
|
||||
|
@ -32,8 +29,6 @@ def _add(store, stix_data=None, allow_custom=False, version=None):
|
|||
|
||||
Args:
|
||||
stix_data (list OR dict OR STIX object): STIX objects to be added
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -46,31 +41,22 @@ def _add(store, stix_data=None, allow_custom=False, version=None):
|
|||
if stix_data["type"] == "bundle":
|
||||
# adding a json bundle - so just grab STIX objects
|
||||
for stix_obj in stix_data.get("objects", []):
|
||||
_add(store, stix_obj, allow_custom=allow_custom, version=version)
|
||||
_add(store, stix_obj, version=version)
|
||||
else:
|
||||
# adding a json STIX object
|
||||
store._data[stix_data["id"]] = stix_data
|
||||
|
||||
elif isinstance(stix_data, str):
|
||||
# adding json encoded string of STIX content
|
||||
stix_data = parse(stix_data, allow_custom=allow_custom, version=version)
|
||||
if stix_data["type"] == "bundle":
|
||||
# recurse on each STIX object in bundle
|
||||
for stix_obj in stix_data.get("objects", []):
|
||||
_add(store, stix_obj, allow_custom=allow_custom, version=version)
|
||||
else:
|
||||
_add(store, stix_data, allow_custom=allow_custom, version=version)
|
||||
|
||||
elif isinstance(stix_data, list):
|
||||
# STIX objects are in a list- recurse on each object
|
||||
for stix_obj in stix_data:
|
||||
_add(store, stix_obj, allow_custom=allow_custom, version=version)
|
||||
_add(store, stix_obj, version=version)
|
||||
|
||||
else:
|
||||
raise TypeError("stix_data must be a STIX object (or list of), JSON formatted STIX (or list of), or a JSON formatted STIX bundle")
|
||||
raise TypeError("stix_data expected to be a python-stix2 object (or list of), JSON formatted STIX (or list of),"
|
||||
" or a JSON formatted STIX bundle. stix_data was of type: " + str(type(stix_data)))
|
||||
|
||||
|
||||
class MemoryStore(DataStore):
|
||||
class MemoryStore(DataStoreMixin):
|
||||
"""Interface to an in-memory dictionary of STIX objects.
|
||||
|
||||
MemoryStore is a wrapper around a paired MemorySink and MemorySource.
|
||||
|
@ -81,8 +67,9 @@ class MemoryStore(DataStore):
|
|||
|
||||
Args:
|
||||
stix_data (list OR dict OR STIX object): STIX content to be added
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
allow_custom (bool): whether to allow custom STIX content.
|
||||
Only applied when export/input functions called, i.e.
|
||||
load_from_file() and save_to_file(). Defaults to True.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -92,11 +79,11 @@ class MemoryStore(DataStore):
|
|||
sink (MemorySink): MemorySink
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=False, version=None):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None):
|
||||
self._data = {}
|
||||
|
||||
if stix_data:
|
||||
_add(self, stix_data, allow_custom=allow_custom, version=version)
|
||||
_add(self, stix_data, version=version)
|
||||
|
||||
super(MemoryStore, self).__init__(
|
||||
source=MemorySource(stix_data=self._data, allow_custom=allow_custom, version=version, _store=True),
|
||||
|
@ -109,8 +96,6 @@ class MemoryStore(DataStore):
|
|||
|
||||
Args:
|
||||
file_path (str): file path to write STIX data to
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
|
||||
"""
|
||||
return self.sink.save_to_file(*args, **kwargs)
|
||||
|
@ -123,8 +108,6 @@ class MemoryStore(DataStore):
|
|||
|
||||
Args:
|
||||
file_path (str): file path to load STIX data from
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
|
@ -141,37 +124,39 @@ class MemorySink(DataSink):
|
|||
Args:
|
||||
stix_data (dict OR list): valid STIX 2.0 content in
|
||||
bundle or a list.
|
||||
_store (bool): if the MemorySink is a part of a DataStore,
|
||||
_store (bool): whether the MemorySink is a part of a MemoryStore,
|
||||
in which case "stix_data" is a direct reference to
|
||||
shared memory with DataSource. Not user supplied
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
allow_custom (bool): whether to allow custom objects/properties
|
||||
when exporting STIX content to file.
|
||||
Default: True.
|
||||
|
||||
Attributes:
|
||||
_data (dict): the in-memory dict that holds STIX objects.
|
||||
If apart of a MemoryStore, dict is shared between with
|
||||
a MemorySource
|
||||
If part of a MemoryStore, the dict is shared with a MemorySource
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=False, version=None, _store=False):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None, _store=False):
|
||||
super(MemorySink, self).__init__()
|
||||
self._data = {}
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
if _store:
|
||||
self._data = stix_data
|
||||
elif stix_data:
|
||||
_add(self, stix_data, allow_custom=allow_custom, version=version)
|
||||
_add(self, stix_data, version=version)
|
||||
|
||||
def add(self, stix_data, allow_custom=False, version=None):
|
||||
_add(self, stix_data, allow_custom=allow_custom, version=version)
|
||||
def add(self, stix_data, version=None):
|
||||
_add(self, stix_data, version=version)
|
||||
add.__doc__ = _add.__doc__
|
||||
|
||||
def save_to_file(self, file_path, allow_custom=False):
|
||||
def save_to_file(self, file_path):
|
||||
file_path = os.path.abspath(file_path)
|
||||
|
||||
if not os.path.exists(os.path.dirname(file_path)):
|
||||
os.makedirs(os.path.dirname(file_path))
|
||||
with open(file_path, "w") as f:
|
||||
f.write(str(Bundle(list(self._data.values()), allow_custom=allow_custom)))
|
||||
f.write(str(Bundle(list(self._data.values()), allow_custom=self.allow_custom)))
|
||||
save_to_file.__doc__ = MemoryStore.save_to_file.__doc__
|
||||
|
||||
|
||||
|
@ -185,33 +170,34 @@ class MemorySource(DataSource):
|
|||
Args:
|
||||
stix_data (dict OR list OR STIX object): valid STIX 2.0 content in
|
||||
bundle or list.
|
||||
_store (bool): if the MemorySource is a part of a DataStore,
|
||||
_store (bool): if the MemorySource is a part of a MemoryStore,
|
||||
in which case "stix_data" is a direct reference to shared
|
||||
memory with DataSink. Not user supplied
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
allow_custom (bool): whether to allow custom objects/properties
|
||||
when importing STIX content from file.
|
||||
Default: True.
|
||||
|
||||
Attributes:
|
||||
_data (dict): the in-memory dict that holds STIX objects.
|
||||
If apart of a MemoryStore, dict is shared between with
|
||||
a MemorySink
|
||||
If part of a MemoryStore, the dict is shared with a MemorySink
|
||||
|
||||
"""
|
||||
def __init__(self, stix_data=None, allow_custom=False, version=None, _store=False):
|
||||
def __init__(self, stix_data=None, allow_custom=True, version=None, _store=False):
|
||||
super(MemorySource, self).__init__()
|
||||
self._data = {}
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
if _store:
|
||||
self._data = stix_data
|
||||
elif stix_data:
|
||||
_add(self, stix_data, allow_custom=allow_custom, version=version)
|
||||
_add(self, stix_data, version=version)
|
||||
|
||||
def get(self, stix_id, _composite_filters=None):
|
||||
"""Retrieve STIX object from in-memory dict via STIX ID.
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
|
||||
Returns:
|
||||
|
@ -250,7 +236,7 @@ class MemorySource(DataSource):
|
|||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX 2 object to retrieve.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
|
||||
Returns:
|
||||
|
@ -260,6 +246,7 @@ class MemorySource(DataSource):
|
|||
is returned in the same form as it as added
|
||||
|
||||
"""
|
||||
|
||||
return [self.get(stix_id=stix_id, _composite_filters=_composite_filters)]
|
||||
|
||||
def query(self, query=None, _composite_filters=None):
|
||||
|
@ -271,7 +258,7 @@ class MemorySource(DataSource):
|
|||
|
||||
Args:
|
||||
query (list): list of filters to search on
|
||||
_composite_filters (set): set of filters passed from the
|
||||
_composite_filters (FilterSet): collection of filters passed from the
|
||||
CompositeDataSource, not user supplied
|
||||
|
||||
Returns:
|
||||
|
@ -281,28 +268,25 @@ class MemorySource(DataSource):
|
|||
is returned in the same form as it as added.
|
||||
|
||||
"""
|
||||
if query is None:
|
||||
query = set()
|
||||
else:
|
||||
if not isinstance(query, list):
|
||||
# make sure don't make set from a Filter object,
|
||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
||||
query = [query]
|
||||
query = set(query)
|
||||
query = FilterSet(query)
|
||||
|
||||
# combine all query filters
|
||||
if self.filters:
|
||||
query.update(self.filters)
|
||||
query.add(self.filters)
|
||||
if _composite_filters:
|
||||
query.update(_composite_filters)
|
||||
query.add(_composite_filters)
|
||||
|
||||
# Apply STIX common property filters.
|
||||
all_data = list(apply_common_filters(self._data.values(), query))
|
||||
|
||||
return all_data
|
||||
|
||||
def load_from_file(self, file_path, allow_custom=False, version=None):
|
||||
file_path = os.path.abspath(file_path)
|
||||
stix_data = json.load(open(file_path, "r"))
|
||||
_add(self, stix_data, allow_custom=allow_custom, version=version)
|
||||
def load_from_file(self, file_path, version=None):
|
||||
stix_data = json.load(open(os.path.abspath(file_path), "r"))
|
||||
|
||||
if stix_data["type"] == "bundle":
|
||||
for stix_obj in stix_data["objects"]:
|
||||
_add(self, stix_data=parse(stix_obj, allow_custom=self.allow_custom, version=stix_data["spec_version"]))
|
||||
else:
|
||||
_add(self, stix_data=parse(stix_data, allow_custom=self.allow_custom, version=version))
|
||||
load_from_file.__doc__ = MemoryStore.load_from_file.__doc__
|
|
@ -0,0 +1,319 @@
|
|||
"""
|
||||
Python STIX 2.x TAXIICollectionStore
|
||||
"""
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from stix2.base import _STIXBase
|
||||
from stix2.core import Bundle, parse
|
||||
from stix2.datastore import (DataSink, DataSource, DataSourceError,
|
||||
DataStoreMixin)
|
||||
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||
from stix2.utils import deduplicate
|
||||
|
||||
try:
|
||||
from taxii2client import ValidationError
|
||||
_taxii2_client = True
|
||||
except ImportError:
|
||||
_taxii2_client = False
|
||||
|
||||
|
||||
TAXII_FILTERS = ['added_after', 'id', 'type', 'version']
|
||||
|
||||
|
||||
class TAXIICollectionStore(DataStoreMixin):
|
||||
"""Provides an interface to a local/remote TAXII Collection
|
||||
of STIX data. TAXIICollectionStore is a wrapper
|
||||
around a paired TAXIICollectionSink and TAXIICollectionSource.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII Collection instance
|
||||
allow_custom (bool): whether to allow custom STIX content to be
|
||||
pushed/retrieved. Defaults to True for TAXIICollectionSource
|
||||
side(retrieving data) and False for TAXIICollectionSink
|
||||
side(pushing data). However, when parameter is supplied, it will
|
||||
be applied to both TAXIICollectionSource/Sink.
|
||||
|
||||
"""
|
||||
def __init__(self, collection, allow_custom=None):
|
||||
if allow_custom is None:
|
||||
allow_custom_source = True
|
||||
allow_custom_sink = False
|
||||
else:
|
||||
allow_custom_sink = allow_custom_source = allow_custom
|
||||
|
||||
super(TAXIICollectionStore, self).__init__(
|
||||
source=TAXIICollectionSource(collection, allow_custom=allow_custom_source),
|
||||
sink=TAXIICollectionSink(collection, allow_custom=allow_custom_sink)
|
||||
)
|
||||
|
||||
|
||||
class TAXIICollectionSink(DataSink):
|
||||
"""Provides an interface for pushing STIX objects to a local/remote
|
||||
TAXII Collection endpoint.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII2 Collection instance
|
||||
allow_custom (bool): Whether to allow custom STIX content to be
|
||||
added to the TAXIICollectionSink. Default: False
|
||||
|
||||
"""
|
||||
def __init__(self, collection, allow_custom=False):
|
||||
super(TAXIICollectionSink, self).__init__()
|
||||
if not _taxii2_client:
|
||||
raise ImportError("taxii2client library is required for usage of TAXIICollectionSink")
|
||||
|
||||
try:
|
||||
if collection.can_write:
|
||||
self.collection = collection
|
||||
else:
|
||||
raise DataSourceError("The TAXII Collection object provided does not have write access"
|
||||
" to the underlying linked Collection resource")
|
||||
|
||||
except (HTTPError, ValidationError) as e:
|
||||
raise DataSourceError("The underlying TAXII Collection resource defined in the supplied TAXII"
|
||||
" Collection object provided could not be reached. Receved error:", e)
|
||||
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
def add(self, stix_data, version=None):
|
||||
"""Add/push STIX content to TAXII Collection endpoint
|
||||
|
||||
Args:
|
||||
stix_data (STIX object OR dict OR str OR list): valid STIX 2.0 content
|
||||
in a STIX object (or Bundle), STIX onject dict (or Bundle dict), or a STIX 2.0
|
||||
json encoded string, or list of any of the following
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
"""
|
||||
if isinstance(stix_data, _STIXBase):
|
||||
# adding python STIX object
|
||||
if stix_data["type"] == "bundle":
|
||||
bundle = stix_data.serialize(encoding="utf-8")
|
||||
else:
|
||||
bundle = Bundle(stix_data, allow_custom=self.allow_custom).serialize(encoding="utf-8")
|
||||
|
||||
elif isinstance(stix_data, dict):
|
||||
# adding python dict (of either Bundle or STIX obj)
|
||||
if stix_data["type"] == "bundle":
|
||||
bundle = parse(stix_data, allow_custom=self.allow_custom, version=version).serialize(encoding="utf-8")
|
||||
else:
|
||||
bundle = Bundle(stix_data, allow_custom=self.allow_custom).serialize(encoding="utf-8")
|
||||
|
||||
elif isinstance(stix_data, list):
|
||||
# adding list of something - recurse on each
|
||||
for obj in stix_data:
|
||||
self.add(obj, version=version)
|
||||
return
|
||||
|
||||
elif isinstance(stix_data, str):
|
||||
# adding json encoded string of STIX content
|
||||
stix_data = parse(stix_data, allow_custom=self.allow_custom, version=version)
|
||||
if stix_data["type"] == "bundle":
|
||||
bundle = stix_data.serialize(encoding="utf-8")
|
||||
else:
|
||||
bundle = Bundle(stix_data, allow_custom=self.allow_custom).serialize(encoding="utf-8")
|
||||
|
||||
else:
|
||||
raise TypeError("stix_data must be as STIX object(or list of),json formatted STIX (or list of), or a json formatted STIX bundle")
|
||||
|
||||
self.collection.add_objects(bundle)
|
||||
|
||||
|
||||
class TAXIICollectionSource(DataSource):
|
||||
"""Provides an interface for searching/retrieving STIX objects
|
||||
from a local/remote TAXII Collection endpoint.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII Collection instance
|
||||
allow_custom (bool): Whether to allow custom STIX content to be
|
||||
added to the FileSystemSink. Default: True
|
||||
|
||||
"""
|
||||
def __init__(self, collection, allow_custom=True):
|
||||
super(TAXIICollectionSource, self).__init__()
|
||||
if not _taxii2_client:
|
||||
raise ImportError("taxii2client library is required for usage of TAXIICollectionSource")
|
||||
|
||||
try:
|
||||
if collection.can_read:
|
||||
self.collection = collection
|
||||
else:
|
||||
raise DataSourceError("The TAXII Collection object provided does not have read access"
|
||||
" to the underlying linked Collection resource")
|
||||
|
||||
except (HTTPError, ValidationError) as e:
|
||||
raise DataSourceError("The underlying TAXII Collection resource defined in the supplied TAXII"
|
||||
" Collection object provided could not be reached. Recieved error:", e)
|
||||
|
||||
self.allow_custom = allow_custom
|
||||
|
||||
def get(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote STIX Collection
|
||||
endpoint.
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(STIX object): STIX object that has the supplied STIX ID.
|
||||
The STIX object is received from TAXII has dict, parsed into
|
||||
a python STIX object and then returned
|
||||
|
||||
"""
|
||||
# combine all query filters
|
||||
query = FilterSet()
|
||||
|
||||
if self.filters:
|
||||
query.add(self.filters)
|
||||
if _composite_filters:
|
||||
query.add(_composite_filters)
|
||||
|
||||
# dont extract TAXII filters from query (to send to TAXII endpoint)
|
||||
# as directly retrieveing a STIX object by ID
|
||||
try:
|
||||
stix_objs = self.collection.get_object(stix_id)["objects"]
|
||||
stix_obj = list(apply_common_filters(stix_objs, query))
|
||||
|
||||
except HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
# if resource not found or access is denied from TAXII server, return None
|
||||
stix_obj = []
|
||||
else:
|
||||
raise DataSourceError("TAXII Collection resource returned error", e)
|
||||
|
||||
if len(stix_obj):
|
||||
stix_obj = parse(stix_obj[0], allow_custom=self.allow_custom, version=version)
|
||||
if stix_obj.id != stix_id:
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
stix_obj = None
|
||||
else:
|
||||
stix_obj = None
|
||||
|
||||
return stix_obj
|
||||
|
||||
def all_versions(self, stix_id, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote TAXII Collection
|
||||
endpoint, all versions of it
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||
_composite_filters (FilterSet): collection of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(see query() as all_versions() is just a wrapper)
|
||||
|
||||
"""
|
||||
# make query in TAXII query format since 'id' is TAXII field
|
||||
query = [
|
||||
Filter("id", "=", stix_id),
|
||||
Filter("version", "=", "all")
|
||||
]
|
||||
|
||||
all_data = self.query(query=query, _composite_filters=_composite_filters)
|
||||
|
||||
# parse STIX objects from TAXII returned json
|
||||
all_data = [parse(stix_obj, allow_custom=self.allow_custom, version=version) for stix_obj in all_data]
|
||||
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
all_data_clean = [stix_obj for stix_obj in all_data if stix_obj.id == stix_id]
|
||||
|
||||
return all_data_clean
|
||||
|
||||
def query(self, query=None, version=None, _composite_filters=None):
|
||||
"""Search and retreive STIX objects based on the complete query
|
||||
|
||||
A "complete query" includes the filters from the query, the filters
|
||||
attached to MemorySource, and any filters passed from a
|
||||
CompositeDataSource (i.e. _composite_filters)
|
||||
|
||||
Args:
|
||||
query (list): list of filters to search on
|
||||
_composite_filters (FilterSet): collection of filters passed from the
|
||||
CompositeDataSource, not user supplied
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(list): list of STIX objects that matches the supplied
|
||||
query. The STIX objects are received from TAXII as dicts,
|
||||
parsed into python STIX objects and then returned.
|
||||
|
||||
"""
|
||||
query = FilterSet(query)
|
||||
|
||||
# combine all query filters
|
||||
if self.filters:
|
||||
query.add(self.filters)
|
||||
if _composite_filters:
|
||||
query.add(_composite_filters)
|
||||
|
||||
# parse taxii query params (that can be applied remotely)
|
||||
taxii_filters = self._parse_taxii_filters(query)
|
||||
|
||||
# taxii2client requires query params as keywords
|
||||
taxii_filters_dict = dict((f.property, f.value) for f in taxii_filters)
|
||||
|
||||
# query TAXII collection
|
||||
try:
|
||||
all_data = self.collection.get_objects(**taxii_filters_dict)["objects"]
|
||||
|
||||
# deduplicate data (before filtering as reduces wasted filtering)
|
||||
all_data = deduplicate(all_data)
|
||||
|
||||
# apply local (CompositeDataSource, TAXIICollectionSource and query) filters
|
||||
query.remove(taxii_filters)
|
||||
all_data = list(apply_common_filters(all_data, query))
|
||||
|
||||
except HTTPError as e:
|
||||
# if resources not found or access is denied from TAXII server, return empty list
|
||||
if e.response.status_code == 404:
|
||||
raise DataSourceError("The requested STIX objects for the TAXII Collection resource defined in"
|
||||
" the supplied TAXII Collection object are either not found or access is"
|
||||
" denied. Received error: ", e)
|
||||
|
||||
# parse python STIX objects from the STIX object dicts
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=self.allow_custom, version=version) for stix_obj_dict in all_data]
|
||||
|
||||
return stix_objs
|
||||
|
||||
def _parse_taxii_filters(self, query):
|
||||
"""Parse out TAXII filters that the TAXII server can filter on
|
||||
|
||||
Does not put in TAXII spec format as the TAXII2Client (that we use)
|
||||
does this for us.
|
||||
|
||||
Notes:
|
||||
Currently, the TAXII2Client can handle TAXII filters where the
|
||||
filter value is list, as both a comma-seperated string or python list
|
||||
|
||||
For instance - "?match[type]=indicator,sighting" can be in a
|
||||
filter in any of these formats:
|
||||
|
||||
Filter("type", "<any op>", "indicator,sighting")
|
||||
|
||||
Filter("type", "<any op>", ["indicator", "sighting"])
|
||||
|
||||
|
||||
Args:
|
||||
query (list): list of filters to extract which ones are TAXII
|
||||
specific.
|
||||
|
||||
Returns:
|
||||
A list of TAXII filters that meet the TAXII filtering parameters.
|
||||
|
||||
"""
|
||||
taxii_filters = []
|
||||
|
||||
for filter_ in query:
|
||||
if filter_.property in TAXII_FILTERS:
|
||||
taxii_filters.append(filter_)
|
||||
|
||||
return taxii_filters
|
|
@ -1,7 +1,10 @@
|
|||
"""Python STIX 2.0 Environment API.
|
||||
"""
|
||||
|
||||
import copy
|
||||
|
||||
from .core import parse as _parse
|
||||
from .sources import CompositeDataSource, DataStore
|
||||
from .datastore import CompositeDataSource, DataStoreMixin
|
||||
|
||||
|
||||
class ObjectFactory(object):
|
||||
|
@ -30,19 +33,43 @@ class ObjectFactory(object):
|
|||
|
||||
self._defaults = {}
|
||||
if created_by_ref:
|
||||
self._defaults['created_by_ref'] = created_by_ref
|
||||
self.set_default_creator(created_by_ref)
|
||||
if created:
|
||||
self._defaults['created'] = created
|
||||
# If the user provides a default "created" time, we also want to use
|
||||
# that as the modified time.
|
||||
self._defaults['modified'] = created
|
||||
self.set_default_created(created)
|
||||
if external_references:
|
||||
self._defaults['external_references'] = external_references
|
||||
self.set_default_external_refs(external_references)
|
||||
if object_marking_refs:
|
||||
self._defaults['object_marking_refs'] = object_marking_refs
|
||||
self.set_default_object_marking_refs(object_marking_refs)
|
||||
self._list_append = list_append
|
||||
self._list_properties = ['external_references', 'object_marking_refs']
|
||||
|
||||
def set_default_creator(self, creator=None):
|
||||
"""Set default value for the `created_by_ref` property.
|
||||
|
||||
"""
|
||||
self._defaults['created_by_ref'] = creator
|
||||
|
||||
def set_default_created(self, created=None):
|
||||
"""Set default value for the `created` property.
|
||||
|
||||
"""
|
||||
self._defaults['created'] = created
|
||||
# If the user provides a default "created" time, we also want to use
|
||||
# that as the modified time.
|
||||
self._defaults['modified'] = created
|
||||
|
||||
def set_default_external_refs(self, external_references=None):
|
||||
"""Set default external references.
|
||||
|
||||
"""
|
||||
self._defaults['external_references'] = external_references
|
||||
|
||||
def set_default_object_marking_refs(self, object_marking_refs=None):
|
||||
"""Set default object markings.
|
||||
|
||||
"""
|
||||
self._defaults['object_marking_refs'] = object_marking_refs
|
||||
|
||||
def create(self, cls, **kwargs):
|
||||
"""Create a STIX object using object factory defaults.
|
||||
|
||||
|
@ -75,7 +102,7 @@ class ObjectFactory(object):
|
|||
return cls(**properties)
|
||||
|
||||
|
||||
class Environment(object):
|
||||
class Environment(DataStoreMixin):
|
||||
"""Abstract away some of the nasty details of working with STIX content.
|
||||
|
||||
Args:
|
||||
|
@ -86,6 +113,15 @@ class Environment(object):
|
|||
source (DataSource, optional): Source for retrieving STIX objects.
|
||||
sink (DataSink, optional): Destination for saving STIX objects.
|
||||
Invalid if `store` is also provided.
|
||||
|
||||
.. automethod:: get
|
||||
.. automethod:: all_versions
|
||||
.. automethod:: query
|
||||
.. automethod:: creator_of
|
||||
.. automethod:: relationships
|
||||
.. automethod:: related_to
|
||||
.. automethod:: add
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, factory=ObjectFactory(), store=None, source=None, sink=None):
|
||||
|
@ -105,25 +141,27 @@ class Environment(object):
|
|||
return self.factory.create(*args, **kwargs)
|
||||
create.__doc__ = ObjectFactory.create.__doc__
|
||||
|
||||
get = DataStore.__dict__['get']
|
||||
all_versions = DataStore.__dict__['all_versions']
|
||||
query = DataStore.__dict__['query']
|
||||
creator_of = DataStore.__dict__['creator_of']
|
||||
relationships = DataStore.__dict__['relationships']
|
||||
related_to = DataStore.__dict__['related_to']
|
||||
add = DataStore.__dict__['add']
|
||||
def set_default_creator(self, *args, **kwargs):
|
||||
return self.factory.set_default_creator(*args, **kwargs)
|
||||
set_default_creator.__doc__ = ObjectFactory.set_default_creator.__doc__
|
||||
|
||||
def set_default_created(self, *args, **kwargs):
|
||||
return self.factory.set_default_created(*args, **kwargs)
|
||||
set_default_created.__doc__ = ObjectFactory.set_default_created.__doc__
|
||||
|
||||
def set_default_external_refs(self, *args, **kwargs):
|
||||
return self.factory.set_default_external_refs(*args, **kwargs)
|
||||
set_default_external_refs.__doc__ = ObjectFactory.set_default_external_refs.__doc__
|
||||
|
||||
def set_default_object_marking_refs(self, *args, **kwargs):
|
||||
return self.factory.set_default_object_marking_refs(*args, **kwargs)
|
||||
set_default_object_marking_refs.__doc__ = ObjectFactory.set_default_object_marking_refs.__doc__
|
||||
|
||||
def add_filters(self, *args, **kwargs):
|
||||
try:
|
||||
return self.source.filters.update(*args, **kwargs)
|
||||
except AttributeError:
|
||||
raise AttributeError('Environment has no data source')
|
||||
return self.source.filters.add(*args, **kwargs)
|
||||
|
||||
def add_filter(self, *args, **kwargs):
|
||||
try:
|
||||
return self.source.filters.add(*args, **kwargs)
|
||||
except AttributeError:
|
||||
raise AttributeError('Environment has no data source')
|
||||
return self.source.filters.add(*args, **kwargs)
|
||||
|
||||
def parse(self, *args, **kwargs):
|
||||
return _parse(*args, **kwargs)
|
||||
|
|
|
@ -163,6 +163,13 @@ class ParseError(STIXError, ValueError):
|
|||
super(ParseError, self).__init__(msg)
|
||||
|
||||
|
||||
class CustomContentError(STIXError, ValueError):
|
||||
"""Custom STIX Content (SDO, Observable, Extension, etc.) detected."""
|
||||
|
||||
def __init__(self, msg):
|
||||
super(CustomContentError, self).__init__(msg)
|
||||
|
||||
|
||||
class InvalidSelectorError(STIXError, AssertionError):
|
||||
"""Granular Marking selector violation. The selector must resolve into an existing STIX object property."""
|
||||
|
||||
|
|
|
@ -116,9 +116,9 @@ def remove_markings(obj, marking, selectors):
|
|||
granular_markings = utils.compress_markings(granular_markings)
|
||||
|
||||
if granular_markings:
|
||||
return new_version(obj, granular_markings=granular_markings)
|
||||
return new_version(obj, granular_markings=granular_markings, allow_custom=True)
|
||||
else:
|
||||
return new_version(obj, granular_markings=None)
|
||||
return new_version(obj, granular_markings=None, allow_custom=True)
|
||||
|
||||
|
||||
def add_markings(obj, marking, selectors):
|
||||
|
@ -152,7 +152,7 @@ def add_markings(obj, marking, selectors):
|
|||
|
||||
granular_marking = utils.expand_markings(granular_marking)
|
||||
granular_marking = utils.compress_markings(granular_marking)
|
||||
return new_version(obj, granular_markings=granular_marking)
|
||||
return new_version(obj, granular_markings=granular_marking, allow_custom=True)
|
||||
|
||||
|
||||
def clear_markings(obj, selectors):
|
||||
|
@ -207,9 +207,9 @@ def clear_markings(obj, selectors):
|
|||
granular_markings = utils.compress_markings(granular_markings)
|
||||
|
||||
if granular_markings:
|
||||
return new_version(obj, granular_markings=granular_markings)
|
||||
return new_version(obj, granular_markings=granular_markings, allow_custom=True)
|
||||
else:
|
||||
return new_version(obj, granular_markings=None)
|
||||
return new_version(obj, granular_markings=None, allow_custom=True)
|
||||
|
||||
|
||||
def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=False):
|
||||
|
|
|
@ -37,7 +37,7 @@ def add_markings(obj, marking):
|
|||
|
||||
object_markings = set(obj.get("object_marking_refs", []) + marking)
|
||||
|
||||
return new_version(obj, object_marking_refs=list(object_markings))
|
||||
return new_version(obj, object_marking_refs=list(object_markings), allow_custom=True)
|
||||
|
||||
|
||||
def remove_markings(obj, marking):
|
||||
|
@ -69,9 +69,9 @@ def remove_markings(obj, marking):
|
|||
|
||||
new_markings = [x for x in object_markings if x not in marking]
|
||||
if new_markings:
|
||||
return new_version(obj, object_marking_refs=new_markings)
|
||||
return new_version(obj, object_marking_refs=new_markings, allow_custom=True)
|
||||
else:
|
||||
return new_version(obj, object_marking_refs=None)
|
||||
return new_version(obj, object_marking_refs=None, allow_custom=True)
|
||||
|
||||
|
||||
def set_markings(obj, marking):
|
||||
|
@ -103,7 +103,7 @@ def clear_markings(obj):
|
|||
A new version of the given SDO or SRO with object_marking_refs cleared.
|
||||
|
||||
"""
|
||||
return new_version(obj, object_marking_refs=None)
|
||||
return new_version(obj, object_marking_refs=None, allow_custom=True)
|
||||
|
||||
|
||||
def is_marked(obj, marking=None):
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
import base64
|
||||
import binascii
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from .utils import parse_into_datetime
|
||||
|
||||
|
||||
def escape_quotes_and_backslashes(s):
|
||||
return s.replace(u'\\', u'\\\\').replace(u"'", u"\\'")
|
||||
|
@ -24,10 +27,13 @@ class StringConstant(_Constant):
|
|||
|
||||
class TimestampConstant(_Constant):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
try:
|
||||
self.value = parse_into_datetime(value)
|
||||
except Exception:
|
||||
raise ValueError("must be a datetime object or timestamp string.")
|
||||
|
||||
def __str__(self):
|
||||
return "t'%s'" % escape_quotes_and_backslashes(self.value)
|
||||
return "t%s" % repr(self.value)
|
||||
|
||||
|
||||
class IntegerConstant(_Constant):
|
||||
|
@ -46,7 +52,7 @@ class FloatConstant(_Constant):
|
|||
try:
|
||||
self.value = float(value)
|
||||
except Exception:
|
||||
raise ValueError("must be an float.")
|
||||
raise ValueError("must be a float.")
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % self.value
|
||||
|
@ -56,24 +62,29 @@ class BooleanConstant(_Constant):
|
|||
def __init__(self, value):
|
||||
if isinstance(value, bool):
|
||||
self.value = value
|
||||
return
|
||||
|
||||
trues = ['true', 't']
|
||||
falses = ['false', 'f']
|
||||
try:
|
||||
if value.lower() in trues:
|
||||
self.value = True
|
||||
if value.lower() in falses:
|
||||
return
|
||||
elif value.lower() in falses:
|
||||
self.value = False
|
||||
return
|
||||
except AttributeError:
|
||||
if value == 1:
|
||||
self.value = True
|
||||
if value == 0:
|
||||
return
|
||||
elif value == 0:
|
||||
self.value = False
|
||||
return
|
||||
|
||||
raise ValueError("must be a boolean value.")
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % self.value
|
||||
return str(self.value).lower()
|
||||
|
||||
|
||||
_HASH_REGEX = {
|
||||
|
@ -132,20 +143,28 @@ class ListConstant(_Constant):
|
|||
self.value = values
|
||||
|
||||
def __str__(self):
|
||||
return "(" + ", ".join([("%s" % x) for x in self.value]) + ")"
|
||||
return "(" + ", ".join([("%s" % make_constant(x)) for x in self.value]) + ")"
|
||||
|
||||
|
||||
def make_constant(value):
|
||||
if isinstance(value, _Constant):
|
||||
return value
|
||||
|
||||
try:
|
||||
return parse_into_datetime(value)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if isinstance(value, str):
|
||||
return StringConstant(value)
|
||||
elif isinstance(value, bool):
|
||||
return BooleanConstant(value)
|
||||
elif isinstance(value, int):
|
||||
return IntegerConstant(value)
|
||||
elif isinstance(value, float):
|
||||
return FloatConstant(value)
|
||||
elif isinstance(value, list):
|
||||
return ListConstant(value)
|
||||
elif isinstance(value, bool):
|
||||
return BooleanConstant(value)
|
||||
else:
|
||||
raise ValueError("Unable to create a constant from %s" % value)
|
||||
|
||||
|
@ -210,15 +229,12 @@ class ObjectPath(object):
|
|||
|
||||
|
||||
class _PatternExpression(object):
|
||||
|
||||
@staticmethod
|
||||
def escape_quotes_and_backslashes(s):
|
||||
return s.replace(u'\\', u'\\\\').replace(u"'", u"\\'")
|
||||
pass
|
||||
|
||||
|
||||
class _ComparisonExpression(_PatternExpression):
|
||||
def __init__(self, operator, lhs, rhs, negated=False):
|
||||
if operator == "=" and isinstance(rhs, ListConstant):
|
||||
if operator == "=" and isinstance(rhs, (ListConstant, list)):
|
||||
self.operator = "IN"
|
||||
else:
|
||||
self.operator = operator
|
||||
|
@ -234,13 +250,6 @@ class _ComparisonExpression(_PatternExpression):
|
|||
self.root_type = self.lhs.object_type_name
|
||||
|
||||
def __str__(self):
|
||||
# if isinstance(self.rhs, list):
|
||||
# final_rhs = []
|
||||
# for r in self.rhs:
|
||||
# final_rhs.append("'" + self.escape_quotes_and_backslashes("%s" % r) + "'")
|
||||
# rhs_string = "(" + ", ".join(final_rhs) + ")"
|
||||
# else:
|
||||
# rhs_string = self.rhs
|
||||
if self.negated:
|
||||
return "%s NOT %s %s" % (self.lhs, self.operator, self.rhs)
|
||||
else:
|
||||
|
@ -383,7 +392,7 @@ class RepeatQualifier(_ExpressionQualifier):
|
|||
elif isinstance(times_to_repeat, int):
|
||||
self.times_to_repeat = IntegerConstant(times_to_repeat)
|
||||
else:
|
||||
raise ValueError("%s is not a valid argument for a Within Qualifier" % times_to_repeat)
|
||||
raise ValueError("%s is not a valid argument for a Repeat Qualifier" % times_to_repeat)
|
||||
|
||||
def __str__(self):
|
||||
return "REPEATS %s TIMES" % self.times_to_repeat
|
||||
|
@ -404,18 +413,18 @@ class WithinQualifier(_ExpressionQualifier):
|
|||
|
||||
class StartStopQualifier(_ExpressionQualifier):
|
||||
def __init__(self, start_time, stop_time):
|
||||
if isinstance(start_time, IntegerConstant):
|
||||
if isinstance(start_time, TimestampConstant):
|
||||
self.start_time = start_time
|
||||
elif isinstance(start_time, int):
|
||||
self.start_time = IntegerConstant(start_time)
|
||||
elif isinstance(start_time, datetime.date):
|
||||
self.start_time = TimestampConstant(start_time)
|
||||
else:
|
||||
raise ValueError("%s is not a valid argument for a Within Qualifier" % start_time)
|
||||
if isinstance(stop_time, IntegerConstant):
|
||||
raise ValueError("%s is not a valid argument for a Start/Stop Qualifier" % start_time)
|
||||
if isinstance(stop_time, TimestampConstant):
|
||||
self.stop_time = stop_time
|
||||
elif isinstance(stop_time, int):
|
||||
self.stop_time = IntegerConstant(stop_time)
|
||||
elif isinstance(stop_time, datetime.date):
|
||||
self.stop_time = TimestampConstant(stop_time)
|
||||
else:
|
||||
raise ValueError("%s is not a valid argument for a Within Qualifier" % stop_time)
|
||||
raise ValueError("%s is not a valid argument for a Start/Stop Qualifier" % stop_time)
|
||||
|
||||
def __str__(self):
|
||||
return "START %s STOP %s" % (self.start_time, self.stop_time)
|
||||
|
|
|
@ -12,7 +12,7 @@ from stix2patterns.validator import run_validator
|
|||
|
||||
from .base import _STIXBase
|
||||
from .exceptions import DictionaryKeyError
|
||||
from .utils import get_dict, parse_into_datetime
|
||||
from .utils import _get_dict, parse_into_datetime
|
||||
|
||||
|
||||
class Property(object):
|
||||
|
@ -129,6 +129,8 @@ class ListProperty(Property):
|
|||
# constructor again
|
||||
result.append(valid)
|
||||
continue
|
||||
elif type(self.contained) is DictionaryProperty:
|
||||
obj_type = dict
|
||||
else:
|
||||
obj_type = self.contained
|
||||
|
||||
|
@ -232,7 +234,7 @@ class DictionaryProperty(Property):
|
|||
|
||||
def clean(self, value):
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
except ValueError:
|
||||
raise ValueError("The dictionary property must contain a dictionary")
|
||||
if dictified == {}:
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
"""
|
||||
Python STIX 2.x TAXIICollectionStore
|
||||
"""
|
||||
|
||||
from stix2.base import _STIXBase
|
||||
from stix2.core import Bundle, parse
|
||||
from stix2.sources import DataSink, DataSource, DataStore
|
||||
from stix2.sources.filters import Filter, apply_common_filters
|
||||
from stix2.utils import deduplicate
|
||||
|
||||
TAXII_FILTERS = ['added_after', 'id', 'type', 'version']
|
||||
|
||||
|
||||
class TAXIICollectionStore(DataStore):
|
||||
"""Provides an interface to a local/remote TAXII Collection
|
||||
of STIX data. TAXIICollectionStore is a wrapper
|
||||
around a paired TAXIICollectionSink and TAXIICollectionSource.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII Collection instance
|
||||
"""
|
||||
def __init__(self, collection):
|
||||
super(TAXIICollectionStore, self).__init__(
|
||||
source=TAXIICollectionSource(collection),
|
||||
sink=TAXIICollectionSink(collection)
|
||||
)
|
||||
|
||||
|
||||
class TAXIICollectionSink(DataSink):
|
||||
"""Provides an interface for pushing STIX objects to a local/remote
|
||||
TAXII Collection endpoint.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII2 Collection instance
|
||||
|
||||
"""
|
||||
def __init__(self, collection):
|
||||
super(TAXIICollectionSink, self).__init__()
|
||||
self.collection = collection
|
||||
|
||||
def add(self, stix_data, allow_custom=False, version=None):
|
||||
"""Add/push STIX content to TAXII Collection endpoint
|
||||
|
||||
Args:
|
||||
stix_data (STIX object OR dict OR str OR list): valid STIX 2.0 content
|
||||
in a STIX object (or Bundle), STIX onject dict (or Bundle dict), or a STIX 2.0
|
||||
json encoded string, or list of any of the following
|
||||
allow_custom (bool): whether to allow custom objects/properties or
|
||||
not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
"""
|
||||
if isinstance(stix_data, _STIXBase):
|
||||
# adding python STIX object
|
||||
bundle = dict(Bundle(stix_data, allow_custom=allow_custom))
|
||||
|
||||
elif isinstance(stix_data, dict):
|
||||
# adding python dict (of either Bundle or STIX obj)
|
||||
if stix_data["type"] == "bundle":
|
||||
bundle = stix_data
|
||||
else:
|
||||
bundle = dict(Bundle(stix_data, allow_custom=allow_custom))
|
||||
|
||||
elif isinstance(stix_data, list):
|
||||
# adding list of something - recurse on each
|
||||
for obj in stix_data:
|
||||
self.add(obj, allow_custom=allow_custom, version=version)
|
||||
|
||||
elif isinstance(stix_data, str):
|
||||
# adding json encoded string of STIX content
|
||||
stix_data = parse(stix_data, allow_custom=allow_custom, version=version)
|
||||
if stix_data["type"] == "bundle":
|
||||
bundle = dict(stix_data)
|
||||
else:
|
||||
bundle = dict(Bundle(stix_data, allow_custom=allow_custom))
|
||||
|
||||
else:
|
||||
raise TypeError("stix_data must be as STIX object(or list of),json formatted STIX (or list of), or a json formatted STIX bundle")
|
||||
|
||||
self.collection.add_objects(bundle)
|
||||
|
||||
|
||||
class TAXIICollectionSource(DataSource):
|
||||
"""Provides an interface for searching/retrieving STIX objects
|
||||
from a local/remote TAXII Collection endpoint.
|
||||
|
||||
Args:
|
||||
collection (taxii2.Collection): TAXII Collection instance
|
||||
|
||||
"""
|
||||
def __init__(self, collection):
|
||||
super(TAXIICollectionSource, self).__init__()
|
||||
self.collection = collection
|
||||
|
||||
def get(self, stix_id, allow_custom=False, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote STIX Collection
|
||||
endpoint.
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX object to be retrieved.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(STIX object): STIX object that has the supplied STIX ID.
|
||||
The STIX object is received from TAXII has dict, parsed into
|
||||
a python STIX object and then returned
|
||||
|
||||
"""
|
||||
# combine all query filters
|
||||
query = set()
|
||||
if self.filters:
|
||||
query.update(self.filters)
|
||||
if _composite_filters:
|
||||
query.update(_composite_filters)
|
||||
|
||||
# dont extract TAXII filters from query (to send to TAXII endpoint)
|
||||
# as directly retrieveing a STIX object by ID
|
||||
stix_objs = self.collection.get_object(stix_id)["objects"]
|
||||
|
||||
stix_obj = list(apply_common_filters(stix_objs, query))
|
||||
|
||||
if len(stix_obj):
|
||||
stix_obj = parse(stix_obj[0], allow_custom=allow_custom, version=version)
|
||||
if stix_obj.id != stix_id:
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
stix_obj = None
|
||||
else:
|
||||
stix_obj = None
|
||||
|
||||
return stix_obj
|
||||
|
||||
def all_versions(self, stix_id, allow_custom=False, version=None, _composite_filters=None):
|
||||
"""Retrieve STIX object from local/remote TAXII Collection
|
||||
endpoint, all versions of it
|
||||
|
||||
Args:
|
||||
stix_id (str): The STIX ID of the STIX objects to be retrieved.
|
||||
_composite_filters (set): set of filters passed from the parent
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(see query() as all_versions() is just a wrapper)
|
||||
|
||||
"""
|
||||
# make query in TAXII query format since 'id' is TAXII field
|
||||
query = [
|
||||
Filter("match[id]", "=", stix_id),
|
||||
Filter("match[version]", "=", "all")
|
||||
]
|
||||
|
||||
all_data = self.query(query=query, allow_custom=allow_custom, _composite_filters=_composite_filters)
|
||||
|
||||
# parse STIX objects from TAXII returned json
|
||||
all_data = [parse(stix_obj, allow_custom=allow_custom, version=version) for stix_obj in all_data]
|
||||
|
||||
# check - was added to handle erroneous TAXII servers
|
||||
all_data_clean = [stix_obj for stix_obj in all_data if stix_obj.id == stix_id]
|
||||
|
||||
return all_data_clean
|
||||
|
||||
def query(self, query=None, allow_custom=False, version=None, _composite_filters=None):
|
||||
"""Search and retreive STIX objects based on the complete query
|
||||
|
||||
A "complete query" includes the filters from the query, the filters
|
||||
attached to MemorySource, and any filters passed from a
|
||||
CompositeDataSource (i.e. _composite_filters)
|
||||
|
||||
Args:
|
||||
query (list): list of filters to search on
|
||||
_composite_filters (set): set of filters passed from the
|
||||
CompositeDataSource, not user supplied
|
||||
allow_custom (bool): whether to retrieve custom objects/properties
|
||||
or not. Default: False.
|
||||
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If
|
||||
None, use latest version.
|
||||
|
||||
Returns:
|
||||
(list): list of STIX objects that matches the supplied
|
||||
query. The STIX objects are received from TAXII as dicts,
|
||||
parsed into python STIX objects and then returned.
|
||||
|
||||
"""
|
||||
if query is None:
|
||||
query = set()
|
||||
else:
|
||||
if not isinstance(query, list):
|
||||
# make sure dont make set from a Filter object,
|
||||
# need to make a set from a list of Filter objects (even if just one Filter)
|
||||
query = [query]
|
||||
query = set(query)
|
||||
|
||||
# combine all query filters
|
||||
if self.filters:
|
||||
query.update(self.filters)
|
||||
if _composite_filters:
|
||||
query.update(_composite_filters)
|
||||
|
||||
# separate taxii query terms (can be done remotely)
|
||||
taxii_filters = self._parse_taxii_filters(query)
|
||||
|
||||
# query TAXII collection
|
||||
all_data = self.collection.get_objects(filters=taxii_filters)["objects"]
|
||||
|
||||
# deduplicate data (before filtering as reduces wasted filtering)
|
||||
all_data = deduplicate(all_data)
|
||||
|
||||
# apply local (CompositeDataSource, TAXIICollectionSource and query filters)
|
||||
all_data = list(apply_common_filters(all_data, query))
|
||||
|
||||
# parse python STIX objects from the STIX object dicts
|
||||
stix_objs = [parse(stix_obj_dict, allow_custom=allow_custom, version=version) for stix_obj_dict in all_data]
|
||||
|
||||
return stix_objs
|
||||
|
||||
def _parse_taxii_filters(self, query):
|
||||
"""Parse out TAXII filters that the TAXII server can filter on.
|
||||
|
||||
Note:
|
||||
For instance - "?match[type]=indicator,sighting" should be in a
|
||||
query dict as follows:
|
||||
|
||||
Filter("type", "=", "indicator,sighting")
|
||||
|
||||
Args:
|
||||
query (list): list of filters to extract which ones are TAXII
|
||||
specific.
|
||||
|
||||
Returns:
|
||||
params (dict): dict of the TAXII filters but in format required
|
||||
for 'requests.get()'.
|
||||
|
||||
"""
|
||||
params = {}
|
||||
|
||||
for filter_ in query:
|
||||
if filter_.property in TAXII_FILTERS:
|
||||
if filter_.property == "added_after":
|
||||
params[filter_.property] = filter_.value
|
||||
else:
|
||||
taxii_field = "match[%s]" % filter_.property
|
||||
params[taxii_field] = filter_.value
|
||||
return params
|
|
@ -46,3 +46,114 @@ def malware(uuid4, clock):
|
|||
@pytest.fixture
|
||||
def relationship(uuid4, clock):
|
||||
return stix2.Relationship(**RELATIONSHIP_KWARGS)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def stix_objs1():
|
||||
ind1 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind2 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind3 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.936Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind4 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind5 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
return [ind1, ind2, ind3, ind4, ind5]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def stix_objs2():
|
||||
ind6 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-31T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind7 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
ind8 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
return [ind6, ind7, ind8]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def real_stix_objs2(stix_objs2):
|
||||
return [stix2.parse(x) for x in stix_objs2]
|
||||
|
|
|
@ -37,14 +37,18 @@ RELATIONSHIP_IDS = [
|
|||
'relationship--a0cbb21c-8daf-4a7f-96aa-7155a4ef8f70'
|
||||
]
|
||||
|
||||
# All required args for a Campaign instance
|
||||
# *_KWARGS contains all required arguments to create an instance of that STIX object
|
||||
# *_MORE_KWARGS contains all the required arguments, plus some optional ones
|
||||
|
||||
ATTACK_PATTERN_KWARGS = dict(
|
||||
name="Phishing",
|
||||
)
|
||||
|
||||
CAMPAIGN_KWARGS = dict(
|
||||
name="Green Group Attacks Against Finance",
|
||||
description="Campaign by Green Group against a series of targets in the financial services sector.",
|
||||
)
|
||||
|
||||
|
||||
# All required args for a Campaign instance, plus some optional args
|
||||
CAMPAIGN_MORE_KWARGS = dict(
|
||||
type='campaign',
|
||||
id=CAMPAIGN_ID,
|
||||
|
@ -55,25 +59,29 @@ CAMPAIGN_MORE_KWARGS = dict(
|
|||
description="Campaign by Green Group against a series of targets in the financial services sector.",
|
||||
)
|
||||
|
||||
# Minimum required args for an Identity instance
|
||||
COURSE_OF_ACTION_KWARGS = dict(
|
||||
name="Block",
|
||||
)
|
||||
|
||||
IDENTITY_KWARGS = dict(
|
||||
name="John Smith",
|
||||
identity_class="individual",
|
||||
)
|
||||
|
||||
# Minimum required args for an Indicator instance
|
||||
INDICATOR_KWARGS = dict(
|
||||
labels=['malicious-activity'],
|
||||
pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
|
||||
)
|
||||
|
||||
# Minimum required args for a Malware instance
|
||||
INTRUSION_SET_KWARGS = dict(
|
||||
name="Bobcat Breakin",
|
||||
)
|
||||
|
||||
MALWARE_KWARGS = dict(
|
||||
labels=['ransomware'],
|
||||
name="Cryptolocker",
|
||||
)
|
||||
|
||||
# All required args for a Malware instance, plus some optional args
|
||||
MALWARE_MORE_KWARGS = dict(
|
||||
type='malware',
|
||||
id=MALWARE_ID,
|
||||
|
@ -84,14 +92,45 @@ MALWARE_MORE_KWARGS = dict(
|
|||
description="A ransomware related to ..."
|
||||
)
|
||||
|
||||
# Minimum required args for a Relationship instance
|
||||
OBSERVED_DATA_KWARGS = dict(
|
||||
first_observed=FAKE_TIME,
|
||||
last_observed=FAKE_TIME,
|
||||
number_observed=1,
|
||||
objects={
|
||||
"0": {
|
||||
"type": "windows-registry-key",
|
||||
"key": "HKEY_LOCAL_MACHINE\\System\\Foo\\Bar",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
REPORT_KWARGS = dict(
|
||||
labels=["campaign"],
|
||||
name="Bad Cybercrime",
|
||||
published=FAKE_TIME,
|
||||
object_refs=[INDICATOR_ID],
|
||||
)
|
||||
|
||||
RELATIONSHIP_KWARGS = dict(
|
||||
relationship_type="indicates",
|
||||
source_ref=INDICATOR_ID,
|
||||
target_ref=MALWARE_ID,
|
||||
)
|
||||
|
||||
# Minimum required args for a Sighting instance
|
||||
SIGHTING_KWARGS = dict(
|
||||
sighting_of_ref=INDICATOR_ID,
|
||||
)
|
||||
|
||||
THREAT_ACTOR_KWARGS = dict(
|
||||
labels=["crime-syndicate"],
|
||||
name="Evil Org",
|
||||
)
|
||||
|
||||
TOOL_KWARGS = dict(
|
||||
labels=["remote-access"],
|
||||
name="VNC",
|
||||
)
|
||||
|
||||
VULNERABILITY_KWARGS = dict(
|
||||
name="Heartbleed",
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import stix2
|
|||
|
||||
EXPECTED_BUNDLE = """{
|
||||
"type": "bundle",
|
||||
"id": "bundle--00000000-0000-0000-0000-000000000004",
|
||||
"id": "bundle--00000000-0000-0000-0000-000000000007",
|
||||
"spec_version": "2.0",
|
||||
"objects": [
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ EXPECTED_BUNDLE = """{
|
|||
},
|
||||
{
|
||||
"type": "malware",
|
||||
"id": "malware--00000000-0000-0000-0000-000000000002",
|
||||
"id": "malware--00000000-0000-0000-0000-000000000003",
|
||||
"created": "2017-01-01T12:34:56.000Z",
|
||||
"modified": "2017-01-01T12:34:56.000Z",
|
||||
"name": "Cryptolocker",
|
||||
|
@ -32,7 +32,7 @@ EXPECTED_BUNDLE = """{
|
|||
},
|
||||
{
|
||||
"type": "relationship",
|
||||
"id": "relationship--00000000-0000-0000-0000-000000000003",
|
||||
"id": "relationship--00000000-0000-0000-0000-000000000005",
|
||||
"created": "2017-01-01T12:34:56.000Z",
|
||||
"modified": "2017-01-01T12:34:56.000Z",
|
||||
"relationship_type": "indicates",
|
||||
|
@ -44,7 +44,7 @@ EXPECTED_BUNDLE = """{
|
|||
|
||||
EXPECTED_BUNDLE_DICT = {
|
||||
"type": "bundle",
|
||||
"id": "bundle--00000000-0000-0000-0000-000000000004",
|
||||
"id": "bundle--00000000-0000-0000-0000-000000000007",
|
||||
"spec_version": "2.0",
|
||||
"objects": [
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ EXPECTED_BUNDLE_DICT = {
|
|||
},
|
||||
{
|
||||
"type": "malware",
|
||||
"id": "malware--00000000-0000-0000-0000-000000000002",
|
||||
"id": "malware--00000000-0000-0000-0000-000000000003",
|
||||
"created": "2017-01-01T12:34:56.000Z",
|
||||
"modified": "2017-01-01T12:34:56.000Z",
|
||||
"name": "Cryptolocker",
|
||||
|
@ -70,7 +70,7 @@ EXPECTED_BUNDLE_DICT = {
|
|||
},
|
||||
{
|
||||
"type": "relationship",
|
||||
"id": "relationship--00000000-0000-0000-0000-000000000003",
|
||||
"id": "relationship--00000000-0000-0000-0000-000000000005",
|
||||
"created": "2017-01-01T12:34:56.000Z",
|
||||
"modified": "2017-01-01T12:34:56.000Z",
|
||||
"relationship_type": "indicates",
|
||||
|
|
|
@ -2,7 +2,14 @@ import pytest
|
|||
|
||||
import stix2
|
||||
|
||||
from .constants import FAKE_TIME
|
||||
from .constants import FAKE_TIME, MARKING_DEFINITION_ID
|
||||
|
||||
IDENTITY_CUSTOM_PROP = stix2.Identity(
|
||||
name="John Smith",
|
||||
identity_class="individual",
|
||||
x_foo="bar",
|
||||
allow_custom=True,
|
||||
)
|
||||
|
||||
|
||||
def test_identity_custom_property():
|
||||
|
@ -17,6 +24,20 @@ def test_identity_custom_property():
|
|||
)
|
||||
assert str(excinfo.value) == "'custom_properties' must be a dictionary"
|
||||
|
||||
with pytest.raises(stix2.exceptions.ExtraPropertiesError) as excinfo:
|
||||
stix2.Identity(
|
||||
id="identity--311b2d2d-f010-5473-83ec-1edf84858f4c",
|
||||
created="2015-12-21T19:59:11Z",
|
||||
modified="2015-12-21T19:59:11Z",
|
||||
name="John Smith",
|
||||
identity_class="individual",
|
||||
custom_properties={
|
||||
"foo": "bar",
|
||||
},
|
||||
foo="bar",
|
||||
)
|
||||
assert "Unexpected properties for Identity" in str(excinfo.value)
|
||||
|
||||
identity = stix2.Identity(
|
||||
id="identity--311b2d2d-f010-5473-83ec-1edf84858f4c",
|
||||
created="2015-12-21T19:59:11Z",
|
||||
|
@ -27,7 +48,6 @@ def test_identity_custom_property():
|
|||
"foo": "bar",
|
||||
},
|
||||
)
|
||||
|
||||
assert identity.foo == "bar"
|
||||
|
||||
|
||||
|
@ -81,19 +101,162 @@ def test_parse_identity_custom_property(data):
|
|||
assert identity.foo == "bar"
|
||||
|
||||
|
||||
def test_custom_property_in_bundled_object():
|
||||
identity = stix2.Identity(
|
||||
name="John Smith",
|
||||
identity_class="individual",
|
||||
x_foo="bar",
|
||||
allow_custom=True,
|
||||
)
|
||||
bundle = stix2.Bundle(identity, allow_custom=True)
|
||||
def test_custom_property_object_in_bundled_object():
|
||||
bundle = stix2.Bundle(IDENTITY_CUSTOM_PROP, allow_custom=True)
|
||||
|
||||
assert bundle.objects[0].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(bundle)
|
||||
|
||||
|
||||
def test_custom_properties_object_in_bundled_object():
|
||||
obj = stix2.Identity(
|
||||
name="John Smith",
|
||||
identity_class="individual",
|
||||
custom_properties={
|
||||
"x_foo": "bar",
|
||||
}
|
||||
)
|
||||
bundle = stix2.Bundle(obj, allow_custom=True)
|
||||
|
||||
assert bundle.objects[0].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(bundle)
|
||||
|
||||
|
||||
def test_custom_property_dict_in_bundled_object():
|
||||
custom_identity = {
|
||||
'type': 'identity',
|
||||
'id': 'identity--311b2d2d-f010-5473-83ec-1edf84858f4c',
|
||||
'created': '2015-12-21T19:59:11Z',
|
||||
'name': 'John Smith',
|
||||
'identity_class': 'individual',
|
||||
'x_foo': 'bar',
|
||||
}
|
||||
with pytest.raises(stix2.exceptions.ExtraPropertiesError):
|
||||
bundle = stix2.Bundle(custom_identity)
|
||||
|
||||
bundle = stix2.Bundle(custom_identity, allow_custom=True)
|
||||
assert bundle.objects[0].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(bundle)
|
||||
|
||||
|
||||
def test_custom_properties_dict_in_bundled_object():
|
||||
custom_identity = {
|
||||
'type': 'identity',
|
||||
'id': 'identity--311b2d2d-f010-5473-83ec-1edf84858f4c',
|
||||
'created': '2015-12-21T19:59:11Z',
|
||||
'name': 'John Smith',
|
||||
'identity_class': 'individual',
|
||||
'custom_properties': {
|
||||
'x_foo': 'bar',
|
||||
},
|
||||
}
|
||||
bundle = stix2.Bundle(custom_identity)
|
||||
|
||||
assert bundle.objects[0].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(bundle)
|
||||
|
||||
|
||||
def test_custom_property_in_observed_data():
|
||||
artifact = stix2.File(
|
||||
allow_custom=True,
|
||||
name='test',
|
||||
x_foo='bar'
|
||||
)
|
||||
observed_data = stix2.ObservedData(
|
||||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
assert observed_data.objects['0'].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(observed_data)
|
||||
|
||||
|
||||
def test_custom_property_object_in_observable_extension():
|
||||
ntfs = stix2.NTFSExt(
|
||||
allow_custom=True,
|
||||
sid=1,
|
||||
x_foo='bar',
|
||||
)
|
||||
artifact = stix2.File(
|
||||
name='test',
|
||||
extensions={'ntfs-ext': ntfs},
|
||||
)
|
||||
observed_data = stix2.ObservedData(
|
||||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
assert observed_data.objects['0'].extensions['ntfs-ext'].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(observed_data)
|
||||
|
||||
|
||||
def test_custom_property_dict_in_observable_extension():
|
||||
with pytest.raises(stix2.exceptions.ExtraPropertiesError):
|
||||
artifact = stix2.File(
|
||||
name='test',
|
||||
extensions={
|
||||
'ntfs-ext': {
|
||||
'sid': 1,
|
||||
'x_foo': 'bar',
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
artifact = stix2.File(
|
||||
allow_custom=True,
|
||||
name='test',
|
||||
extensions={
|
||||
'ntfs-ext': {
|
||||
'allow_custom': True,
|
||||
'sid': 1,
|
||||
'x_foo': 'bar',
|
||||
}
|
||||
},
|
||||
)
|
||||
observed_data = stix2.ObservedData(
|
||||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
assert observed_data.objects['0'].extensions['ntfs-ext'].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(observed_data)
|
||||
|
||||
|
||||
def test_identity_custom_property_revoke():
|
||||
identity = IDENTITY_CUSTOM_PROP.revoke()
|
||||
assert identity.x_foo == "bar"
|
||||
|
||||
|
||||
def test_identity_custom_property_edit_markings():
|
||||
marking_obj = stix2.MarkingDefinition(
|
||||
id=MARKING_DEFINITION_ID,
|
||||
definition_type="statement",
|
||||
definition=stix2.StatementMarking(statement="Copyright 2016, Example Corp")
|
||||
)
|
||||
marking_obj2 = stix2.MarkingDefinition(
|
||||
id=MARKING_DEFINITION_ID,
|
||||
definition_type="statement",
|
||||
definition=stix2.StatementMarking(statement="Another one")
|
||||
)
|
||||
|
||||
# None of the following should throw exceptions
|
||||
identity = IDENTITY_CUSTOM_PROP.add_markings(marking_obj)
|
||||
identity2 = identity.add_markings(marking_obj2, ['x_foo'])
|
||||
identity2.remove_markings(marking_obj.id)
|
||||
identity2.remove_markings(marking_obj2.id, ['x_foo'])
|
||||
identity2.clear_markings()
|
||||
identity2.clear_markings('x_foo')
|
||||
|
||||
|
||||
def test_custom_marking_no_init_1():
|
||||
@stix2.CustomMarking('x-new-obj', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
|
@ -170,6 +333,24 @@ def test_custom_object_no_init_2():
|
|||
assert no2.property1 == 'something'
|
||||
|
||||
|
||||
def test_custom_object_invalid_type_name():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.sdo.CustomObject('x', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class NewObj(object):
|
||||
pass # pragma: no cover
|
||||
assert "Invalid type name 'x': " in str(excinfo.value)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.sdo.CustomObject('x_new_object', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class NewObj2(object):
|
||||
pass # pragma: no cover
|
||||
assert "Invalid type name 'x_new_object':" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_parse_custom_object_type():
|
||||
nt_string = """{
|
||||
"type": "x-new-type",
|
||||
|
@ -194,6 +375,20 @@ def test_parse_unregistered_custom_object_type():
|
|||
assert "use the CustomObject decorator." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_parse_unregistered_custom_object_type_w_allow_custom():
|
||||
"""parse an unknown custom object, allowed by passing
|
||||
'allow_custom' flag
|
||||
"""
|
||||
nt_string = """{
|
||||
"type": "x-foobar-observable",
|
||||
"created": "2015-12-21T19:59:11Z",
|
||||
"property1": "something"
|
||||
}"""
|
||||
|
||||
custom_obj = stix2.parse(nt_string, allow_custom=True)
|
||||
assert custom_obj["type"] == "x-foobar-observable"
|
||||
|
||||
|
||||
@stix2.observables.CustomObservable('x-new-observable', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
('property2', stix2.properties.IntegerProperty()),
|
||||
|
@ -254,6 +449,24 @@ def test_custom_observable_object_no_init_2():
|
|||
assert no2.property1 == 'something'
|
||||
|
||||
|
||||
def test_custom_observable_object_invalid_type_name():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomObservable('x', [
|
||||
('property1', stix2.properties.StringProperty()),
|
||||
])
|
||||
class NewObs(object):
|
||||
pass # pragma: no cover
|
||||
assert "Invalid observable type name 'x':" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomObservable('x_new_obs', [
|
||||
('property1', stix2.properties.StringProperty()),
|
||||
])
|
||||
class NewObs2(object):
|
||||
pass # pragma: no cover
|
||||
assert "Invalid observable type name 'x_new_obs':" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_observable_object_invalid_ref_property():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomObservable('x-new-obs', [
|
||||
|
@ -322,6 +535,7 @@ def test_parse_custom_observable_object():
|
|||
}"""
|
||||
|
||||
nt = stix2.parse_observable(nt_string, [])
|
||||
assert isinstance(nt, stix2.core._STIXBase)
|
||||
assert nt.property1 == 'something'
|
||||
|
||||
|
||||
|
@ -331,10 +545,46 @@ def test_parse_unregistered_custom_observable_object():
|
|||
"property1": "something"
|
||||
}"""
|
||||
|
||||
with pytest.raises(stix2.exceptions.ParseError) as excinfo:
|
||||
with pytest.raises(stix2.exceptions.CustomContentError) as excinfo:
|
||||
stix2.parse_observable(nt_string)
|
||||
assert "Can't parse unknown observable type" in str(excinfo.value)
|
||||
|
||||
parsed_custom = stix2.parse_observable(nt_string, allow_custom=True)
|
||||
assert parsed_custom['property1'] == 'something'
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
assert parsed_custom.property1 == 'something'
|
||||
assert not isinstance(parsed_custom, stix2.core._STIXBase)
|
||||
|
||||
|
||||
def test_parse_unregistered_custom_observable_object_with_no_type():
|
||||
nt_string = """{
|
||||
"property1": "something"
|
||||
}"""
|
||||
|
||||
with pytest.raises(stix2.exceptions.ParseError) as excinfo:
|
||||
stix2.parse_observable(nt_string, allow_custom=True)
|
||||
assert "Can't parse observable with no 'type' property" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_parse_observed_data_with_custom_observable():
|
||||
input_str = """{
|
||||
"type": "observed-data",
|
||||
"id": "observed-data--dc20c4ca-a2a3-4090-a5d5-9558c3af4758",
|
||||
"created": "2016-04-06T19:58:16.000Z",
|
||||
"modified": "2016-04-06T19:58:16.000Z",
|
||||
"first_observed": "2015-12-21T19:00:00Z",
|
||||
"last_observed": "2015-12-21T19:00:00Z",
|
||||
"number_observed": 1,
|
||||
"objects": {
|
||||
"0": {
|
||||
"type": "x-foobar-observable",
|
||||
"property1": "something"
|
||||
}
|
||||
}
|
||||
}"""
|
||||
parsed = stix2.parse(input_str, allow_custom=True)
|
||||
assert parsed.objects['0']['property1'] == 'something'
|
||||
|
||||
|
||||
def test_parse_invalid_custom_observable_object():
|
||||
nt_string = """{
|
||||
|
@ -394,10 +644,10 @@ def test_observed_data_with_custom_observable_object():
|
|||
assert ob_data.objects['0'].property1 == 'something'
|
||||
|
||||
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
'property2': stix2.properties.IntegerProperty(),
|
||||
})
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
('property2', stix2.properties.IntegerProperty()),
|
||||
])
|
||||
class NewExtension():
|
||||
def __init__(self, property2=None, **kwargs):
|
||||
if property2 and property2 < 10:
|
||||
|
@ -428,6 +678,7 @@ def test_custom_extension():
|
|||
|
||||
|
||||
def test_custom_extension_wrong_observable_type():
|
||||
# NewExtension is an extension of DomainName, not File
|
||||
ext = NewExtension(property1='something')
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.File(name="abc.txt",
|
||||
|
@ -438,15 +689,36 @@ def test_custom_extension_wrong_observable_type():
|
|||
assert 'Cannot determine extension type' in excinfo.value.reason
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", [
|
||||
"""{
|
||||
"keys": [
|
||||
{
|
||||
"test123": 123,
|
||||
"test345": "aaaa"
|
||||
}
|
||||
]
|
||||
}""",
|
||||
])
|
||||
def test_custom_extension_with_list_and_dict_properties_observable_type(data):
|
||||
@stix2.observables.CustomExtension(stix2.UserAccount, 'some-extension', [
|
||||
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True))
|
||||
])
|
||||
class SomeCustomExtension:
|
||||
pass
|
||||
|
||||
example = SomeCustomExtension(keys=[{'test123': 123, 'test345': 'aaaa'}])
|
||||
assert data == str(example)
|
||||
|
||||
|
||||
def test_custom_extension_invalid_observable():
|
||||
# These extensions are being applied to improperly-created Observables.
|
||||
# The Observable classes should have been created with the CustomObservable decorator.
|
||||
class Foo(object):
|
||||
pass
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(Foo, 'x-new-ext', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
@stix2.observables.CustomExtension(Foo, 'x-new-ext', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class FooExtension():
|
||||
pass # pragma: no cover
|
||||
assert str(excinfo.value) == "'observable' must be a valid Observable class!"
|
||||
|
@ -454,9 +726,9 @@ def test_custom_extension_invalid_observable():
|
|||
class Bar(stix2.observables._Observable):
|
||||
pass
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(Bar, 'x-new-ext', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
@stix2.observables.CustomExtension(Bar, 'x-new-ext', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class BarExtension():
|
||||
pass
|
||||
assert "Unknown observable type" in str(excinfo.value)
|
||||
|
@ -465,35 +737,61 @@ def test_custom_extension_invalid_observable():
|
|||
class Baz(stix2.observables._Observable):
|
||||
_type = 'Baz'
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(Baz, 'x-new-ext', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
@stix2.observables.CustomExtension(Baz, 'x-new-ext', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class BazExtension():
|
||||
pass
|
||||
assert "Unknown observable type" in str(excinfo.value)
|
||||
assert "Custom observables must be created with the @CustomObservable decorator." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_extension_invalid_type_name():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(stix2.File, 'x', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
class FooExtension():
|
||||
pass # pragma: no cover
|
||||
assert "Invalid extension type name 'x':" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(stix2.File, 'x_new_ext', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
class BlaExtension():
|
||||
pass # pragma: no cover
|
||||
assert "Invalid extension type name 'x_new_ext':" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_extension_no_properties():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', None)
|
||||
class BarExtension():
|
||||
pass
|
||||
assert "'properties' must be a dict!" in str(excinfo.value)
|
||||
assert "Must supply a list, containing tuples." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_extension_empty_properties():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', [])
|
||||
class BarExtension():
|
||||
pass
|
||||
assert "Must supply a list, containing tuples." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_extension_dict_properties():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', {})
|
||||
class BarExtension():
|
||||
pass
|
||||
assert "'properties' must be a dict!" in str(excinfo.value)
|
||||
assert "Must supply a list, containing tuples." in str(excinfo.value)
|
||||
|
||||
|
||||
def test_custom_extension_no_init_1():
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-extension', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-extension', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class NewExt():
|
||||
pass
|
||||
|
||||
|
@ -502,9 +800,9 @@ def test_custom_extension_no_init_1():
|
|||
|
||||
|
||||
def test_custom_extension_no_init_2():
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', {
|
||||
'property1': stix2.properties.StringProperty(required=True),
|
||||
})
|
||||
@stix2.observables.CustomExtension(stix2.DomainName, 'x-new-ext2', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
])
|
||||
class NewExt2(object):
|
||||
pass
|
||||
|
||||
|
@ -542,7 +840,11 @@ def test_parse_observable_with_unregistered_custom_extension():
|
|||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.parse_observable(input_str)
|
||||
assert "Can't parse Unknown extension type" in str(excinfo.value)
|
||||
assert "Can't parse unknown extension type" in str(excinfo.value)
|
||||
|
||||
parsed_ob = stix2.parse_observable(input_str, allow_custom=True)
|
||||
assert parsed_ob['extensions']['x-foobar-ext']['property1'] == 'foo'
|
||||
assert not isinstance(parsed_ob['extensions']['x-foobar-ext'], stix2.core._STIXBase)
|
||||
|
||||
|
||||
def test_register_custom_object():
|
||||
|
@ -553,3 +855,8 @@ def test_register_custom_object():
|
|||
stix2._register_type(CustomObject2)
|
||||
# Note that we will always check against newest OBJ_MAP.
|
||||
assert (CustomObject2._type, CustomObject2) in stix2.OBJ_MAP.items()
|
||||
|
||||
|
||||
def test_extension_property_location():
|
||||
assert 'extensions' in stix2.v21.observables.OBJ_MAP_OBSERVABLE['x-new-observable']._properties
|
||||
assert 'extensions' not in stix2.v21.observables.EXT_MAP['domain-name']['x-new-ext']._properties
|
||||
|
|
|
@ -1,557 +0,0 @@
|
|||
import pytest
|
||||
from taxii2client import Collection
|
||||
|
||||
from stix2 import Filter, MemorySink, MemorySource
|
||||
from stix2.sources import (CompositeDataSource, DataSink, DataSource, make_id,
|
||||
taxii)
|
||||
from stix2.sources.filters import apply_common_filters
|
||||
from stix2.utils import deduplicate
|
||||
|
||||
COLLECTION_URL = 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'
|
||||
|
||||
|
||||
class MockTAXIIClient(object):
|
||||
"""Mock for taxii2_client.TAXIIClient"""
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def collection():
|
||||
return Collection(COLLECTION_URL, MockTAXIIClient())
|
||||
|
||||
|
||||
IND1 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND2 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND3 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.936Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND4 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND5 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND6 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-31T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND7 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
IND8 = {
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
|
||||
STIX_OBJS2 = [IND6, IND7, IND8]
|
||||
STIX_OBJS1 = [IND1, IND2, IND3, IND4, IND5]
|
||||
|
||||
|
||||
def test_ds_abstract_class_smoke():
|
||||
with pytest.raises(TypeError):
|
||||
DataSource()
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
DataSink()
|
||||
|
||||
|
||||
def test_ds_taxii(collection):
|
||||
ds = taxii.TAXIICollectionSource(collection)
|
||||
assert ds.collection is not None
|
||||
|
||||
|
||||
def test_ds_taxii_name(collection):
|
||||
ds = taxii.TAXIICollectionSource(collection)
|
||||
assert ds.collection is not None
|
||||
|
||||
|
||||
def test_parse_taxii_filters():
|
||||
query = [
|
||||
Filter("added_after", "=", "2016-02-01T00:00:01.000Z"),
|
||||
Filter("id", "=", "taxii stix object ID"),
|
||||
Filter("type", "=", "taxii stix object ID"),
|
||||
Filter("version", "=", "first"),
|
||||
Filter("created_by_ref", "=", "Bane"),
|
||||
]
|
||||
|
||||
expected_params = {
|
||||
"added_after": "2016-02-01T00:00:01.000Z",
|
||||
"match[id]": "taxii stix object ID",
|
||||
"match[type]": "taxii stix object ID",
|
||||
"match[version]": "first"
|
||||
}
|
||||
|
||||
ds = taxii.TAXIICollectionSource(collection)
|
||||
|
||||
taxii_filters = ds._parse_taxii_filters(query)
|
||||
|
||||
assert taxii_filters == expected_params
|
||||
|
||||
|
||||
def test_add_get_remove_filter():
|
||||
ds = taxii.TAXIICollectionSource(collection)
|
||||
|
||||
# First 3 filters are valid, remaining properties are erroneous in some way
|
||||
valid_filters = [
|
||||
Filter('type', '=', 'malware'),
|
||||
Filter('id', '!=', 'stix object id'),
|
||||
Filter('labels', 'in', ["heartbleed", "malicious-activity"]),
|
||||
]
|
||||
|
||||
# Invalid filters - wont pass creation
|
||||
# these filters will not be allowed to be created
|
||||
# check proper errors are raised when trying to create them
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
# create Filter that has an operator that is not allowed
|
||||
Filter('modified', '*', 'not supported operator - just place holder')
|
||||
assert str(excinfo.value) == "Filter operator '*' not supported for specified property: 'modified'"
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
# create Filter that has a value type that is not allowed
|
||||
Filter('created', '=', object())
|
||||
# On Python 2, the type of object() is `<type 'object'>` On Python 3, it's `<class 'object'>`.
|
||||
assert str(excinfo.value).startswith("Filter value type")
|
||||
assert str(excinfo.value).endswith("is not supported. The type must be a Python immutable type or dictionary")
|
||||
|
||||
assert len(ds.filters) == 0
|
||||
|
||||
ds.filters.add(valid_filters[0])
|
||||
assert len(ds.filters) == 1
|
||||
|
||||
# Addin the same filter again will have no effect since `filters` uses a set
|
||||
ds.filters.add(valid_filters[0])
|
||||
assert len(ds.filters) == 1
|
||||
|
||||
ds.filters.add(valid_filters[1])
|
||||
assert len(ds.filters) == 2
|
||||
ds.filters.add(valid_filters[2])
|
||||
assert len(ds.filters) == 3
|
||||
|
||||
assert set(valid_filters) == ds.filters
|
||||
|
||||
# remove
|
||||
ds.filters.remove(valid_filters[0])
|
||||
|
||||
assert len(ds.filters) == 2
|
||||
|
||||
ds.filters.update(valid_filters)
|
||||
|
||||
|
||||
def test_apply_common_filters():
|
||||
stix_objs = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.997Z",
|
||||
"description": "\n\nTITLE:\n\tPoison Ivy",
|
||||
"id": "malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111",
|
||||
"labels": [
|
||||
"remote-access-trojan"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.997Z",
|
||||
"name": "Poison Ivy",
|
||||
"type": "malware"
|
||||
},
|
||||
{
|
||||
"created": "2014-05-08T09:00:00.000Z",
|
||||
"id": "indicator--a932fcc6-e032-176c-126f-cb970a5a1ade",
|
||||
"labels": [
|
||||
"file-hash-watchlist"
|
||||
],
|
||||
"modified": "2014-05-08T09:00:00.000Z",
|
||||
"name": "File hash for Poison Ivy variant",
|
||||
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2014-05-08T09:00:00.000000Z"
|
||||
},
|
||||
{
|
||||
"created": "2014-05-08T09:00:00.000Z",
|
||||
"granular_markings": [
|
||||
{
|
||||
"marking_ref": "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed",
|
||||
"selectors": [
|
||||
"relationship_type"
|
||||
]
|
||||
}
|
||||
],
|
||||
"id": "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463",
|
||||
"modified": "2014-05-08T09:00:00.000Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"
|
||||
],
|
||||
"relationship_type": "indicates",
|
||||
"revoked": True,
|
||||
"source_ref": "indicator--a932fcc6-e032-176c-126f-cb970a5a1ade",
|
||||
"target_ref": "malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111",
|
||||
"type": "relationship"
|
||||
},
|
||||
{
|
||||
"id": "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef",
|
||||
"created": "2016-02-14T00:00:00.000Z",
|
||||
"created_by_ref": "identity--00000000-0000-0000-0000-b8e91df99dc9",
|
||||
"modified": "2016-02-14T00:00:00.000Z",
|
||||
"type": "vulnerability",
|
||||
"name": "CVE-2014-0160",
|
||||
"description": "The (1) TLS...",
|
||||
"external_references": [
|
||||
{
|
||||
"source_name": "cve",
|
||||
"external_id": "CVE-2014-0160"
|
||||
}
|
||||
],
|
||||
"labels": ["heartbleed", "has-logo"]
|
||||
}
|
||||
]
|
||||
|
||||
filters = [
|
||||
Filter("type", "!=", "relationship"),
|
||||
Filter("id", "=", "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463"),
|
||||
Filter("labels", "in", "remote-access-trojan"),
|
||||
Filter("created", ">", "2015-01-01T01:00:00.000Z"),
|
||||
Filter("revoked", "=", True),
|
||||
Filter("revoked", "!=", True),
|
||||
Filter("object_marking_refs", "=", "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"),
|
||||
Filter("granular_markings.selectors", "in", "relationship_type"),
|
||||
Filter("granular_markings.marking_ref", "=", "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed"),
|
||||
Filter("external_references.external_id", "in", "CVE-2014-0160,CVE-2017-6608"),
|
||||
Filter("created_by_ref", "=", "identity--00000000-0000-0000-0000-b8e91df99dc9"),
|
||||
Filter("object_marking_refs", "=", "marking-definition--613f2e26-0000-0000-0000-b8e91df99dc9"),
|
||||
Filter("granular_markings.selectors", "in", "description"),
|
||||
Filter("external_references.source_name", "=", "CVE"),
|
||||
]
|
||||
|
||||
# "Return any object whose type is not relationship"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[0]]))
|
||||
ids = [r['id'] for r in resp]
|
||||
assert stix_objs[0]['id'] in ids
|
||||
assert stix_objs[1]['id'] in ids
|
||||
assert stix_objs[3]['id'] in ids
|
||||
assert len(ids) == 3
|
||||
|
||||
# "Return any object that matched id relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[1]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object that contains remote-access-trojan in labels"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[2]]))
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object created after 2015-01-01T01:00:00.000Z"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[3]]))
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
# "Return any revoked object"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[4]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object whose not revoked"
|
||||
# Note that if 'revoked' property is not present in object.
|
||||
# Currently we can't use such an expression to filter for... :(
|
||||
resp = list(apply_common_filters(stix_objs, [filters[5]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
# "Return any object that matches marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9 in object_marking_refs"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[6]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object that contains relationship_type in their selectors AND
|
||||
# also has marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed in marking_ref"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[7], filters[8]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object that contains CVE-2014-0160,CVE-2017-6608 in their external_id"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[9]]))
|
||||
assert resp[0]['id'] == stix_objs[3]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object that matches created_by_ref identity--00000000-0000-0000-0000-b8e91df99dc9"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[10]]))
|
||||
assert len(resp) == 1
|
||||
|
||||
# "Return any object that matches marking-definition--613f2e26-0000-0000-0000-b8e91df99dc9 in object_marking_refs" (None)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[11]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
# "Return any object that contains description in its selectors" (None)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[12]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
# "Return any object that object that matches CVE in source_name" (None, case sensitive)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[13]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
|
||||
def test_filters0():
|
||||
# "Return any object modified before 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("modified", "<", "2017-01-28T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
|
||||
def test_filters1():
|
||||
# "Return any object modified after 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("modified", ">", "2017-01-28T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_filters2():
|
||||
# "Return any object modified after or on 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("modified", ">=", "2017-01-27T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
|
||||
def test_filters3():
|
||||
# "Return any object modified before or on 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("modified", "<=", "2017-01-27T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
|
||||
def test_filters4():
|
||||
# Assert invalid Filter cannot be created
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
Filter("modified", "?", "2017-01-27T13:49:53.935Z")
|
||||
assert str(excinfo.value) == ("Filter operator '?' not supported "
|
||||
"for specified property: 'modified'")
|
||||
|
||||
|
||||
def test_filters5():
|
||||
# "Return any object whose id is not indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f"
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("id", "!=", "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_filters6():
|
||||
# Test filtering on non-common property
|
||||
resp = list(apply_common_filters(STIX_OBJS2, [Filter("name", "=", "Malicious site hosting downloader")]))
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
|
||||
def test_filters7():
|
||||
# Test filtering on embedded property
|
||||
stix_objects = list(STIX_OBJS2) + [{
|
||||
"type": "observed-data",
|
||||
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
|
||||
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
"created": "2016-04-06T19:58:16.000Z",
|
||||
"modified": "2016-04-06T19:58:16.000Z",
|
||||
"first_observed": "2015-12-21T19:00:00Z",
|
||||
"last_observed": "2015-12-21T19:00:00Z",
|
||||
"number_observed": 50,
|
||||
"objects": {
|
||||
"0": {
|
||||
"type": "file",
|
||||
"hashes": {
|
||||
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
|
||||
},
|
||||
"extensions": {
|
||||
"pdf-ext": {
|
||||
"version": "1.7",
|
||||
"document_info_dict": {
|
||||
"Title": "Sample document",
|
||||
"Author": "Adobe Systems Incorporated",
|
||||
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
|
||||
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
|
||||
"CreationDate": "20070412090123-02"
|
||||
},
|
||||
"pdfid0": "DFCE52BD827ECF765649852119D",
|
||||
"pdfid1": "57A1E0F9ED2AE523E313C"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
resp = list(apply_common_filters(stix_objects, [Filter("objects.0.extensions.pdf-ext.version", ">", "1.2")]))
|
||||
assert resp[0]['id'] == stix_objects[3]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_deduplicate():
|
||||
unique = deduplicate(STIX_OBJS1)
|
||||
|
||||
# Only 3 objects are unique
|
||||
# 2 id's vary
|
||||
# 2 modified times vary for a particular id
|
||||
|
||||
assert len(unique) == 3
|
||||
|
||||
ids = [obj['id'] for obj in unique]
|
||||
mods = [obj['modified'] for obj in unique]
|
||||
|
||||
assert "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f" in ids
|
||||
assert "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f" in ids
|
||||
assert "2017-01-27T13:49:53.935Z" in mods
|
||||
assert "2017-01-27T13:49:53.936Z" in mods
|
||||
|
||||
|
||||
def test_add_remove_composite_datasource():
|
||||
cds = CompositeDataSource()
|
||||
ds1 = MemorySource()
|
||||
ds2 = MemorySource()
|
||||
ds3 = MemorySink()
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
cds.add_data_sources([ds1, ds2, ds1, ds3])
|
||||
assert str(excinfo.value) == ("DataSource (to be added) is not of type "
|
||||
"stix2.DataSource. DataSource type is '<class 'stix2.sources.memory.MemorySink'>'")
|
||||
|
||||
cds.add_data_sources([ds1, ds2, ds1])
|
||||
|
||||
assert len(cds.get_all_data_sources()) == 2
|
||||
|
||||
cds.remove_data_sources([ds1.id, ds2.id])
|
||||
|
||||
assert len(cds.get_all_data_sources()) == 0
|
||||
|
||||
|
||||
def test_composite_datasource_operations():
|
||||
BUNDLE1 = dict(id="bundle--%s" % make_id(),
|
||||
objects=STIX_OBJS1,
|
||||
spec_version="2.0",
|
||||
type="bundle")
|
||||
cds1 = CompositeDataSource()
|
||||
ds1_1 = MemorySource(stix_data=BUNDLE1)
|
||||
ds1_2 = MemorySource(stix_data=STIX_OBJS2)
|
||||
|
||||
cds2 = CompositeDataSource()
|
||||
ds2_1 = MemorySource(stix_data=BUNDLE1)
|
||||
ds2_2 = MemorySource(stix_data=STIX_OBJS2)
|
||||
|
||||
cds1.add_data_sources([ds1_1, ds1_2])
|
||||
cds2.add_data_sources([ds2_1, ds2_2])
|
||||
|
||||
indicators = cds1.all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
# In STIX_OBJS2 changed the 'modified' property to a later time...
|
||||
assert len(indicators) == 2
|
||||
|
||||
cds1.add_data_sources([cds2])
|
||||
|
||||
indicator = cds1.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
assert indicator["id"] == "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
assert indicator["modified"] == "2017-01-31T13:49:53.935Z"
|
||||
assert indicator["type"] == "indicator"
|
||||
|
||||
query1 = [
|
||||
Filter("type", "=", "indicator")
|
||||
]
|
||||
|
||||
query2 = [
|
||||
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z")
|
||||
]
|
||||
|
||||
cds1.filters.update(query2)
|
||||
|
||||
results = cds1.query(query1)
|
||||
|
||||
# STIX_OBJS2 has indicator with later time, one with different id, one with
|
||||
# original time in STIX_OBJS1
|
||||
assert len(results) == 3
|
||||
|
||||
indicator = cds1.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
assert indicator["id"] == "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
assert indicator["modified"] == "2017-01-31T13:49:53.935Z"
|
||||
assert indicator["type"] == "indicator"
|
||||
|
||||
# There is only one indicator with different ID. Since we use the same data
|
||||
# when deduplicated, only two indicators (one with different modified).
|
||||
results = cds1.all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert len(results) == 2
|
||||
|
||||
# Since we have filters already associated with our CompositeSource providing
|
||||
# nothing returns the same as cds1.query(query1) (the associated query is query2)
|
||||
results = cds1.query([])
|
||||
assert len(results) == 3
|
||||
|
||||
|
||||
def test_composite_datastore_no_datasource():
|
||||
cds = CompositeDataSource()
|
||||
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
cds.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert 'CompositeDataSource has no data source' in str(excinfo.value)
|
|
@ -0,0 +1,117 @@
|
|||
import pytest
|
||||
|
||||
from stix2.datastore import (CompositeDataSource, DataSink, DataSource,
|
||||
DataStoreMixin)
|
||||
from stix2.datastore.filters import Filter
|
||||
from stix2.test.constants import CAMPAIGN_MORE_KWARGS
|
||||
|
||||
|
||||
def test_datasource_abstract_class_raises_error():
|
||||
with pytest.raises(TypeError):
|
||||
DataSource()
|
||||
|
||||
|
||||
def test_datasink_abstract_class_raises_error():
|
||||
with pytest.raises(TypeError):
|
||||
DataSink()
|
||||
|
||||
|
||||
def test_datastore_smoke():
|
||||
assert DataStoreMixin() is not None
|
||||
|
||||
|
||||
def test_datastore_get_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_all_versions_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_query_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().query([Filter("type", "=", "indicator")])
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_creator_of_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().creator_of(CAMPAIGN_MORE_KWARGS)
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_relationships_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().relationships(obj="indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
target_only=True)
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_related_to_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().related_to(obj="indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
target_only=True)
|
||||
assert "DataStoreMixin has no data source to query" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_datastore_add_raises():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
DataStoreMixin().add(CAMPAIGN_MORE_KWARGS)
|
||||
assert "DataStoreMixin has no data sink to put objects in" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_get_raises_error():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
CompositeDataSource().get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert "CompositeDataSource has no data sources" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_all_versions_raises_error():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
CompositeDataSource().all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert "CompositeDataSource has no data sources" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_query_raises_error():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
CompositeDataSource().query([Filter("type", "=", "indicator")])
|
||||
assert "CompositeDataSource has no data sources" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_relationships_raises_error():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
CompositeDataSource().relationships(obj="indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
target_only=True)
|
||||
assert "CompositeDataSource has no data sources" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_related_to_raises_error():
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
CompositeDataSource().related_to(obj="indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
target_only=True)
|
||||
assert "CompositeDataSource has no data sources" == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_add_data_source_raises_error():
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
ind = "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
CompositeDataSource().add_data_source(ind)
|
||||
assert "DataSource (to be added) is not of type stix2.DataSource. DataSource type is '{}'".format(type(ind)) == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_add_data_sources_raises_error():
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
ind = "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
CompositeDataSource().add_data_sources(ind)
|
||||
assert "DataSource (to be added) is not of type stix2.DataSource. DataSource type is '{}'".format(type(ind)) == str(excinfo.value)
|
||||
|
||||
|
||||
def test_composite_datastore_no_datasource():
|
||||
cds = CompositeDataSource()
|
||||
with pytest.raises(AttributeError) as excinfo:
|
||||
cds.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert 'CompositeDataSource has no data source' in str(excinfo.value)
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
@ -6,10 +7,10 @@ import pytest
|
|||
from stix2 import (Bundle, Campaign, CustomObject, FileSystemSink,
|
||||
FileSystemSource, FileSystemStore, Filter, Identity,
|
||||
Indicator, Malware, Relationship, properties)
|
||||
|
||||
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID,
|
||||
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
|
||||
MALWARE_ID, MALWARE_KWARGS, RELATIONSHIP_IDS)
|
||||
from stix2.test.constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID,
|
||||
IDENTITY_KWARGS, INDICATOR_ID,
|
||||
INDICATOR_KWARGS, MALWARE_ID, MALWARE_KWARGS,
|
||||
RELATIONSHIP_IDS)
|
||||
|
||||
FS_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "stix2_data")
|
||||
|
||||
|
@ -45,6 +46,41 @@ def fs_sink():
|
|||
shutil.rmtree(os.path.join(FS_PATH, "campaign"), True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bad_json_files():
|
||||
# create erroneous JSON files for tests to make sure handled gracefully
|
||||
|
||||
with open(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-non-json.txt"), "w+") as f:
|
||||
f.write("Im not a JSON file")
|
||||
|
||||
with open(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-bad-json.json"), "w+") as f:
|
||||
f.write("Im not a JSON formatted file")
|
||||
|
||||
yield True # dummy yield so can have teardown
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-non-json.txt"))
|
||||
os.remove(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-bad-json.json"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bad_stix_files():
|
||||
# create erroneous STIX JSON files for tests to make sure handled correctly
|
||||
|
||||
# bad STIX object
|
||||
stix_obj = {
|
||||
"id": "intrusion-set--test-bad-stix",
|
||||
"spec_version": "2.0"
|
||||
# no "type" field
|
||||
}
|
||||
|
||||
with open(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-non-stix.json"), "w+") as f:
|
||||
f.write(json.dumps(stix_obj))
|
||||
|
||||
yield True # dummy yield so can have teardown
|
||||
|
||||
os.remove(os.path.join(FS_PATH, "intrusion-set", "intrusion-set--test-non-stix.json"))
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def rel_fs_store():
|
||||
cam = Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS)
|
||||
|
@ -76,6 +112,26 @@ def test_filesystem_sink_nonexistent_folder():
|
|||
assert "for STIX data does not exist" in str(excinfo)
|
||||
|
||||
|
||||
def test_filesystem_source_bad_json_file(fs_source, bad_json_files):
|
||||
# this tests the handling of two bad json files
|
||||
# - one file should just be skipped (silently) as its a ".txt" extension
|
||||
# - one file should be parsed and raise Exception bc its not JSON
|
||||
try:
|
||||
fs_source.get("intrusion-set--test-bad-json")
|
||||
except TypeError as e:
|
||||
assert "intrusion-set--test-bad-json" in str(e)
|
||||
assert "could either not be parsed to JSON or was not valid STIX JSON" in str(e)
|
||||
|
||||
|
||||
def test_filesystem_source_bad_stix_file(fs_source, bad_stix_files):
|
||||
# this tests handling of bad STIX json object
|
||||
try:
|
||||
fs_source.get("intrusion-set--test-non-stix")
|
||||
except TypeError as e:
|
||||
assert "intrusion-set--test-non-stix" in str(e)
|
||||
assert "could either not be parsed to JSON or was not valid STIX JSON" in str(e)
|
||||
|
||||
|
||||
def test_filesytem_source_get_object(fs_source):
|
||||
# get object
|
||||
mal = fs_source.get("malware--6b616fc1-1505-48e3-8b2c-0d19337bff38")
|
||||
|
@ -364,7 +420,7 @@ def test_filesystem_object_with_custom_property(fs_store):
|
|||
|
||||
fs_store.add(camp, True)
|
||||
|
||||
camp_r = fs_store.get(camp.id, allow_custom=True)
|
||||
camp_r = fs_store.get(camp.id)
|
||||
assert camp_r.id == camp.id
|
||||
assert camp_r.x_empire == camp.x_empire
|
||||
|
||||
|
@ -376,9 +432,9 @@ def test_filesystem_object_with_custom_property_in_bundle(fs_store):
|
|||
allow_custom=True)
|
||||
|
||||
bundle = Bundle(camp, allow_custom=True)
|
||||
fs_store.add(bundle, allow_custom=True)
|
||||
fs_store.add(bundle)
|
||||
|
||||
camp_r = fs_store.get(camp.id, allow_custom=True)
|
||||
camp_r = fs_store.get(camp.id)
|
||||
assert camp_r.id == camp.id
|
||||
assert camp_r.x_empire == camp.x_empire
|
||||
|
||||
|
@ -391,9 +447,9 @@ def test_filesystem_custom_object(fs_store):
|
|||
pass
|
||||
|
||||
newobj = NewObj(property1='something')
|
||||
fs_store.add(newobj, allow_custom=True)
|
||||
fs_store.add(newobj)
|
||||
|
||||
newobj_r = fs_store.get(newobj.id, allow_custom=True)
|
||||
newobj_r = fs_store.get(newobj.id)
|
||||
assert newobj_r.id == newobj.id
|
||||
assert newobj_r.property1 == 'something'
|
||||
|
|
@ -0,0 +1,463 @@
|
|||
import pytest
|
||||
|
||||
from stix2 import parse
|
||||
from stix2.datastore.filters import Filter, apply_common_filters
|
||||
from stix2.utils import STIXdatetime, parse_into_datetime
|
||||
|
||||
stix_objs = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.997Z",
|
||||
"description": "\n\nTITLE:\n\tPoison Ivy",
|
||||
"id": "malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111",
|
||||
"labels": [
|
||||
"remote-access-trojan"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.997Z",
|
||||
"name": "Poison Ivy",
|
||||
"type": "malware"
|
||||
},
|
||||
{
|
||||
"created": "2014-05-08T09:00:00.000Z",
|
||||
"id": "indicator--a932fcc6-e032-176c-126f-cb970a5a1ade",
|
||||
"labels": [
|
||||
"file-hash-watchlist"
|
||||
],
|
||||
"modified": "2014-05-08T09:00:00.000Z",
|
||||
"name": "File hash for Poison Ivy variant",
|
||||
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2014-05-08T09:00:00.000000Z"
|
||||
},
|
||||
{
|
||||
"created": "2014-05-08T09:00:00.000Z",
|
||||
"granular_markings": [
|
||||
{
|
||||
"marking_ref": "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed",
|
||||
"selectors": [
|
||||
"relationship_type"
|
||||
]
|
||||
}
|
||||
],
|
||||
"id": "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463",
|
||||
"modified": "2014-05-08T09:00:00.000Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"
|
||||
],
|
||||
"relationship_type": "indicates",
|
||||
"revoked": True,
|
||||
"source_ref": "indicator--a932fcc6-e032-176c-126f-cb970a5a1ade",
|
||||
"target_ref": "malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111",
|
||||
"type": "relationship"
|
||||
},
|
||||
{
|
||||
"id": "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef",
|
||||
"created": "2016-02-14T00:00:00.000Z",
|
||||
"created_by_ref": "identity--00000000-0000-0000-0000-b8e91df99dc9",
|
||||
"modified": "2016-02-14T00:00:00.000Z",
|
||||
"type": "vulnerability",
|
||||
"name": "CVE-2014-0160",
|
||||
"description": "The (1) TLS...",
|
||||
"external_references": [
|
||||
{
|
||||
"source_name": "cve",
|
||||
"external_id": "CVE-2014-0160"
|
||||
}
|
||||
],
|
||||
"labels": ["heartbleed", "has-logo"]
|
||||
},
|
||||
{
|
||||
"type": "observed-data",
|
||||
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
|
||||
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
"created": "2016-04-06T19:58:16.000Z",
|
||||
"modified": "2016-04-06T19:58:16.000Z",
|
||||
"first_observed": "2015-12-21T19:00:00Z",
|
||||
"last_observed": "2015-12-21T19:00:00Z",
|
||||
"number_observed": 1,
|
||||
"objects": {
|
||||
"0": {
|
||||
"type": "file",
|
||||
"name": "HAL 9000.exe"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
filters = [
|
||||
Filter("type", "!=", "relationship"),
|
||||
Filter("id", "=", "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463"),
|
||||
Filter("labels", "in", "remote-access-trojan"),
|
||||
Filter("created", ">", "2015-01-01T01:00:00.000Z"),
|
||||
Filter("revoked", "=", True),
|
||||
Filter("revoked", "!=", True),
|
||||
Filter("object_marking_refs", "=", "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"),
|
||||
Filter("granular_markings.selectors", "in", "relationship_type"),
|
||||
Filter("granular_markings.marking_ref", "=", "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed"),
|
||||
Filter("external_references.external_id", "in", "CVE-2014-0160,CVE-2017-6608"),
|
||||
Filter("created_by_ref", "=", "identity--00000000-0000-0000-0000-b8e91df99dc9"),
|
||||
Filter("object_marking_refs", "=", "marking-definition--613f2e26-0000-0000-0000-b8e91df99dc9"),
|
||||
Filter("granular_markings.selectors", "in", "description"),
|
||||
Filter("external_references.source_name", "=", "CVE"),
|
||||
Filter("objects", "=", {"0": {"type": "file", "name": "HAL 9000.exe"}})
|
||||
]
|
||||
|
||||
# same as above objects but converted to real Python STIX2 objects
|
||||
# to test filters against true Python STIX2 objects
|
||||
real_stix_objs = [parse(stix_obj) for stix_obj in stix_objs]
|
||||
|
||||
|
||||
def test_filter_ops_check():
|
||||
# invalid filters - non supported operators
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
# create Filter that has an operator that is not allowed
|
||||
Filter('modified', '*', 'not supported operator')
|
||||
assert str(excinfo.value) == "Filter operator '*' not supported for specified property: 'modified'"
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
Filter("type", "%", "4")
|
||||
assert "Filter operator '%' not supported for specified property" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_filter_value_type_check():
|
||||
# invalid filters - non supported value types
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
Filter('created', '=', object())
|
||||
# On Python 2, the type of object() is `<type 'object'>` On Python 3, it's `<class 'object'>`.
|
||||
assert any([s in str(excinfo.value) for s in ["<type 'object'>", "'<class 'object'>'"]])
|
||||
assert "is not supported. The type must be a Python immutable type or dictionary" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
Filter("type", "=", complex(2, -1))
|
||||
assert any([s in str(excinfo.value) for s in ["<type 'complex'>", "'<class 'complex'>'"]])
|
||||
assert "is not supported. The type must be a Python immutable type or dictionary" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
Filter("type", "=", set([16, 23]))
|
||||
assert any([s in str(excinfo.value) for s in ["<type 'set'>", "'<class 'set'>'"]])
|
||||
assert "is not supported. The type must be a Python immutable type or dictionary" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_filter_type_underscore_check():
|
||||
# check that Filters where property="type", value (name) doesnt have underscores
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
Filter("type", "=", "oh_underscore")
|
||||
assert "Filter for property 'type' cannot have its value 'oh_underscore'" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_apply_common_filters0():
|
||||
# "Return any object whose type is not relationship"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[0]]))
|
||||
ids = [r['id'] for r in resp]
|
||||
assert stix_objs[0]['id'] in ids
|
||||
assert stix_objs[1]['id'] in ids
|
||||
assert stix_objs[3]['id'] in ids
|
||||
assert len(ids) == 4
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[0]]))
|
||||
ids = [r.id for r in resp]
|
||||
assert real_stix_objs[0].id in ids
|
||||
assert real_stix_objs[1].id in ids
|
||||
assert real_stix_objs[3].id in ids
|
||||
assert len(ids) == 4
|
||||
|
||||
|
||||
def test_apply_common_filters1():
|
||||
# "Return any object that matched id relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[1]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[1]]))
|
||||
assert resp[0].id == real_stix_objs[2].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters2():
|
||||
# "Return any object that contains remote-access-trojan in labels"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[2]]))
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[2]]))
|
||||
assert resp[0].id == real_stix_objs[0].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters3():
|
||||
# "Return any object created after 2015-01-01T01:00:00.000Z"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[3]]))
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[3]]))
|
||||
assert resp[0].id == real_stix_objs[0].id
|
||||
assert len(resp) == 3
|
||||
|
||||
|
||||
def test_apply_common_filters4():
|
||||
# "Return any revoked object"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[4]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[4]]))
|
||||
assert resp[0].id == real_stix_objs[2].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters5():
|
||||
# "Return any object whose not revoked"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[5]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[5]]))
|
||||
assert len(resp) == 4
|
||||
|
||||
|
||||
def test_apply_common_filters6():
|
||||
# "Return any object that matches marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9 in object_marking_refs"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[6]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[6]]))
|
||||
assert resp[0].id == real_stix_objs[2].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters7():
|
||||
# "Return any object that contains relationship_type in their selectors AND
|
||||
# also has marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed in marking_ref"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[7], filters[8]]))
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[7], filters[8]]))
|
||||
assert resp[0].id == real_stix_objs[2].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters8():
|
||||
# "Return any object that contains CVE-2014-0160,CVE-2017-6608 in their external_id"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[9]]))
|
||||
assert resp[0]['id'] == stix_objs[3]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[9]]))
|
||||
assert resp[0].id == real_stix_objs[3].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters9():
|
||||
# "Return any object that matches created_by_ref identity--00000000-0000-0000-0000-b8e91df99dc9"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[10]]))
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[10]]))
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_apply_common_filters10():
|
||||
# "Return any object that matches marking-definition--613f2e26-0000-0000-0000-b8e91df99dc9 in object_marking_refs" (None)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[11]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[11]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
|
||||
def test_apply_common_filters11():
|
||||
# "Return any object that contains description in its selectors" (None)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[12]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[12]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
|
||||
def test_apply_common_filters12():
|
||||
# "Return any object that matches CVE in source_name" (None, case sensitive)
|
||||
resp = list(apply_common_filters(stix_objs, [filters[13]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[13]]))
|
||||
assert len(resp) == 0
|
||||
|
||||
|
||||
def test_apply_common_filters13():
|
||||
# Return any object that matches file object in "objects"
|
||||
resp = list(apply_common_filters(stix_objs, [filters[14]]))
|
||||
assert resp[0]["id"] == stix_objs[4]["id"]
|
||||
assert len(resp) == 1
|
||||
# important additional check to make sure original File dict was
|
||||
# not converted to File object. (this was a deep bug found)
|
||||
assert isinstance(resp[0]["objects"]["0"], dict)
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs, [filters[14]]))
|
||||
assert resp[0].id == real_stix_objs[4].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_datetime_filter_behavior():
|
||||
"""if a filter is initialized with its value being a datetime object
|
||||
OR the STIX object property being filtered on is a datetime object, all
|
||||
resulting comparisons executed are done on the string representations
|
||||
of the datetime objects, as the Filter functionality will convert
|
||||
all datetime objects to there string forms using format_datetim()
|
||||
|
||||
This test makes sure all datetime comparisons are carried out correctly
|
||||
"""
|
||||
filter_with_dt_obj = Filter("created", "=", parse_into_datetime("2016-02-14T00:00:00.000Z", "millisecond"))
|
||||
filter_with_str = Filter("created", "=", "2016-02-14T00:00:00.000Z")
|
||||
|
||||
# check that filter value is converted from datetime to str
|
||||
assert isinstance(filter_with_dt_obj.value, str)
|
||||
|
||||
# compare datetime string to filter w/ datetime obj
|
||||
resp = list(apply_common_filters(stix_objs, [filter_with_dt_obj]))
|
||||
assert len(resp) == 1
|
||||
assert resp[0]["id"] == "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef"
|
||||
|
||||
# compare datetime obj to filter w/ datetime obj
|
||||
resp = list(apply_common_filters(real_stix_objs, [filter_with_dt_obj]))
|
||||
assert len(resp) == 1
|
||||
assert resp[0]["id"] == "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef"
|
||||
assert isinstance(resp[0].created, STIXdatetime) # make sure original object not altered
|
||||
|
||||
# compare datetime string to filter w/ str
|
||||
resp = list(apply_common_filters(stix_objs, [filter_with_str]))
|
||||
assert len(resp) == 1
|
||||
assert resp[0]["id"] == "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef"
|
||||
|
||||
# compare datetime obj to filter w/ str
|
||||
resp = list(apply_common_filters(real_stix_objs, [filter_with_str]))
|
||||
assert len(resp) == 1
|
||||
assert resp[0]["id"] == "vulnerability--ee916c28-c7a4-4d0d-ad56-a8d357f89fef"
|
||||
assert isinstance(resp[0].created, STIXdatetime) # make sure original object not altered
|
||||
|
||||
|
||||
def test_filters0(stix_objs2, real_stix_objs2):
|
||||
# "Return any object modified before 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("modified", "<", "2017-01-28T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == stix_objs2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs2, [Filter("modified", "<", parse_into_datetime("2017-01-28T13:49:53.935Z"))]))
|
||||
assert resp[0].id == real_stix_objs2[1].id
|
||||
assert len(resp) == 2
|
||||
|
||||
|
||||
def test_filters1(stix_objs2, real_stix_objs2):
|
||||
# "Return any object modified after 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("modified", ">", "2017-01-28T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == stix_objs2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs2, [Filter("modified", ">", parse_into_datetime("2017-01-28T13:49:53.935Z"))]))
|
||||
assert resp[0].id == real_stix_objs2[0].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_filters2(stix_objs2, real_stix_objs2):
|
||||
# "Return any object modified after or on 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("modified", ">=", "2017-01-27T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == stix_objs2[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs2, [Filter("modified", ">=", parse_into_datetime("2017-01-27T13:49:53.935Z"))]))
|
||||
assert resp[0].id == real_stix_objs2[0].id
|
||||
assert len(resp) == 3
|
||||
|
||||
|
||||
def test_filters3(stix_objs2, real_stix_objs2):
|
||||
# "Return any object modified before or on 2017-01-28T13:49:53.935Z"
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("modified", "<=", "2017-01-27T13:49:53.935Z")]))
|
||||
assert resp[0]['id'] == stix_objs2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
# "Return any object modified before or on 2017-01-28T13:49:53.935Z"
|
||||
fv = Filter("modified", "<=", parse_into_datetime("2017-01-27T13:49:53.935Z"))
|
||||
resp = list(apply_common_filters(real_stix_objs2, [fv]))
|
||||
assert resp[0].id == real_stix_objs2[1].id
|
||||
assert len(resp) == 2
|
||||
|
||||
|
||||
def test_filters4():
|
||||
# Assert invalid Filter cannot be created
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
Filter("modified", "?", "2017-01-27T13:49:53.935Z")
|
||||
assert str(excinfo.value) == ("Filter operator '?' not supported "
|
||||
"for specified property: 'modified'")
|
||||
|
||||
|
||||
def test_filters5(stix_objs2, real_stix_objs2):
|
||||
# "Return any object whose id is not indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f"
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("id", "!=", "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f")]))
|
||||
assert resp[0]['id'] == stix_objs2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs2, [Filter("id", "!=", "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f")]))
|
||||
assert resp[0].id == real_stix_objs2[0].id
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_filters6(stix_objs2, real_stix_objs2):
|
||||
# Test filtering on non-common property
|
||||
resp = list(apply_common_filters(stix_objs2, [Filter("name", "=", "Malicious site hosting downloader")]))
|
||||
assert resp[0]['id'] == stix_objs2[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objs2, [Filter("name", "=", "Malicious site hosting downloader")]))
|
||||
assert resp[0].id == real_stix_objs2[0].id
|
||||
assert len(resp) == 3
|
||||
|
||||
|
||||
def test_filters7(stix_objs2, real_stix_objs2):
|
||||
# Test filtering on embedded property
|
||||
obsvd_data_obj = {
|
||||
"type": "observed-data",
|
||||
"id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
|
||||
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
"created": "2016-04-06T19:58:16.000Z",
|
||||
"modified": "2016-04-06T19:58:16.000Z",
|
||||
"first_observed": "2015-12-21T19:00:00Z",
|
||||
"last_observed": "2015-12-21T19:00:00Z",
|
||||
"number_observed": 50,
|
||||
"objects": {
|
||||
"0": {
|
||||
"type": "file",
|
||||
"hashes": {
|
||||
"SHA-256": "35a01331e9ad96f751278b891b6ea09699806faedfa237d40513d92ad1b7100f"
|
||||
},
|
||||
"extensions": {
|
||||
"pdf-ext": {
|
||||
"version": "1.7",
|
||||
"document_info_dict": {
|
||||
"Title": "Sample document",
|
||||
"Author": "Adobe Systems Incorporated",
|
||||
"Creator": "Adobe FrameMaker 5.5.3 for Power Macintosh",
|
||||
"Producer": "Acrobat Distiller 3.01 for Power Macintosh",
|
||||
"CreationDate": "20070412090123-02"
|
||||
},
|
||||
"pdfid0": "DFCE52BD827ECF765649852119D",
|
||||
"pdfid1": "57A1E0F9ED2AE523E313C"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stix_objects = list(stix_objs2) + [obsvd_data_obj]
|
||||
real_stix_objects = list(real_stix_objs2) + [parse(obsvd_data_obj)]
|
||||
|
||||
resp = list(apply_common_filters(stix_objects, [Filter("objects.0.extensions.pdf-ext.version", ">", "1.2")]))
|
||||
assert resp[0]['id'] == stix_objects[3]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = list(apply_common_filters(real_stix_objects, [Filter("objects.0.extensions.pdf-ext.version", ">", "1.2")]))
|
||||
assert resp[0].id == real_stix_objects[3].id
|
||||
assert len(resp) == 1
|
|
@ -0,0 +1,87 @@
|
|||
import pytest
|
||||
|
||||
from stix2.datastore import CompositeDataSource, make_id
|
||||
from stix2.datastore.filters import Filter
|
||||
from stix2.datastore.memory import MemorySink, MemorySource
|
||||
|
||||
|
||||
def test_add_remove_composite_datasource():
|
||||
cds = CompositeDataSource()
|
||||
ds1 = MemorySource()
|
||||
ds2 = MemorySource()
|
||||
ds3 = MemorySink()
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
cds.add_data_sources([ds1, ds2, ds1, ds3])
|
||||
assert str(excinfo.value) == ("DataSource (to be added) is not of type "
|
||||
"stix2.DataSource. DataSource type is '<class 'stix2.datastore.memory.MemorySink'>'")
|
||||
|
||||
cds.add_data_sources([ds1, ds2, ds1])
|
||||
|
||||
assert len(cds.get_all_data_sources()) == 2
|
||||
|
||||
cds.remove_data_sources([ds1.id, ds2.id])
|
||||
|
||||
assert len(cds.get_all_data_sources()) == 0
|
||||
|
||||
|
||||
def test_composite_datasource_operations(stix_objs1, stix_objs2):
|
||||
BUNDLE1 = dict(id="bundle--%s" % make_id(),
|
||||
objects=stix_objs1,
|
||||
spec_version="2.0",
|
||||
type="bundle")
|
||||
cds1 = CompositeDataSource()
|
||||
ds1_1 = MemorySource(stix_data=BUNDLE1)
|
||||
ds1_2 = MemorySource(stix_data=stix_objs2)
|
||||
|
||||
cds2 = CompositeDataSource()
|
||||
ds2_1 = MemorySource(stix_data=BUNDLE1)
|
||||
ds2_2 = MemorySource(stix_data=stix_objs2)
|
||||
|
||||
cds1.add_data_sources([ds1_1, ds1_2])
|
||||
cds2.add_data_sources([ds2_1, ds2_2])
|
||||
|
||||
indicators = cds1.all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
# In STIX_OBJS2 changed the 'modified' property to a later time...
|
||||
assert len(indicators) == 2
|
||||
|
||||
cds1.add_data_sources([cds2])
|
||||
|
||||
indicator = cds1.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
assert indicator["id"] == "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
assert indicator["modified"] == "2017-01-31T13:49:53.935Z"
|
||||
assert indicator["type"] == "indicator"
|
||||
|
||||
query1 = [
|
||||
Filter("type", "=", "indicator")
|
||||
]
|
||||
|
||||
query2 = [
|
||||
Filter("valid_from", "=", "2017-01-27T13:49:53.935382Z")
|
||||
]
|
||||
|
||||
cds1.filters.add(query2)
|
||||
|
||||
results = cds1.query(query1)
|
||||
|
||||
# STIX_OBJS2 has indicator with later time, one with different id, one with
|
||||
# original time in STIX_OBJS1
|
||||
assert len(results) == 3
|
||||
|
||||
indicator = cds1.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
assert indicator["id"] == "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f"
|
||||
assert indicator["modified"] == "2017-01-31T13:49:53.935Z"
|
||||
assert indicator["type"] == "indicator"
|
||||
|
||||
# There is only one indicator with different ID. Since we use the same data
|
||||
# when deduplicated, only two indicators (one with different modified).
|
||||
results = cds1.all_versions("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert len(results) == 2
|
||||
|
||||
# Since we have filters already associated with our CompositeSource providing
|
||||
# nothing returns the same as cds1.query(query1) (the associated query is query2)
|
||||
results = cds1.query([])
|
||||
assert len(results) == 3
|
|
@ -0,0 +1,391 @@
|
|||
import json
|
||||
|
||||
from medallion.filters.basic_filter import BasicFilter
|
||||
import pytest
|
||||
from requests.models import Response
|
||||
from taxii2client import Collection, _filter_kwargs_to_query_params
|
||||
|
||||
from stix2 import (Bundle, TAXIICollectionSink, TAXIICollectionSource,
|
||||
TAXIICollectionStore, ThreatActor)
|
||||
from stix2.datastore import DataSourceError
|
||||
from stix2.datastore.filters import Filter
|
||||
|
||||
COLLECTION_URL = 'https://example.com/api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/'
|
||||
|
||||
|
||||
class MockTAXIICollectionEndpoint(Collection):
|
||||
"""Mock for taxii2_client.TAXIIClient"""
|
||||
|
||||
def __init__(self, url, **kwargs):
|
||||
super(MockTAXIICollectionEndpoint, self).__init__(url, **kwargs)
|
||||
self.objects = []
|
||||
|
||||
def add_objects(self, bundle):
|
||||
self._verify_can_write()
|
||||
if isinstance(bundle, str):
|
||||
bundle = json.loads(bundle)
|
||||
for object in bundle.get("objects", []):
|
||||
self.objects.append(object)
|
||||
|
||||
def get_objects(self, **filter_kwargs):
|
||||
self._verify_can_read()
|
||||
query_params = _filter_kwargs_to_query_params(filter_kwargs)
|
||||
if not isinstance(query_params, dict):
|
||||
query_params = json.loads(query_params)
|
||||
full_filter = BasicFilter(query_params or {})
|
||||
objs = full_filter.process_filter(
|
||||
self.objects,
|
||||
("id", "type", "version"),
|
||||
[]
|
||||
)
|
||||
if objs:
|
||||
return Bundle(objects=objs)
|
||||
else:
|
||||
resp = Response()
|
||||
resp.status_code = 404
|
||||
resp.raise_for_status()
|
||||
|
||||
def get_object(self, id, version=None):
|
||||
self._verify_can_read()
|
||||
query_params = None
|
||||
if version:
|
||||
query_params = _filter_kwargs_to_query_params({"version": version})
|
||||
if query_params:
|
||||
query_params = json.loads(query_params)
|
||||
full_filter = BasicFilter(query_params or {})
|
||||
objs = full_filter.process_filter(
|
||||
self.objects,
|
||||
("version",),
|
||||
[]
|
||||
)
|
||||
if objs:
|
||||
return Bundle(objects=objs)
|
||||
else:
|
||||
resp = Response()
|
||||
resp.status_code = 404
|
||||
resp.raise_for_status()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def collection(stix_objs1):
|
||||
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
|
||||
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
|
||||
"title": "Writable Collection",
|
||||
"description": "This collection is a dropbox for submitting indicators",
|
||||
"can_read": True,
|
||||
"can_write": True,
|
||||
"media_types": [
|
||||
"application/vnd.oasis.stix+json; version=2.0"
|
||||
]
|
||||
})
|
||||
|
||||
mock.objects.extend(stix_objs1)
|
||||
return mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def collection_no_rw_access(stix_objs1):
|
||||
mock = MockTAXIICollectionEndpoint(COLLECTION_URL, **{
|
||||
"id": "91a7b528-80eb-42ed-a74d-c6fbd5a26116",
|
||||
"title": "Not writeable or readable Collection",
|
||||
"description": "This collection is a dropbox for submitting indicators",
|
||||
"can_read": False,
|
||||
"can_write": False,
|
||||
"media_types": [
|
||||
"application/vnd.oasis.stix+json; version=2.0"
|
||||
]
|
||||
})
|
||||
|
||||
mock.objects.extend(stix_objs1)
|
||||
return mock
|
||||
|
||||
|
||||
def test_ds_taxii(collection):
|
||||
ds = TAXIICollectionSource(collection)
|
||||
assert ds.collection is not None
|
||||
|
||||
|
||||
def test_add_stix2_object(collection):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
# create new STIX threat-actor
|
||||
ta = ThreatActor(name="Teddy Bear",
|
||||
labels=["nation-state"],
|
||||
sophistication="innovator",
|
||||
resource_level="government",
|
||||
goals=[
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector",
|
||||
])
|
||||
|
||||
tc_sink.add(ta)
|
||||
|
||||
|
||||
def test_add_stix2_with_custom_object(collection):
|
||||
tc_sink = TAXIICollectionStore(collection, allow_custom=True)
|
||||
|
||||
# create new STIX threat-actor
|
||||
ta = ThreatActor(name="Teddy Bear",
|
||||
labels=["nation-state"],
|
||||
sophistication="innovator",
|
||||
resource_level="government",
|
||||
goals=[
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector",
|
||||
],
|
||||
foo="bar",
|
||||
allow_custom=True)
|
||||
|
||||
tc_sink.add(ta)
|
||||
|
||||
|
||||
def test_add_list_object(collection, indicator):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
# create new STIX threat-actor
|
||||
ta = ThreatActor(name="Teddy Bear",
|
||||
labels=["nation-state"],
|
||||
sophistication="innovator",
|
||||
resource_level="government",
|
||||
goals=[
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector",
|
||||
])
|
||||
|
||||
tc_sink.add([ta, indicator])
|
||||
|
||||
|
||||
def test_add_stix2_bundle_object(collection):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
# create new STIX threat-actor
|
||||
ta = ThreatActor(name="Teddy Bear",
|
||||
labels=["nation-state"],
|
||||
sophistication="innovator",
|
||||
resource_level="government",
|
||||
goals=[
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector",
|
||||
])
|
||||
|
||||
tc_sink.add(Bundle(objects=[ta]))
|
||||
|
||||
|
||||
def test_add_str_object(collection):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
# create new STIX threat-actor
|
||||
ta = """{
|
||||
"type": "threat-actor",
|
||||
"id": "threat-actor--eddff64f-feb1-4469-b07c-499a73c96415",
|
||||
"created": "2018-04-23T16:40:50.847Z",
|
||||
"modified": "2018-04-23T16:40:50.847Z",
|
||||
"name": "Teddy Bear",
|
||||
"goals": [
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector"
|
||||
],
|
||||
"sophistication": "innovator",
|
||||
"resource_level": "government",
|
||||
"labels": [
|
||||
"nation-state"
|
||||
]
|
||||
}"""
|
||||
|
||||
tc_sink.add(ta)
|
||||
|
||||
|
||||
def test_add_dict_object(collection):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
ta = {
|
||||
"type": "threat-actor",
|
||||
"id": "threat-actor--eddff64f-feb1-4469-b07c-499a73c96415",
|
||||
"created": "2018-04-23T16:40:50.847Z",
|
||||
"modified": "2018-04-23T16:40:50.847Z",
|
||||
"name": "Teddy Bear",
|
||||
"goals": [
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector"
|
||||
],
|
||||
"sophistication": "innovator",
|
||||
"resource_level": "government",
|
||||
"labels": [
|
||||
"nation-state"
|
||||
]
|
||||
}
|
||||
|
||||
tc_sink.add(ta)
|
||||
|
||||
|
||||
def test_add_dict_bundle_object(collection):
|
||||
tc_sink = TAXIICollectionSink(collection)
|
||||
|
||||
ta = {
|
||||
"type": "bundle",
|
||||
"id": "bundle--860ccc8d-56c9-4fda-9384-84276fb52fb1",
|
||||
"spec_version": "2.0",
|
||||
"objects": [
|
||||
{
|
||||
"type": "threat-actor",
|
||||
"id": "threat-actor--dc5a2f41-f76e-425a-81fe-33afc7aabd75",
|
||||
"created": "2018-04-23T18:45:11.390Z",
|
||||
"modified": "2018-04-23T18:45:11.390Z",
|
||||
"name": "Teddy Bear",
|
||||
"goals": [
|
||||
"compromising environment NGOs",
|
||||
"water-hole attacks geared towards energy sector"
|
||||
],
|
||||
"sophistication": "innovator",
|
||||
"resource_level": "government",
|
||||
"labels": [
|
||||
"nation-state"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
tc_sink.add(ta)
|
||||
|
||||
|
||||
def test_get_stix2_object(collection):
|
||||
tc_sink = TAXIICollectionSource(collection)
|
||||
|
||||
objects = tc_sink.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
assert objects
|
||||
|
||||
|
||||
def test_parse_taxii_filters(collection):
|
||||
query = [
|
||||
Filter("added_after", "=", "2016-02-01T00:00:01.000Z"),
|
||||
Filter("id", "=", "taxii stix object ID"),
|
||||
Filter("type", "=", "taxii stix object ID"),
|
||||
Filter("version", "=", "first"),
|
||||
Filter("created_by_ref", "=", "Bane"),
|
||||
]
|
||||
|
||||
taxii_filters_expected = [
|
||||
Filter("added_after", "=", "2016-02-01T00:00:01.000Z"),
|
||||
Filter("id", "=", "taxii stix object ID"),
|
||||
Filter("type", "=", "taxii stix object ID"),
|
||||
Filter("version", "=", "first")
|
||||
]
|
||||
|
||||
ds = TAXIICollectionSource(collection)
|
||||
|
||||
taxii_filters = ds._parse_taxii_filters(query)
|
||||
|
||||
assert taxii_filters == taxii_filters_expected
|
||||
|
||||
|
||||
def test_add_get_remove_filter(collection):
|
||||
ds = TAXIICollectionSource(collection)
|
||||
|
||||
# First 3 filters are valid, remaining properties are erroneous in some way
|
||||
valid_filters = [
|
||||
Filter('type', '=', 'malware'),
|
||||
Filter('id', '!=', 'stix object id'),
|
||||
Filter('labels', 'in', ["heartbleed", "malicious-activity"]),
|
||||
]
|
||||
|
||||
assert len(ds.filters) == 0
|
||||
|
||||
ds.filters.add(valid_filters[0])
|
||||
assert len(ds.filters) == 1
|
||||
|
||||
# Addin the same filter again will have no effect since `filters` acts
|
||||
# like a set
|
||||
ds.filters.add(valid_filters[0])
|
||||
assert len(ds.filters) == 1
|
||||
|
||||
ds.filters.add(valid_filters[1])
|
||||
assert len(ds.filters) == 2
|
||||
|
||||
ds.filters.add(valid_filters[2])
|
||||
assert len(ds.filters) == 3
|
||||
|
||||
assert valid_filters == [f for f in ds.filters]
|
||||
|
||||
# remove
|
||||
ds.filters.remove(valid_filters[0])
|
||||
|
||||
assert len(ds.filters) == 2
|
||||
|
||||
ds.filters.add(valid_filters)
|
||||
|
||||
|
||||
def test_get_all_versions(collection):
|
||||
ds = TAXIICollectionStore(collection)
|
||||
|
||||
indicators = ds.all_versions('indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f')
|
||||
# There are 3 indicators but 2 share the same 'modified' timestamp
|
||||
assert len(indicators) == 2
|
||||
|
||||
|
||||
def test_can_read_error(collection_no_rw_access):
|
||||
"""create a TAXIICOllectionSource with a taxii2client.Collection
|
||||
instance that does not have read access, check ValueError exception is raised"""
|
||||
|
||||
with pytest.raises(DataSourceError) as excinfo:
|
||||
TAXIICollectionSource(collection_no_rw_access)
|
||||
assert "Collection object provided does not have read access" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_can_write_error(collection_no_rw_access):
|
||||
"""create a TAXIICOllectionSink with a taxii2client.Collection
|
||||
instance that does not have write access, check ValueError exception is raised"""
|
||||
|
||||
with pytest.raises(DataSourceError) as excinfo:
|
||||
TAXIICollectionSink(collection_no_rw_access)
|
||||
assert "Collection object provided does not have write access" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_get_404():
|
||||
"""a TAXIICollectionSource.get() call that receives an HTTP 404 response
|
||||
code from the taxii2client should be be returned as None.
|
||||
|
||||
TAXII spec states that a TAXII server can return a 404 for nonexistent
|
||||
resources or lack of access. Decided that None is acceptable reponse
|
||||
to imply that state of the TAXII endpoint.
|
||||
"""
|
||||
|
||||
class TAXIICollection404():
|
||||
can_read = True
|
||||
|
||||
def get_object(self, id, version=None):
|
||||
resp = Response()
|
||||
resp.status_code = 404
|
||||
resp.raise_for_status()
|
||||
|
||||
ds = TAXIICollectionSource(TAXIICollection404())
|
||||
|
||||
# this will raise 404 from mock TAXII Client but TAXIICollectionStore
|
||||
# should handle gracefully and return None
|
||||
stix_obj = ds.get("indicator--1")
|
||||
assert stix_obj is None
|
||||
|
||||
|
||||
def test_all_versions_404(collection):
|
||||
""" a TAXIICollectionSource.all_version() call that recieves an HTTP 404
|
||||
response code from the taxii2client should be returned as an exception"""
|
||||
|
||||
ds = TAXIICollectionStore(collection)
|
||||
|
||||
with pytest.raises(DataSourceError) as excinfo:
|
||||
ds.all_versions("indicator--1")
|
||||
assert "are either not found or access is denied" in str(excinfo.value)
|
||||
assert "404" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_query_404(collection):
|
||||
""" a TAXIICollectionSource.query() call that recieves an HTTP 404
|
||||
response code from the taxii2client should be returned as an exception"""
|
||||
|
||||
ds = TAXIICollectionStore(collection)
|
||||
query = [Filter("type", "=", "malware")]
|
||||
|
||||
with pytest.raises(DataSourceError) as excinfo:
|
||||
ds.query(query=query)
|
||||
assert "are either not found or access is denied" in str(excinfo.value)
|
||||
assert "404" in str(excinfo.value)
|
|
@ -47,7 +47,7 @@ def test_object_factory_created():
|
|||
assert ind.modified == FAKE_TIME
|
||||
|
||||
|
||||
def test_object_factory_external_resource():
|
||||
def test_object_factory_external_reference():
|
||||
ext_ref = stix2.ExternalReference(source_name="ACME Threat Intel",
|
||||
description="Threat report")
|
||||
factory = stix2.ObjectFactory(external_references=ext_ref)
|
||||
|
|
|
@ -42,7 +42,7 @@ def test_external_reference_capec():
|
|||
)
|
||||
|
||||
assert str(ref) == CAPEC
|
||||
assert re.match("ExternalReference\(source_name=u?'capec', external_id=u?'CAPEC-550'\)", repr(ref))
|
||||
assert re.match("ExternalReference\\(source_name=u?'capec', external_id=u?'CAPEC-550'\\)", repr(ref))
|
||||
|
||||
|
||||
CAPEC_URL = """{
|
||||
|
@ -109,7 +109,7 @@ def test_external_reference_offline():
|
|||
)
|
||||
|
||||
assert str(ref) == OFFLINE
|
||||
assert re.match("ExternalReference\(source_name=u?'ACME Threat Intel', description=u?'Threat report'\)", repr(ref))
|
||||
assert re.match("ExternalReference\\(source_name=u?'ACME Threat Intel', description=u?'Threat report'\\)", repr(ref))
|
||||
# Yikes! This works
|
||||
assert eval("stix2." + repr(ref)) == ref
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import pytest
|
||||
|
||||
from stix2 import TLP_RED, Malware, markings
|
||||
from stix2.exceptions import MarkingNotFoundError
|
||||
|
||||
from .constants import MALWARE_MORE_KWARGS as MALWARE_KWARGS_CONST
|
||||
from .constants import MARKING_IDS
|
||||
|
@ -546,6 +547,20 @@ def test_remove_marking_bad_selector():
|
|||
markings.remove_markings(before, ["marking-definition--1", "marking-definition--2"], ["title"])
|
||||
|
||||
|
||||
def test_remove_marking_not_present():
|
||||
before = Malware(
|
||||
granular_markings=[
|
||||
{
|
||||
"selectors": ["description"],
|
||||
"marking_ref": MARKING_IDS[0]
|
||||
}
|
||||
],
|
||||
**MALWARE_KWARGS
|
||||
)
|
||||
with pytest.raises(MarkingNotFoundError):
|
||||
markings.remove_markings(before, [MARKING_IDS[1]], ["description"])
|
||||
|
||||
|
||||
IS_MARKED_TEST_DATA = [
|
||||
Malware(
|
||||
granular_markings=[
|
||||
|
@ -1044,3 +1059,10 @@ def test_clear_marking_bad_selector(data, selector):
|
|||
"""Test bad selector raises exception."""
|
||||
with pytest.raises(AssertionError):
|
||||
markings.clear_markings(data, selector)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", CLEAR_MARKINGS_TEST_DATA)
|
||||
def test_clear_marking_not_present(data):
|
||||
"""Test clearing markings for a selector that has no associated markings."""
|
||||
with pytest.raises(MarkingNotFoundError):
|
||||
data = markings.clear_markings(data, ["labels"])
|
||||
|
|
|
@ -45,6 +45,7 @@ def test_indicator_with_all_required_properties():
|
|||
labels=['malicious-activity'],
|
||||
)
|
||||
|
||||
assert ind.revoked is False
|
||||
assert str(ind) == EXPECTED_INDICATOR
|
||||
rep = re.sub(r"(\[|=| )u('|\"|\\\'|\\\")", r"\g<1>\g<2>", repr(ind))
|
||||
assert rep == EXPECTED_INDICATOR_REPR
|
||||
|
|
|
@ -126,7 +126,7 @@ def test_parse_malware(data):
|
|||
|
||||
|
||||
def test_parse_malware_invalid_labels():
|
||||
data = re.compile('\[.+\]', re.DOTALL).sub('1', EXPECTED_MALWARE)
|
||||
data = re.compile('\\[.+\\]', re.DOTALL).sub('1', EXPECTED_MALWARE)
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.parse(data)
|
||||
assert "Invalid value for Malware 'labels'" in str(excinfo.value)
|
||||
|
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
from stix2 import (Bundle, Campaign, CustomObject, Filter, Identity, Indicator,
|
||||
Malware, MemorySource, MemoryStore, Relationship,
|
||||
properties)
|
||||
from stix2.sources import make_id
|
||||
from stix2.datastore import make_id
|
||||
|
||||
from .constants import (CAMPAIGN_ID, CAMPAIGN_KWARGS, IDENTITY_ID,
|
||||
IDENTITY_KWARGS, INDICATOR_ID, INDICATOR_KWARGS,
|
||||
|
@ -136,6 +136,19 @@ def rel_mem_store():
|
|||
yield MemoryStore(stix_objs)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fs_mem_store(request, mem_store):
|
||||
filename = 'memory_test/mem_store.json'
|
||||
mem_store.save_to_file(filename)
|
||||
|
||||
def fin():
|
||||
# teardown, excecuted regardless of exception
|
||||
shutil.rmtree(os.path.dirname(filename))
|
||||
request.addfinalizer(fin)
|
||||
|
||||
return filename
|
||||
|
||||
|
||||
def test_memory_source_get(mem_source):
|
||||
resp = mem_source.get("indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert resp["id"] == "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f"
|
||||
|
@ -187,9 +200,11 @@ def test_memory_store_query_multiple_filters(mem_store):
|
|||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_memory_store_save_load_file(mem_store):
|
||||
filename = 'memory_test/mem_store.json'
|
||||
mem_store.save_to_file(filename)
|
||||
def test_memory_store_save_load_file(mem_store, fs_mem_store):
|
||||
filename = fs_mem_store # the fixture fs_mem_store yields filename where the memory store was written to
|
||||
|
||||
# STIX2 contents of mem_store have already been written to file
|
||||
# (this is done in fixture 'fs_mem_store'), so can already read-in here
|
||||
contents = open(os.path.abspath(filename)).read()
|
||||
|
||||
assert '"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",' in contents
|
||||
|
@ -200,66 +215,13 @@ def test_memory_store_save_load_file(mem_store):
|
|||
assert mem_store2.get("indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f")
|
||||
assert mem_store2.get("indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f")
|
||||
|
||||
shutil.rmtree(os.path.dirname(filename))
|
||||
|
||||
|
||||
def test_memory_store_add_stix_object_str(mem_store):
|
||||
# add stix object string
|
||||
camp_id = "campaign--111111b6-1112-4fb0-111b-b111107ca70a"
|
||||
camp_name = "Aurelius"
|
||||
camp_alias = "Purple Robes"
|
||||
camp = """{
|
||||
"name": "%s",
|
||||
"type": "campaign",
|
||||
"objective": "German and French Intelligence Services",
|
||||
"aliases": ["%s"],
|
||||
"id": "%s",
|
||||
"created": "2017-05-31T21:31:53.197755Z"
|
||||
}""" % (camp_name, camp_alias, camp_id)
|
||||
|
||||
mem_store.add(camp)
|
||||
|
||||
camp_r = mem_store.get(camp_id)
|
||||
assert camp_r["id"] == camp_id
|
||||
assert camp_r["name"] == camp_name
|
||||
assert camp_alias in camp_r["aliases"]
|
||||
|
||||
|
||||
def test_memory_store_add_stix_bundle_str(mem_store):
|
||||
# add stix bundle string
|
||||
camp_id = "campaign--133111b6-1112-4fb0-111b-b111107ca70a"
|
||||
camp_name = "Atilla"
|
||||
camp_alias = "Huns"
|
||||
bund = """{
|
||||
"type": "bundle",
|
||||
"id": "bundle--112211b6-1112-4fb0-111b-b111107ca70a",
|
||||
"spec_version": "2.0",
|
||||
"objects": [
|
||||
{
|
||||
"name": "%s",
|
||||
"type": "campaign",
|
||||
"objective": "Bulgarian, Albanian and Romanian Intelligence Services",
|
||||
"aliases": ["%s"],
|
||||
"id": "%s",
|
||||
"created": "2017-05-31T21:31:53.197755Z"
|
||||
}
|
||||
]
|
||||
}""" % (camp_name, camp_alias, camp_id)
|
||||
|
||||
mem_store.add(bund)
|
||||
|
||||
camp_r = mem_store.get(camp_id)
|
||||
assert camp_r["id"] == camp_id
|
||||
assert camp_r["name"] == camp_name
|
||||
assert camp_alias in camp_r["aliases"]
|
||||
|
||||
|
||||
def test_memory_store_add_invalid_object(mem_store):
|
||||
ind = ('indicator', IND1) # tuple isn't valid
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
mem_store.add(ind)
|
||||
assert 'stix_data must be' in str(excinfo.value)
|
||||
assert 'a STIX object' in str(excinfo.value)
|
||||
assert 'stix_data expected to be' in str(excinfo.value)
|
||||
assert 'a python-stix2 object' in str(excinfo.value)
|
||||
assert 'JSON formatted STIX' in str(excinfo.value)
|
||||
assert 'JSON formatted STIX bundle' in str(excinfo.value)
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
import stix2
|
||||
|
||||
|
||||
|
@ -67,7 +71,11 @@ def test_file_observable_expression():
|
|||
assert str(exp) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f' AND file:mime_type = 'application/x-pdf']" # noqa
|
||||
|
||||
|
||||
def test_multiple_file_observable_expression():
|
||||
@pytest.mark.parametrize("observation_class, op", [
|
||||
(stix2.AndObservationExpression, 'AND'),
|
||||
(stix2.OrObservationExpression, 'OR'),
|
||||
])
|
||||
def test_multiple_file_observable_expression(observation_class, op):
|
||||
exp1 = stix2.EqualityComparisonExpression("file:hashes.'SHA-256'",
|
||||
stix2.HashConstant(
|
||||
"bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c",
|
||||
|
@ -81,8 +89,8 @@ def test_multiple_file_observable_expression():
|
|||
'SHA-256'))
|
||||
op1_exp = stix2.ObservationExpression(bool1_exp)
|
||||
op2_exp = stix2.ObservationExpression(exp3)
|
||||
exp = stix2.AndObservationExpression([op1_exp, op2_exp])
|
||||
assert str(exp) == "[file:hashes.'SHA-256' = 'bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c' OR file:hashes.MD5 = 'cead3f77f6cda6ec00f57d76c9a6879f'] AND [file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']" # noqa
|
||||
exp = observation_class([op1_exp, op2_exp])
|
||||
assert str(exp) == "[file:hashes.'SHA-256' = 'bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c' OR file:hashes.MD5 = 'cead3f77f6cda6ec00f57d76c9a6879f'] {} [file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']".format(op) # noqa
|
||||
|
||||
|
||||
def test_root_types():
|
||||
|
@ -120,6 +128,31 @@ def test_greater_than():
|
|||
assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
|
||||
|
||||
|
||||
def test_less_than():
|
||||
exp = stix2.LessThanComparisonExpression("file:size",
|
||||
1024)
|
||||
assert str(exp) == "file:size < 1024"
|
||||
|
||||
|
||||
def test_greater_than_or_equal():
|
||||
exp = stix2.GreaterThanEqualComparisonExpression("file:size",
|
||||
1024)
|
||||
assert str(exp) == "file:size >= 1024"
|
||||
|
||||
|
||||
def test_less_than_or_equal():
|
||||
exp = stix2.LessThanEqualComparisonExpression("file:size",
|
||||
1024)
|
||||
assert str(exp) == "file:size <= 1024"
|
||||
|
||||
|
||||
def test_not():
|
||||
exp = stix2.LessThanComparisonExpression("file:size",
|
||||
1024,
|
||||
negated=True)
|
||||
assert str(exp) == "file:size NOT < 1024"
|
||||
|
||||
|
||||
def test_and_observable_expression():
|
||||
exp1 = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:account_type",
|
||||
"unix"),
|
||||
|
@ -145,6 +178,15 @@ def test_and_observable_expression():
|
|||
assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1009' AND user-account:account_login = 'Mary']" # noqa
|
||||
|
||||
|
||||
def test_invalid_and_observable_expression():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("user-account:display_name",
|
||||
"admin"),
|
||||
stix2.EqualityComparisonExpression("email-addr:display_name",
|
||||
stix2.StringConstant("admin"))])
|
||||
assert "All operands to an 'AND' expression must have the same object type" in str(excinfo)
|
||||
|
||||
|
||||
def test_hex():
|
||||
exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("file:mime_type",
|
||||
"image/bmp"),
|
||||
|
@ -175,3 +217,164 @@ def test_set_op():
|
|||
def test_timestamp():
|
||||
ts = stix2.TimestampConstant('2014-01-13T07:03:17Z')
|
||||
assert str(ts) == "t'2014-01-13T07:03:17Z'"
|
||||
|
||||
|
||||
def test_boolean():
|
||||
exp = stix2.EqualityComparisonExpression("email-message:is_multipart",
|
||||
True)
|
||||
assert str(exp) == "email-message:is_multipart = true"
|
||||
|
||||
|
||||
def test_binary():
|
||||
const = stix2.BinaryConstant("dGhpcyBpcyBhIHRlc3Q=")
|
||||
exp = stix2.EqualityComparisonExpression("artifact:payload_bin",
|
||||
const)
|
||||
assert str(exp) == "artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q='"
|
||||
|
||||
|
||||
def test_list():
|
||||
exp = stix2.InComparisonExpression("process:name",
|
||||
['proccy', 'proximus', 'badproc'])
|
||||
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
|
||||
|
||||
|
||||
def test_list2():
|
||||
# alternate way to construct an "IN" Comparison Expression
|
||||
exp = stix2.EqualityComparisonExpression("process:name",
|
||||
['proccy', 'proximus', 'badproc'])
|
||||
assert str(exp) == "process:name IN ('proccy', 'proximus', 'badproc')"
|
||||
|
||||
|
||||
def test_invalid_constant_type():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.EqualityComparisonExpression("artifact:payload_bin",
|
||||
{'foo': 'bar'})
|
||||
assert 'Unable to create a constant' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_integer_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.IntegerConstant('foo')
|
||||
assert 'must be an integer' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_timestamp_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.TimestampConstant('foo')
|
||||
assert 'must be a datetime object or timestamp string' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_float_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.FloatConstant('foo')
|
||||
assert 'must be a float' in str(excinfo)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data, result", [
|
||||
(True, True),
|
||||
(False, False),
|
||||
('True', True),
|
||||
('False', False),
|
||||
('true', True),
|
||||
('false', False),
|
||||
('t', True),
|
||||
('f', False),
|
||||
('T', True),
|
||||
('F', False),
|
||||
(1, True),
|
||||
(0, False),
|
||||
])
|
||||
def test_boolean_constant(data, result):
|
||||
boolean = stix2.BooleanConstant(data)
|
||||
assert boolean.value == result
|
||||
|
||||
|
||||
def test_invalid_boolean_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.BooleanConstant('foo')
|
||||
assert 'must be a boolean' in str(excinfo)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("hashtype, data", [
|
||||
('MD5', 'zzz'),
|
||||
('ssdeep', 'zzz=='),
|
||||
])
|
||||
def test_invalid_hash_constant(hashtype, data):
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.HashConstant(data, hashtype)
|
||||
assert 'is not a valid {} hash'.format(hashtype) in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_hex_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.HexConstant('mm')
|
||||
assert "must contain an even number of hexadecimal characters" in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_binary_constant():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.BinaryConstant('foo')
|
||||
assert 'must contain a base64' in str(excinfo)
|
||||
|
||||
|
||||
def test_escape_quotes_and_backslashes():
|
||||
exp = stix2.MatchesComparisonExpression("file:name",
|
||||
"^Final Report.+\\.exe$")
|
||||
assert str(exp) == "file:name MATCHES '^Final Report.+\\\\.exe$'"
|
||||
|
||||
|
||||
def test_like():
|
||||
exp = stix2.LikeComparisonExpression("directory:path",
|
||||
"C:\\Windows\\%\\foo")
|
||||
assert str(exp) == "directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo'"
|
||||
|
||||
|
||||
def test_issuperset():
|
||||
exp = stix2.IsSupersetComparisonExpression("ipv4-addr:value",
|
||||
"198.51.100.0/24")
|
||||
assert str(exp) == "ipv4-addr:value ISSUPERSET '198.51.100.0/24'"
|
||||
|
||||
|
||||
def test_repeat_qualifier():
|
||||
qual = stix2.RepeatQualifier(stix2.IntegerConstant(5))
|
||||
assert str(qual) == 'REPEATS 5 TIMES'
|
||||
|
||||
|
||||
def test_invalid_repeat_qualifier():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.RepeatQualifier('foo')
|
||||
assert 'is not a valid argument for a Repeat Qualifier' in str(excinfo)
|
||||
|
||||
|
||||
def test_invalid_within_qualifier():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.WithinQualifier('foo')
|
||||
assert 'is not a valid argument for a Within Qualifier' in str(excinfo)
|
||||
|
||||
|
||||
def test_startstop_qualifier():
|
||||
qual = stix2.StartStopQualifier(stix2.TimestampConstant('2016-06-01T00:00:00Z'),
|
||||
datetime.datetime(2017, 3, 12, 8, 30, 0))
|
||||
assert str(qual) == "START t'2016-06-01T00:00:00Z' STOP t'2017-03-12T08:30:00Z'"
|
||||
|
||||
qual2 = stix2.StartStopQualifier(datetime.date(2016, 6, 1),
|
||||
stix2.TimestampConstant('2016-07-01T00:00:00Z'))
|
||||
assert str(qual2) == "START t'2016-06-01T00:00:00Z' STOP t'2016-07-01T00:00:00Z'"
|
||||
|
||||
|
||||
def test_invalid_startstop_qualifier():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.StartStopQualifier('foo',
|
||||
stix2.TimestampConstant('2016-06-01T00:00:00Z'))
|
||||
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
stix2.StartStopQualifier(datetime.date(2016, 6, 1),
|
||||
'foo')
|
||||
assert 'is not a valid argument for a Start/Stop Qualifier' in str(excinfo)
|
||||
|
||||
|
||||
def test_make_constant_already_a_constant():
|
||||
str_const = stix2.StringConstant('Foo')
|
||||
result = stix2.patterns.make_constant(str_const)
|
||||
assert result is str_const
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from stix2 import EmailMIMEComponent, ExtensionsProperty, TCPExt
|
||||
from stix2 import CustomObject, EmailMIMEComponent, ExtensionsProperty, TCPExt
|
||||
from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
|
||||
from stix2.properties import (BinaryProperty, BooleanProperty,
|
||||
DictionaryProperty, EmbeddedObjectProperty,
|
||||
|
@ -16,6 +16,8 @@ def test_property():
|
|||
p = Property()
|
||||
|
||||
assert p.required is False
|
||||
assert p.clean('foo') == 'foo'
|
||||
assert p.clean(3) == 3
|
||||
|
||||
|
||||
def test_basic_clean():
|
||||
|
@ -264,6 +266,17 @@ def test_dictionary_property_invalid(d):
|
|||
assert str(excinfo.value) == d[1]
|
||||
|
||||
|
||||
def test_property_list_of_dictionary():
|
||||
@CustomObject('x-new-obj', [
|
||||
('property1', ListProperty(DictionaryProperty(), required=True)),
|
||||
])
|
||||
class NewObj():
|
||||
pass
|
||||
|
||||
test_obj = NewObj(property1=[{'foo': 'bar'}])
|
||||
assert test_obj.property1[0]['foo'] == 'bar'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [
|
||||
{"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"},
|
||||
[('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')],
|
||||
|
|
|
@ -123,8 +123,8 @@ def test_create_relationship_from_objects_rather_than_ids(indicator, malware):
|
|||
|
||||
assert rel.relationship_type == 'indicates'
|
||||
assert rel.source_ref == 'indicator--00000000-0000-0000-0000-000000000001'
|
||||
assert rel.target_ref == 'malware--00000000-0000-0000-0000-000000000002'
|
||||
assert rel.id == 'relationship--00000000-0000-0000-0000-000000000003'
|
||||
assert rel.target_ref == 'malware--00000000-0000-0000-0000-000000000003'
|
||||
assert rel.id == 'relationship--00000000-0000-0000-0000-000000000005'
|
||||
|
||||
|
||||
def test_create_relationship_with_positional_args(indicator, malware):
|
||||
|
@ -132,8 +132,8 @@ def test_create_relationship_with_positional_args(indicator, malware):
|
|||
|
||||
assert rel.relationship_type == 'indicates'
|
||||
assert rel.source_ref == 'indicator--00000000-0000-0000-0000-000000000001'
|
||||
assert rel.target_ref == 'malware--00000000-0000-0000-0000-000000000002'
|
||||
assert rel.id == 'relationship--00000000-0000-0000-0000-000000000003'
|
||||
assert rel.target_ref == 'malware--00000000-0000-0000-0000-000000000003'
|
||||
assert rel.id == 'relationship--00000000-0000-0000-0000-000000000005'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", [
|
||||
|
|
|
@ -86,7 +86,7 @@ def test_create_sighting_from_objects_rather_than_ids(malware): # noqa: F811
|
|||
rel = stix2.Sighting(sighting_of_ref=malware)
|
||||
|
||||
assert rel.sighting_of_ref == 'malware--00000000-0000-0000-0000-000000000001'
|
||||
assert rel.id == 'sighting--00000000-0000-0000-0000-000000000002'
|
||||
assert rel.id == 'sighting--00000000-0000-0000-0000-000000000003'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", [
|
||||
|
|
|
@ -19,6 +19,19 @@ EXPECTED = """{
|
|||
]
|
||||
}"""
|
||||
|
||||
EXPECTED_WITH_REVOKED = """{
|
||||
"type": "tool",
|
||||
"id": "tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
|
||||
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
"created": "2016-04-06T20:03:48.000Z",
|
||||
"modified": "2016-04-06T20:03:48.000Z",
|
||||
"name": "VNC",
|
||||
"revoked": false,
|
||||
"labels": [
|
||||
"remote-access"
|
||||
]
|
||||
}"""
|
||||
|
||||
|
||||
def test_tool_example():
|
||||
tool = stix2.Tool(
|
||||
|
@ -58,4 +71,24 @@ def test_parse_tool(data):
|
|||
assert tool.labels == ["remote-access"]
|
||||
assert tool.name == "VNC"
|
||||
|
||||
|
||||
def test_tool_no_workbench_wrappers():
|
||||
tool = stix2.Tool(name='VNC', labels=['remote-access'])
|
||||
with pytest.raises(AttributeError):
|
||||
tool.created_by()
|
||||
|
||||
|
||||
def test_tool_serialize_with_defaults():
|
||||
tool = stix2.Tool(
|
||||
id="tool--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
|
||||
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
created="2016-04-06T20:03:48.000Z",
|
||||
modified="2016-04-06T20:03:48.000Z",
|
||||
name="VNC",
|
||||
labels=["remote-access"],
|
||||
)
|
||||
|
||||
assert tool.serialize(pretty=True, include_optional_defaults=True) == EXPECTED_WITH_REVOKED
|
||||
|
||||
|
||||
# TODO: Add other examples
|
||||
|
|
|
@ -62,7 +62,7 @@ def test_parse_datetime_invalid(ts):
|
|||
[("a", 1,)],
|
||||
])
|
||||
def test_get_dict(data):
|
||||
assert stix2.utils.get_dict(data)
|
||||
assert stix2.utils._get_dict(data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('data', [
|
||||
|
@ -73,7 +73,7 @@ def test_get_dict(data):
|
|||
])
|
||||
def test_get_dict_invalid(data):
|
||||
with pytest.raises(ValueError):
|
||||
stix2.utils.get_dict(data)
|
||||
stix2.utils._get_dict(data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('stix_id, typ', [
|
||||
|
@ -82,3 +82,21 @@ def test_get_dict_invalid(data):
|
|||
])
|
||||
def test_get_type_from_id(stix_id, typ):
|
||||
assert stix2.utils.get_type_from_id(stix_id) == typ
|
||||
|
||||
|
||||
def test_deduplicate(stix_objs1):
|
||||
unique = stix2.utils.deduplicate(stix_objs1)
|
||||
|
||||
# Only 3 objects are unique
|
||||
# 2 id's vary
|
||||
# 2 modified times vary for a particular id
|
||||
|
||||
assert len(unique) == 3
|
||||
|
||||
ids = [obj['id'] for obj in unique]
|
||||
mods = [obj['modified'] for obj in unique]
|
||||
|
||||
assert "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f" in ids
|
||||
assert "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f" in ids
|
||||
assert "2017-01-27T13:49:53.935Z" in mods
|
||||
assert "2017-01-27T13:49:53.936Z" in mods
|
||||
|
|
|
@ -88,11 +88,15 @@ def test_versioning_error_bad_modified_value():
|
|||
|
||||
assert excinfo.value.cls == stix2.Campaign
|
||||
assert excinfo.value.prop_name == "modified"
|
||||
assert excinfo.value.reason == "The new modified datetime cannot be before the current modified datatime."
|
||||
assert excinfo.value.reason == "The new modified datetime cannot be before than or equal to the current modified datetime." \
|
||||
"It cannot be equal, as according to STIX 2 specification, objects that are different " \
|
||||
"but have the same id and modified timestamp do not have defined consumer behavior."
|
||||
|
||||
msg = "Invalid value for {0} '{1}': {2}"
|
||||
msg = msg.format(stix2.Campaign.__name__, "modified",
|
||||
"The new modified datetime cannot be before the current modified datatime.")
|
||||
"The new modified datetime cannot be before than or equal to the current modified datetime."
|
||||
"It cannot be equal, as according to STIX 2 specification, objects that are different "
|
||||
"but have the same id and modified timestamp do not have defined consumer behavior.")
|
||||
assert str(excinfo.value) == msg
|
||||
|
||||
|
||||
|
@ -153,7 +157,9 @@ def test_versioning_error_dict_bad_modified_value():
|
|||
|
||||
assert excinfo.value.cls == dict
|
||||
assert excinfo.value.prop_name == "modified"
|
||||
assert excinfo.value.reason == "The new modified datetime cannot be before the current modified datatime."
|
||||
assert excinfo.value.reason == "The new modified datetime cannot be before than or equal to the current modified datetime." \
|
||||
"It cannot be equal, as according to STIX 2 specification, objects that are different " \
|
||||
"but have the same id and modified timestamp do not have defined consumer behavior."
|
||||
|
||||
|
||||
def test_versioning_error_dict_no_modified_value():
|
||||
|
@ -206,3 +212,40 @@ def test_revoke_invalid_cls():
|
|||
stix2.utils.revoke(campaign_v1)
|
||||
|
||||
assert 'cannot revoke object of this type' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_remove_custom_stix_property():
|
||||
mal = stix2.Malware(name="ColePowers",
|
||||
labels=["rootkit"],
|
||||
x_custom="armada",
|
||||
allow_custom=True)
|
||||
|
||||
mal_nc = stix2.utils.remove_custom_stix(mal)
|
||||
|
||||
assert "x_custom" not in mal_nc
|
||||
assert stix2.utils.parse_into_datetime(mal["modified"], precision="millisecond") < stix2.utils.parse_into_datetime(mal_nc["modified"],
|
||||
precision="millisecond")
|
||||
|
||||
|
||||
def test_remove_custom_stix_object():
|
||||
@stix2.CustomObject("x-animal", [
|
||||
("species", stix2.properties.StringProperty(required=True)),
|
||||
("animal_class", stix2.properties.StringProperty()),
|
||||
])
|
||||
class Animal(object):
|
||||
pass
|
||||
|
||||
animal = Animal(species="lion", animal_class="mammal")
|
||||
|
||||
nc = stix2.utils.remove_custom_stix(animal)
|
||||
|
||||
assert nc is None
|
||||
|
||||
|
||||
def test_remove_custom_stix_no_custom():
|
||||
campaign_v1 = stix2.Campaign(**CAMPAIGN_MORE_KWARGS)
|
||||
campaign_v2 = stix2.utils.remove_custom_stix(campaign_v1)
|
||||
|
||||
assert len(campaign_v1.keys()) == len(campaign_v2.keys())
|
||||
assert campaign_v1.id == campaign_v2.id
|
||||
assert campaign_v1.description == campaign_v2.description
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
import os
|
||||
|
||||
import stix2
|
||||
from stix2.workbench import (AttackPattern, Bundle, Campaign, CourseOfAction,
|
||||
ExternalReference, FileSystemSource, Filter,
|
||||
Identity, Indicator, IntrusionSet, Malware,
|
||||
MarkingDefinition, ObservedData, Relationship,
|
||||
Report, StatementMarking, ThreatActor, Tool,
|
||||
Vulnerability, add_data_source, all_versions,
|
||||
attack_patterns, campaigns, courses_of_action,
|
||||
create, get, identities, indicators,
|
||||
intrusion_sets, malware, observed_data, query,
|
||||
reports, save, set_default_created,
|
||||
set_default_creator, set_default_external_refs,
|
||||
set_default_object_marking_refs, threat_actors,
|
||||
tools, vulnerabilities)
|
||||
|
||||
from .constants import (ATTACK_PATTERN_ID, ATTACK_PATTERN_KWARGS, CAMPAIGN_ID,
|
||||
CAMPAIGN_KWARGS, COURSE_OF_ACTION_ID,
|
||||
COURSE_OF_ACTION_KWARGS, IDENTITY_ID, IDENTITY_KWARGS,
|
||||
INDICATOR_ID, INDICATOR_KWARGS, INTRUSION_SET_ID,
|
||||
INTRUSION_SET_KWARGS, MALWARE_ID, MALWARE_KWARGS,
|
||||
OBSERVED_DATA_ID, OBSERVED_DATA_KWARGS, REPORT_ID,
|
||||
REPORT_KWARGS, THREAT_ACTOR_ID, THREAT_ACTOR_KWARGS,
|
||||
TOOL_ID, TOOL_KWARGS, VULNERABILITY_ID,
|
||||
VULNERABILITY_KWARGS)
|
||||
|
||||
|
||||
def test_workbench_environment():
|
||||
|
||||
# Create a STIX object
|
||||
ind = create(Indicator, id=INDICATOR_ID, **INDICATOR_KWARGS)
|
||||
save(ind)
|
||||
|
||||
resp = get(INDICATOR_ID)
|
||||
assert resp['labels'][0] == 'malicious-activity'
|
||||
|
||||
resp = all_versions(INDICATOR_ID)
|
||||
assert len(resp) == 1
|
||||
|
||||
# Search on something other than id
|
||||
q = [Filter('type', '=', 'vulnerability')]
|
||||
resp = query(q)
|
||||
assert len(resp) == 0
|
||||
|
||||
|
||||
def test_workbench_get_all_attack_patterns():
|
||||
mal = AttackPattern(id=ATTACK_PATTERN_ID, **ATTACK_PATTERN_KWARGS)
|
||||
save(mal)
|
||||
|
||||
resp = attack_patterns()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == ATTACK_PATTERN_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_campaigns():
|
||||
cam = Campaign(id=CAMPAIGN_ID, **CAMPAIGN_KWARGS)
|
||||
save(cam)
|
||||
|
||||
resp = campaigns()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == CAMPAIGN_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_courses_of_action():
|
||||
coa = CourseOfAction(id=COURSE_OF_ACTION_ID, **COURSE_OF_ACTION_KWARGS)
|
||||
save(coa)
|
||||
|
||||
resp = courses_of_action()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == COURSE_OF_ACTION_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_identities():
|
||||
idty = Identity(id=IDENTITY_ID, **IDENTITY_KWARGS)
|
||||
save(idty)
|
||||
|
||||
resp = identities()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == IDENTITY_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_indicators():
|
||||
resp = indicators()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == INDICATOR_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_intrusion_sets():
|
||||
ins = IntrusionSet(id=INTRUSION_SET_ID, **INTRUSION_SET_KWARGS)
|
||||
save(ins)
|
||||
|
||||
resp = intrusion_sets()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == INTRUSION_SET_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_malware():
|
||||
mal = Malware(id=MALWARE_ID, **MALWARE_KWARGS)
|
||||
save(mal)
|
||||
|
||||
resp = malware()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == MALWARE_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_observed_data():
|
||||
od = ObservedData(id=OBSERVED_DATA_ID, **OBSERVED_DATA_KWARGS)
|
||||
save(od)
|
||||
|
||||
resp = observed_data()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == OBSERVED_DATA_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_reports():
|
||||
rep = Report(id=REPORT_ID, **REPORT_KWARGS)
|
||||
save(rep)
|
||||
|
||||
resp = reports()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == REPORT_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_threat_actors():
|
||||
thr = ThreatActor(id=THREAT_ACTOR_ID, **THREAT_ACTOR_KWARGS)
|
||||
save(thr)
|
||||
|
||||
resp = threat_actors()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == THREAT_ACTOR_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_tools():
|
||||
tool = Tool(id=TOOL_ID, **TOOL_KWARGS)
|
||||
save(tool)
|
||||
|
||||
resp = tools()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == TOOL_ID
|
||||
|
||||
|
||||
def test_workbench_get_all_vulnerabilities():
|
||||
vuln = Vulnerability(id=VULNERABILITY_ID, **VULNERABILITY_KWARGS)
|
||||
save(vuln)
|
||||
|
||||
resp = vulnerabilities()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].id == VULNERABILITY_ID
|
||||
|
||||
|
||||
def test_workbench_add_to_bundle():
|
||||
vuln = Vulnerability(**VULNERABILITY_KWARGS)
|
||||
bundle = Bundle(vuln)
|
||||
assert bundle.objects[0].name == 'Heartbleed'
|
||||
|
||||
|
||||
def test_workbench_relationships():
|
||||
rel = Relationship(INDICATOR_ID, 'indicates', MALWARE_ID)
|
||||
save(rel)
|
||||
|
||||
ind = get(INDICATOR_ID)
|
||||
resp = ind.relationships()
|
||||
assert len(resp) == 1
|
||||
assert resp[0].relationship_type == 'indicates'
|
||||
assert resp[0].source_ref == INDICATOR_ID
|
||||
assert resp[0].target_ref == MALWARE_ID
|
||||
|
||||
|
||||
def test_workbench_created_by():
|
||||
intset = IntrusionSet(name="Breach 123", created_by_ref=IDENTITY_ID)
|
||||
save(intset)
|
||||
creator = intset.created_by()
|
||||
assert creator.id == IDENTITY_ID
|
||||
|
||||
|
||||
def test_workbench_related():
|
||||
rel1 = Relationship(MALWARE_ID, 'targets', IDENTITY_ID)
|
||||
rel2 = Relationship(CAMPAIGN_ID, 'uses', MALWARE_ID)
|
||||
save([rel1, rel2])
|
||||
|
||||
resp = get(MALWARE_ID).related()
|
||||
assert len(resp) == 3
|
||||
assert any(x['id'] == CAMPAIGN_ID for x in resp)
|
||||
assert any(x['id'] == INDICATOR_ID for x in resp)
|
||||
assert any(x['id'] == IDENTITY_ID for x in resp)
|
||||
|
||||
resp = get(MALWARE_ID).related(relationship_type='indicates')
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_workbench_related_with_filters():
|
||||
malware = Malware(labels=["ransomware"], name="CryptorBit", created_by_ref=IDENTITY_ID)
|
||||
rel = Relationship(malware.id, 'variant-of', MALWARE_ID)
|
||||
save([malware, rel])
|
||||
|
||||
filters = [Filter('created_by_ref', '=', IDENTITY_ID)]
|
||||
resp = get(MALWARE_ID).related(filters=filters)
|
||||
|
||||
assert len(resp) == 1
|
||||
assert resp[0].name == malware.name
|
||||
assert resp[0].created_by_ref == IDENTITY_ID
|
||||
|
||||
# filters arg can also be single filter
|
||||
resp = get(MALWARE_ID).related(filters=filters[0])
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_add_data_source():
|
||||
fs_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "stix2_data")
|
||||
fs = FileSystemSource(fs_path)
|
||||
add_data_source(fs)
|
||||
|
||||
resp = tools()
|
||||
assert len(resp) == 3
|
||||
resp_ids = [tool.id for tool in resp]
|
||||
assert TOOL_ID in resp_ids
|
||||
assert 'tool--03342581-f790-4f03-ba41-e82e67392e23' in resp_ids
|
||||
assert 'tool--242f3da3-4425-4d11-8f5c-b842886da966' in resp_ids
|
||||
|
||||
|
||||
def test_additional_filter():
|
||||
resp = tools(Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'))
|
||||
assert len(resp) == 2
|
||||
|
||||
|
||||
def test_additional_filters_list():
|
||||
resp = tools([Filter('created_by_ref', '=', 'identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5'),
|
||||
Filter('name', '=', 'Windows Credential Editor')])
|
||||
assert len(resp) == 1
|
||||
|
||||
|
||||
def test_default_creator():
|
||||
set_default_creator(IDENTITY_ID)
|
||||
campaign = Campaign(**CAMPAIGN_KWARGS)
|
||||
|
||||
assert 'created_by_ref' not in CAMPAIGN_KWARGS
|
||||
assert campaign.created_by_ref == IDENTITY_ID
|
||||
|
||||
|
||||
def test_default_created_timestamp():
|
||||
timestamp = "2018-03-19T01:02:03.000Z"
|
||||
set_default_created(timestamp)
|
||||
campaign = Campaign(**CAMPAIGN_KWARGS)
|
||||
|
||||
assert 'created' not in CAMPAIGN_KWARGS
|
||||
assert stix2.utils.format_datetime(campaign.created) == timestamp
|
||||
assert stix2.utils.format_datetime(campaign.modified) == timestamp
|
||||
|
||||
|
||||
def test_default_external_refs():
|
||||
ext_ref = ExternalReference(source_name="ACME Threat Intel",
|
||||
description="Threat report")
|
||||
set_default_external_refs(ext_ref)
|
||||
campaign = Campaign(**CAMPAIGN_KWARGS)
|
||||
|
||||
assert campaign.external_references[0].source_name == "ACME Threat Intel"
|
||||
assert campaign.external_references[0].description == "Threat report"
|
||||
|
||||
|
||||
def test_default_object_marking_refs():
|
||||
stmt_marking = StatementMarking("Copyright 2016, Example Corp")
|
||||
mark_def = MarkingDefinition(definition_type="statement",
|
||||
definition=stmt_marking)
|
||||
set_default_object_marking_refs(mark_def)
|
||||
campaign = Campaign(**CAMPAIGN_KWARGS)
|
||||
|
||||
assert campaign.object_marking_refs[0] == mark_def.id
|
||||
|
||||
|
||||
def test_workbench_custom_property_object_in_observable_extension():
|
||||
ntfs = stix2.NTFSExt(
|
||||
allow_custom=True,
|
||||
sid=1,
|
||||
x_foo='bar',
|
||||
)
|
||||
artifact = stix2.File(
|
||||
name='test',
|
||||
extensions={'ntfs-ext': ntfs},
|
||||
)
|
||||
observed_data = ObservedData(
|
||||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
assert observed_data.objects['0'].extensions['ntfs-ext'].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(observed_data)
|
||||
|
||||
|
||||
def test_workbench_custom_property_dict_in_observable_extension():
|
||||
artifact = stix2.File(
|
||||
allow_custom=True,
|
||||
name='test',
|
||||
extensions={
|
||||
'ntfs-ext': {
|
||||
'allow_custom': True,
|
||||
'sid': 1,
|
||||
'x_foo': 'bar',
|
||||
}
|
||||
},
|
||||
)
|
||||
observed_data = ObservedData(
|
||||
allow_custom=True,
|
||||
first_observed="2015-12-21T19:00:00Z",
|
||||
last_observed="2015-12-21T19:00:00Z",
|
||||
number_observed=0,
|
||||
objects={"0": artifact},
|
||||
)
|
||||
|
||||
assert observed_data.objects['0'].extensions['ntfs-ext'].x_foo == "bar"
|
||||
assert '"x_foo": "bar"' in str(observed_data)
|
|
@ -1,5 +1,4 @@
|
|||
"""Utility functions and classes for the stix2 library."""
|
||||
|
||||
from collections import Mapping
|
||||
import copy
|
||||
import datetime as dt
|
||||
|
@ -16,6 +15,11 @@ from .exceptions import (InvalidValueError, RevokeError,
|
|||
# timestamps in a single object, the timestamps will vary by a few microseconds.
|
||||
NOW = object()
|
||||
|
||||
# STIX object properties that cannot be modified
|
||||
STIX_UNMOD_PROPERTIES = ["created", "created_by_ref", "id", "type"]
|
||||
|
||||
TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$'
|
||||
|
||||
|
||||
class STIXdatetime(dt.datetime):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
|
@ -138,7 +142,7 @@ def parse_into_datetime(value, precision=None):
|
|||
return STIXdatetime(ts, precision=precision)
|
||||
|
||||
|
||||
def get_dict(data):
|
||||
def _get_dict(data):
|
||||
"""Return data as a dictionary.
|
||||
|
||||
Input can be a dictionary, string, or file-like object.
|
||||
|
@ -164,7 +168,7 @@ def get_dict(data):
|
|||
def find_property_index(obj, properties, tuple_to_find):
|
||||
"""Recursively find the property in the object model, return the index
|
||||
according to the _properties OrderedDict. If it's a list look for
|
||||
individual objects.
|
||||
individual objects. Returns and integer indicating its location
|
||||
"""
|
||||
from .base import _STIXBase
|
||||
try:
|
||||
|
@ -181,6 +185,11 @@ def find_property_index(obj, properties, tuple_to_find):
|
|||
tuple_to_find)
|
||||
if val is not None:
|
||||
return val
|
||||
elif isinstance(item, dict):
|
||||
for idx, val in enumerate(sorted(item)):
|
||||
if (tuple_to_find[0] == val and
|
||||
item.get(val) == tuple_to_find[1]):
|
||||
return idx
|
||||
elif isinstance(pv, dict):
|
||||
if pv.get(tuple_to_find[0]) is not None:
|
||||
try:
|
||||
|
@ -219,7 +228,7 @@ def new_version(data, **kwargs):
|
|||
properties_to_change = kwargs.keys()
|
||||
|
||||
# Make sure certain properties aren't trying to change
|
||||
for prop in ["created", "created_by_ref", "id", "type"]:
|
||||
for prop in STIX_UNMOD_PROPERTIES:
|
||||
if prop in properties_to_change:
|
||||
unchangable_properties.append(prop)
|
||||
if unchangable_properties:
|
||||
|
@ -231,8 +240,11 @@ def new_version(data, **kwargs):
|
|||
elif 'modified' in data:
|
||||
old_modified_property = parse_into_datetime(data.get('modified'), precision='millisecond')
|
||||
new_modified_property = parse_into_datetime(kwargs['modified'], precision='millisecond')
|
||||
if new_modified_property < old_modified_property:
|
||||
raise InvalidValueError(cls, 'modified', "The new modified datetime cannot be before the current modified datatime.")
|
||||
if new_modified_property <= old_modified_property:
|
||||
raise InvalidValueError(cls, 'modified',
|
||||
"The new modified datetime cannot be before than or equal to the current modified datetime."
|
||||
"It cannot be equal, as according to STIX 2 specification, objects that are different "
|
||||
"but have the same id and modified timestamp do not have defined consumer behavior.")
|
||||
new_obj_inner.update(kwargs)
|
||||
# Exclude properties with a value of 'None' in case data is not an instance of a _STIXBase subclass
|
||||
return cls(**{k: v for k, v in new_obj_inner.items() if v is not None})
|
||||
|
@ -250,7 +262,7 @@ def revoke(data):
|
|||
|
||||
if data.get("revoked"):
|
||||
raise RevokeError("revoke")
|
||||
return new_version(data, revoked=True)
|
||||
return new_version(data, revoked=True, allow_custom=True)
|
||||
|
||||
|
||||
def get_class_hierarchy_names(obj):
|
||||
|
@ -261,5 +273,68 @@ def get_class_hierarchy_names(obj):
|
|||
return names
|
||||
|
||||
|
||||
def remove_custom_stix(stix_obj):
|
||||
"""Remove any custom STIX objects or properties.
|
||||
|
||||
Warning: This function is a best effort utility, in that
|
||||
it will remove custom objects and properties based on the
|
||||
type names; i.e. if "x-" prefixes object types, and "x\\_"
|
||||
prefixes property types. According to the STIX2 spec,
|
||||
those naming conventions are a SHOULDs not MUSTs, meaning
|
||||
that valid custom STIX content may ignore those conventions
|
||||
and in effect render this utility function invalid when used
|
||||
on that STIX content.
|
||||
|
||||
Args:
|
||||
stix_obj (dict OR python-stix obj): a single python-stix object
|
||||
or dict of a STIX object
|
||||
|
||||
Returns:
|
||||
A new version of the object with any custom content removed
|
||||
"""
|
||||
|
||||
if stix_obj["type"].startswith("x-"):
|
||||
# if entire object is custom, discard
|
||||
return None
|
||||
|
||||
custom_props = []
|
||||
for prop in stix_obj.items():
|
||||
if prop[0].startswith("x_"):
|
||||
# for every custom property, record it and set value to None
|
||||
# (so we can pass it to new_version() and it will be dropped)
|
||||
custom_props.append((prop[0], None))
|
||||
|
||||
if custom_props:
|
||||
# obtain set of object properties that can be transferred
|
||||
# to a new object version. This is 1)custom props with their
|
||||
# values set to None, and 2)any properties left that are not
|
||||
# unmodifiable STIX properties or the "modified" property
|
||||
|
||||
# set of properties that are not supplied to new_version()
|
||||
# to be used for updating properties. This includes unmodifiable
|
||||
# properties (properties that new_version() just re-uses from the
|
||||
# existing STIX object) and the "modified" property. We dont supply the
|
||||
# "modified" property so that new_version() creates a new datetime
|
||||
# value for this property
|
||||
non_supplied_props = STIX_UNMOD_PROPERTIES + ["modified"]
|
||||
|
||||
props = [(prop, stix_obj[prop]) for prop in stix_obj if prop not in non_supplied_props]
|
||||
|
||||
# add to set the custom properties we want to get rid of (with their value=None)
|
||||
props.extend(custom_props)
|
||||
|
||||
new_obj = new_version(stix_obj, **(dict(props)))
|
||||
|
||||
while parse_into_datetime(new_obj["modified"]) == parse_into_datetime(stix_obj["modified"]):
|
||||
# Prevents bug when fast computation allows multiple STIX object
|
||||
# versions to be created in single unit of time
|
||||
new_obj = new_version(stix_obj, **(dict(props)))
|
||||
|
||||
return new_obj
|
||||
|
||||
else:
|
||||
return stix_obj
|
||||
|
||||
|
||||
def get_type_from_id(stix_id):
|
||||
return stix_id.split('--', 1)[0]
|
||||
|
|
|
@ -10,9 +10,10 @@ from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact,
|
|||
Directory, DomainName, EmailAddress, EmailMessage,
|
||||
EmailMIMEComponent, ExtensionsProperty, File,
|
||||
HTTPRequestExt, ICMPExt, IPv4Address, IPv6Address,
|
||||
MACAddress, Mutex, NetworkTraffic, NTFSExt, PDFExt,
|
||||
Process, RasterImageExt, SocketExt, Software, TCPExt,
|
||||
UNIXAccountExt, UserAccount, WindowsPEBinaryExt,
|
||||
MACAddress, Mutex, NetworkTraffic, NTFSExt,
|
||||
ObservableProperty, PDFExt, Process, RasterImageExt,
|
||||
SocketExt, Software, TCPExt, UNIXAccountExt,
|
||||
UserAccount, WindowsPEBinaryExt,
|
||||
WindowsPEOptionalHeaderType, WindowsPESection,
|
||||
WindowsProcessExt, WindowsRegistryKey,
|
||||
WindowsRegistryValueType, WindowsServiceExt,
|
||||
|
|
|
@ -7,10 +7,14 @@ from ..markings import _MarkingsMixin
|
|||
from ..properties import (HashesProperty, IDProperty, ListProperty, Property,
|
||||
ReferenceProperty, SelectorProperty, StringProperty,
|
||||
TimestampProperty, TypeProperty)
|
||||
from ..utils import NOW, get_dict
|
||||
from ..utils import NOW, _get_dict
|
||||
|
||||
|
||||
class ExternalReference(_STIXBase):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709261>`__.
|
||||
"""
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -27,6 +31,10 @@ class ExternalReference(_STIXBase):
|
|||
|
||||
|
||||
class KillChainPhase(_STIXBase):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709267>`__.
|
||||
"""
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -36,6 +44,10 @@ class KillChainPhase(_STIXBase):
|
|||
|
||||
|
||||
class GranularMarking(_STIXBase):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709290>`__.
|
||||
"""
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -45,15 +57,24 @@ class GranularMarking(_STIXBase):
|
|||
|
||||
|
||||
class TLPMarking(_STIXBase):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709287>`__.
|
||||
"""
|
||||
|
||||
# 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):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709286>`__.
|
||||
"""
|
||||
|
||||
_type = 'statement'
|
||||
_properties = OrderedDict()
|
||||
|
@ -82,6 +103,10 @@ class MarkingProperty(Property):
|
|||
|
||||
|
||||
class MarkingDefinition(_STIXBase, _MarkingsMixin):
|
||||
# TODO: Update with 2.1 Link
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part1-stix-core/stix-v2.0-cs01-part1-stix-core.html#_Toc496709284>`__.
|
||||
"""
|
||||
|
||||
_type = 'marking-definition'
|
||||
_properties = OrderedDict()
|
||||
|
@ -106,7 +131,7 @@ class MarkingDefinition(_STIXBase, _MarkingsMixin):
|
|||
raise ValueError("definition_type must be a valid marking type")
|
||||
|
||||
if not isinstance(kwargs['definition'], marking_type):
|
||||
defn = get_dict(kwargs['definition'])
|
||||
defn = _get_dict(kwargs['definition'])
|
||||
kwargs['definition'] = marking_type(**defn)
|
||||
|
||||
super(MarkingDefinition, self).__init__(**kwargs)
|
||||
|
|
|
@ -6,25 +6,35 @@ Observable and do not have a ``_type`` attribute.
|
|||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
import copy
|
||||
import re
|
||||
|
||||
from ..base import _Extension, _Observable, _STIXBase
|
||||
from ..exceptions import (AtLeastOnePropertyError, DependentPropertiesError,
|
||||
ParseError)
|
||||
from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
|
||||
DependentPropertiesError, ParseError)
|
||||
from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
|
||||
EmbeddedObjectProperty, EnumProperty, FloatProperty,
|
||||
HashesProperty, HexProperty, IntegerProperty,
|
||||
ListProperty, ObjectReferenceProperty, Property,
|
||||
StringProperty, TimestampProperty, TypeProperty)
|
||||
from ..utils import get_dict
|
||||
from ..utils import TYPE_REGEX, _get_dict
|
||||
|
||||
|
||||
class ObservableProperty(Property):
|
||||
"""Property for holding Cyber Observable Objects.
|
||||
"""
|
||||
|
||||
def __init__(self, allow_custom=False, *args, **kwargs):
|
||||
self.allow_custom = allow_custom
|
||||
super(ObservableProperty, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
# get deep copy since we are going modify the dict and might
|
||||
# modify the original dict as _get_dict() does not return new
|
||||
# dict when passed a dict
|
||||
dictified = copy.deepcopy(dictified)
|
||||
except ValueError:
|
||||
raise ValueError("The observable property must contain a dictionary")
|
||||
if dictified == {}:
|
||||
|
@ -33,7 +43,10 @@ class ObservableProperty(Property):
|
|||
valid_refs = dict((k, v['type']) for (k, v) in dictified.items())
|
||||
|
||||
for key, obj in dictified.items():
|
||||
parsed_obj = parse_observable(obj, valid_refs)
|
||||
if self.allow_custom:
|
||||
parsed_obj = parse_observable(obj, valid_refs, allow_custom=True)
|
||||
else:
|
||||
parsed_obj = parse_observable(obj, valid_refs)
|
||||
dictified[key] = parsed_obj
|
||||
|
||||
return dictified
|
||||
|
@ -43,13 +56,18 @@ class ExtensionsProperty(DictionaryProperty):
|
|||
"""Property for representing extensions on Observable objects.
|
||||
"""
|
||||
|
||||
def __init__(self, enclosing_type=None, required=False):
|
||||
def __init__(self, allow_custom=False, enclosing_type=None, required=False):
|
||||
self.allow_custom = allow_custom
|
||||
self.enclosing_type = enclosing_type
|
||||
super(ExtensionsProperty, self).__init__(required)
|
||||
|
||||
def clean(self, value):
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
# get deep copy since we are going modify the dict and might
|
||||
# modify the original dict as _get_dict() does not return new
|
||||
# dict when passed a dict
|
||||
dictified = copy.deepcopy(dictified)
|
||||
except ValueError:
|
||||
raise ValueError("The extensions property must contain a dictionary")
|
||||
if dictified == {}:
|
||||
|
@ -61,19 +79,27 @@ class ExtensionsProperty(DictionaryProperty):
|
|||
if key in specific_type_map:
|
||||
cls = specific_type_map[key]
|
||||
if type(subvalue) is dict:
|
||||
dictified[key] = cls(**subvalue)
|
||||
if self.allow_custom:
|
||||
subvalue['allow_custom'] = True
|
||||
dictified[key] = cls(**subvalue)
|
||||
else:
|
||||
dictified[key] = cls(**subvalue)
|
||||
elif type(subvalue) is cls:
|
||||
# If already an instance of an _Extension class, assume it's valid
|
||||
dictified[key] = subvalue
|
||||
else:
|
||||
raise ValueError("Cannot determine extension type.")
|
||||
else:
|
||||
raise ValueError("The key used in the extensions dictionary is not an extension type name")
|
||||
raise CustomContentError("Can't parse unknown extension type: {}".format(key))
|
||||
else:
|
||||
raise ValueError("The enclosing type '%s' has no extensions defined" % self.enclosing_type)
|
||||
return dictified
|
||||
|
||||
|
||||
class Artifact(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716219>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'artifact'
|
||||
_properties = OrderedDict()
|
||||
|
@ -93,6 +119,9 @@ class Artifact(_Observable):
|
|||
|
||||
|
||||
class AutonomousSystem(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716221>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'autonomous-system'
|
||||
_properties = OrderedDict()
|
||||
|
@ -106,6 +135,9 @@ class AutonomousSystem(_Observable):
|
|||
|
||||
|
||||
class Directory(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716223>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'directory'
|
||||
_properties = OrderedDict()
|
||||
|
@ -123,6 +155,9 @@ class Directory(_Observable):
|
|||
|
||||
|
||||
class DomainName(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716225>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'domain-name'
|
||||
_properties = OrderedDict()
|
||||
|
@ -135,6 +170,9 @@ class DomainName(_Observable):
|
|||
|
||||
|
||||
class EmailAddress(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716227>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'email-addr'
|
||||
_properties = OrderedDict()
|
||||
|
@ -148,6 +186,9 @@ class EmailAddress(_Observable):
|
|||
|
||||
|
||||
class EmailMIMEComponent(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716231>`__.
|
||||
""" # noqa
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -163,6 +204,9 @@ class EmailMIMEComponent(_STIXBase):
|
|||
|
||||
|
||||
class EmailMessage(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716229>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'email-message'
|
||||
_properties = OrderedDict()
|
||||
|
@ -194,6 +238,9 @@ class EmailMessage(_Observable):
|
|||
|
||||
|
||||
class ArchiveExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716235>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'archive-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -205,6 +252,9 @@ class ArchiveExt(_Extension):
|
|||
|
||||
|
||||
class AlternateDataStream(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716239>`__.
|
||||
""" # noqa
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -215,6 +265,9 @@ class AlternateDataStream(_STIXBase):
|
|||
|
||||
|
||||
class NTFSExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716237>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'ntfs-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -225,6 +278,9 @@ class NTFSExt(_Extension):
|
|||
|
||||
|
||||
class PDFExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716241>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'pdf-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -238,6 +294,9 @@ class PDFExt(_Extension):
|
|||
|
||||
|
||||
class RasterImageExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716243>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'raster-image-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -251,6 +310,9 @@ class RasterImageExt(_Extension):
|
|||
|
||||
|
||||
class WindowsPEOptionalHeaderType(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716248>`__.
|
||||
""" # noqa
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -293,6 +355,9 @@ class WindowsPEOptionalHeaderType(_STIXBase):
|
|||
|
||||
|
||||
class WindowsPESection(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716250>`__.
|
||||
""" # noqa
|
||||
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -304,6 +369,9 @@ class WindowsPESection(_STIXBase):
|
|||
|
||||
|
||||
class WindowsPEBinaryExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716245>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'windows-pebinary-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -324,6 +392,9 @@ class WindowsPEBinaryExt(_Extension):
|
|||
|
||||
|
||||
class File(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716233>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'file'
|
||||
_properties = OrderedDict()
|
||||
|
@ -355,6 +426,9 @@ class File(_Observable):
|
|||
|
||||
|
||||
class IPv4Address(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716252>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'ipv4-addr'
|
||||
_properties = OrderedDict()
|
||||
|
@ -368,6 +442,9 @@ class IPv4Address(_Observable):
|
|||
|
||||
|
||||
class IPv6Address(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716254>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'ipv6-addr'
|
||||
_properties = OrderedDict()
|
||||
|
@ -381,6 +458,9 @@ class IPv6Address(_Observable):
|
|||
|
||||
|
||||
class MACAddress(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716256>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'mac-addr'
|
||||
_properties = OrderedDict()
|
||||
|
@ -392,6 +472,9 @@ class MACAddress(_Observable):
|
|||
|
||||
|
||||
class Mutex(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716258>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'mutex'
|
||||
_properties = OrderedDict()
|
||||
|
@ -403,6 +486,9 @@ class Mutex(_Observable):
|
|||
|
||||
|
||||
class HTTPRequestExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716262>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'http-request-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -417,6 +503,9 @@ class HTTPRequestExt(_Extension):
|
|||
|
||||
|
||||
class ICMPExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716264>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'icmp-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -427,6 +516,9 @@ class ICMPExt(_Extension):
|
|||
|
||||
|
||||
class SocketExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716266>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'socket-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -465,6 +557,9 @@ class SocketExt(_Extension):
|
|||
|
||||
|
||||
class TCPExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716271>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'tcp-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -475,6 +570,9 @@ class TCPExt(_Extension):
|
|||
|
||||
|
||||
class NetworkTraffic(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716260>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'network-traffic'
|
||||
_properties = OrderedDict()
|
||||
|
@ -506,6 +604,9 @@ class NetworkTraffic(_Observable):
|
|||
|
||||
|
||||
class WindowsProcessExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716275>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'windows-process-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -520,6 +621,9 @@ class WindowsProcessExt(_Extension):
|
|||
|
||||
|
||||
class WindowsServiceExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716277>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'windows-service-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -555,6 +659,9 @@ class WindowsServiceExt(_Extension):
|
|||
|
||||
|
||||
class Process(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716273>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'process'
|
||||
_properties = OrderedDict()
|
||||
|
@ -593,6 +700,9 @@ class Process(_Observable):
|
|||
|
||||
|
||||
class Software(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716282>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'software'
|
||||
_properties = OrderedDict()
|
||||
|
@ -608,6 +718,9 @@ class Software(_Observable):
|
|||
|
||||
|
||||
class URL(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716284>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'url'
|
||||
_properties = OrderedDict()
|
||||
|
@ -619,6 +732,9 @@ class URL(_Observable):
|
|||
|
||||
|
||||
class UNIXAccountExt(_Extension):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716289>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'unix-account-ext'
|
||||
_properties = OrderedDict()
|
||||
|
@ -631,6 +747,9 @@ class UNIXAccountExt(_Extension):
|
|||
|
||||
|
||||
class UserAccount(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716286>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'user-account'
|
||||
_properties = OrderedDict()
|
||||
|
@ -654,6 +773,9 @@ class UserAccount(_Observable):
|
|||
|
||||
|
||||
class WindowsRegistryValueType(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716293>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'windows-registry-value-type'
|
||||
_properties = OrderedDict()
|
||||
|
@ -679,6 +801,9 @@ class WindowsRegistryValueType(_STIXBase):
|
|||
|
||||
|
||||
class WindowsRegistryKey(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716291>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'windows-registry-key'
|
||||
_properties = OrderedDict()
|
||||
|
@ -700,6 +825,9 @@ class WindowsRegistryKey(_Observable):
|
|||
|
||||
|
||||
class X509V3ExtenstionsType(_STIXBase):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716298>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'x509-v3-extensions-type'
|
||||
_properties = OrderedDict()
|
||||
|
@ -724,6 +852,9 @@ class X509V3ExtenstionsType(_STIXBase):
|
|||
|
||||
|
||||
class X509Certificate(_Observable):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part4-cyber-observable-objects/stix-v2.0-cs01-part4-cyber-observable-objects.html#_Toc496716296>`__.
|
||||
""" # noqa
|
||||
|
||||
_type = 'x509-certificate'
|
||||
_properties = OrderedDict()
|
||||
|
@ -807,7 +938,12 @@ def parse_observable(data, _valid_refs=None, allow_custom=False):
|
|||
An instantiated Python STIX Cyber Observable object.
|
||||
"""
|
||||
|
||||
obj = get_dict(data)
|
||||
obj = _get_dict(data)
|
||||
# get deep copy since we are going modify the dict and might
|
||||
# modify the original dict as _get_dict() does not return new
|
||||
# dict when passed a dict
|
||||
obj = copy.deepcopy(obj)
|
||||
|
||||
obj['_valid_refs'] = _valid_refs or []
|
||||
|
||||
if 'type' not in obj:
|
||||
|
@ -815,15 +951,23 @@ def parse_observable(data, _valid_refs=None, allow_custom=False):
|
|||
try:
|
||||
obj_class = OBJ_MAP_OBSERVABLE[obj['type']]
|
||||
except KeyError:
|
||||
raise ParseError("Can't parse unknown observable type '%s'! For custom observables, "
|
||||
"use the CustomObservable decorator." % obj['type'])
|
||||
if allow_custom:
|
||||
# flag allows for unknown custom objects too, but will not
|
||||
# be parsed into STIX observable object, just returned as is
|
||||
return obj
|
||||
raise CustomContentError("Can't parse unknown observable type '%s'! For custom observables, "
|
||||
"use the CustomObservable decorator." % obj['type'])
|
||||
|
||||
if 'extensions' in obj and obj['type'] in EXT_MAP:
|
||||
for name, ext in obj['extensions'].items():
|
||||
if name not in EXT_MAP[obj['type']]:
|
||||
raise ParseError("Can't parse Unknown extension type '%s' for observable type '%s'!" % (name, obj['type']))
|
||||
ext_class = EXT_MAP[obj['type']][name]
|
||||
obj['extensions'][name] = ext_class(allow_custom=allow_custom, **obj['extensions'][name])
|
||||
try:
|
||||
ext_class = EXT_MAP[obj['type']][name]
|
||||
except KeyError:
|
||||
if not allow_custom:
|
||||
raise CustomContentError("Can't parse unknown extension type '%s'"
|
||||
"for observable type '%s'!" % (name, obj['type']))
|
||||
else: # extension was found
|
||||
obj['extensions'][name] = ext_class(allow_custom=allow_custom, **obj['extensions'][name])
|
||||
|
||||
return obj_class(allow_custom=allow_custom, **obj)
|
||||
|
||||
|
@ -851,6 +995,12 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
|||
|
||||
class _Custom(cls, _Observable):
|
||||
|
||||
if not re.match(TYPE_REGEX, type):
|
||||
raise ValueError("Invalid observable type name '%s': must only contain the "
|
||||
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||
elif len(type) < 3 or len(type) > 250:
|
||||
raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type)
|
||||
|
||||
_type = type
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -871,6 +1021,9 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
|||
"is not a ListProperty containing ObjectReferenceProperty." % prop_name)
|
||||
|
||||
_properties.update(properties)
|
||||
_properties.update([
|
||||
('extensions', ExtensionsProperty(enclosing_type=_type)),
|
||||
])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
_Observable.__init__(self, **kwargs)
|
||||
|
@ -921,13 +1074,17 @@ def CustomExtension(observable=None, type='x-custom-observable', properties=None
|
|||
|
||||
class _Custom(cls, _Extension):
|
||||
|
||||
_type = type
|
||||
_properties = {
|
||||
'extensions': ExtensionsProperty(enclosing_type=_type),
|
||||
}
|
||||
if not re.match(TYPE_REGEX, type):
|
||||
raise ValueError("Invalid extension type name '%s': must only contain the "
|
||||
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||
elif len(type) < 3 or len(type) > 250:
|
||||
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
|
||||
|
||||
if not isinstance(properties, dict) or not properties:
|
||||
raise ValueError("'properties' must be a dict!")
|
||||
_type = type
|
||||
_properties = OrderedDict()
|
||||
|
||||
if not properties or not isinstance(properties, list):
|
||||
raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]")
|
||||
|
||||
_properties.update(properties)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""STIX 2.0 Domain Objects"""
|
||||
"""STIX 2.0 Domain Objects.
|
||||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
import re
|
||||
|
||||
import stix2
|
||||
|
||||
|
@ -9,7 +11,7 @@ from ..markings import _MarkingsMixin
|
|||
from ..properties import (BooleanProperty, IDProperty, IntegerProperty,
|
||||
ListProperty, PatternProperty, ReferenceProperty,
|
||||
StringProperty, TimestampProperty, TypeProperty)
|
||||
from ..utils import NOW
|
||||
from ..utils import NOW, TYPE_REGEX
|
||||
from .common import ExternalReference, GranularMarking, KillChainPhase
|
||||
from .observables import ObservableProperty
|
||||
|
||||
|
@ -19,6 +21,9 @@ class STIXDomainObject(_STIXBase, _MarkingsMixin):
|
|||
|
||||
|
||||
class AttackPattern(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714302>`__.
|
||||
"""
|
||||
|
||||
_type = 'attack-pattern'
|
||||
_properties = OrderedDict()
|
||||
|
@ -31,7 +36,7 @@ class AttackPattern(STIXDomainObject):
|
|||
('name', StringProperty(required=True)),
|
||||
('description', StringProperty()),
|
||||
('kill_chain_phases', ListProperty(KillChainPhase)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -40,6 +45,9 @@ class AttackPattern(STIXDomainObject):
|
|||
|
||||
|
||||
class Campaign(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714305>`__.
|
||||
"""
|
||||
|
||||
_type = 'campaign'
|
||||
_properties = OrderedDict()
|
||||
|
@ -55,7 +63,7 @@ class Campaign(STIXDomainObject):
|
|||
('first_seen', TimestampProperty()),
|
||||
('last_seen', TimestampProperty()),
|
||||
('objective', StringProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -64,6 +72,9 @@ class Campaign(STIXDomainObject):
|
|||
|
||||
|
||||
class CourseOfAction(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714308>`__.
|
||||
"""
|
||||
|
||||
_type = 'course-of-action'
|
||||
_properties = OrderedDict()
|
||||
|
@ -75,7 +86,7 @@ class CourseOfAction(STIXDomainObject):
|
|||
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
|
||||
('name', StringProperty(required=True)),
|
||||
('description', StringProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -84,6 +95,9 @@ class CourseOfAction(STIXDomainObject):
|
|||
|
||||
|
||||
class Identity(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714311>`__.
|
||||
"""
|
||||
|
||||
_type = 'identity'
|
||||
_properties = OrderedDict()
|
||||
|
@ -98,7 +112,7 @@ class Identity(STIXDomainObject):
|
|||
('identity_class', StringProperty(required=True)),
|
||||
('sectors', ListProperty(StringProperty)),
|
||||
('contact_information', StringProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -107,6 +121,9 @@ class Identity(STIXDomainObject):
|
|||
|
||||
|
||||
class Indicator(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714314>`__.
|
||||
"""
|
||||
|
||||
_type = 'indicator'
|
||||
_properties = OrderedDict()
|
||||
|
@ -122,7 +139,7 @@ class Indicator(STIXDomainObject):
|
|||
('valid_from', TimestampProperty(default=lambda: NOW)),
|
||||
('valid_until', TimestampProperty()),
|
||||
('kill_chain_phases', ListProperty(KillChainPhase)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty, required=True)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -131,6 +148,9 @@ class Indicator(STIXDomainObject):
|
|||
|
||||
|
||||
class IntrusionSet(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714317>`__.
|
||||
"""
|
||||
|
||||
_type = 'intrusion-set'
|
||||
_properties = OrderedDict()
|
||||
|
@ -149,7 +169,7 @@ class IntrusionSet(STIXDomainObject):
|
|||
('resource_level', StringProperty()),
|
||||
('primary_motivation', StringProperty()),
|
||||
('secondary_motivations', ListProperty(StringProperty)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -158,6 +178,9 @@ class IntrusionSet(STIXDomainObject):
|
|||
|
||||
|
||||
class Malware(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714320>`__.
|
||||
"""
|
||||
|
||||
_type = 'malware'
|
||||
_properties = OrderedDict()
|
||||
|
@ -170,7 +193,7 @@ class Malware(STIXDomainObject):
|
|||
('name', StringProperty(required=True)),
|
||||
('description', StringProperty()),
|
||||
('kill_chain_phases', ListProperty(KillChainPhase)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty, required=True)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -179,6 +202,9 @@ class Malware(STIXDomainObject):
|
|||
|
||||
|
||||
class ObservedData(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714323>`__.
|
||||
"""
|
||||
|
||||
_type = 'observed-data'
|
||||
_properties = OrderedDict()
|
||||
|
@ -192,15 +218,24 @@ class ObservedData(STIXDomainObject):
|
|||
('last_observed', TimestampProperty(required=True)),
|
||||
('number_observed', IntegerProperty(required=True)),
|
||||
('objects', ObservableProperty(required=True)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
('granular_markings', ListProperty(GranularMarking)),
|
||||
])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__allow_custom = kwargs.get('allow_custom', False)
|
||||
self._properties['objects'].allow_custom = kwargs.get('allow_custom', False)
|
||||
|
||||
super(ObservedData, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Report(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714326>`__.
|
||||
"""
|
||||
|
||||
_type = 'report'
|
||||
_properties = OrderedDict()
|
||||
|
@ -214,7 +249,7 @@ class Report(STIXDomainObject):
|
|||
('description', StringProperty()),
|
||||
('published', TimestampProperty(required=True)),
|
||||
('object_refs', ListProperty(ReferenceProperty, required=True)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty, required=True)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -223,6 +258,9 @@ class Report(STIXDomainObject):
|
|||
|
||||
|
||||
class ThreatActor(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714329>`__.
|
||||
"""
|
||||
|
||||
_type = 'threat-actor'
|
||||
_properties = OrderedDict()
|
||||
|
@ -242,7 +280,7 @@ class ThreatActor(STIXDomainObject):
|
|||
('primary_motivation', StringProperty()),
|
||||
('secondary_motivations', ListProperty(StringProperty)),
|
||||
('personal_motivations', ListProperty(StringProperty)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty, required=True)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -251,6 +289,9 @@ class ThreatActor(STIXDomainObject):
|
|||
|
||||
|
||||
class Tool(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714332>`__.
|
||||
"""
|
||||
|
||||
_type = 'tool'
|
||||
_properties = OrderedDict()
|
||||
|
@ -264,7 +305,7 @@ class Tool(STIXDomainObject):
|
|||
('description', StringProperty()),
|
||||
('kill_chain_phases', ListProperty(KillChainPhase)),
|
||||
('tool_version', StringProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty, required=True)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -273,6 +314,9 @@ class Tool(STIXDomainObject):
|
|||
|
||||
|
||||
class Vulnerability(STIXDomainObject):
|
||||
"""For more detailed information on this object's properties, see
|
||||
`the STIX 2.0 specification <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714335>`__.
|
||||
"""
|
||||
|
||||
_type = 'vulnerability'
|
||||
_properties = OrderedDict()
|
||||
|
@ -284,7 +328,7 @@ class Vulnerability(STIXDomainObject):
|
|||
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
|
||||
('name', StringProperty(required=True)),
|
||||
('description', StringProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -320,6 +364,13 @@ def CustomObject(type='x-custom-type', properties=None):
|
|||
def custom_builder(cls):
|
||||
|
||||
class _Custom(cls, STIXDomainObject):
|
||||
|
||||
if not re.match(TYPE_REGEX, type):
|
||||
raise ValueError("Invalid type name '%s': must only contain the "
|
||||
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||
elif len(type) < 3 or len(type) > 250:
|
||||
raise ValueError("Invalid type name '%s': must be between 3 and 250 characters." % type)
|
||||
|
||||
_type = type
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -337,7 +388,7 @@ def CustomObject(type='x-custom-type', properties=None):
|
|||
|
||||
# This is to follow the general properties structure.
|
||||
_properties.update([
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
|
|
@ -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 <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714340>`__.
|
||||
"""
|
||||
|
||||
_type = 'relationship'
|
||||
_properties = OrderedDict()
|
||||
|
@ -29,7 +32,7 @@ class Relationship(STIXRelationshipObject):
|
|||
('description', StringProperty()),
|
||||
('source_ref', ReferenceProperty(required=True)),
|
||||
('target_ref', ReferenceProperty(required=True)),
|
||||
('revoked', BooleanProperty()),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
@ -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 <http://docs.oasis-open.org/cti/stix/v2.0/cs01/part2-stix-objects/stix-v2.0-cs01-part2-stix-objects.html#_Toc496714343>`__.
|
||||
"""
|
||||
|
||||
_type = 'sighting'
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -65,8 +72,8 @@ class Sighting(STIXRelationshipObject):
|
|||
('sighting_of_ref', ReferenceProperty(required=True)),
|
||||
('observed_data_refs', ListProperty(ReferenceProperty(type="observed-data"))),
|
||||
('where_sighted_refs', ListProperty(ReferenceProperty(type="identity"))),
|
||||
('summary', BooleanProperty()),
|
||||
('revoked', BooleanProperty()),
|
||||
('summary', BooleanProperty(default=lambda: False)),
|
||||
('revoked', BooleanProperty(default=lambda: False)),
|
||||
('labels', ListProperty(StringProperty)),
|
||||
('external_references', ListProperty(ExternalReference)),
|
||||
('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))),
|
||||
|
|
|
@ -8,7 +8,7 @@ from ..properties import (BooleanProperty, DictionaryProperty, HashesProperty,
|
|||
IDProperty, ListProperty, Property,
|
||||
ReferenceProperty, SelectorProperty, StringProperty,
|
||||
TimestampProperty, TypeProperty)
|
||||
from ..utils import NOW, get_dict
|
||||
from ..utils import NOW, _get_dict
|
||||
|
||||
|
||||
class ExternalReference(_STIXBase):
|
||||
|
@ -135,7 +135,7 @@ class MarkingDefinition(_STIXBase, _MarkingsMixin):
|
|||
raise ValueError("definition_type must be a valid marking type")
|
||||
|
||||
if not isinstance(kwargs['definition'], marking_type):
|
||||
defn = get_dict(kwargs['definition'])
|
||||
defn = _get_dict(kwargs['definition'])
|
||||
kwargs['definition'] = marking_type(**defn)
|
||||
|
||||
super(MarkingDefinition, self).__init__(**kwargs)
|
||||
|
|
|
@ -6,25 +6,35 @@ Observable and do not have a ``_type`` attribute.
|
|||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
import copy
|
||||
import re
|
||||
|
||||
from ..base import _Extension, _Observable, _STIXBase
|
||||
from ..exceptions import (AtLeastOnePropertyError, DependentPropertiesError,
|
||||
ParseError)
|
||||
from ..exceptions import (AtLeastOnePropertyError, CustomContentError,
|
||||
DependentPropertiesError, ParseError)
|
||||
from ..properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
|
||||
EmbeddedObjectProperty, EnumProperty, FloatProperty,
|
||||
HashesProperty, HexProperty, IntegerProperty,
|
||||
ListProperty, ObjectReferenceProperty, Property,
|
||||
StringProperty, TimestampProperty, TypeProperty)
|
||||
from ..utils import get_dict
|
||||
from ..utils import TYPE_REGEX, _get_dict
|
||||
|
||||
|
||||
class ObservableProperty(Property):
|
||||
"""Property for holding Cyber Observable Objects.
|
||||
"""
|
||||
|
||||
def __init__(self, allow_custom=False, *args, **kwargs):
|
||||
self.allow_custom = allow_custom
|
||||
super(ObservableProperty, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
# get deep copy since we are going modify the dict and might
|
||||
# modify the original dict as _get_dict() does not return new
|
||||
# dict when passed a dict
|
||||
dictified = copy.deepcopy(dictified)
|
||||
except ValueError:
|
||||
raise ValueError("The observable property must contain a dictionary")
|
||||
if dictified == {}:
|
||||
|
@ -33,7 +43,10 @@ class ObservableProperty(Property):
|
|||
valid_refs = dict((k, v['type']) for (k, v) in dictified.items())
|
||||
|
||||
for key, obj in dictified.items():
|
||||
parsed_obj = parse_observable(obj, valid_refs)
|
||||
if self.allow_custom:
|
||||
parsed_obj = parse_observable(obj, valid_refs, allow_custom=True)
|
||||
else:
|
||||
parsed_obj = parse_observable(obj, valid_refs)
|
||||
dictified[key] = parsed_obj
|
||||
|
||||
return dictified
|
||||
|
@ -43,13 +56,18 @@ class ExtensionsProperty(DictionaryProperty):
|
|||
"""Property for representing extensions on Observable objects.
|
||||
"""
|
||||
|
||||
def __init__(self, enclosing_type=None, required=False):
|
||||
def __init__(self, allow_custom=False, enclosing_type=None, required=False):
|
||||
self.allow_custom = allow_custom
|
||||
self.enclosing_type = enclosing_type
|
||||
super(ExtensionsProperty, self).__init__(required)
|
||||
|
||||
def clean(self, value):
|
||||
try:
|
||||
dictified = get_dict(value)
|
||||
dictified = _get_dict(value)
|
||||
# get deep copy since we are going modify the dict and might
|
||||
# modify the original dict as _get_dict() does not return new
|
||||
# dict when passed a dict
|
||||
dictified = copy.deepcopy(dictified)
|
||||
except ValueError:
|
||||
raise ValueError("The extensions property must contain a dictionary")
|
||||
if dictified == {}:
|
||||
|
@ -61,13 +79,18 @@ class ExtensionsProperty(DictionaryProperty):
|
|||
if key in specific_type_map:
|
||||
cls = specific_type_map[key]
|
||||
if type(subvalue) is dict:
|
||||
dictified[key] = cls(**subvalue)
|
||||
if self.allow_custom:
|
||||
subvalue['allow_custom'] = True
|
||||
dictified[key] = cls(**subvalue)
|
||||
else:
|
||||
dictified[key] = cls(**subvalue)
|
||||
elif type(subvalue) is cls:
|
||||
# If already an instance of an _Extension class, assume it's valid
|
||||
dictified[key] = subvalue
|
||||
else:
|
||||
raise ValueError("Cannot determine extension type.")
|
||||
else:
|
||||
raise ValueError("The key used in the extensions dictionary is not an extension type name")
|
||||
raise CustomContentError("Can't parse unknown extension type: {}".format(key))
|
||||
else:
|
||||
raise ValueError("The enclosing type '%s' has no extensions defined" % self.enclosing_type)
|
||||
return dictified
|
||||
|
@ -807,7 +830,7 @@ def parse_observable(data, _valid_refs=None, allow_custom=False):
|
|||
An instantiated Python STIX Cyber Observable object.
|
||||
"""
|
||||
|
||||
obj = get_dict(data)
|
||||
obj = _get_dict(data)
|
||||
obj['_valid_refs'] = _valid_refs or []
|
||||
|
||||
if 'type' not in obj:
|
||||
|
@ -820,11 +843,14 @@ def parse_observable(data, _valid_refs=None, allow_custom=False):
|
|||
|
||||
if 'extensions' in obj and obj['type'] in EXT_MAP:
|
||||
for name, ext in obj['extensions'].items():
|
||||
if name not in EXT_MAP[obj['type']]:
|
||||
raise ParseError("Can't parse Unknown extension type '%s' for observable type '%s'!" % (name, obj['type']))
|
||||
ext_class = EXT_MAP[obj['type']][name]
|
||||
obj['extensions'][name] = ext_class(allow_custom=allow_custom, **obj['extensions'][name])
|
||||
|
||||
try:
|
||||
ext_class = EXT_MAP[obj['type']][name]
|
||||
except KeyError:
|
||||
if not allow_custom:
|
||||
raise CustomContentError("Can't parse unknown extension type '%s'"
|
||||
"for observable type '%s'!" % (name, obj['type']))
|
||||
else: # extension was found
|
||||
obj['extensions'][name] = ext_class(allow_custom=allow_custom, **obj['extensions'][name])
|
||||
return obj_class(allow_custom=allow_custom, **obj)
|
||||
|
||||
|
||||
|
@ -851,6 +877,12 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
|||
|
||||
class _Custom(cls, _Observable):
|
||||
|
||||
if not re.match(TYPE_REGEX, type):
|
||||
raise ValueError("Invalid observable type name '%s': must only contain the "
|
||||
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||
elif len(type) < 3 or len(type) > 250:
|
||||
raise ValueError("Invalid observable type name '%s': must be between 3 and 250 characters." % type)
|
||||
|
||||
_type = type
|
||||
_properties = OrderedDict()
|
||||
_properties.update([
|
||||
|
@ -871,6 +903,9 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
|||
"is not a ListProperty containing ObjectReferenceProperty." % prop_name)
|
||||
|
||||
_properties.update(properties)
|
||||
_properties.update([
|
||||
('extensions', ExtensionsProperty(enclosing_type=_type)),
|
||||
])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
_Observable.__init__(self, **kwargs)
|
||||
|
@ -921,13 +956,19 @@ def CustomExtension(observable=None, type='x-custom-observable', properties=None
|
|||
|
||||
class _Custom(cls, _Extension):
|
||||
|
||||
if not re.match(TYPE_REGEX, type):
|
||||
raise ValueError("Invalid extension type name '%s': must only contain the "
|
||||
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type)
|
||||
elif len(type) < 3 or len(type) > 250:
|
||||
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
|
||||
|
||||
_type = type
|
||||
_properties = {
|
||||
'extensions': ExtensionsProperty(enclosing_type=_type),
|
||||
}
|
||||
|
||||
if not isinstance(properties, dict) or not properties:
|
||||
raise ValueError("'properties' must be a dict!")
|
||||
if not properties or not isinstance(properties, list):
|
||||
raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]")
|
||||
|
||||
_properties.update(properties)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "0.4.0"
|
||||
__version__ = "1.0.2"
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
"""Functions and class wrappers for interacting with STIX data at a high level.
|
||||
|
||||
.. autofunction:: create
|
||||
.. autofunction:: set_default_creator
|
||||
.. autofunction:: set_default_created
|
||||
.. autofunction:: set_default_external_refs
|
||||
.. autofunction:: set_default_object_marking_refs
|
||||
.. autofunction:: get
|
||||
.. autofunction:: all_versions
|
||||
.. autofunction:: query
|
||||
.. autofunction:: creator_of
|
||||
.. autofunction:: relationships
|
||||
.. autofunction:: related_to
|
||||
.. autofunction:: save
|
||||
.. autofunction:: add_filters
|
||||
.. autofunction:: add_filter
|
||||
.. autofunction:: parse
|
||||
.. autofunction:: add_data_source
|
||||
.. autofunction:: add_data_sources
|
||||
|
||||
"""
|
||||
|
||||
import stix2
|
||||
from . import AttackPattern as _AttackPattern
|
||||
from . import Campaign as _Campaign
|
||||
from . import CourseOfAction as _CourseOfAction
|
||||
from . import Identity as _Identity
|
||||
from . import Indicator as _Indicator
|
||||
from . import IntrusionSet as _IntrusionSet
|
||||
from . import Malware as _Malware
|
||||
from . import ObservedData as _ObservedData
|
||||
from . import Report as _Report
|
||||
from . import ThreatActor as _ThreatActor
|
||||
from . import Tool as _Tool
|
||||
from . import Vulnerability as _Vulnerability
|
||||
from . import (AlternateDataStream, ArchiveExt, Artifact, AutonomousSystem, # noqa: F401
|
||||
Bundle, CustomExtension, CustomMarking, CustomObservable,
|
||||
Directory, DomainName, EmailAddress, EmailMessage,
|
||||
EmailMIMEComponent, Environment, ExtensionsProperty,
|
||||
ExternalReference, File, FileSystemSource, Filter,
|
||||
GranularMarking, HTTPRequestExt, ICMPExt, IPv4Address,
|
||||
IPv6Address, KillChainPhase, MACAddress, MarkingDefinition,
|
||||
MemoryStore, Mutex, NetworkTraffic, NTFSExt, parse_observable,
|
||||
PDFExt, Process, RasterImageExt, Relationship, Sighting,
|
||||
SocketExt, Software, StatementMarking, TAXIICollectionSource,
|
||||
TCPExt, TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, TLPMarking,
|
||||
UNIXAccountExt, URL, UserAccount, WindowsPEBinaryExt,
|
||||
WindowsPEOptionalHeaderType, WindowsPESection,
|
||||
WindowsProcessExt, WindowsRegistryKey, WindowsRegistryValueType,
|
||||
WindowsServiceExt, X509Certificate, X509V3ExtenstionsType)
|
||||
from .datastore.filters import FilterSet
|
||||
|
||||
# Use an implicit MemoryStore
|
||||
_environ = Environment(store=MemoryStore())
|
||||
|
||||
create = _environ.create
|
||||
set_default_creator = _environ.set_default_creator
|
||||
set_default_created = _environ.set_default_created
|
||||
set_default_external_refs = _environ.set_default_external_refs
|
||||
set_default_object_marking_refs = _environ.set_default_object_marking_refs
|
||||
get = _environ.get
|
||||
all_versions = _environ.all_versions
|
||||
query = _environ.query
|
||||
creator_of = _environ.creator_of
|
||||
relationships = _environ.relationships
|
||||
related_to = _environ.related_to
|
||||
save = _environ.add
|
||||
add_filters = _environ.add_filters
|
||||
add_filter = _environ.add_filter
|
||||
parse = _environ.parse
|
||||
add_data_source = _environ.source.add_data_source
|
||||
add_data_sources = _environ.source.add_data_sources
|
||||
|
||||
|
||||
# Wrap SDOs with helper functions
|
||||
|
||||
|
||||
STIX_OBJS = [_AttackPattern, _Campaign, _CourseOfAction, _Identity,
|
||||
_Indicator, _IntrusionSet, _Malware, _ObservedData, _Report,
|
||||
_ThreatActor, _Tool, _Vulnerability]
|
||||
|
||||
STIX_OBJ_DOCS = """
|
||||
|
||||
.. method:: created_by(*args, **kwargs)
|
||||
|
||||
{}
|
||||
|
||||
.. method:: relationships(*args, **kwargs)
|
||||
|
||||
{}
|
||||
|
||||
.. method:: related(*args, **kwargs)
|
||||
|
||||
{}
|
||||
|
||||
""".format(_environ.creator_of.__doc__,
|
||||
_environ.relationships.__doc__,
|
||||
_environ.related_to.__doc__)
|
||||
|
||||
|
||||
def _created_by_wrapper(self, *args, **kwargs):
|
||||
return _environ.creator_of(self, *args, **kwargs)
|
||||
|
||||
|
||||
def _relationships_wrapper(self, *args, **kwargs):
|
||||
return _environ.relationships(self, *args, **kwargs)
|
||||
|
||||
|
||||
def _related_wrapper(self, *args, **kwargs):
|
||||
return _environ.related_to(self, *args, **kwargs)
|
||||
|
||||
|
||||
def _observed_data_init(self, *args, **kwargs):
|
||||
self.__allow_custom = kwargs.get('allow_custom', False)
|
||||
self._properties['objects'].allow_custom = kwargs.get('allow_custom', False)
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
def _constructor_wrapper(obj_type):
|
||||
# Use an intermediate wrapper class so the implicit environment will create objects that have our wrapper functions
|
||||
class_dict = dict(
|
||||
created_by=_created_by_wrapper,
|
||||
relationships=_relationships_wrapper,
|
||||
related=_related_wrapper,
|
||||
**obj_type.__dict__
|
||||
)
|
||||
|
||||
# Avoid TypeError about super() in ObservedData
|
||||
if 'ObservedData' in obj_type.__name__:
|
||||
class_dict['__init__'] = _observed_data_init
|
||||
|
||||
wrapped_type = type(obj_type.__name__, obj_type.__bases__, class_dict)
|
||||
|
||||
@staticmethod
|
||||
def new_constructor(cls, *args, **kwargs):
|
||||
x = _environ.create(wrapped_type, *args, **kwargs)
|
||||
return x
|
||||
return new_constructor
|
||||
|
||||
|
||||
def _setup_workbench():
|
||||
# Create wrapper classes whose constructors call the implicit environment's create()
|
||||
for obj_type in STIX_OBJS:
|
||||
new_class_dict = {
|
||||
'__new__': _constructor_wrapper(obj_type),
|
||||
'__doc__': 'Workbench wrapper around the `{0} <stix2.v20.sdo.rst#stix2.v20.sdo.{0}>`__ object. {1}'.format(obj_type.__name__, STIX_OBJ_DOCS)
|
||||
}
|
||||
new_class = type(obj_type.__name__, (), new_class_dict)
|
||||
|
||||
# Add our new class to this module's globals and to the library-wide mapping.
|
||||
# This allows parse() to use the wrapped classes.
|
||||
globals()[obj_type.__name__] = new_class
|
||||
stix2.OBJ_MAP[obj_type._type] = new_class
|
||||
new_class = None
|
||||
|
||||
|
||||
_setup_workbench()
|
||||
|
||||
|
||||
# Functions to get all objects of a specific type
|
||||
|
||||
|
||||
def attack_patterns(filters=None):
|
||||
"""Retrieve all Attack Pattern objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'attack-pattern'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def campaigns(filters=None):
|
||||
"""Retrieve all Campaign objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'campaign'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def courses_of_action(filters=None):
|
||||
"""Retrieve all Course of Action objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'course-of-action'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def identities(filters=None):
|
||||
"""Retrieve all Identity objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'identity'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def indicators(filters=None):
|
||||
"""Retrieve all Indicator objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'indicator'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def intrusion_sets(filters=None):
|
||||
"""Retrieve all Intrusion Set objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'intrusion-set'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def malware(filters=None):
|
||||
"""Retrieve all Malware objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'malware'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def observed_data(filters=None):
|
||||
"""Retrieve all Observed Data objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'observed-data'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def reports(filters=None):
|
||||
"""Retrieve all Report objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'report'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def threat_actors(filters=None):
|
||||
"""Retrieve all Threat Actor objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'threat-actor'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def tools(filters=None):
|
||||
"""Retrieve all Tool objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'tool'))
|
||||
return query(filter_list)
|
||||
|
||||
|
||||
def vulnerabilities(filters=None):
|
||||
"""Retrieve all Vulnerability objects.
|
||||
|
||||
Args:
|
||||
filters (list, optional): A list of additional filters to apply to
|
||||
the query.
|
||||
|
||||
"""
|
||||
filter_list = FilterSet(filters)
|
||||
filter_list.add(Filter('type', '=', 'vulnerability'))
|
||||
return query(filter_list)
|
44
tox.ini
44
tox.ini
|
@ -1,41 +1,45 @@
|
|||
[tox]
|
||||
envlist = py27,py34,py35,py36,pycodestyle,isort-check
|
||||
envlist = py27,py34,py35,py36,style,isort-check,packaging
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
-U
|
||||
tox
|
||||
pytest
|
||||
pytest-cov
|
||||
coverage
|
||||
-U
|
||||
tox
|
||||
pytest
|
||||
pytest-cov
|
||||
coverage
|
||||
taxii2-client
|
||||
medallion
|
||||
commands =
|
||||
py.test --cov=stix2 stix2/test/ --cov-report term-missing
|
||||
pytest --ignore=stix2/test/test_workbench.py --cov=stix2 stix2/test/ --cov-report term-missing
|
||||
pytest stix2/test/test_workbench.py --cov=stix2 --cov-report term-missing --cov-append
|
||||
|
||||
passenv = CI TRAVIS TRAVIS_*
|
||||
|
||||
[testenv:pycodestyle]
|
||||
[testenv:style]
|
||||
deps =
|
||||
flake8
|
||||
pycodestyle
|
||||
commands =
|
||||
pycodestyle ./stix2
|
||||
flake8
|
||||
|
||||
[pycodestyle]
|
||||
max-line-length=160
|
||||
|
||||
[flake8]
|
||||
max-line-length=160
|
||||
max-line-length = 160
|
||||
|
||||
[testenv:isort-check]
|
||||
deps = isort
|
||||
commands =
|
||||
isort -rc stix2 examples -df
|
||||
isort -rc stix2 examples -c
|
||||
isort -rc stix2 examples -df
|
||||
isort -rc stix2 examples -c
|
||||
|
||||
[testenv:packaging]
|
||||
deps =
|
||||
readme_renderer
|
||||
commands =
|
||||
python setup.py check -r -s
|
||||
|
||||
[travis]
|
||||
python =
|
||||
2.7: py27, pycodestyle
|
||||
3.4: py34, pycodestyle
|
||||
3.5: py35, pycodestyle
|
||||
3.6: py36, pycodestyle
|
||||
2.7: py27, style
|
||||
3.4: py34, style
|
||||
3.5: py35, style
|
||||
3.6: py36, style, packaging
|
||||
|
|
Loading…
Reference in New Issue