diff --git a/docs/guide/creating.ipynb b/docs/guide/creating.ipynb index 83efb56..92a3336 100644 --- a/docs/guide/creating.ipynb +++ b/docs/guide/creating.ipynb @@ -144,12 +144,12 @@ ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
        "    "type": "indicator",\n",
-       "    "id": "indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951",\n",
-       "    "created": "2018-04-05T18:32:24.193Z",\n",
-       "    "modified": "2018-04-05T18:32:24.193Z",\n",
+       "    "id": "indicator--2f3d4926-163d-4aef-bcd2-19dea96916ae",\n",
+       "    "created": "2019-05-13T13:14:48.509Z",\n",
+       "    "modified": "2019-05-13T13:14:48.509Z",\n",
        "    "name": "File hash for malware variant",\n",
        "    "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
-       "    "valid_from": "2018-04-05T18:32:24.193659Z",\n",
+       "    "valid_from": "2019-05-13T13:14:48.509629Z",\n",
        "    "labels": [\n",
        "        "malicious-activity"\n",
        "    ]\n",
@@ -465,9 +465,9 @@
        ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
        ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
        "    "type": "malware",\n",
-       "    "id": "malware--3d7f0c1c-616a-4868-aa7b-150821d2a429",\n",
-       "    "created": "2018-04-05T18:32:46.584Z",\n",
-       "    "modified": "2018-04-05T18:32:46.584Z",\n",
+       "    "id": "malware--1f2aba70-f0ae-49cd-9267-6fcb1e43be67",\n",
+       "    "created": "2019-05-13T13:15:04.698Z",\n",
+       "    "modified": "2019-05-13T13:15:04.698Z",\n",
        "    "name": "Poison Ivy",\n",
        "    "labels": [\n",
        "        "remote-access-trojan"\n",
@@ -588,12 +588,12 @@
        ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n",
        ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
        "    "type": "relationship",\n",
-       "    "id": "relationship--34ddc7b4-4965-4615-b286-1c8bbaa1e7db",\n",
-       "    "created": "2018-04-05T18:32:49.474Z",\n",
-       "    "modified": "2018-04-05T18:32:49.474Z",\n",
+       "    "id": "relationship--80c174fa-36d1-47c2-9a9d-ce0c636bedcc",\n",
+       "    "created": "2019-05-13T13:15:13.152Z",\n",
+       "    "modified": "2019-05-13T13:15:13.152Z",\n",
        "    "relationship_type": "indicates",\n",
-       "    "source_ref": "indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951",\n",
-       "    "target_ref": "malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"\n",
+       "    "source_ref": "indicator--2f3d4926-163d-4aef-bcd2-19dea96916ae",\n",
+       "    "target_ref": "malware--1f2aba70-f0ae-49cd-9267-6fcb1e43be67"\n",
        "}\n",
        "
\n" ], @@ -700,12 +700,12 @@ ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
        "    "type": "relationship",\n",
-       "    "id": "relationship--0a646403-f7e7-4cfd-b945-cab5cde05857",\n",
-       "    "created": "2018-04-05T18:32:51.417Z",\n",
-       "    "modified": "2018-04-05T18:32:51.417Z",\n",
+       "    "id": "relationship--47395d23-dedd-45d4-8db1-c9ffaf44493d",\n",
+       "    "created": "2019-05-13T13:15:16.566Z",\n",
+       "    "modified": "2019-05-13T13:15:16.566Z",\n",
        "    "relationship_type": "indicates",\n",
-       "    "source_ref": "indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951",\n",
-       "    "target_ref": "malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"\n",
+       "    "source_ref": "indicator--2f3d4926-163d-4aef-bcd2-19dea96916ae",\n",
+       "    "target_ref": "malware--1f2aba70-f0ae-49cd-9267-6fcb1e43be67"\n",
        "}\n",
        "
