diff --git a/docs/guide/DataStore, CompositeDataSource, Filters.ipynb b/docs/guide/DataStore, CompositeDataSource, Filters.ipynb index 4614e61..04662cc 100644 --- a/docs/guide/DataStore, CompositeDataSource, Filters.ipynb +++ b/docs/guide/DataStore, CompositeDataSource, Filters.ipynb @@ -255,9 +255,9 @@ ], "metadata": { "kernelspec": { - "display_name": "cti-python-stix2", + "display_name": "Python 3", "language": "python", - "name": "cti-python-stix2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/FileSystem.ipynb b/docs/guide/FileSystem.ipynb index 6a2b17d..9239131 100644 --- a/docs/guide/FileSystem.ipynb +++ b/docs/guide/FileSystem.ipynb @@ -497,9 +497,9 @@ ], "metadata": { "kernelspec": { - "display_name": "cti-python-stix2", + "display_name": "Python 3", "language": "python", - "name": "cti-python-stix2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/Memory.ipynb b/docs/guide/Memory.ipynb index 6fcb399..29daae6 100644 --- a/docs/guide/Memory.ipynb +++ b/docs/guide/Memory.ipynb @@ -256,9 +256,9 @@ ], "metadata": { "kernelspec": { - "display_name": "cti-python-stix2", + "display_name": "Python 3", "language": "python", - "name": "cti-python-stix2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/TAXIICollection.ipynb b/docs/guide/TAXIICollection.ipynb index 1180c74..48b4656 100644 --- a/docs/guide/TAXIICollection.ipynb +++ b/docs/guide/TAXIICollection.ipynb @@ -2387,7 +2387,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "from stix2 import TAXIICollectionSink, ThreatActor\n", @@ -2482,9 +2484,9 @@ ], "metadata": { "kernelspec": { - "display_name": "cti-python-stix2", + "display_name": "Python 3", "language": "python", - "name": "cti-python-stix2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/creating.ipynb b/docs/guide/creating.ipynb index 2c0f132..6cfea7f 100644 --- a/docs/guide/creating.ipynb +++ b/docs/guide/creating.ipynb @@ -869,9 +869,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/custom.ipynb b/docs/guide/custom.ipynb index 0626692..2254fa8 100644 --- a/docs/guide/custom.ipynb +++ b/docs/guide/custom.ipynb @@ -916,9 +916,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/environment.ipynb b/docs/guide/environment.ipynb index d2a0de2..a9184a1 100644 --- a/docs/guide/environment.ipynb +++ b/docs/guide/environment.ipynb @@ -723,9 +723,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/docs/guide/markings.ipynb b/docs/guide/markings.ipynb index 7e512a9..cb8f762 100644 --- a/docs/guide/markings.ipynb +++ b/docs/guide/markings.ipynb @@ -146,14 +146,14 @@ ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
" "type": "indicator",\n",
- " "id": "indicator--aa0a1159-32b8-44d7-ba58-574ab6b9c9af",\n",
- " "created": "2017-09-26T23:38:12.161Z",\n",
- " "modified": "2017-09-26T23:38:12.161Z",\n",
+ " "id": "indicator--409a0b15-1108-4251-8aee-a08995976561",\n",
+ " "created": "2017-10-04T14:42:54.685Z",\n",
+ " "modified": "2017-10-04T14:42:54.685Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:12.161492Z",\n",
+ " "valid_from": "2017-10-04T14:42:54.685184Z",\n",
" "object_marking_refs": [\n",
" "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"\n",
" ]\n",
@@ -263,8 +263,8 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "marking-definition",\n",
- " "id": "marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b",\n",
- " "created": "2017-09-26T23:38:13.988639Z",\n",
+ " "id": "marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53",\n",
+ " "created": "2017-10-04T14:43:04.090873Z",\n",
" "definition_type": "statement",\n",
" "definition": {\n",
" "statement": "Copyright 2017, Example Corp"\n",
@@ -376,16 +376,16 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--79913250-0e10-45d2-925d-53ee3747eac5",\n",
- " "created": "2017-09-26T23:38:15.669Z",\n",
- " "modified": "2017-09-26T23:38:15.669Z",\n",
+ " "id": "indicator--526cda4e-6745-4cd6-852f-0750c6a79784",\n",
+ " "created": "2017-10-04T14:43:09.586Z",\n",
+ " "modified": "2017-10-04T14:43:09.586Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:15.669626Z",\n",
+ " "valid_from": "2017-10-04T14:43:09.586133Z",\n",
" "object_marking_refs": [\n",
- " "marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b"\n",
+ " "marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"\n",
" ]\n",
"}\n",
"
\n"
@@ -484,14 +484,14 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--f96f6de3-184d-4d18-85cd-c1517265b775",\n",
- " "created": "2017-09-26T23:38:17.187Z",\n",
- " "modified": "2017-09-26T23:38:17.187Z",\n",
+ " "id": "indicator--1505b789-fcd2-48ee-bea9-3b20627a4abd",\n",
+ " "created": "2017-10-04T14:43:20.049Z",\n",
+ " "modified": "2017-10-04T14:43:20.049Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:17.18725Z",\n",
+ " "valid_from": "2017-10-04T14:43:20.049166Z",\n",
" "object_marking_refs": [\n",
" "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"\n",
" ]\n",
@@ -599,9 +599,9 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "malware",\n",
- " "id": "malware--1c57d899-1255-4f08-b084-289296b3aa0d",\n",
- " "created": "2017-09-26T23:38:18.729Z",\n",
- " "modified": "2017-09-26T23:38:18.729Z",\n",
+ " "id": "malware--9f8970eb-b398-41b6-b8c8-8a607ad3a2c5",\n",
+ " "created": "2017-10-04T14:43:26.129Z",\n",
+ " "modified": "2017-10-04T14:43:26.129Z",\n",
" "name": "Poison Ivy",\n",
" "description": "A ransomware related to ...",\n",
" "labels": [\n",
@@ -609,7 +609,7 @@
" ],\n",
" "granular_markings": [\n",
" {\n",
- " "marking_ref": "marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b",\n",
+ " "marking_ref": "marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53",\n",
" "selectors": [\n",
" "description"\n",
" ]\n",
@@ -696,12 +696,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Both object markings and granular markings can also be added to STIX objects which have already been created. Doing so will create a new version of the object (note the updated ``modified`` time)."
+ "Both object markings and granular markings can also be added to STIX objects which have already been created.\n",
+ "\n",
+ "**Note**: Doing so will create a new version of the object (note the updated ``modified`` time)."
]
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 21,
"metadata": {},
"outputs": [
{
@@ -777,17 +779,17 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--aa0a1159-32b8-44d7-ba58-574ab6b9c9af",\n",
- " "created": "2017-09-26T23:38:12.161Z",\n",
- " "modified": "2017-09-26T23:38:22.548Z",\n",
+ " "id": "indicator--409a0b15-1108-4251-8aee-a08995976561",\n",
+ " "created": "2017-10-04T14:42:54.685Z",\n",
+ " "modified": "2017-10-04T15:03:46.599Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:12.161492Z",\n",
+ " "valid_from": "2017-10-04T14:42:54.685184Z",\n",
" "object_marking_refs": [\n",
- " "marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b",\n",
- " "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"\n",
+ " "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82",\n",
+ " "marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"\n",
" ]\n",
"}\n",
"
\n"
@@ -796,15 +798,13 @@
""
]
},
- "execution_count": 9,
+ "execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "from stix2.markings import add_markings\n",
- "\n",
- "indicator4 = add_markings(indicator, marking_definition.id)\n",
+ "indicator4 = indicator.add_markings(marking_definition)\n",
"print(indicator4)"
]
},
@@ -817,7 +817,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 22,
"metadata": {},
"outputs": [
{
@@ -893,14 +893,14 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--aa0a1159-32b8-44d7-ba58-574ab6b9c9af",\n",
- " "created": "2017-09-26T23:38:12.161Z",\n",
- " "modified": "2017-09-26T23:38:24.574Z",\n",
+ " "id": "indicator--409a0b15-1108-4251-8aee-a08995976561",\n",
+ " "created": "2017-10-04T14:42:54.685Z",\n",
+ " "modified": "2017-10-04T15:03:54.290Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:12.161492Z",\n",
+ " "valid_from": "2017-10-04T14:42:54.685184Z",\n",
" "object_marking_refs": [\n",
" "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"\n",
" ]\n",
@@ -911,15 +911,13 @@
""
]
},
- "execution_count": 10,
+ "execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "from stix2.markings import remove_markings\n",
- "\n",
- "indicator5 = remove_markings(indicator4, marking_definition.id)\n",
+ "indicator5 = indicator4.remove_markings(marking_definition)\n",
"print(indicator5)"
]
},
@@ -932,7 +930,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 23,
"metadata": {},
"outputs": [
{
@@ -1008,17 +1006,17 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--aa0a1159-32b8-44d7-ba58-574ab6b9c9af",\n",
- " "created": "2017-09-26T23:38:12.161Z",\n",
- " "modified": "2017-09-26T23:38:26.215Z",\n",
+ " "id": "indicator--409a0b15-1108-4251-8aee-a08995976561",\n",
+ " "created": "2017-10-04T14:42:54.685Z",\n",
+ " "modified": "2017-10-04T15:04:04.218Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:12.161492Z",\n",
+ " "valid_from": "2017-10-04T14:42:54.685184Z",\n",
" "object_marking_refs": [\n",
- " "marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b",\n",
- " "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da"\n",
+ " "marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da",\n",
+ " "marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53"\n",
" ]\n",
"}\n",
"
\n"
@@ -1027,16 +1025,15 @@
""
]
},
- "execution_count": 11,
+ "execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from stix2 import TLP_GREEN\n",
- "from stix2.markings import set_markings\n",
"\n",
- "indicator6 = set_markings(indicator5, [TLP_GREEN.id, marking_definition.id])\n",
+ "indicator6 = indicator5.set_markings([TLP_GREEN, marking_definition])\n",
"print(indicator6)"
]
},
@@ -1125,14 +1122,14 @@
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */{\n",
" "type": "indicator",\n",
- " "id": "indicator--aa0a1159-32b8-44d7-ba58-574ab6b9c9af",\n",
- " "created": "2017-09-26T23:38:12.161Z",\n",
- " "modified": "2017-09-26T23:38:27.900Z",\n",
+ " "id": "indicator--409a0b15-1108-4251-8aee-a08995976561",\n",
+ " "created": "2017-10-04T14:42:54.685Z",\n",
+ " "modified": "2017-10-04T14:54:39.331Z",\n",
" "labels": [\n",
" "malicious-activity"\n",
" ],\n",
" "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
- " "valid_from": "2017-09-26T23:38:12.161492Z"\n",
+ " "valid_from": "2017-10-04T14:42:54.685184Z"\n",
"}\n",
"
\n"
],
@@ -1146,9 +1143,7 @@
}
],
"source": [
- "from stix2.markings import clear_markings\n",
- "\n",
- "indicator7 = clear_markings(indicator5)\n",
+ "indicator7 = indicator5.clear_markings()\n",
"print(indicator7)"
]
},
@@ -1170,32 +1165,57 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "['marking-definition--b039cd22-b453-40c7-b9d8-20f8ae1ba29b',\n",
- " 'marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da']"
+ "['marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da',\n",
+ " 'marking-definition--030bb5c6-c5eb-4e9c-8e7a-b9aab08ded53']"
]
},
- "execution_count": 13,
+ "execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "from stix2.markings import get_markings\n",
- "\n",
- "get_markings(indicator6)"
+ "indicator6.get_markings()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "You can also get a list of granular markings by passing a list of selectors to ``get_markings``:"
+ "To get a list of the granular markings on an object, pass the object and a list of selectors to ``get_markings``:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9']"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "malware.get_markings('name')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can also call ``get_markings()`` as a method on the STIX object."
]
},
{
@@ -1215,36 +1235,14 @@
}
],
"source": [
- "get_markings(malware, 'name')"
+ "malware.get_markings('name')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "You can also check if an object is marked by a specific markings. Again, for granular markings, pass in the selector or list of selectors."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from stix2.markings import is_marked\n",
- "\n",
- "is_marked(indicator, TLP_AMBER.id)"
+ "Finally, you may also check if an object is marked by a specific markings. Again, for granular markings, pass in the selector or list of selectors."
]
},
{
@@ -1264,12 +1262,32 @@
}
],
"source": [
- "is_marked(malware, TLP_WHITE.id, 'name')"
+ "indicator.is_marked(TLP_AMBER.id)"
]
},
{
"cell_type": "code",
"execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "malware.is_marked(TLP_WHITE.id, 'name')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
"metadata": {
"scrolled": true
},
@@ -1280,21 +1298,21 @@
"False"
]
},
- "execution_count": 17,
+ "execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "is_marked(malware, TLP_WHITE.id, 'description')"
+ "malware.is_marked(TLP_WHITE.id, 'description')"
]
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 2",
+ "display_name": "Python 3",
"language": "python",
- "name": "python2"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/docs/guide/parsing.ipynb b/docs/guide/parsing.ipynb
index f645740..e991e0c 100644
--- a/docs/guide/parsing.ipynb
+++ b/docs/guide/parsing.ipynb
@@ -109,9 +109,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 2",
+ "display_name": "Python 3",
"language": "python",
- "name": "python2"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/docs/guide/serializing.ipynb b/docs/guide/serializing.ipynb
index 8ca4460..8fcc19d 100644
--- a/docs/guide/serializing.ipynb
+++ b/docs/guide/serializing.ipynb
@@ -178,9 +178,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 2",
+ "display_name": "Python 3",
"language": "python",
- "name": "python2"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/docs/guide/versioning.ipynb b/docs/guide/versioning.ipynb
index d38ba94..30ceb69 100644
--- a/docs/guide/versioning.ipynb
+++ b/docs/guide/versioning.ipynb
@@ -322,9 +322,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 2",
+ "display_name": "Python 3",
"language": "python",
- "name": "python2"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/stix2/__init__.py b/stix2/__init__.py
index 770f8cb..55911a4 100644
--- a/stix2/__init__.py
+++ b/stix2/__init__.py
@@ -25,6 +25,8 @@ from .common import (TLP_AMBER, TLP_GREEN, TLP_RED, TLP_WHITE, CustomMarking,
MarkingDefinition, StatementMarking, TLPMarking)
from .core import Bundle, _register_type, parse
from .environment import Environment, ObjectFactory
+from .markings import (add_markings, clear_markings, get_markings, is_marked,
+ remove_markings, set_markings)
from .observables import (URL, AlternateDataStream, ArchiveExt, Artifact,
AutonomousSystem, CustomExtension, CustomObservable,
Directory, DomainName, EmailAddress, EmailMessage,
diff --git a/stix2/common.py b/stix2/common.py
index bd177fd..602e43f 100644
--- a/stix2/common.py
+++ b/stix2/common.py
@@ -3,6 +3,7 @@
from collections import OrderedDict
from .base import _STIXBase
+from .markings import MarkingsMixin
from .properties import (HashesProperty, IDProperty, ListProperty, Property,
ReferenceProperty, SelectorProperty, StringProperty,
TimestampProperty, TypeProperty)
@@ -76,7 +77,7 @@ class MarkingProperty(Property):
raise ValueError("must be a Statement, TLP Marking or a registered marking.")
-class MarkingDefinition(_STIXBase):
+class MarkingDefinition(_STIXBase, MarkingsMixin):
_type = 'marking-definition'
_properties = OrderedDict()
_properties.update([
diff --git a/stix2/markings/__init__.py b/stix2/markings/__init__.py
index 9194ee1..69f3ace 100644
--- a/stix2/markings/__init__.py
+++ b/stix2/markings/__init__.py
@@ -224,3 +224,16 @@ def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=Fa
result = result or object_markings.is_marked(obj, object_marks)
return result
+
+
+class MarkingsMixin():
+ pass
+
+
+# Note that all of these methods will return a new object because of immutability
+MarkingsMixin.get_markings = get_markings
+MarkingsMixin.set_markings = set_markings
+MarkingsMixin.remove_markings = remove_markings
+MarkingsMixin.add_markings = add_markings
+MarkingsMixin.clear_markings = clear_markings
+MarkingsMixin.is_marked = is_marked
diff --git a/stix2/markings/granular_markings.py b/stix2/markings/granular_markings.py
index 893428e..3fe3a48 100644
--- a/stix2/markings/granular_markings.py
+++ b/stix2/markings/granular_markings.py
@@ -90,6 +90,7 @@ def remove_markings(obj, marking, selectors):
"""
selectors = utils.convert_to_list(selectors)
+ marking = utils.convert_to_marking_list(marking)
utils.validate(obj, selectors)
granular_markings = obj.get("granular_markings")
@@ -99,12 +100,9 @@ def remove_markings(obj, marking, selectors):
granular_markings = utils.expand_markings(granular_markings)
- if isinstance(marking, list):
- to_remove = []
- for m in marking:
- to_remove.append({"marking_ref": m, "selectors": selectors})
- else:
- to_remove = [{"marking_ref": marking, "selectors": selectors}]
+ to_remove = []
+ for m in marking:
+ to_remove.append({"marking_ref": m, "selectors": selectors})
remove = utils.build_granular_marking(to_remove).get("granular_markings")
@@ -142,14 +140,12 @@ def add_markings(obj, marking, selectors):
"""
selectors = utils.convert_to_list(selectors)
+ marking = utils.convert_to_marking_list(marking)
utils.validate(obj, selectors)
- if isinstance(marking, list):
- granular_marking = []
- for m in marking:
- granular_marking.append({"marking_ref": m, "selectors": sorted(selectors)})
- else:
- granular_marking = [{"marking_ref": marking, "selectors": sorted(selectors)}]
+ granular_marking = []
+ for m in marking:
+ granular_marking.append({"marking_ref": m, "selectors": sorted(selectors)})
if obj.get("granular_markings"):
granular_marking.extend(obj.get("granular_markings"))
@@ -246,7 +242,7 @@ def is_marked(obj, marking=None, selectors=None, inherited=False, descendants=Fa
raise TypeError("Required argument 'selectors' must be provided")
selectors = utils.convert_to_list(selectors)
- marking = utils.convert_to_list(marking)
+ marking = utils.convert_to_marking_list(marking)
utils.validate(obj, selectors)
granular_markings = obj.get("granular_markings", [])
diff --git a/stix2/markings/object_markings.py b/stix2/markings/object_markings.py
index ce77966..cb78294 100644
--- a/stix2/markings/object_markings.py
+++ b/stix2/markings/object_markings.py
@@ -33,7 +33,7 @@ def add_markings(obj, marking):
A new version of the given SDO or SRO with specified markings added.
"""
- marking = utils.convert_to_list(marking)
+ marking = utils.convert_to_marking_list(marking)
object_markings = set(obj.get("object_marking_refs", []) + marking)
@@ -57,7 +57,7 @@ def remove_markings(obj, marking):
A new version of the given SDO or SRO with specified markings removed.
"""
- marking = utils.convert_to_list(marking)
+ marking = utils.convert_to_marking_list(marking)
object_markings = obj.get("object_marking_refs", [])
@@ -123,7 +123,7 @@ def is_marked(obj, marking=None):
provided marking refs match, True is returned.
"""
- marking = utils.convert_to_list(marking)
+ marking = utils.convert_to_marking_list(marking)
object_markings = obj.get("object_marking_refs", [])
if marking:
diff --git a/stix2/markings/utils.py b/stix2/markings/utils.py
index 6fed976..3024fe8 100644
--- a/stix2/markings/utils.py
+++ b/stix2/markings/utils.py
@@ -39,6 +39,12 @@ def _validate_selector(obj, selector):
return True
+def _get_marking_id(marking):
+ if type(marking).__name__ is 'MarkingDefinition': # avoid circular import
+ return marking.id
+ return marking
+
+
def validate(obj, selectors):
"""Given an SDO or SRO, check that each selector is valid."""
if selectors:
@@ -59,6 +65,15 @@ def convert_to_list(data):
return [data]
+def convert_to_marking_list(data):
+ """Convert input into a list of marking identifiers."""
+ if data is not None:
+ if isinstance(data, list):
+ return [_get_marking_id(x) for x in data]
+ else:
+ return [_get_marking_id(data)]
+
+
def compress_markings(granular_markings):
"""Compress granular markings list.
diff --git a/stix2/sdo.py b/stix2/sdo.py
index cdbb9ca..c3eb619 100644
--- a/stix2/sdo.py
+++ b/stix2/sdo.py
@@ -6,6 +6,7 @@ import stix2
from .base import _STIXBase
from .common import ExternalReference, GranularMarking, KillChainPhase
+from .markings import MarkingsMixin
from .observables import ObservableProperty
from .properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, PatternProperty, ReferenceProperty,
@@ -13,7 +14,11 @@ from .properties import (BooleanProperty, IDProperty, IntegerProperty,
from .utils import NOW
-class AttackPattern(_STIXBase):
+class STIXDomainObject(_STIXBase, MarkingsMixin):
+ pass
+
+
+class AttackPattern(STIXDomainObject):
_type = 'attack-pattern'
_properties = OrderedDict()
@@ -34,7 +39,7 @@ class AttackPattern(_STIXBase):
])
-class Campaign(_STIXBase):
+class Campaign(STIXDomainObject):
_type = 'campaign'
_properties = OrderedDict()
@@ -58,7 +63,7 @@ class Campaign(_STIXBase):
])
-class CourseOfAction(_STIXBase):
+class CourseOfAction(STIXDomainObject):
_type = 'course-of-action'
_properties = OrderedDict()
@@ -78,7 +83,7 @@ class CourseOfAction(_STIXBase):
])
-class Identity(_STIXBase):
+class Identity(STIXDomainObject):
_type = 'identity'
_properties = OrderedDict()
@@ -101,7 +106,7 @@ class Identity(_STIXBase):
])
-class Indicator(_STIXBase):
+class Indicator(STIXDomainObject):
_type = 'indicator'
_properties = OrderedDict()
@@ -125,7 +130,7 @@ class Indicator(_STIXBase):
])
-class IntrusionSet(_STIXBase):
+class IntrusionSet(STIXDomainObject):
_type = 'intrusion-set'
_properties = OrderedDict()
@@ -152,7 +157,7 @@ class IntrusionSet(_STIXBase):
])
-class Malware(_STIXBase):
+class Malware(STIXDomainObject):
_type = 'malware'
_properties = OrderedDict()
@@ -173,7 +178,7 @@ class Malware(_STIXBase):
])
-class ObservedData(_STIXBase):
+class ObservedData(STIXDomainObject):
_type = 'observed-data'
_properties = OrderedDict()
@@ -195,7 +200,7 @@ class ObservedData(_STIXBase):
])
-class Report(_STIXBase):
+class Report(STIXDomainObject):
_type = 'report'
_properties = OrderedDict()
@@ -217,7 +222,7 @@ class Report(_STIXBase):
])
-class ThreatActor(_STIXBase):
+class ThreatActor(STIXDomainObject):
_type = 'threat-actor'
_properties = OrderedDict()
@@ -245,7 +250,7 @@ class ThreatActor(_STIXBase):
])
-class Tool(_STIXBase):
+class Tool(STIXDomainObject):
_type = 'tool'
_properties = OrderedDict()
@@ -267,7 +272,7 @@ class Tool(_STIXBase):
])
-class Vulnerability(_STIXBase):
+class Vulnerability(STIXDomainObject):
_type = 'vulnerability'
_properties = OrderedDict()
@@ -314,7 +319,7 @@ def CustomObject(type='x-custom-type', properties=None):
def custom_builder(cls):
- class _Custom(cls, _STIXBase):
+ class _Custom(cls, STIXDomainObject):
_type = type
_properties = OrderedDict()
_properties.update([
diff --git a/stix2/sro.py b/stix2/sro.py
index af483bc..4fa0465 100644
--- a/stix2/sro.py
+++ b/stix2/sro.py
@@ -4,13 +4,18 @@ from collections import OrderedDict
from .base import _STIXBase
from .common import ExternalReference, GranularMarking
+from .markings import MarkingsMixin
from .properties import (BooleanProperty, IDProperty, IntegerProperty,
ListProperty, ReferenceProperty, StringProperty,
TimestampProperty, TypeProperty)
from .utils import NOW
-class Relationship(_STIXBase):
+class STIXRelationshipObject(_STIXBase, MarkingsMixin):
+ pass
+
+
+class Relationship(STIXRelationshipObject):
_type = 'relationship'
_properties = OrderedDict()
@@ -45,7 +50,7 @@ class Relationship(_STIXBase):
super(Relationship, self).__init__(**kwargs)
-class Sighting(_STIXBase):
+class Sighting(STIXRelationshipObject):
_type = 'sighting'
_properties = OrderedDict()
_properties.update([
diff --git a/stix2/test/test_granular_markings.py b/stix2/test/test_granular_markings.py
index e910ad3..f8fc803 100644
--- a/stix2/test/test_granular_markings.py
+++ b/stix2/test/test_granular_markings.py
@@ -1,7 +1,7 @@
import pytest
-from stix2 import Malware, markings
+from stix2 import TLP_RED, Malware, markings
from .constants import MALWARE_MORE_KWARGS as MALWARE_KWARGS_CONST
from .constants import MARKING_IDS
@@ -45,6 +45,7 @@ def test_add_marking_mark_one_selector_multiple_refs():
},
],
**MALWARE_KWARGS),
+ MARKING_IDS[0],
),
(
MALWARE_KWARGS,
@@ -56,13 +57,26 @@ def test_add_marking_mark_one_selector_multiple_refs():
},
],
**MALWARE_KWARGS),
+ MARKING_IDS[0],
+ ),
+ (
+ Malware(**MALWARE_KWARGS),
+ Malware(
+ granular_markings=[
+ {
+ "selectors": ["description", "name"],
+ "marking_ref": TLP_RED.id,
+ },
+ ],
+ **MALWARE_KWARGS),
+ TLP_RED,
),
])
def test_add_marking_mark_multiple_selector_one_refs(data):
before = data[0]
after = data[1]
- before = markings.add_markings(before, [MARKING_IDS[0]], ["description", "name"])
+ before = markings.add_markings(before, data[2], ["description", "name"])
for m in before["granular_markings"]:
assert m in after["granular_markings"]
@@ -347,36 +361,42 @@ def test_get_markings_positional_arguments_combinations(data):
assert set(markings.get_markings(data, "x.z.foo2", False, True)) == set(["10"])
-@pytest.mark.parametrize("before", [
- Malware(
- granular_markings=[
- {
- "selectors": ["description"],
- "marking_ref": MARKING_IDS[0]
- },
- {
- "selectors": ["description"],
- "marking_ref": MARKING_IDS[1]
- },
- ],
- **MALWARE_KWARGS
+@pytest.mark.parametrize("data", [
+ (
+ Malware(
+ granular_markings=[
+ {
+ "selectors": ["description"],
+ "marking_ref": MARKING_IDS[0]
+ },
+ {
+ "selectors": ["description"],
+ "marking_ref": MARKING_IDS[1]
+ },
+ ],
+ **MALWARE_KWARGS
+ ),
+ [MARKING_IDS[0], MARKING_IDS[1]],
),
- dict(
- granular_markings=[
- {
- "selectors": ["description"],
- "marking_ref": MARKING_IDS[0]
- },
- {
- "selectors": ["description"],
- "marking_ref": MARKING_IDS[1]
- },
- ],
- **MALWARE_KWARGS
+ (
+ dict(
+ granular_markings=[
+ {
+ "selectors": ["description"],
+ "marking_ref": MARKING_IDS[0]
+ },
+ {
+ "selectors": ["description"],
+ "marking_ref": MARKING_IDS[1]
+ },
+ ],
+ **MALWARE_KWARGS
+ ),
+ [MARKING_IDS[0], MARKING_IDS[1]],
),
])
-def test_remove_marking_remove_one_selector_with_multiple_refs(before):
- before = markings.remove_markings(before, [MARKING_IDS[0], MARKING_IDS[1]], ["description"])
+def test_remove_marking_remove_one_selector_with_multiple_refs(data):
+ before = markings.remove_markings(data[0], data[1], ["description"])
assert "granular_markings" not in before
diff --git a/stix2/test/test_markings.py b/stix2/test/test_markings.py
index 0c6069a..456bf92 100644
--- a/stix2/test/test_markings.py
+++ b/stix2/test/test_markings.py
@@ -241,4 +241,14 @@ def test_marking_wrong_type_construction():
assert str(excinfo.value) == "Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]"
-# TODO: Add other examples
+def test_campaign_add_markings():
+ campaign = stix2.Campaign(
+ id="campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
+ created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
+ created="2016-04-06T20:03:00Z",
+ modified="2016-04-06T20:03:00Z",
+ name="Green Group Attacks Against Finance",
+ description="Campaign by Green Group against a series of targets in the financial services sector.",
+ )
+ campaign = campaign.add_markings(TLP_WHITE)
+ assert campaign.object_marking_refs[0] == TLP_WHITE.id
diff --git a/stix2/test/test_object_markings.py b/stix2/test/test_object_markings.py
index 36e8e4d..10949ab 100644
--- a/stix2/test/test_object_markings.py
+++ b/stix2/test/test_object_markings.py
@@ -1,7 +1,7 @@
import pytest
-from stix2 import Malware, exceptions, markings
+from stix2 import TLP_AMBER, Malware, exceptions, markings
from .constants import FAKE_TIME, MALWARE_ID, MARKING_IDS
from .constants import MALWARE_KWARGS as MALWARE_KWARGS_CONST
@@ -21,18 +21,26 @@ MALWARE_KWARGS.update({
Malware(**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
+ MARKING_IDS[0],
),
(
MALWARE_KWARGS,
dict(object_marking_refs=[MARKING_IDS[0]],
**MALWARE_KWARGS),
+ MARKING_IDS[0],
+ ),
+ (
+ Malware(**MALWARE_KWARGS),
+ Malware(object_marking_refs=[TLP_AMBER.id],
+ **MALWARE_KWARGS),
+ TLP_AMBER,
),
])
def test_add_markings_one_marking(data):
before = data[0]
after = data[1]
- before = markings.add_markings(before, MARKING_IDS[0], None)
+ before = markings.add_markings(before, data[2], None)
for m in before["object_marking_refs"]:
assert m in after["object_marking_refs"]
@@ -280,19 +288,28 @@ def test_remove_markings_object_level(data):
**MALWARE_KWARGS),
Malware(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
+ [MARKING_IDS[0], MARKING_IDS[2]],
),
(
dict(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], MARKING_IDS[2]],
**MALWARE_KWARGS),
dict(object_marking_refs=[MARKING_IDS[1]],
**MALWARE_KWARGS),
+ [MARKING_IDS[0], MARKING_IDS[2]],
+ ),
+ (
+ Malware(object_marking_refs=[MARKING_IDS[0], MARKING_IDS[1], TLP_AMBER.id],
+ **MALWARE_KWARGS),
+ Malware(object_marking_refs=[MARKING_IDS[1]],
+ **MALWARE_KWARGS),
+ [MARKING_IDS[0], TLP_AMBER],
),
])
def test_remove_markings_multiple(data):
before = data[0]
after = data[1]
- before = markings.remove_markings(before, [MARKING_IDS[0], MARKING_IDS[2]], None)
+ before = markings.remove_markings(before, data[2], None)
assert before['object_marking_refs'] == after['object_marking_refs']