stix2arango 1.1.4__tar.gz → 1.1.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of stix2arango might be problematic. Click here for more details.
- {stix2arango-1.1.4 → stix2arango-1.1.6}/PKG-INFO +1 -1
- {stix2arango-1.1.4 → stix2arango-1.1.6}/pyproject.toml +1 -1
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/stix2arango/bundle_loader.py +38 -21
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/utils.py +3 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/test_bundle_loader.py +44 -14
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/test_utils.py +16 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/.env.example +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/.env.markdown +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/.github/workflows/create-release.yml +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/.github/workflows/run-tests.yml +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/.gitignore +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/LICENSE +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/README.md +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/docs/README.md +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/docs/stix2arango.png +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/requirements.txt +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/__init__.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/__main__.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/config.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/services/__init__.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/services/arangodb_service.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/services/version_annotator.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/stix2arango/__init__.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/stix2arango/stix2arango.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango/templates/marking-definition.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/stix2arango.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/README.md +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/custom-sco-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/custom-sco-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/custom-sdo-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/custom-sdo-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/duplicate-objects-all-properties-same.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/duplicate-objects-properties-different.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-object-removed.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-object-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-object.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-sdo-sco-sro-smo.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/nested-embedded-ref.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/non-standard-embedded-relationship.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sco-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sco-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-another.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-condensed-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-condensed-update-1.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-condensed-update-2.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-yet-another.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/smo-embedded-ref-1.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/smo-embedded-ref-2.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/smo-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/smo-updated-2.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/smo-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/source-object-does-not-exist.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sro-original.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sro-updated.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/target-object-does-not-exist.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/update_with_diff_modified_times_1.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/update_with_diff_modified_times_2.json +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/requirements.txt +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/__init__.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/base_test.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_00-basic-import-logic-with-embedded.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_01-basic-import-no-embedded.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_02-basic-import-no-stix2arango_note.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_03-import-with-no-update-detected.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_04-update-detected-because-of-stix2arango-note.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_05-update-detected-because-of-modified-time-change.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_06-update-detected-because-of-modified-time-change-not-in-order.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_07-test-default-imported-objects.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_08-duplicate-objects-in-bundle-all-identical.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_09-duplicate-objects-but-diff-times-in-bundle.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_10-updating-object-no-modified-time.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_11-custom-sdos.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_12-custom-scos.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_13-updating-smos.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_14-non-standard-embedded-relationship.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_15-testing-when-sro-target-not-in-collection.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_16-testing-when-sro-source-not-in-collection.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_17-testing-update-of-embedded-refs.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_18-testing-nested-embedded-ref.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_19_update_with_diff_created_times.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_20-embedded-sro-update-for-sdo.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_21-embedded-sro-update-for-sco.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_22-embedded-sro-update-for-smo.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_23-embedded-sro-removed.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_24-test-hidden-properties.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_25-ignore-embedded-rels-smo.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_26-ignore-embedded-rels-sro.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/test_arango_service.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/test_main.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/test_stix2arango.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/tests/tests.env +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/README.md +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_atlas.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_attack_enterprise.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_attack_ics.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_attack_mobile.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_capec.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_cwe.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_disarm.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_locations.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_sigma_rules.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_tlp.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_yara_rules.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cve_processor/README.md +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cve_processor/insert_archive_cve.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cve_processor/manager.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/stix2arango/add_ref_types.py +0 -0
- {stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/stix2arango/update_taxii_index_with_date_transform.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stix2arango
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.6
|
|
4
4
|
Summary: stix2arango is a command line tool that takes a group of STIX 2.1 objects in a bundle and inserts them into ArangoDB. It can also handle updates to existing objects in ArangoDB imported in a bundle.
|
|
5
5
|
Project-URL: Homepage, https://github.com/muchdogesec/stix2arango
|
|
6
6
|
Project-URL: Issues, https://github.com/muchdogesec/stix2arango/issues
|
|
@@ -10,6 +10,9 @@ import ijson
|
|
|
10
10
|
import json
|
|
11
11
|
from collections import Counter
|
|
12
12
|
|
|
13
|
+
from stix2arango.utils import get_embedded_refs
|
|
14
|
+
|
|
15
|
+
|
|
13
16
|
class BundleLoader:
|
|
14
17
|
def __init__(self, file_path, chunk_size_min=20_000, db_path=""):
|
|
15
18
|
self.file_path = Path(file_path)
|
|
@@ -19,34 +22,37 @@ class BundleLoader:
|
|
|
19
22
|
|
|
20
23
|
self.db_path = db_path
|
|
21
24
|
if not self.db_path:
|
|
22
|
-
self.temp_path = tempfile.NamedTemporaryFile(
|
|
25
|
+
self.temp_path = tempfile.NamedTemporaryFile(
|
|
26
|
+
prefix="s2a_bundle_loader--", suffix=".sqlite"
|
|
27
|
+
)
|
|
23
28
|
self.db_path = self.temp_path.name
|
|
24
29
|
self._init_db()
|
|
25
30
|
|
|
26
31
|
def _init_db(self):
|
|
27
32
|
"""Initialize SQLite DB with objects table."""
|
|
28
33
|
self.conn = sqlite3.connect(self.db_path)
|
|
29
|
-
self.conn.execute(
|
|
34
|
+
self.conn.execute(
|
|
35
|
+
"""
|
|
30
36
|
CREATE TABLE IF NOT EXISTS objects (
|
|
31
37
|
id TEXT PRIMARY KEY,
|
|
32
38
|
type TEXT,
|
|
33
39
|
raw TEXT
|
|
34
40
|
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
self.conn.execute(
|
|
38
|
-
self.conn.execute(
|
|
41
|
+
"""
|
|
42
|
+
)
|
|
43
|
+
self.conn.execute("PRAGMA synchronous = OFF;")
|
|
44
|
+
self.conn.execute("PRAGMA journal_mode = MEMORY;")
|
|
45
|
+
self.conn.execute("PRAGMA temp_store = MEMORY;")
|
|
39
46
|
self.conn.commit()
|
|
40
47
|
|
|
41
|
-
|
|
42
48
|
def save_to_sqlite(self, objects):
|
|
43
49
|
"""Save one STIX object to the SQLite database."""
|
|
44
|
-
self.inserted = getattr(self,
|
|
50
|
+
self.inserted = getattr(self, "inserted", 0)
|
|
45
51
|
|
|
46
52
|
try:
|
|
47
53
|
self.conn.executemany(
|
|
48
54
|
"INSERT OR REPLACE INTO objects (id, type, raw) VALUES (?, ?, ?)",
|
|
49
|
-
[(obj[
|
|
55
|
+
[(obj["id"], obj["type"], json.dumps(obj)) for obj in objects],
|
|
50
56
|
)
|
|
51
57
|
except sqlite3.IntegrityError as e:
|
|
52
58
|
print(f"Failed to insert len({objects}) objects: {e}")
|
|
@@ -55,6 +61,13 @@ class BundleLoader:
|
|
|
55
61
|
self.inserted += len(objects)
|
|
56
62
|
# logging.info(f"inserted {self.inserted}")
|
|
57
63
|
|
|
64
|
+
@staticmethod
|
|
65
|
+
def get_refs(obj):
|
|
66
|
+
refs = []
|
|
67
|
+
for _type, targets in get_embedded_refs(obj):
|
|
68
|
+
refs.extend(targets)
|
|
69
|
+
return refs
|
|
70
|
+
|
|
58
71
|
def build_groups(self):
|
|
59
72
|
"""
|
|
60
73
|
Iterates the STIX bundle and uses union-find to group IDs such that for every
|
|
@@ -63,30 +76,35 @@ class BundleLoader:
|
|
|
63
76
|
"""
|
|
64
77
|
all_ids: dict[str, list[str]] = dict() # All object IDs in the file
|
|
65
78
|
logging.info(f"loading into {self.db_path}")
|
|
66
|
-
|
|
67
|
-
with open(self.file_path,
|
|
68
|
-
objects = ijson.items(f,
|
|
79
|
+
|
|
80
|
+
with open(self.file_path, "rb") as f:
|
|
81
|
+
objects = ijson.items(f, "objects.item", use_float=True)
|
|
69
82
|
to_insert = []
|
|
70
83
|
for obj in objects:
|
|
71
|
-
obj_id = obj.get(
|
|
84
|
+
obj_id = obj.get("id")
|
|
72
85
|
to_insert.append(obj)
|
|
73
86
|
all_ids.setdefault(obj_id, [])
|
|
74
|
-
if obj[
|
|
75
|
-
|
|
87
|
+
if obj["type"] == "relationship" and all(
|
|
88
|
+
x in obj for x in ["target_ref", "source_ref"]
|
|
89
|
+
):
|
|
90
|
+
sr, tr = [obj["source_ref"], obj["target_ref"]]
|
|
76
91
|
all_ids[obj_id].extend([sr, tr])
|
|
77
92
|
all_ids.setdefault(sr, []).extend([tr, obj_id])
|
|
78
93
|
all_ids.setdefault(tr, []).extend([sr, obj_id])
|
|
94
|
+
for ref in self.get_refs(obj):
|
|
95
|
+
all_ids[obj_id].append(ref)
|
|
79
96
|
if len(to_insert) >= self.chunk_size_min:
|
|
80
97
|
self.save_to_sqlite(to_insert)
|
|
81
98
|
to_insert.clear()
|
|
82
99
|
if to_insert:
|
|
83
100
|
self.save_to_sqlite(to_insert)
|
|
84
|
-
|
|
101
|
+
|
|
85
102
|
logging.info(f"loaded {self.inserted} into {self.db_path}")
|
|
86
103
|
handled = set()
|
|
87
104
|
|
|
88
105
|
self.groups = []
|
|
89
106
|
group = set()
|
|
107
|
+
|
|
90
108
|
def from_ids(all_ids):
|
|
91
109
|
for obj_id in all_ids:
|
|
92
110
|
if obj_id in handled:
|
|
@@ -104,18 +122,17 @@ class BundleLoader:
|
|
|
104
122
|
if group:
|
|
105
123
|
self.groups.append(tuple(group))
|
|
106
124
|
return self.groups
|
|
107
|
-
|
|
125
|
+
|
|
108
126
|
def load_objects_by_ids(self, ids):
|
|
109
127
|
"""Retrieve a list of STIX objects by their IDs from the SQLite database."""
|
|
110
|
-
placeholders =
|
|
128
|
+
placeholders = ",".join(["?"] * len(ids))
|
|
111
129
|
query = f"SELECT raw FROM objects WHERE id IN ({placeholders})"
|
|
112
130
|
cursor = self.conn.execute(query, list(ids))
|
|
113
131
|
return [json.loads(row[0]) for row in cursor.fetchall()]
|
|
114
132
|
|
|
115
|
-
|
|
116
133
|
def get_objects(self, group):
|
|
117
134
|
return list(self.load_objects_by_ids(group))
|
|
118
|
-
|
|
135
|
+
|
|
119
136
|
@property
|
|
120
137
|
def chunks(self):
|
|
121
138
|
for group in self.groups or self.build_groups():
|
|
@@ -123,4 +140,4 @@ class BundleLoader:
|
|
|
123
140
|
|
|
124
141
|
def __del__(self):
|
|
125
142
|
with contextlib.suppress(Exception):
|
|
126
|
-
os.remove(self.db_path)
|
|
143
|
+
os.remove(self.db_path)
|
|
@@ -125,6 +125,9 @@ def get_embedded_refs(object: list | dict, xpath: list = [], attributes=None):
|
|
|
125
125
|
if match := EMBEDDED_RELATIONSHIP_RE.fullmatch(key):
|
|
126
126
|
relationship_type = "-".join(xpath + match.group(1).split("_"))
|
|
127
127
|
targets = value if isinstance(value, list) else [value]
|
|
128
|
+
targets = [_target for _target in targets if _target and isinstance(_target, str)]
|
|
129
|
+
if not targets:
|
|
130
|
+
continue
|
|
128
131
|
if attributes and key not in attributes:
|
|
129
132
|
continue
|
|
130
133
|
embedded_refs.append((relationship_type, targets))
|
|
@@ -5,31 +5,51 @@ import tempfile
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from unittest.mock import patch
|
|
7
7
|
|
|
8
|
-
from stix2arango.stix2arango.bundle_loader import
|
|
8
|
+
from stix2arango.stix2arango.bundle_loader import (
|
|
9
|
+
BundleLoader,
|
|
10
|
+
) # adjust this import path
|
|
9
11
|
|
|
10
12
|
# Sample bundle with related and unrelated objects
|
|
11
13
|
STIX_BUNDLE = {
|
|
12
14
|
"type": "bundle",
|
|
13
15
|
"id": "bundle--example",
|
|
14
16
|
"objects": [
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
{
|
|
18
|
+
"id": "indicator--1",
|
|
19
|
+
"type": "indicator",
|
|
20
|
+
"bad_ref": "some-ref--7",
|
|
21
|
+
"created_by_ref": "creator--1",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "indicator--2",
|
|
25
|
+
"type": "indicator",
|
|
26
|
+
"object_marking_refs": ["marking--1", "marking--2"],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "relationship--1",
|
|
30
|
+
"type": "relationship",
|
|
31
|
+
"source_ref": "indicator--1",
|
|
32
|
+
"target_ref": "indicator--2",
|
|
33
|
+
},
|
|
18
34
|
{"id": "attack-pattern--3", "type": "attack-pattern"},
|
|
19
|
-
|
|
35
|
+
{"id": "marking--1", "type": "marking-definition"},
|
|
36
|
+
],
|
|
20
37
|
}
|
|
21
38
|
|
|
39
|
+
|
|
22
40
|
@pytest.fixture
|
|
23
41
|
def temp_json_file():
|
|
24
|
-
with tempfile.NamedTemporaryFile(delete=False, mode=
|
|
42
|
+
with tempfile.NamedTemporaryFile(delete=False, mode="w", suffix=".json") as f:
|
|
25
43
|
json.dump(STIX_BUNDLE, f)
|
|
26
44
|
return f.name
|
|
27
45
|
|
|
46
|
+
|
|
28
47
|
def test_init_db_and_tempfile_creation():
|
|
29
48
|
loader = BundleLoader(file_path=tempfile.mkstemp()[1])
|
|
30
49
|
assert isinstance(loader.db_path, str)
|
|
31
50
|
assert Path(loader.db_path).exists()
|
|
32
51
|
|
|
52
|
+
|
|
33
53
|
def test_save_to_sqlite_inserts_objects(temp_json_file):
|
|
34
54
|
loader = BundleLoader(file_path=temp_json_file)
|
|
35
55
|
objects = STIX_BUNDLE["objects"]
|
|
@@ -39,17 +59,24 @@ def test_save_to_sqlite_inserts_objects(temp_json_file):
|
|
|
39
59
|
count = cursor.fetchone()[0]
|
|
40
60
|
assert count == len(objects)
|
|
41
61
|
|
|
62
|
+
|
|
42
63
|
def test_build_groups_creates_correct_groups(temp_json_file):
|
|
43
|
-
loader = BundleLoader(file_path=temp_json_file, chunk_size_min=
|
|
64
|
+
loader = BundleLoader(file_path=temp_json_file, chunk_size_min=3)
|
|
44
65
|
groups = loader.build_groups()
|
|
45
66
|
|
|
46
67
|
# There should be at least 2 groups: one for related indicators, one for attack-pattern
|
|
47
68
|
assert isinstance(groups, list)
|
|
48
69
|
flat = [id_ for group in groups for id_ in group]
|
|
49
|
-
assert
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
assert set(flat) == {
|
|
71
|
+
"some-ref--7",
|
|
72
|
+
"indicator--2",
|
|
73
|
+
"indicator--1",
|
|
74
|
+
"relationship--1",
|
|
75
|
+
"creator--1",
|
|
76
|
+
"attack-pattern--3",
|
|
77
|
+
"marking--1",
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
|
|
54
81
|
def test_load_objects_by_ids(temp_json_file):
|
|
55
82
|
loader = BundleLoader(file_path=temp_json_file)
|
|
@@ -59,6 +86,7 @@ def test_load_objects_by_ids(temp_json_file):
|
|
|
59
86
|
assert isinstance(result, list)
|
|
60
87
|
assert {obj["id"] for obj in result} == {"indicator--1", "attack-pattern--3"}
|
|
61
88
|
|
|
89
|
+
|
|
62
90
|
def test_get_objects_returns_objects(temp_json_file):
|
|
63
91
|
loader = BundleLoader(file_path=temp_json_file)
|
|
64
92
|
loader.save_to_sqlite(STIX_BUNDLE["objects"])
|
|
@@ -67,6 +95,7 @@ def test_get_objects_returns_objects(temp_json_file):
|
|
|
67
95
|
assert isinstance(result, list)
|
|
68
96
|
assert result[0]["id"] == "indicator--1"
|
|
69
97
|
|
|
98
|
+
|
|
70
99
|
def test_chunks_generator(temp_json_file):
|
|
71
100
|
loader = BundleLoader(file_path=temp_json_file, chunk_size_min=1)
|
|
72
101
|
chunks = list(loader.chunks)
|
|
@@ -76,18 +105,20 @@ def test_chunks_generator(temp_json_file):
|
|
|
76
105
|
assert isinstance(chunk, list)
|
|
77
106
|
assert all("id" in obj for obj in chunk)
|
|
78
107
|
|
|
108
|
+
|
|
79
109
|
def test_chunks_with_no_existing_groups_calls_build_groups(temp_json_file):
|
|
80
110
|
loader = BundleLoader(file_path=temp_json_file, chunk_size_min=1)
|
|
81
|
-
with patch.object(loader,
|
|
111
|
+
with patch.object(loader, "build_groups", wraps=loader.build_groups) as mocked:
|
|
82
112
|
chunks = list(loader.chunks)
|
|
83
113
|
mocked.assert_called_once()
|
|
84
114
|
assert len(chunks) > 0
|
|
85
115
|
|
|
116
|
+
|
|
86
117
|
def test_no_crash_on_missing_relationship_fields(temp_json_file):
|
|
87
118
|
# Remove `source_ref` and `target_ref` to simulate bad data
|
|
88
119
|
bad_bundle = {
|
|
89
120
|
"type": "bundle",
|
|
90
|
-
"objects": [{"id": "bad--1", "type": "relationship"}]
|
|
121
|
+
"objects": [{"id": "bad--1", "type": "relationship"}],
|
|
91
122
|
}
|
|
92
123
|
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".json") as f:
|
|
93
124
|
json.dump(bad_bundle, f)
|
|
@@ -104,4 +135,3 @@ def test_sqlite_file_removed_after_gc(temp_json_file):
|
|
|
104
135
|
assert db_path.exists()
|
|
105
136
|
del loader
|
|
106
137
|
assert not db_path.exists(), "should already be deleted"
|
|
107
|
-
|
|
@@ -52,6 +52,22 @@ def test_get_embedded_refs():
|
|
|
52
52
|
("abcde-abcd-efgh", ["ref8"]),
|
|
53
53
|
]
|
|
54
54
|
|
|
55
|
+
def test_get_embedded_refs_empty():
|
|
56
|
+
assert utils.get_embedded_refs(
|
|
57
|
+
{
|
|
58
|
+
"abc_ref": "ref1",
|
|
59
|
+
"empty_ref": "", #skipped entirely
|
|
60
|
+
"some_empty_refs": ["ref10", "", "ref9"], # empty ref skipped
|
|
61
|
+
"abcd_refs": ["ref1", "ref2"],
|
|
62
|
+
"abcde": [{"abcdef_ref": "ref7"}, {"abcd_efgh_ref": "ref8"}],
|
|
63
|
+
}
|
|
64
|
+
) == [
|
|
65
|
+
("abc", ["ref1"]),
|
|
66
|
+
("some-empty", ["ref10", "ref9"]),
|
|
67
|
+
("abcd", ["ref1", "ref2"]),
|
|
68
|
+
("abcde-abcdef", ["ref7"]),
|
|
69
|
+
("abcde-abcd-efgh", ["ref8"]),
|
|
70
|
+
]
|
|
55
71
|
|
|
56
72
|
def test_get_embedded_refs__attributes_whitelist():
|
|
57
73
|
assert utils.get_embedded_refs(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-object-removed.json
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-object-updated.json
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/embedded-ref-sdo-sco-sro-smo.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-another.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/sigma-rule-bundle-yet-another.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/source-object-does-not-exist.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/files/stix2arango/target-object-does-not-exist.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_01-basic-import-no-embedded.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_18-testing-nested-embedded-ref.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_20-embedded-sro-update-for-sdo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_21-embedded-sro-update-for-sco.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_22-embedded-sro-update-for-smo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_23-embedded-sro-removed.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_24-test-hidden-properties.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_25-ignore-embedded-rels-smo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/tests/src/full_tests/test_26-ignore-embedded-rels-sro.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_atlas.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_attack_ics.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_capec.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_cwe.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_disarm.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_locations.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_sigma_rules.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_tlp.py
RENAMED
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cti_processor/insert_archive_yara_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.4 → stix2arango-1.1.6}/utilities/arango_cve_processor/insert_archive_cve.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|