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")