Merge branch 'master' of github.com:oasis-open/cti-python-stix2
commit
77ca5ae2f9
13
CHANGELOG
13
CHANGELOG
|
@ -1,6 +1,19 @@
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
1.3.1 - 2020-03-06
|
||||||
|
|
||||||
|
* #322 Adds encoding option FileSystemSource and MemorySource
|
||||||
|
* #354 Adds ability to specify id-contributing properties on custom SCOs
|
||||||
|
* #346 Certain SCO properties are no longer deprecated
|
||||||
|
* #327 Fixes missing 'name' property on Marking Definitions
|
||||||
|
* #303 Fixes bug with escaping quotes in patterns
|
||||||
|
* #331 Fixes crashing bug of property names that conflict with Mapping methods
|
||||||
|
* #337 Fixes bug with detecting STIX version of content when parsing
|
||||||
|
* #342, #343 Fixes bug when adding SCOs to Memory or FileSystem Stores
|
||||||
|
* #348 Fixes bug with generating deterministic IDs for SCOs
|
||||||
|
* #344 Fixes bug with propagating errors from the pattern validator
|
||||||
|
|
||||||
1.3.0 - 2020-01-04
|
1.3.0 - 2020-01-04
|
||||||
|
|
||||||
* #305 Updates support of STIX 2.1 to WD06
|
* #305 Updates support of STIX 2.1 to WD06
|
||||||
|
|
|
@ -175,9 +175,9 @@
|
||||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\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",
|
".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\">"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--e7fd0fe0-25ff-4fcb-abe5-b6254a9d1a22"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--d6996982-5fb7-4364-b716-b618516989b6"</span><span class=\"p\">,</span>\n",
|
||||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2019-07-25T18:18:18.241Z"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:27.349Z"</span><span class=\"p\">,</span>\n",
|
||||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2019-07-25T18:18:18.241Z"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:27.349Z"</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\">"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\">"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=\"nt\">"x_foo"</span><span class=\"p\">:</span> <span class=\"s2\">"bar"</span>\n",
|
||||||
|
@ -287,9 +287,9 @@
|
||||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\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",
|
".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\">"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--033b5f42-c94f-488f-8efa-2b6a167f0d6f"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--a167d2de-9fc4-4734-a1ae-57a548aad22a"</span><span class=\"p\">,</span>\n",
|
||||||
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2019-07-25T18:18:21.352Z"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:29.180Z"</span><span class=\"p\">,</span>\n",
|
||||||
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2019-07-25T18:18:21.352Z"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:29.180Z"</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\">"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\">"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=\"nt\">"x_foo"</span><span class=\"p\">:</span> <span class=\"s2\">"bar"</span>\n",
|
||||||
|
@ -511,7 +511,7 @@
|
||||||
" <span class=\"nt\">"type"</span><span class=\"p\">:</span> <span class=\"s2\">"identity"</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-4473-83ec-1edf84858f4c"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"identity--311b2d2d-f010-4473-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\">"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\">"2019-07-25T18:18:25.927Z"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:32.934Z"</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\">"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=\"nt\">"identity_class"</span><span class=\"p\">:</span> <span class=\"s2\">"individual"</span>\n",
|
||||||
"<span class=\"p\">}</span>\n",
|
"<span class=\"p\">}</span>\n",
|
||||||
|
@ -544,7 +544,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 7,
|
"execution_count": 8,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
|
@ -569,7 +569,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 8,
|
"execution_count": 9,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -645,9 +645,9 @@
|
||||||
".highlight .vm { color: #19177C } /* Name.Variable.Magic */\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",
|
".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\">"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--b1e4fe7f-7985-451d-855c-6ba5c265b22a"</span><span class=\"p\">,</span>\n",
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-animal--1f7ce0ad-fd3a-4cf0-9cd7-13f7bef9ecd4"</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\">"created"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:38.010Z"</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\">"modified"</span><span class=\"p\">:</span> <span class=\"s2\">"2020-03-05T05:06:38.010Z"</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\">"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=\"nt\">"animal_class"</span><span class=\"p\">:</span> <span class=\"s2\">"mammal"</span>\n",
|
||||||
"<span class=\"p\">}</span>\n",
|
"<span class=\"p\">}</span>\n",
|
||||||
|
@ -657,7 +657,7 @@
|
||||||
"<IPython.core.display.HTML object>"
|
"<IPython.core.display.HTML object>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 8,
|
"execution_count": 9,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
@ -677,7 +677,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 9,
|
"execution_count": 10,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -703,7 +703,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": 11,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -784,7 +784,7 @@
|
||||||
"<IPython.core.display.HTML object>"
|
"<IPython.core.display.HTML object>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 10,
|
"execution_count": 11,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 12,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -846,7 +846,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 12,
|
"execution_count": 13,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -931,7 +931,7 @@
|
||||||
"<IPython.core.display.HTML object>"
|
"<IPython.core.display.HTML object>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 12,
|
"execution_count": 13,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
@ -962,7 +962,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 14,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
|
@ -1043,7 +1043,7 @@
|
||||||
"<IPython.core.display.HTML object>"
|
"<IPython.core.display.HTML object>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 13,
|
"execution_count": 14,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
},
|
},
|
||||||
|
@ -1125,7 +1125,7 @@
|
||||||
"<IPython.core.display.HTML object>"
|
"<IPython.core.display.HTML object>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 13,
|
"execution_count": 14,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
@ -1155,6 +1155,316 @@
|
||||||
"print(obs_data.objects[\"0\"].property_2)"
|
"print(obs_data.objects[\"0\"].property_2)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### ID-Contributing Properties for Custom Cyber Observables\n",
|
||||||
|
"STIX 2.1 Cyber Observables (SCOs) have deterministic IDs, meaning that the ID of a SCO is based on the values of some of its properties. Thus, if multiple cyber observables of the same type have the same values for their ID-contributing properties, then these SCOs will have the same ID. UUIDv5 is used for the deterministic IDs, using the namespace `\"00abedb4-aa42-466c-9c01-fed23315a9b7\"`. A SCO's ID-contributing properties may consist of a combination of required properties and optional properties.\n",
|
||||||
|
"\n",
|
||||||
|
"If a SCO type does not have any ID contributing properties defined, or all of the ID-contributing properties are not present on the object, then the SCO uses a randomly-generated UUIDv4. Thus, you can optionally define which of your custom SCO's properties should be ID-contributing properties. Similar to standard SCOs, your custom SCO's ID-contributing properties can be any combination of the SCO's required and optional properties.\n",
|
||||||
|
"\n",
|
||||||
|
"You define the ID-contributing properties when defining your custom SCO with the `CustomObservable` decorator. After the list of properties, you can optionally define the list of id-contributing properties. If you do not want to specify any id-contributing properties for your custom SCO, then you do not need to do anything additional.\n",
|
||||||
|
"\n",
|
||||||
|
"See the example below:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"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\">"x-new-observable-2"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-new-observable-2--6bc655d6-dcb8-52a3-a862-46848c17e599"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"a_property"</span><span class=\"p\">:</span> <span class=\"s2\">"A property"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"property_2"</span><span class=\"p\">:</span> <span class=\"mi\">2000</span>\n",
|
||||||
|
"<span class=\"p\">}</span>\n",
|
||||||
|
"</pre></div>\n"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.HTML object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 15,
|
||||||
|
"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\">"x-new-observable-2"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-new-observable-2--6bc655d6-dcb8-52a3-a862-46848c17e599"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"a_property"</span><span class=\"p\">:</span> <span class=\"s2\">"A property"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"property_2"</span><span class=\"p\">:</span> <span class=\"mi\">3000</span>\n",
|
||||||
|
"<span class=\"p\">}</span>\n",
|
||||||
|
"</pre></div>\n"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.HTML object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 15,
|
||||||
|
"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\">"x-new-observable-2"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"id"</span><span class=\"p\">:</span> <span class=\"s2\">"x-new-observable-2--1e56f9c3-a73b-5fbd-b348-83c76523c4df"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"a_property"</span><span class=\"p\">:</span> <span class=\"s2\">"A different property"</span><span class=\"p\">,</span>\n",
|
||||||
|
" <span class=\"nt\">"property_2"</span><span class=\"p\">:</span> <span class=\"mi\">3000</span>\n",
|
||||||
|
"<span class=\"p\">}</span>\n",
|
||||||
|
"</pre></div>\n"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.HTML object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 15,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from stix2.v21 import CustomObservable # IDs and Deterministic IDs are NOT part of STIX 2.0 Custom Observables\n",
|
||||||
|
"\n",
|
||||||
|
"@CustomObservable('x-new-observable-2', [\n",
|
||||||
|
" ('a_property', properties.StringProperty(required=True)),\n",
|
||||||
|
" ('property_2', properties.IntegerProperty()),\n",
|
||||||
|
"], [\n",
|
||||||
|
" 'a_property'\n",
|
||||||
|
"])\n",
|
||||||
|
"class NewObservable2():\n",
|
||||||
|
" pass\n",
|
||||||
|
"\n",
|
||||||
|
"new_observable_a = NewObservable2(a_property=\"A property\", property_2=2000)\n",
|
||||||
|
"print(new_observable_a)\n",
|
||||||
|
"\n",
|
||||||
|
"new_observable_b = NewObservable2(a_property=\"A property\", property_2=3000)\n",
|
||||||
|
"print(new_observable_b)\n",
|
||||||
|
"\n",
|
||||||
|
"new_observable_c = NewObservable2(a_property=\"A different property\", property_2=3000)\n",
|
||||||
|
"print(new_observable_c)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this example, `a_property` is the only id-contributing property. Notice that the ID for `new_observable_a` and `new_observable_b` is the same since they have the same value for the id-contributing `a_property` property."
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
@ -1483,21 +1793,21 @@
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "Python 3",
|
"display_name": "Python 2",
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"name": "python3"
|
"name": "python2"
|
||||||
},
|
},
|
||||||
"language_info": {
|
"language_info": {
|
||||||
"codemirror_mode": {
|
"codemirror_mode": {
|
||||||
"name": "ipython",
|
"name": "ipython",
|
||||||
"version": 3
|
"version": 2
|
||||||
},
|
},
|
||||||
"file_extension": ".py",
|
"file_extension": ".py",
|
||||||
"mimetype": "text/x-python",
|
"mimetype": "text/x-python",
|
||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython2",
|
||||||
"version": "3.6.3"
|
"version": "2.7.15+"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 1.3.0
|
current_version = 1.3.1
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,10 @@ def _custom_marking_builder(cls, type, properties, version):
|
||||||
return _CustomMarking
|
return _CustomMarking
|
||||||
|
|
||||||
|
|
||||||
def _custom_observable_builder(cls, type, properties, version):
|
def _custom_observable_builder(cls, type, properties, version, id_contrib_props=None):
|
||||||
|
if id_contrib_props is None:
|
||||||
|
id_contrib_props = []
|
||||||
|
|
||||||
class _CustomObservable(cls, _Observable):
|
class _CustomObservable(cls, _Observable):
|
||||||
|
|
||||||
if not re.match(TYPE_REGEX, type):
|
if not re.match(TYPE_REGEX, type):
|
||||||
|
@ -98,6 +101,8 @@ def _custom_observable_builder(cls, type, properties, version):
|
||||||
|
|
||||||
_type = type
|
_type = type
|
||||||
_properties = OrderedDict(properties)
|
_properties = OrderedDict(properties)
|
||||||
|
if version != '2.0':
|
||||||
|
_id_contributing_properties = id_contrib_props
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
_Observable.__init__(self, **kwargs)
|
_Observable.__init__(self, **kwargs)
|
||||||
|
|
|
@ -15,7 +15,7 @@ from stix2.datastore import (
|
||||||
DataSink, DataSource, DataSourceError, DataStoreMixin,
|
DataSink, DataSource, DataSourceError, DataStoreMixin,
|
||||||
)
|
)
|
||||||
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
from stix2.datastore.filters import Filter, FilterSet, apply_common_filters
|
||||||
from stix2.utils import format_datetime, get_type_from_id, is_marking
|
from stix2.utils import format_datetime, get_type_from_id
|
||||||
|
|
||||||
|
|
||||||
def _timestamp2filename(timestamp):
|
def _timestamp2filename(timestamp):
|
||||||
|
@ -329,11 +329,50 @@ def _check_object_from_file(query, filepath, allow_custom, version, encoding):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _is_versioned_type_dir(type_path, type_name):
|
||||||
|
"""
|
||||||
|
Try to detect whether the given directory is for a versioned type of STIX
|
||||||
|
object. This is done by looking for a directory whose name is a STIX ID
|
||||||
|
of the appropriate type. If found, treat this type as versioned. This
|
||||||
|
doesn't work when a versioned type directory is empty (it will be
|
||||||
|
mis-classified as unversioned), but this detection is only necessary when
|
||||||
|
reading/querying data. If a directory is empty, you'll get no results
|
||||||
|
either way.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
type_path: A path to a directory containing one type of STIX object.
|
||||||
|
type_name: The STIX type name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the directory looks like it contains versioned objects; False
|
||||||
|
if not.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
OSError: If there are errors accessing directory contents or stat()'ing
|
||||||
|
files
|
||||||
|
"""
|
||||||
|
id_regex = re.compile(
|
||||||
|
r"^" + re.escape(type_name) +
|
||||||
|
r"--[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}"
|
||||||
|
r"-[0-9a-f]{12}$",
|
||||||
|
re.I,
|
||||||
|
)
|
||||||
|
|
||||||
|
for entry in os.listdir(type_path):
|
||||||
|
s = os.stat(os.path.join(type_path, entry))
|
||||||
|
if stat.S_ISDIR(s.st_mode) and id_regex.match(entry):
|
||||||
|
is_versioned = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
is_versioned = False
|
||||||
|
|
||||||
|
return is_versioned
|
||||||
|
|
||||||
|
|
||||||
def _search_versioned(query, type_path, auth_ids, allow_custom, version, encoding):
|
def _search_versioned(query, type_path, auth_ids, allow_custom, version, encoding):
|
||||||
"""
|
"""
|
||||||
Searches the given directory, which contains data for STIX objects of a
|
Searches the given directory, which contains data for STIX objects of a
|
||||||
particular versioned type (i.e. not markings), and return any which match
|
particular versioned type, and return any which match the query.
|
||||||
the query.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query: The query to match against
|
query: The query to match against
|
||||||
|
@ -390,36 +429,24 @@ def _search_versioned(query, type_path, auth_ids, allow_custom, version, encodin
|
||||||
|
|
||||||
# For backward-compatibility, also search for plain files named after
|
# For backward-compatibility, also search for plain files named after
|
||||||
# object IDs, in the type directory.
|
# object IDs, in the type directory.
|
||||||
id_files = _get_matching_dir_entries(
|
backcompat_results = _search_unversioned(
|
||||||
type_path, auth_ids, stat.S_ISREG,
|
query, type_path, auth_ids, allow_custom, version, encoding,
|
||||||
".json",
|
|
||||||
)
|
)
|
||||||
for id_file in id_files:
|
results.extend(backcompat_results)
|
||||||
id_path = os.path.join(type_path, id_file)
|
|
||||||
|
|
||||||
try:
|
|
||||||
stix_obj = _check_object_from_file(
|
|
||||||
query, id_path, allow_custom,
|
|
||||||
version, encoding,
|
|
||||||
)
|
|
||||||
if stix_obj:
|
|
||||||
results.append(stix_obj)
|
|
||||||
except IOError as e:
|
|
||||||
if e.errno != errno.ENOENT:
|
|
||||||
raise
|
|
||||||
# else, file-not-found is ok, just skip
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def _search_markings(query, markings_path, auth_ids, allow_custom, version, encoding):
|
def _search_unversioned(
|
||||||
|
query, type_path, auth_ids, allow_custom, version, encoding,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Searches the given directory, which contains markings data, and return any
|
Searches the given directory, which contains unversioned data, and return
|
||||||
which match the query.
|
any objects which match the query.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query: The query to match against
|
query: The query to match against
|
||||||
markings_path: The directory with STIX markings files
|
type_path: The directory with STIX files of unversioned type
|
||||||
auth_ids: Search optimization based on object ID
|
auth_ids: Search optimization based on object ID
|
||||||
allow_custom (bool): Whether to allow custom properties as well unknown
|
allow_custom (bool): Whether to allow custom properties as well unknown
|
||||||
custom objects.
|
custom objects.
|
||||||
|
@ -441,11 +468,11 @@ def _search_markings(query, markings_path, auth_ids, allow_custom, version, enco
|
||||||
"""
|
"""
|
||||||
results = []
|
results = []
|
||||||
id_files = _get_matching_dir_entries(
|
id_files = _get_matching_dir_entries(
|
||||||
markings_path, auth_ids, stat.S_ISREG,
|
type_path, auth_ids, stat.S_ISREG,
|
||||||
".json",
|
".json",
|
||||||
)
|
)
|
||||||
for id_file in id_files:
|
for id_file in id_files:
|
||||||
id_path = os.path.join(markings_path, id_file)
|
id_path = os.path.join(type_path, id_file)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stix_obj = _check_object_from_file(
|
stix_obj = _check_object_from_file(
|
||||||
|
@ -530,12 +557,14 @@ class FileSystemSink(DataSink):
|
||||||
"""Write the given STIX object to a file in the STIX file directory.
|
"""Write the given STIX object to a file in the STIX file directory.
|
||||||
"""
|
"""
|
||||||
type_dir = os.path.join(self._stix_dir, stix_obj["type"])
|
type_dir = os.path.join(self._stix_dir, stix_obj["type"])
|
||||||
if is_marking(stix_obj):
|
|
||||||
filename = stix_obj["id"]
|
# All versioned objects should have a "modified" property.
|
||||||
obj_dir = type_dir
|
if "modified" in stix_obj:
|
||||||
else:
|
|
||||||
filename = _timestamp2filename(stix_obj["modified"])
|
filename = _timestamp2filename(stix_obj["modified"])
|
||||||
obj_dir = os.path.join(type_dir, stix_obj["id"])
|
obj_dir = os.path.join(type_dir, stix_obj["id"])
|
||||||
|
else:
|
||||||
|
filename = stix_obj["id"]
|
||||||
|
obj_dir = type_dir
|
||||||
|
|
||||||
file_path = os.path.join(obj_dir, filename + ".json")
|
file_path = os.path.join(obj_dir, filename + ".json")
|
||||||
|
|
||||||
|
@ -649,12 +678,14 @@ class FileSystemSource(DataSource):
|
||||||
all_data = self.all_versions(stix_id, version=version, _composite_filters=_composite_filters)
|
all_data = self.all_versions(stix_id, version=version, _composite_filters=_composite_filters)
|
||||||
|
|
||||||
if all_data:
|
if all_data:
|
||||||
if is_marking(stix_id):
|
# Simple check for a versioned STIX type: see if the objects have a
|
||||||
# Markings are unversioned; there shouldn't be more than one
|
# "modified" property. (Need only check one, since they are all of
|
||||||
# result.
|
# the same type.)
|
||||||
stix_obj = all_data[0]
|
is_versioned = "modified" in all_data[0]
|
||||||
else:
|
if is_versioned:
|
||||||
stix_obj = sorted(all_data, key=lambda k: k['modified'])[-1]
|
stix_obj = sorted(all_data, key=lambda k: k['modified'])[-1]
|
||||||
|
else:
|
||||||
|
stix_obj = all_data[0]
|
||||||
else:
|
else:
|
||||||
stix_obj = None
|
stix_obj = None
|
||||||
|
|
||||||
|
@ -720,14 +751,15 @@ class FileSystemSource(DataSource):
|
||||||
)
|
)
|
||||||
for type_dir in type_dirs:
|
for type_dir in type_dirs:
|
||||||
type_path = os.path.join(self._stix_dir, type_dir)
|
type_path = os.path.join(self._stix_dir, type_dir)
|
||||||
if type_dir == "marking-definition":
|
type_is_versioned = _is_versioned_type_dir(type_path, type_dir)
|
||||||
type_results = _search_markings(
|
if type_is_versioned:
|
||||||
|
type_results = _search_versioned(
|
||||||
query, type_path, auth_ids,
|
query, type_path, auth_ids,
|
||||||
self.allow_custom, version,
|
self.allow_custom, version,
|
||||||
self.encoding,
|
self.encoding,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
type_results = _search_versioned(
|
type_results = _search_unversioned(
|
||||||
query, type_path, auth_ids,
|
query, type_path, auth_ids,
|
||||||
self.allow_custom, version,
|
self.allow_custom, version,
|
||||||
self.encoding,
|
self.encoding,
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
import importlib
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
from antlr4 import CommonTokenStream, InputStream
|
|
||||||
from antlr4.tree.Trees import Trees
|
|
||||||
import six
|
|
||||||
from stix2patterns.exceptions import ParseException
|
from stix2patterns.exceptions import ParseException
|
||||||
from stix2patterns.grammars.STIXPatternLexer import STIXPatternLexer
|
|
||||||
from stix2patterns.grammars.STIXPatternParser import (
|
from stix2patterns.grammars.STIXPatternParser import (
|
||||||
STIXPatternParser, TerminalNode,
|
STIXPatternParser, TerminalNode,
|
||||||
)
|
)
|
||||||
from stix2patterns.grammars.STIXPatternVisitor import STIXPatternVisitor
|
from stix2patterns.grammars.STIXPatternVisitor import STIXPatternVisitor
|
||||||
from stix2patterns.validator import STIXPatternErrorListener
|
from stix2patterns.v20.pattern import Pattern
|
||||||
|
|
||||||
from .patterns import *
|
from .patterns import *
|
||||||
from .patterns import _BooleanExpression
|
from .patterns import _BooleanExpression
|
||||||
|
@ -328,41 +324,9 @@ class STIXPatternVisitorForSTIX2(STIXPatternVisitor):
|
||||||
|
|
||||||
def create_pattern_object(pattern, module_suffix="", module_name=""):
|
def create_pattern_object(pattern, module_suffix="", module_name=""):
|
||||||
"""
|
"""
|
||||||
Validates a pattern against the STIX Pattern grammar. Error messages are
|
Create a STIX pattern AST from a pattern string.
|
||||||
returned in a list. The test passed if the returned list is empty.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
start = ''
|
pattern_obj = Pattern(pattern)
|
||||||
if isinstance(pattern, six.string_types):
|
|
||||||
start = pattern[:2]
|
|
||||||
pattern = InputStream(pattern)
|
|
||||||
|
|
||||||
if not start:
|
|
||||||
start = pattern.readline()[:2]
|
|
||||||
pattern.seek(0)
|
|
||||||
|
|
||||||
parseErrListener = STIXPatternErrorListener()
|
|
||||||
|
|
||||||
lexer = STIXPatternLexer(pattern)
|
|
||||||
# it always adds a console listener by default... remove it.
|
|
||||||
lexer.removeErrorListeners()
|
|
||||||
|
|
||||||
stream = CommonTokenStream(lexer)
|
|
||||||
|
|
||||||
parser = STIXPatternParser(stream)
|
|
||||||
|
|
||||||
parser.buildParseTrees = True
|
|
||||||
# it always adds a console listener by default... remove it.
|
|
||||||
parser.removeErrorListeners()
|
|
||||||
parser.addErrorListener(parseErrListener)
|
|
||||||
|
|
||||||
# To improve error messages, replace "<INVALID>" in the literal
|
|
||||||
# names with symbolic names. This is a hack, but seemed like
|
|
||||||
# the simplest workaround.
|
|
||||||
for i, lit_name in enumerate(parser.literalNames):
|
|
||||||
if lit_name == u"<INVALID>":
|
|
||||||
parser.literalNames[i] = parser.symbolicNames[i]
|
|
||||||
|
|
||||||
tree = parser.pattern()
|
|
||||||
builder = STIXPatternVisitorForSTIX2(module_suffix, module_name)
|
builder = STIXPatternVisitorForSTIX2(module_suffix, module_name)
|
||||||
return builder.visit(tree)
|
return pattern_obj.visit(builder)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"ctime": "2020-10-06T01:54:32.000Z",
|
||||||
|
"contains_refs": [
|
||||||
|
"directory--80539e31-85f3-4304-bd14-e2e8c10859a5",
|
||||||
|
"file--e9e03175-0357-41b5-a2aa-eb99b455cd0c",
|
||||||
|
"directory--f6c54233-027b-4464-8126-da1324d8f66c"
|
||||||
|
],
|
||||||
|
"path": "/performance/Democrat.gif",
|
||||||
|
"type": "directory",
|
||||||
|
"id": "directory--572827aa-e0cd-44fd-afd5-a717a7585f39"
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import uuid
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import stix2
|
import stix2
|
||||||
|
@ -665,6 +667,76 @@ def test_observed_data_with_custom_observable_object():
|
||||||
assert ob_data.objects['0'].property1 == 'something'
|
assert ob_data.objects['0'].property1 == 'something'
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_det_id_1():
|
||||||
|
@stix2.v21.CustomObservable(
|
||||||
|
'x-det-id-observable-1', [
|
||||||
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
('property2', stix2.properties.IntegerProperty()),
|
||||||
|
], [
|
||||||
|
'property1',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class DetIdObs1():
|
||||||
|
pass
|
||||||
|
|
||||||
|
dio_1 = DetIdObs1(property1='I am property1!', property2=42)
|
||||||
|
dio_2 = DetIdObs1(property1='I am property1!', property2=24)
|
||||||
|
assert dio_1.property1 == dio_2.property1 == 'I am property1!'
|
||||||
|
assert dio_1.id == dio_2.id
|
||||||
|
|
||||||
|
uuid_obj = uuid.UUID(dio_1.id[-36:])
|
||||||
|
assert uuid_obj.variant == uuid.RFC_4122
|
||||||
|
assert uuid_obj.version == 5
|
||||||
|
|
||||||
|
dio_3 = DetIdObs1(property1='I am property1!', property2=42)
|
||||||
|
dio_4 = DetIdObs1(property1='I am also property1!', property2=24)
|
||||||
|
assert dio_3.property1 == 'I am property1!'
|
||||||
|
assert dio_4.property1 == 'I am also property1!'
|
||||||
|
assert dio_3.id != dio_4.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_det_id_2():
|
||||||
|
@stix2.v21.CustomObservable(
|
||||||
|
'x-det-id-observable-2', [
|
||||||
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
('property2', stix2.properties.IntegerProperty()),
|
||||||
|
], [
|
||||||
|
'property1', 'property2',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class DetIdObs2():
|
||||||
|
pass
|
||||||
|
|
||||||
|
dio_1 = DetIdObs2(property1='I am property1!', property2=42)
|
||||||
|
dio_2 = DetIdObs2(property1='I am property1!', property2=42)
|
||||||
|
assert dio_1.property1 == dio_2.property1 == 'I am property1!'
|
||||||
|
assert dio_1.property2 == dio_2.property2 == 42
|
||||||
|
assert dio_1.id == dio_2.id
|
||||||
|
|
||||||
|
dio_3 = DetIdObs2(property1='I am property1!', property2=42)
|
||||||
|
dio_4 = DetIdObs2(property1='I am also property1!', property2=42)
|
||||||
|
assert dio_3.property1 == 'I am property1!'
|
||||||
|
assert dio_4.property1 == 'I am also property1!'
|
||||||
|
assert dio_3.property2 == dio_4.property2 == 42
|
||||||
|
assert dio_3.id != dio_4.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_no_id_contrib_props():
|
||||||
|
@stix2.v21.CustomObservable(
|
||||||
|
'x-det-id-observable-3', [
|
||||||
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class DetIdObs3():
|
||||||
|
pass
|
||||||
|
|
||||||
|
dio = DetIdObs3(property1="I am property1!")
|
||||||
|
|
||||||
|
uuid_obj = uuid.UUID(dio.id[-36:])
|
||||||
|
assert uuid_obj.variant == uuid.RFC_4122
|
||||||
|
assert uuid_obj.version == 4
|
||||||
|
|
||||||
|
|
||||||
@stix2.v21.CustomExtension(
|
@stix2.v21.CustomExtension(
|
||||||
stix2.v21.DomainName, 'x-new-ext', [
|
stix2.v21.DomainName, 'x-new-ext', [
|
||||||
('property1', stix2.properties.StringProperty(required=True)),
|
('property1', stix2.properties.StringProperty(required=True)),
|
||||||
|
|
|
@ -221,6 +221,16 @@ def test_filesystem_source_backward_compatible(fs_source):
|
||||||
assert result.malware_types == ["version four"]
|
assert result.malware_types == ["version four"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_filesystem_source_sco(fs_source):
|
||||||
|
results = fs_source.query([stix2.Filter("type", "=", "directory")])
|
||||||
|
|
||||||
|
assert len(results) == 1
|
||||||
|
result = results[0]
|
||||||
|
assert result["type"] == "directory"
|
||||||
|
assert result["id"] == "directory--572827aa-e0cd-44fd-afd5-a717a7585f39"
|
||||||
|
assert result["path"] == "/performance/Democrat.gif"
|
||||||
|
|
||||||
|
|
||||||
def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
|
def test_filesystem_sink_add_python_stix_object(fs_sink, fs_source):
|
||||||
# add python stix object
|
# add python stix object
|
||||||
camp1 = stix2.v21.Campaign(
|
camp1 = stix2.v21.Campaign(
|
||||||
|
@ -435,6 +445,24 @@ def test_filesystem_sink_marking(fs_sink):
|
||||||
os.remove(marking_filepath)
|
os.remove(marking_filepath)
|
||||||
|
|
||||||
|
|
||||||
|
def test_filesystem_sink_sco(fs_sink):
|
||||||
|
file_sco = {
|
||||||
|
"type": "file",
|
||||||
|
"id": "file--decfcc48-31b3-45f5-87c8-1b3a5d71a307",
|
||||||
|
"name": "cats.png",
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_sink.add(file_sco)
|
||||||
|
sco_filepath = os.path.join(
|
||||||
|
FS_PATH, "file", file_sco["id"] + ".json",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(sco_filepath)
|
||||||
|
|
||||||
|
os.remove(sco_filepath)
|
||||||
|
os.rmdir(os.path.dirname(sco_filepath))
|
||||||
|
|
||||||
|
|
||||||
def test_filesystem_store_get_stored_as_bundle(fs_store):
|
def test_filesystem_store_get_stored_as_bundle(fs_store):
|
||||||
coa = fs_store.get("course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f")
|
coa = fs_store.get("course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f")
|
||||||
assert coa.id == "course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f"
|
assert coa.id == "course-of-action--95ddb356-7ba0-4bd9-a889-247262b8946f"
|
||||||
|
@ -473,9 +501,10 @@ def test_filesystem_store_query_single_filter(fs_store):
|
||||||
|
|
||||||
def test_filesystem_store_empty_query(fs_store):
|
def test_filesystem_store_empty_query(fs_store):
|
||||||
results = fs_store.query() # returns all
|
results = fs_store.query() # returns all
|
||||||
assert len(results) == 30
|
assert len(results) == 31
|
||||||
assert "tool--242f3da3-4425-4d11-8f5c-b842886da966" in [obj.id for obj in results]
|
assert "tool--242f3da3-4425-4d11-8f5c-b842886da966" in [obj.id for obj in results]
|
||||||
assert "marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168" in [obj.id for obj in results]
|
assert "marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168" in [obj.id for obj in results]
|
||||||
|
assert "directory--572827aa-e0cd-44fd-afd5-a717a7585f39" in [obj.id for obj in results]
|
||||||
|
|
||||||
|
|
||||||
def test_filesystem_store_query_multiple_filters(fs_store):
|
def test_filesystem_store_query_multiple_filters(fs_store):
|
||||||
|
@ -487,7 +516,7 @@ def test_filesystem_store_query_multiple_filters(fs_store):
|
||||||
|
|
||||||
def test_filesystem_store_query_dont_include_type_folder(fs_store):
|
def test_filesystem_store_query_dont_include_type_folder(fs_store):
|
||||||
results = fs_store.query(stix2.Filter("type", "!=", "tool"))
|
results = fs_store.query(stix2.Filter("type", "!=", "tool"))
|
||||||
assert len(results) == 28
|
assert len(results) == 29
|
||||||
|
|
||||||
|
|
||||||
def test_filesystem_store_add(fs_store):
|
def test_filesystem_store_add(fs_store):
|
||||||
|
@ -574,6 +603,26 @@ def test_filesystem_store_add_marking(fs_store):
|
||||||
os.remove(marking_filepath)
|
os.remove(marking_filepath)
|
||||||
|
|
||||||
|
|
||||||
|
def test_filesystem_store_add_sco(fs_store):
|
||||||
|
sco = stix2.v21.EmailAddress(
|
||||||
|
value="jdoe@example.com",
|
||||||
|
)
|
||||||
|
|
||||||
|
fs_store.add(sco)
|
||||||
|
sco_filepath = os.path.join(
|
||||||
|
FS_PATH, "email-addr", sco["id"] + ".json",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(sco_filepath)
|
||||||
|
|
||||||
|
sco_r = fs_store.get(sco["id"])
|
||||||
|
assert sco_r["id"] == sco["id"]
|
||||||
|
assert sco_r["value"] == sco["value"]
|
||||||
|
|
||||||
|
os.remove(sco_filepath)
|
||||||
|
os.rmdir(os.path.dirname(sco_filepath))
|
||||||
|
|
||||||
|
|
||||||
def test_filesystem_object_with_custom_property(fs_store):
|
def test_filesystem_object_with_custom_property(fs_store):
|
||||||
camp = stix2.v21.Campaign(
|
camp = stix2.v21.Campaign(
|
||||||
name="Scipio Africanus",
|
name="Scipio Africanus",
|
||||||
|
@ -1024,6 +1073,7 @@ def test_search_auth_set_black_empty(rel_fs_store):
|
||||||
"attack-pattern",
|
"attack-pattern",
|
||||||
"campaign",
|
"campaign",
|
||||||
"course-of-action",
|
"course-of-action",
|
||||||
|
"directory",
|
||||||
"identity",
|
"identity",
|
||||||
"indicator",
|
"indicator",
|
||||||
"intrusion-set",
|
"intrusion-set",
|
||||||
|
|
|
@ -271,7 +271,7 @@ def test_indicator_stix20_invalid_pattern():
|
||||||
)
|
)
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.v21.Indicator
|
assert excinfo.value.cls == stix2.v21.Indicator
|
||||||
assert "FAIL: The same qualifier is used more than once" in str(excinfo.value)
|
assert "FAIL: Duplicate qualifier type encountered: WITHIN" in str(excinfo.value)
|
||||||
|
|
||||||
ind = stix2.v21.Indicator(
|
ind = stix2.v21.Indicator(
|
||||||
type="indicator",
|
type="indicator",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from stix2patterns.exceptions import ParseException
|
||||||
|
|
||||||
import stix2
|
import stix2
|
||||||
from stix2.pattern_visitor import create_pattern_object
|
from stix2.pattern_visitor import create_pattern_object
|
||||||
|
@ -515,3 +516,8 @@ def test_list_constant():
|
||||||
def test_parsing_multiple_slashes_quotes():
|
def test_parsing_multiple_slashes_quotes():
|
||||||
patt_obj = create_pattern_object("[ file:name = 'weird_name\\'' ]")
|
patt_obj = create_pattern_object("[ file:name = 'weird_name\\'' ]")
|
||||||
assert str(patt_obj) == "[file:name = 'weird_name\\'']"
|
assert str(patt_obj) == "[file:name = 'weird_name\\'']"
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_error():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
create_pattern_object("[ file: name = 'weirdname]")
|
||||||
|
|
|
@ -966,7 +966,7 @@ class X509Certificate(_Observable):
|
||||||
self._check_at_least_one_property(att_list)
|
self._check_at_least_one_property(att_list)
|
||||||
|
|
||||||
|
|
||||||
def CustomObservable(type='x-custom-observable', properties=None):
|
def CustomObservable(type='x-custom-observable', properties=None, id_contrib_props=None):
|
||||||
"""Custom STIX Cyber Observable Object type decorator.
|
"""Custom STIX Cyber Observable Object type decorator.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -987,7 +987,7 @@ def CustomObservable(type='x-custom-observable', properties=None):
|
||||||
properties,
|
properties,
|
||||||
[('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))],
|
[('extensions', ExtensionsProperty(spec_version='2.1', enclosing_type=type))],
|
||||||
]))
|
]))
|
||||||
return _custom_observable_builder(cls, type, _properties, '2.1')
|
return _custom_observable_builder(cls, type, _properties, '2.1', id_contrib_props)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "1.3.0"
|
__version__ = "1.3.1"
|
||||||
|
|
Loading…
Reference in New Issue