\n" ], @@ -810,26 +810,26 @@ ".highlight .vm { color: #19177C } /* Name.Variable.Magic */\n", ".highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
{\n",
        "    "type": "bundle",\n",
-       "    "id": "bundle--f83477e5-f853-47e1-a267-43f3aa1bd5b0",\n",
+       "    "id": "bundle--388c9b2c-936c-420a-baa5-04f48d682a01",\n",
        "    "spec_version": "2.0",\n",
        "    "objects": [\n",
        "        {\n",
        "            "type": "indicator",\n",
-       "            "id": "indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951",\n",
-       "            "created": "2018-04-05T18:32:24.193Z",\n",
-       "            "modified": "2018-04-05T18:32:24.193Z",\n",
+       "            "id": "indicator--2f3d4926-163d-4aef-bcd2-19dea96916ae",\n",
+       "            "created": "2019-05-13T13:14:48.509Z",\n",
+       "            "modified": "2019-05-13T13:14:48.509Z",\n",
        "            "name": "File hash for malware variant",\n",
        "            "pattern": "[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']",\n",
-       "            "valid_from": "2018-04-05T18:32:24.193659Z",\n",
+       "            "valid_from": "2019-05-13T13:14:48.509629Z",\n",
        "            "labels": [\n",
        "                "malicious-activity"\n",
        "            ]\n",
        "        },\n",
        "        {\n",
        "            "type": "malware",\n",
-       "            "id": "malware--3d7f0c1c-616a-4868-aa7b-150821d2a429",\n",
-       "            "created": "2018-04-05T18:32:46.584Z",\n",
-       "            "modified": "2018-04-05T18:32:46.584Z",\n",
+       "            "id": "malware--1f2aba70-f0ae-49cd-9267-6fcb1e43be67",\n",
+       "            "created": "2019-05-13T13:15:04.698Z",\n",
+       "            "modified": "2019-05-13T13:15:04.698Z",\n",
        "            "name": "Poison Ivy",\n",
        "            "labels": [\n",
        "                "remote-access-trojan"\n",
@@ -837,12 +837,12 @@
        "        },\n",
        "        {\n",
        "            "type": "relationship",\n",
-       "            "id": "relationship--34ddc7b4-4965-4615-b286-1c8bbaa1e7db",\n",
-       "            "created": "2018-04-05T18:32:49.474Z",\n",
-       "            "modified": "2018-04-05T18:32:49.474Z",\n",
+       "            "id": "relationship--80c174fa-36d1-47c2-9a9d-ce0c636bedcc",\n",
+       "            "created": "2019-05-13T13:15:13.152Z",\n",
+       "            "modified": "2019-05-13T13:15:13.152Z",\n",
        "            "relationship_type": "indicates",\n",
-       "            "source_ref": "indicator--548af3be-39d7-4a3e-93c2-1a63cccf8951",\n",
-       "            "target_ref": "malware--3d7f0c1c-616a-4868-aa7b-150821d2a429"\n",
+       "            "source_ref": "indicator--2f3d4926-163d-4aef-bcd2-19dea96916ae",\n",
+       "            "target_ref": "malware--1f2aba70-f0ae-49cd-9267-6fcb1e43be67"\n",
        "        }\n",
        "    ]\n",
        "}\n",
@@ -863,6 +863,249 @@
     "bundle = Bundle(indicator, malware, relationship)\n",
     "print(bundle)"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Creating Cyber Observable References\n",
+    "Cyber Observable Objects have properties that can reference other Cyber Observable Objects. In order to create those references, use the ``_valid_refs`` property as shown in the following examples. It should be noted that ``_valid_refs`` is necessary when creating references to Cyber Observable Objects since some embedded references can only point to certain types, and ``_valid_refs`` helps ensure consistency. \n",
+    "\n",
+    "There are two cases."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Case 1: Specifying the type of the Cyber Observable Objects being referenced\n",
+    "In the following example, the IPv4Address object has its ``resolves_to_refs`` property specified. As per the spec, this property's value must be a list of reference(s) to MACAddress objects. In this case, those references are strings that state the type of the Cyber Observable Object being referenced, and are provided in ``_valid_refs``."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
{\n",
+       "    "type": "ipv4-addr",\n",
+       "    "value": "177.60.40.7",\n",
+       "    "resolves_to_refs": [\n",
+       "        "1",\n",
+       "        "2"\n",
+       "    ]\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from stix2 import IPv4Address\n", + "\n", + "ip4 = IPv4Address(\n", + " _valid_refs={\"1\": \"mac-addr\", \"2\": \"mac-addr\"},\n", + " value=\"177.60.40.7\",\n", + " resolves_to_refs=[\"1\", \"2\"]\n", + ")\n", + "\n", + "print(ip4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Case 2: Specifying the name of the Cyber Observable Objects being referenced\n", + "The following example is just like the one provided in Case 1 above, with one key difference: instead of using strings to specify the type of the Cyber Observable Objects being referenced in ``_valid_refs``, the referenced Cyber Observable Objects are created beforehand and then their names are provided in ``_valid_refs``." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
{\n",
+       "    "type": "ipv4-addr",\n",
+       "    "value": "177.60.40.7",\n",
+       "    "resolves_to_refs": [\n",
+       "        "1",\n",
+       "        "2"\n",
+       "    ]\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from stix2 import MACAddress\n", + "\n", + "mac_addr_a = MACAddress(value=\"a1:b2:c3:d4:e5:f6\")\n", + "mac_addr_b = MACAddress(value=\"a7:b8:c9:d0:e1:f2\")\n", + "\n", + "ip4_valid_refs = IPv4Address(\n", + " _valid_refs={\"1\": mac_addr_a, \"2\": mac_addr_b},\n", + " value=\"177.60.40.7\",\n", + " resolves_to_refs=[\"1\", \"2\"]\n", + ")\n", + "\n", + "print(ip4_valid_refs)" + ] } ], "metadata": { @@ -881,7 +1124,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.6.7" } }, "nbformat": 4, diff --git a/stix2/base.py b/stix2/base.py index 9fcdf56..a9a801e 100644 --- a/stix2/base.py +++ b/stix2/base.py @@ -308,7 +308,10 @@ class _Observable(_STIXBase): allowed_types = prop.valid_types try: - ref_type = self._STIXBase__valid_refs[ref] + try: + ref_type = self._STIXBase__valid_refs[ref].type + except AttributeError: + ref_type = self._STIXBase__valid_refs[ref] except TypeError: raise ValueError("'%s' must be created with _valid_refs as a dict, not a list." % self.__class__.__name__) diff --git a/stix2/test/v20/test_observed_data.py b/stix2/test/v20/test_observed_data.py index 84cdf72..95daf22 100644 --- a/stix2/test/v20/test_observed_data.py +++ b/stix2/test/v20/test_observed_data.py @@ -960,6 +960,24 @@ def test_ip4_address_example(): assert ip4.resolves_to_refs == ["4", "5"] +def test_ip4_address_valid_refs(): + mac1 = stix2.v20.MACAddress( + value="a1:b2:c3:d4:e5:f6", + ) + mac2 = stix2.v20.MACAddress( + value="a7:b8:c9:d0:e1:f2", + ) + + ip4 = stix2.v20.IPv4Address( + _valid_refs={"1": mac1, "2": mac2}, + value="177.60.40.7", + resolves_to_refs=["1", "2"], + ) + + assert ip4.value == "177.60.40.7" + assert ip4.resolves_to_refs == ["1", "2"] + + def test_ip4_address_example_cidr(): ip4 = stix2.v20.IPv4Address(value="198.51.100.0/24") diff --git a/stix2/test/v21/test_observed_data.py b/stix2/test/v21/test_observed_data.py index 5d0f9b1..864dd7a 100644 --- a/stix2/test/v21/test_observed_data.py +++ b/stix2/test/v21/test_observed_data.py @@ -940,6 +940,24 @@ def test_ip4_address_example(): assert ip4.resolves_to_refs == ["4", "5"] +def test_ip4_address_valid_refs(): + mac1 = stix2.v21.MACAddress( + value="a1:b2:c3:d4:e5:f6", + ) + mac2 = stix2.v21.MACAddress( + value="a7:b8:c9:d0:e1:f2", + ) + + ip4 = stix2.v21.IPv4Address( + _valid_refs={"1": mac1, "2": mac2}, + value="177.60.40.7", + resolves_to_refs=["1", "2"], + ) + + assert ip4.value == "177.60.40.7" + assert ip4.resolves_to_refs == ["1", "2"] + + def test_ip4_address_example_cidr(): ip4 = stix2.v21.IPv4Address(value="198.51.100.0/24")