stix2arango 1.1.2__tar.gz → 1.1.4__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.2 → stix2arango-1.1.4}/PKG-INFO +17 -17
- {stix2arango-1.1.2 → stix2arango-1.1.4}/README.md +16 -16
- {stix2arango-1.1.2 → stix2arango-1.1.4}/pyproject.toml +1 -1
- stix2arango-1.1.4/stix2arango/__main__.py +81 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/services/arangodb_service.py +2 -2
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/stix2arango/stix2arango.py +9 -5
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/utils.py +6 -8
- stix2arango-1.1.4/tests/src/test_arango_service.py +61 -0
- stix2arango-1.1.4/tests/src/test_main.py +131 -0
- stix2arango-1.1.4/tests/src/test_utils.py +172 -0
- stix2arango-1.1.2/stix2arango/__main__.py +0 -27
- {stix2arango-1.1.2 → stix2arango-1.1.4}/.env.example +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/.env.markdown +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/.github/workflows/create-release.yml +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/.github/workflows/run-tests.yml +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/.gitignore +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/LICENSE +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/docs/README.md +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/docs/stix2arango.png +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/requirements.txt +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/__init__.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/config.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/services/__init__.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/services/version_annotator.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/stix2arango/__init__.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/stix2arango/bundle_loader.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango/templates/marking-definition.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/stix2arango.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/README.md +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/custom-sco-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/custom-sco-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/custom-sdo-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/custom-sdo-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/duplicate-objects-all-properties-same.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/duplicate-objects-properties-different.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-object-removed.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-object-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-object.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-sdo-sco-sro-smo.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/nested-embedded-ref.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/non-standard-embedded-relationship.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sco-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sco-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-another.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-condensed-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-condensed-update-1.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-condensed-update-2.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-yet-another.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/smo-embedded-ref-1.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/smo-embedded-ref-2.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/smo-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/smo-updated-2.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/smo-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/source-object-does-not-exist.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sro-original.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/sro-updated.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/target-object-does-not-exist.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/update_with_diff_modified_times_1.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/update_with_diff_modified_times_2.json +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/requirements.txt +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/__init__.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/base_test.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_00-basic-import-logic-with-embedded.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_01-basic-import-no-embedded.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_02-basic-import-no-stix2arango_note.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_03-import-with-no-update-detected.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_04-update-detected-because-of-stix2arango-note.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_05-update-detected-because-of-modified-time-change.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_06-update-detected-because-of-modified-time-change-not-in-order.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_07-test-default-imported-objects.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_08-duplicate-objects-in-bundle-all-identical.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_09-duplicate-objects-but-diff-times-in-bundle.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_10-updating-object-no-modified-time.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_11-custom-sdos.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_12-custom-scos.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_13-updating-smos.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_14-non-standard-embedded-relationship.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_15-testing-when-sro-target-not-in-collection.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_16-testing-when-sro-source-not-in-collection.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_17-testing-update-of-embedded-refs.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_18-testing-nested-embedded-ref.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_19_update_with_diff_created_times.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_20-embedded-sro-update-for-sdo.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_21-embedded-sro-update-for-sco.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_22-embedded-sro-update-for-smo.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_23-embedded-sro-removed.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_24-test-hidden-properties.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_25-ignore-embedded-rels-smo.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_26-ignore-embedded-rels-sro.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/test_bundle_loader.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/test_stix2arango.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/tests/tests.env +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/README.md +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_atlas.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_attack_enterprise.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_attack_ics.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_attack_mobile.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_capec.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_cwe.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_disarm.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_locations.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_sigma_rules.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_tlp.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_yara_rules.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cve_processor/README.md +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cve_processor/insert_archive_cve.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cve_processor/manager.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/stix2arango/add_ref_types.py +0 -0
- {stix2arango-1.1.2 → stix2arango-1.1.4}/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.4
|
|
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
|
|
@@ -60,20 +60,6 @@ Note, the installation assumes ArangoDB is already installed locally.
|
|
|
60
60
|
|
|
61
61
|
[You can install ArangoDB here](https://arangodb.com/download/). stix2arango is compatible with both the Enterprise and Community versions.
|
|
62
62
|
|
|
63
|
-
#### A note for Mac users
|
|
64
|
-
|
|
65
|
-
Fellow Mac users, ArangoDB can be installed and run using homebrew as follows;
|
|
66
|
-
|
|
67
|
-
```shell
|
|
68
|
-
## Install
|
|
69
|
-
brew install arangodb
|
|
70
|
-
## Run
|
|
71
|
-
brew services start arangodb
|
|
72
|
-
## will now be accessible in a browser at: http://127.0.0.1:8529 . Default username is root with no password set (leave blank)
|
|
73
|
-
## Stop
|
|
74
|
-
brew services stop arangodb
|
|
75
|
-
```
|
|
76
|
-
|
|
77
63
|
### Configuration options
|
|
78
64
|
|
|
79
65
|
stix2arango has various settings that are defined in an `.env` file.
|
|
@@ -100,12 +86,14 @@ python3 stix2arango.py \
|
|
|
100
86
|
Where;
|
|
101
87
|
|
|
102
88
|
* `--file` (required): is the path to the valid STIX 2.1 bundle .json file
|
|
103
|
-
* `--database` (required): is the name of the Arango database the objects should be stored in.
|
|
89
|
+
* `--database` (required): is the name of the Arango database the objects should be stored in.
|
|
90
|
+
* `--create_db` (default `true`): If database does not exist, stix2arango will create it. You can set to `false` to stop this behaviour (and avoid the risk of incorrect DBs being created). Generally setting to `false` is a good idea if you know the databases exist. This setting will only work if the Arango user being used to authenticate has permissions to create new databases.
|
|
104
91
|
* `--collection` (required): is the name of the Arango collection in the database specified the objects should be stored in. If the collection does not exist, stix2arango will create it
|
|
105
92
|
* `--stix2arango_note` (optional): Will be stored under the `_stix2arango_note` custom attribute in ArangoDB. Useful as can be used in AQL. `a-z` characters only. Max 24 chars.
|
|
106
93
|
* `--ignore_embedded_relationships` (optional, boolean): if `true` passed, this will stop ANY embedded relationships from being generated. This applies for all object types (SDO, SCO, SRO, SMO). If you want to target certain object types see `ignore_embedded_relationships_sro` and `ignore_embedded_relationships_sro` flags. ` Default is `false`
|
|
107
94
|
* `--ignore_embedded_relationships_sro` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SRO objects (`type` = `relationship`). Default is `false`
|
|
108
|
-
* `--ignore_embedded_relationships_smo` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SMO objects (`type` = `marking-
|
|
95
|
+
* `--ignore_embedded_relationships_smo` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SMO objects (`type` = `marking-defirnition`, `extension-definition`, `language-content`). Default is `false`
|
|
96
|
+
* `--include_embedded_relationships_attributes` (optional, stix `_ref` or `_refs` attribute): if you only want to create embedded relationships from certain keys (attributes) in a STIX object you can pass a list of attributes here. e.g. `object_refs created_by_ref` . In this example, embedded relationships to all objects listed in `object_refs` and objects in `created_by_ref` will be created between source (the objects that house these attibutes) and destinations (the objects listed as values for these attributes)
|
|
109
97
|
* `--is_large_file` (pass flag): Use this mode when the bundle is very large (>100mb), this will chunk the input into multiple files before loading into memory.
|
|
110
98
|
|
|
111
99
|
For example, [using the MITRE ATT&CK Enterprise bundle](https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json);
|
|
@@ -132,6 +120,18 @@ python3 stix2arango.py \
|
|
|
132
120
|
--is_large_file
|
|
133
121
|
```
|
|
134
122
|
|
|
123
|
+
If you want to include embedded relationships for `created_by_ref` and `object_marking_refs` attibutes collection, you would run;
|
|
124
|
+
|
|
125
|
+
```shell
|
|
126
|
+
python3 stix2arango.py \
|
|
127
|
+
--file cti_knowledge_base_store/mitre-attack-enterprise/enterprise-attack-15_1.json \
|
|
128
|
+
--database stix2arango_demo \
|
|
129
|
+
--collection demo_2 \
|
|
130
|
+
--stix2arango_note v15.1 \
|
|
131
|
+
--include_embedded_relationships_attributes object_refs created_by_ref \
|
|
132
|
+
--is_large_file
|
|
133
|
+
```
|
|
134
|
+
|
|
135
135
|
#### A note on embedded relationships
|
|
136
136
|
|
|
137
137
|
stix2arango can handle all embedded references to other STIX objects under `_ref` and `_refs` properties in a STIX object when `--ignore_embedded_relationships` is set to false.
|
|
@@ -37,20 +37,6 @@ Note, the installation assumes ArangoDB is already installed locally.
|
|
|
37
37
|
|
|
38
38
|
[You can install ArangoDB here](https://arangodb.com/download/). stix2arango is compatible with both the Enterprise and Community versions.
|
|
39
39
|
|
|
40
|
-
#### A note for Mac users
|
|
41
|
-
|
|
42
|
-
Fellow Mac users, ArangoDB can be installed and run using homebrew as follows;
|
|
43
|
-
|
|
44
|
-
```shell
|
|
45
|
-
## Install
|
|
46
|
-
brew install arangodb
|
|
47
|
-
## Run
|
|
48
|
-
brew services start arangodb
|
|
49
|
-
## will now be accessible in a browser at: http://127.0.0.1:8529 . Default username is root with no password set (leave blank)
|
|
50
|
-
## Stop
|
|
51
|
-
brew services stop arangodb
|
|
52
|
-
```
|
|
53
|
-
|
|
54
40
|
### Configuration options
|
|
55
41
|
|
|
56
42
|
stix2arango has various settings that are defined in an `.env` file.
|
|
@@ -77,12 +63,14 @@ python3 stix2arango.py \
|
|
|
77
63
|
Where;
|
|
78
64
|
|
|
79
65
|
* `--file` (required): is the path to the valid STIX 2.1 bundle .json file
|
|
80
|
-
* `--database` (required): is the name of the Arango database the objects should be stored in.
|
|
66
|
+
* `--database` (required): is the name of the Arango database the objects should be stored in.
|
|
67
|
+
* `--create_db` (default `true`): If database does not exist, stix2arango will create it. You can set to `false` to stop this behaviour (and avoid the risk of incorrect DBs being created). Generally setting to `false` is a good idea if you know the databases exist. This setting will only work if the Arango user being used to authenticate has permissions to create new databases.
|
|
81
68
|
* `--collection` (required): is the name of the Arango collection in the database specified the objects should be stored in. If the collection does not exist, stix2arango will create it
|
|
82
69
|
* `--stix2arango_note` (optional): Will be stored under the `_stix2arango_note` custom attribute in ArangoDB. Useful as can be used in AQL. `a-z` characters only. Max 24 chars.
|
|
83
70
|
* `--ignore_embedded_relationships` (optional, boolean): if `true` passed, this will stop ANY embedded relationships from being generated. This applies for all object types (SDO, SCO, SRO, SMO). If you want to target certain object types see `ignore_embedded_relationships_sro` and `ignore_embedded_relationships_sro` flags. ` Default is `false`
|
|
84
71
|
* `--ignore_embedded_relationships_sro` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SRO objects (`type` = `relationship`). Default is `false`
|
|
85
|
-
* `--ignore_embedded_relationships_smo` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SMO objects (`type` = `marking-
|
|
72
|
+
* `--ignore_embedded_relationships_smo` (optional, boolean): if `true` passed, will stop any embedded relationships from being generated from SMO objects (`type` = `marking-defirnition`, `extension-definition`, `language-content`). Default is `false`
|
|
73
|
+
* `--include_embedded_relationships_attributes` (optional, stix `_ref` or `_refs` attribute): if you only want to create embedded relationships from certain keys (attributes) in a STIX object you can pass a list of attributes here. e.g. `object_refs created_by_ref` . In this example, embedded relationships to all objects listed in `object_refs` and objects in `created_by_ref` will be created between source (the objects that house these attibutes) and destinations (the objects listed as values for these attributes)
|
|
86
74
|
* `--is_large_file` (pass flag): Use this mode when the bundle is very large (>100mb), this will chunk the input into multiple files before loading into memory.
|
|
87
75
|
|
|
88
76
|
For example, [using the MITRE ATT&CK Enterprise bundle](https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json);
|
|
@@ -109,6 +97,18 @@ python3 stix2arango.py \
|
|
|
109
97
|
--is_large_file
|
|
110
98
|
```
|
|
111
99
|
|
|
100
|
+
If you want to include embedded relationships for `created_by_ref` and `object_marking_refs` attibutes collection, you would run;
|
|
101
|
+
|
|
102
|
+
```shell
|
|
103
|
+
python3 stix2arango.py \
|
|
104
|
+
--file cti_knowledge_base_store/mitre-attack-enterprise/enterprise-attack-15_1.json \
|
|
105
|
+
--database stix2arango_demo \
|
|
106
|
+
--collection demo_2 \
|
|
107
|
+
--stix2arango_note v15.1 \
|
|
108
|
+
--include_embedded_relationships_attributes object_refs created_by_ref \
|
|
109
|
+
--is_large_file
|
|
110
|
+
```
|
|
111
|
+
|
|
112
112
|
#### A note on embedded relationships
|
|
113
113
|
|
|
114
114
|
stix2arango can handle all embedded references to other STIX objects under `_ref` and `_refs` properties in a STIX object when `--ignore_embedded_relationships` is set to false.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from stix2arango.stix2arango import Stix2Arango
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def parse_bool(value: str):
|
|
6
|
+
value = value.lower()
|
|
7
|
+
# ["false", "no", "n"]
|
|
8
|
+
return value in ["yes", "y", "true", "1"]
|
|
9
|
+
|
|
10
|
+
def parse_ref(value: str):
|
|
11
|
+
if not (value.endswith('_ref') or value.endswith('_refs')):
|
|
12
|
+
raise argparse.ArgumentTypeError('value must end with _ref or _refs')
|
|
13
|
+
return value
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def parse_arguments():
|
|
17
|
+
parser = argparse.ArgumentParser(description="Import STIX JSON into ArangoDB")
|
|
18
|
+
parser.add_argument("--file", required=True, help="Path to STIX JSON file")
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"--is_large_file",
|
|
21
|
+
action="store_true",
|
|
22
|
+
help="Use large file mode [Use this mode when the bundle is very large, this will enable you stix2arango to chunk before loading into memory]",
|
|
23
|
+
)
|
|
24
|
+
parser.add_argument("--database", required=True, help="ArangoDB database name")
|
|
25
|
+
parser.add_argument(
|
|
26
|
+
"--create_db",
|
|
27
|
+
default=True,
|
|
28
|
+
type=parse_bool,
|
|
29
|
+
help="whether or not to skip the creation of database, requires admin permission",
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument("--collection", required=True, help="ArangoDB collection name")
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--stix2arango_note", required=False, help="Note for the import", default=""
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--ignore_embedded_relationships",
|
|
37
|
+
required=False,
|
|
38
|
+
help="Ignore Embedded Relationship for the import",
|
|
39
|
+
type=parse_bool,
|
|
40
|
+
default=False,
|
|
41
|
+
)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--ignore_embedded_relationships_sro",
|
|
44
|
+
required=False,
|
|
45
|
+
help="Ignore Embedded Relationship for imported SROs",
|
|
46
|
+
type=parse_bool,
|
|
47
|
+
default=False,
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--ignore_embedded_relationships_smo",
|
|
51
|
+
required=False,
|
|
52
|
+
help="Ignore Embedded Relationship for imported SMOs",
|
|
53
|
+
type=parse_bool,
|
|
54
|
+
default=False,
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--include_embedded_relationships_attributes",
|
|
58
|
+
required=False,
|
|
59
|
+
help="Only create embedded relationships for keys",
|
|
60
|
+
action="extend",
|
|
61
|
+
nargs="+",
|
|
62
|
+
type=parse_ref
|
|
63
|
+
)
|
|
64
|
+
return parser.parse_args()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def main():
|
|
68
|
+
args = parse_arguments()
|
|
69
|
+
stix_obj = Stix2Arango(
|
|
70
|
+
database=args.database,
|
|
71
|
+
collection=args.collection,
|
|
72
|
+
file=args.file,
|
|
73
|
+
create_db=args.create_db,
|
|
74
|
+
stix2arango_note=args.stix2arango_note,
|
|
75
|
+
ignore_embedded_relationships=args.ignore_embedded_relationships,
|
|
76
|
+
ignore_embedded_relationships_sro=args.ignore_embedded_relationships_sro,
|
|
77
|
+
ignore_embedded_relationships_smo=args.ignore_embedded_relationships_smo,
|
|
78
|
+
is_large_file=args.is_large_file,
|
|
79
|
+
include_embedded_relationships_attributes=args.include_embedded_relationships_attributes,
|
|
80
|
+
)
|
|
81
|
+
stix_obj.run()
|
|
@@ -63,7 +63,7 @@ class ArangoDBService:
|
|
|
63
63
|
|
|
64
64
|
if self.db.has_graph(self.ARANGO_GRAPH):
|
|
65
65
|
self.cti2stix_graph = self.db.graph(self.ARANGO_GRAPH)
|
|
66
|
-
elif
|
|
66
|
+
elif create_db:
|
|
67
67
|
self.cti2stix_graph = self.db.create_graph(self.ARANGO_GRAPH)
|
|
68
68
|
|
|
69
69
|
self.collections: dict[str, StandardCollection] = {}
|
|
@@ -199,7 +199,7 @@ class ArangoDBService:
|
|
|
199
199
|
|
|
200
200
|
@staticmethod
|
|
201
201
|
def fix_edge_ref(_id):
|
|
202
|
-
c, _, _key = _id.
|
|
202
|
+
c, _, _key = _id.rpartition('/')
|
|
203
203
|
if not c:
|
|
204
204
|
c = "missing_collection"
|
|
205
205
|
return f"{c}/{_key}"
|
|
@@ -42,6 +42,7 @@ class Stix2Arango:
|
|
|
42
42
|
ignore_embedded_relationships=False,
|
|
43
43
|
ignore_embedded_relationships_sro=True,
|
|
44
44
|
ignore_embedded_relationships_smo=True,
|
|
45
|
+
include_embedded_relationships_attributes=None,
|
|
45
46
|
bundle_id=None,
|
|
46
47
|
username=config.ARANGODB_USERNAME,
|
|
47
48
|
password=config.ARANGODB_PASSWORD,
|
|
@@ -80,15 +81,16 @@ class Stix2Arango:
|
|
|
80
81
|
self.file = file
|
|
81
82
|
self._is_large_file = is_large_file
|
|
82
83
|
self.note = stix2arango_note or ""
|
|
83
|
-
self.identity_ref = utils.load_file_from_url(config.STIX2ARANGO_IDENTITY)
|
|
84
|
+
self.identity_ref = utils.load_file_from_url(config.STIX2ARANGO_IDENTITY).copy()
|
|
84
85
|
self.default_ref_objects = [
|
|
85
|
-
utils.load_file_from_url(link)
|
|
86
|
+
utils.load_file_from_url(link).copy()
|
|
86
87
|
for link in config.MARKING_DEFINITION_REFS + config.IDENTITY_REFS
|
|
87
88
|
]
|
|
88
89
|
self.bundle_id = bundle_id
|
|
89
90
|
self.ignore_embedded_relationships = ignore_embedded_relationships
|
|
90
91
|
self.ignore_embedded_relationships_smo = ignore_embedded_relationships_smo
|
|
91
92
|
self.ignore_embedded_relationships_sro = ignore_embedded_relationships_sro
|
|
93
|
+
self.include_embedded_relationships_attributes = include_embedded_relationships_attributes
|
|
92
94
|
self.object_key_mapping = {}
|
|
93
95
|
if create_collection:
|
|
94
96
|
self.create_s2a_indexes()
|
|
@@ -472,14 +474,16 @@ class Stix2Arango:
|
|
|
472
474
|
for obj in tqdm(bundle_objects, desc="upload_embedded_edges"):
|
|
473
475
|
if obj["id"] not in inserted_object_ids:
|
|
474
476
|
continue
|
|
475
|
-
if
|
|
477
|
+
if self.include_embedded_relationships_attributes:
|
|
478
|
+
pass
|
|
479
|
+
elif (
|
|
476
480
|
self.ignore_embedded_relationships_smo and obj["type"] in SMO_TYPES
|
|
477
481
|
) or (
|
|
478
482
|
self.ignore_embedded_relationships_sro and obj["type"] == "relationship"
|
|
479
483
|
):
|
|
480
484
|
continue
|
|
481
485
|
|
|
482
|
-
for ref_type, targets in utils.get_embedded_refs(obj):
|
|
486
|
+
for ref_type, targets in utils.get_embedded_refs(obj, attributes=self.include_embedded_relationships_attributes):
|
|
483
487
|
utils.create_relationship_obj(
|
|
484
488
|
obj=obj,
|
|
485
489
|
source=obj.get("id"),
|
|
@@ -578,7 +582,7 @@ class Stix2Arango:
|
|
|
578
582
|
self.filename, all_objects
|
|
579
583
|
)
|
|
580
584
|
|
|
581
|
-
if not self.ignore_embedded_relationships:
|
|
585
|
+
if (not self.ignore_embedded_relationships) or self.include_embedded_relationships_attributes:
|
|
582
586
|
module_logger.info(
|
|
583
587
|
"Creating new embedded relationships using _refs and _ref"
|
|
584
588
|
)
|
|
@@ -8,7 +8,7 @@ import json
|
|
|
8
8
|
import hashlib
|
|
9
9
|
import os
|
|
10
10
|
from . import config
|
|
11
|
-
from datetime import datetime
|
|
11
|
+
from datetime import UTC, datetime
|
|
12
12
|
|
|
13
13
|
module_logger = logging.getLogger("data_ingestion_service")
|
|
14
14
|
from arango.database import StandardDatabase
|
|
@@ -67,10 +67,6 @@ def create_relationship_obj(
|
|
|
67
67
|
relationship_object["_bundle_id"] = bundle_id
|
|
68
68
|
relationship_object["_file_name"] = os.path.basename(arango_obj.file or "")
|
|
69
69
|
relationship_object["_stix2arango_note"] = arango_obj.note
|
|
70
|
-
relationship_object["_record_created"] = datetime.now().strftime(
|
|
71
|
-
"%Y-%m-%dT%H:%M:%S.%f"
|
|
72
|
-
)
|
|
73
|
-
relationship_object["_record_modified"] = relationship_object["_record_created"]
|
|
74
70
|
relationship_object["_is_ref"] = True
|
|
75
71
|
relationship_object["type"] = "relationship"
|
|
76
72
|
relationship_object["spec_version"] = "2.1"
|
|
@@ -120,7 +116,7 @@ def remove_duplicates(objects):
|
|
|
120
116
|
return list(objects_hashmap.values())
|
|
121
117
|
|
|
122
118
|
|
|
123
|
-
def get_embedded_refs(object: list | dict, xpath: list = []):
|
|
119
|
+
def get_embedded_refs(object: list | dict, xpath: list = [], attributes=None):
|
|
124
120
|
embedded_refs = []
|
|
125
121
|
if isinstance(object, dict):
|
|
126
122
|
for key, value in object.items():
|
|
@@ -129,11 +125,13 @@ def get_embedded_refs(object: list | dict, xpath: list = []):
|
|
|
129
125
|
if match := EMBEDDED_RELATIONSHIP_RE.fullmatch(key):
|
|
130
126
|
relationship_type = "-".join(xpath + match.group(1).split("_"))
|
|
131
127
|
targets = value if isinstance(value, list) else [value]
|
|
128
|
+
if attributes and key not in attributes:
|
|
129
|
+
continue
|
|
132
130
|
embedded_refs.append((relationship_type, targets))
|
|
133
131
|
elif isinstance(value, list):
|
|
134
|
-
embedded_refs.extend(get_embedded_refs(value, xpath + [key]))
|
|
132
|
+
embedded_refs.extend(get_embedded_refs(value, xpath + [key], attributes=attributes))
|
|
135
133
|
elif isinstance(object, list):
|
|
136
134
|
for obj in object:
|
|
137
135
|
if isinstance(obj, dict):
|
|
138
|
-
embedded_refs.extend(get_embedded_refs(obj, xpath))
|
|
136
|
+
embedded_refs.extend(get_embedded_refs(obj, xpath, attributes=attributes))
|
|
139
137
|
return embedded_refs
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from stix2arango import config
|
|
5
|
+
from stix2arango.services.arangodb_service import ArangoDBService
|
|
6
|
+
from stix2arango.stix2arango.stix2arango import Stix2Arango
|
|
7
|
+
import arango.exceptions
|
|
8
|
+
from unittest.mock import patch, MagicMock
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_get_db_name():
|
|
12
|
+
assert ArangoDBService.get_db_name("test") == 'test_database'
|
|
13
|
+
assert ArangoDBService.get_db_name("test_database") == 'test_database'
|
|
14
|
+
|
|
15
|
+
@pytest.fixture(scope='module')
|
|
16
|
+
def service():
|
|
17
|
+
s = ArangoDBService('test_s2a_arango_service', [], [], host_url=Stix2Arango.ARANGODB_URL, username=config.ARANGODB_USERNAME, password=config.ARANGODB_PASSWORD, create_db=True)
|
|
18
|
+
yield s
|
|
19
|
+
s.sys_db.delete_database('test_s2a_arango_service_database')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_init_creates_graph(service):
|
|
23
|
+
assert service.db.has_graph('test_s2a_arango_service_graph')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_create_db(service):
|
|
27
|
+
service.create_database('test_s2a_arango_service2')
|
|
28
|
+
assert service.sys_db.has_database('test_s2a_arango_service2')
|
|
29
|
+
service.create_database('test_s2a_arango_service2')
|
|
30
|
+
service.sys_db.delete_database('test_s2a_arango_service2')
|
|
31
|
+
|
|
32
|
+
def test_create_collection(service):
|
|
33
|
+
assert service.create_collection('ss_vertex_collection').info()['name'] == 'ss_vertex_collection', "created collection must have the passed name"
|
|
34
|
+
assert service.create_collection('ss_vertex_collection').info()['name'] == 'ss_vertex_collection', "recreating should not throw error"
|
|
35
|
+
|
|
36
|
+
def test_execute_raw_query(service):
|
|
37
|
+
c = service.create_collection('execute_raw_query')
|
|
38
|
+
c.insert_many([{"a": 1}, {"a": 2}, {"a": 3}])
|
|
39
|
+
assert service.execute_raw_query("FOR d IN @@collection FILTER d.a >= 2 RETURN d.a", bind_vars={'@collection': c.name}) == [2, 3]
|
|
40
|
+
with pytest.raises(arango.exceptions.AQLQueryExecuteError):
|
|
41
|
+
service.execute_raw_query("FOR d IN @@collection FILTER d.a >= 2 RETURN d.a")
|
|
42
|
+
|
|
43
|
+
def test_fix_edge_ref():
|
|
44
|
+
assert ArangoDBService.fix_edge_ref('nothing') == "missing_collection/nothing"
|
|
45
|
+
assert ArangoDBService.fix_edge_ref('abcd/nothing') == "abcd/nothing"
|
|
46
|
+
|
|
47
|
+
def test_transactional_resets_db(service):
|
|
48
|
+
db = service.db
|
|
49
|
+
with patch('arango.database.TransactionDatabase.commit_transaction') as mock_commit, service.transactional():
|
|
50
|
+
pass
|
|
51
|
+
assert service.db == db, "db not reset to original after context exit"
|
|
52
|
+
mock_commit.assert_called_once()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_transactional_resets_db__on_failure(service):
|
|
56
|
+
db = service.db
|
|
57
|
+
with patch('arango.database.TransactionDatabase.abort_transaction') as mock_abort, pytest.raises(Exception), service.transactional():
|
|
58
|
+
raise Exception("must raise")
|
|
59
|
+
assert service.db == db, "db not reset to original after context exit"
|
|
60
|
+
mock_abort.assert_called_once()
|
|
61
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
import pytest
|
|
4
|
+
from stix2arango.__main__ import parse_arguments, main
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.mark.parametrize(
|
|
8
|
+
"args",
|
|
9
|
+
[
|
|
10
|
+
[],
|
|
11
|
+
["--database", "somedb"],
|
|
12
|
+
["--file", "somefile"],
|
|
13
|
+
["--file", "somefile", "--database", "somedb"],
|
|
14
|
+
["--collection", "somefile", "--database", "somedb"],
|
|
15
|
+
],
|
|
16
|
+
)
|
|
17
|
+
def test_database_and_file_required(monkeypatch, args):
|
|
18
|
+
monkeypatch.setattr(sys, "argv", ["prog", *args])
|
|
19
|
+
with pytest.raises(SystemExit) as e:
|
|
20
|
+
parse_arguments()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.mark.parametrize(
|
|
24
|
+
"args,parsed_output",
|
|
25
|
+
[
|
|
26
|
+
(
|
|
27
|
+
["--collection", "somefile", "--database", "somedb", "--file", "some-file"],
|
|
28
|
+
{
|
|
29
|
+
"file": "some-file",
|
|
30
|
+
"is_large_file": False,
|
|
31
|
+
"database": "somedb",
|
|
32
|
+
"create_db": True,
|
|
33
|
+
"collection": "somefile",
|
|
34
|
+
"stix2arango_note": "",
|
|
35
|
+
"ignore_embedded_relationships": False,
|
|
36
|
+
"ignore_embedded_relationships_sro": False,
|
|
37
|
+
"ignore_embedded_relationships_smo": False,
|
|
38
|
+
"include_embedded_relationships_attributes": None,
|
|
39
|
+
},
|
|
40
|
+
),
|
|
41
|
+
(
|
|
42
|
+
[
|
|
43
|
+
"--collection",
|
|
44
|
+
"somefile",
|
|
45
|
+
"--database",
|
|
46
|
+
"somedb",
|
|
47
|
+
"--file",
|
|
48
|
+
"some-file",
|
|
49
|
+
"--ignore_embedded_relationships_smo",
|
|
50
|
+
"yes",
|
|
51
|
+
],
|
|
52
|
+
{
|
|
53
|
+
"file": "some-file",
|
|
54
|
+
"is_large_file": False,
|
|
55
|
+
"database": "somedb",
|
|
56
|
+
"create_db": True,
|
|
57
|
+
"collection": "somefile",
|
|
58
|
+
"stix2arango_note": "",
|
|
59
|
+
"ignore_embedded_relationships": False,
|
|
60
|
+
"ignore_embedded_relationships_sro": False,
|
|
61
|
+
"ignore_embedded_relationships_smo": True,
|
|
62
|
+
"include_embedded_relationships_attributes": None,
|
|
63
|
+
},
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
[
|
|
67
|
+
"--collection",
|
|
68
|
+
"somefile",
|
|
69
|
+
"--database",
|
|
70
|
+
"somedb",
|
|
71
|
+
"--file",
|
|
72
|
+
"some-file",
|
|
73
|
+
"--ignore_embedded_relationships_smo",
|
|
74
|
+
"yes",
|
|
75
|
+
"--include_embedded_relationships_attributes",
|
|
76
|
+
"abc_ref",
|
|
77
|
+
"abcdef_refs",
|
|
78
|
+
],
|
|
79
|
+
{
|
|
80
|
+
"file": "some-file",
|
|
81
|
+
"is_large_file": False,
|
|
82
|
+
"database": "somedb",
|
|
83
|
+
"create_db": True,
|
|
84
|
+
"collection": "somefile",
|
|
85
|
+
"stix2arango_note": "",
|
|
86
|
+
"ignore_embedded_relationships": False,
|
|
87
|
+
"ignore_embedded_relationships_sro": False,
|
|
88
|
+
"ignore_embedded_relationships_smo": True,
|
|
89
|
+
"include_embedded_relationships_attributes": ["abc_ref", "abcdef_refs"],
|
|
90
|
+
},
|
|
91
|
+
),
|
|
92
|
+
],
|
|
93
|
+
)
|
|
94
|
+
def test_parse_args(monkeypatch, args, parsed_output):
|
|
95
|
+
args = ["prog", *args]
|
|
96
|
+
monkeypatch.setattr(sys, "argv", args)
|
|
97
|
+
assert parse_arguments().__dict__ == parsed_output
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_main_calls_correctly(monkeypatch):
|
|
101
|
+
args = [
|
|
102
|
+
"prog",
|
|
103
|
+
"--collection",
|
|
104
|
+
"somefile",
|
|
105
|
+
"--database",
|
|
106
|
+
"somedb",
|
|
107
|
+
"--file",
|
|
108
|
+
"some-file",
|
|
109
|
+
"--ignore_embedded_relationships_smo",
|
|
110
|
+
"yes",
|
|
111
|
+
"--include_embedded_relationships_attributes",
|
|
112
|
+
"abc_ref",
|
|
113
|
+
"abcdef_refs",
|
|
114
|
+
]
|
|
115
|
+
monkeypatch.setattr(sys, "argv", args)
|
|
116
|
+
with patch("stix2arango.__main__.Stix2Arango") as mock_s2a_init:
|
|
117
|
+
main()
|
|
118
|
+
mock_s2a_init.assert_called_once_with(
|
|
119
|
+
**{
|
|
120
|
+
"file": "some-file",
|
|
121
|
+
"is_large_file": False,
|
|
122
|
+
"database": "somedb",
|
|
123
|
+
"create_db": True,
|
|
124
|
+
"collection": "somefile",
|
|
125
|
+
"stix2arango_note": "",
|
|
126
|
+
"ignore_embedded_relationships": False,
|
|
127
|
+
"ignore_embedded_relationships_sro": False,
|
|
128
|
+
"ignore_embedded_relationships_smo": True,
|
|
129
|
+
"include_embedded_relationships_attributes": ["abc_ref", "abcdef_refs"],
|
|
130
|
+
}
|
|
131
|
+
)
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from unittest.mock import MagicMock, patch
|
|
3
|
+
import pytest
|
|
4
|
+
from stix2arango import utils
|
|
5
|
+
from stix2arango.config import DOGESEC_IDENTITY
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_load_file_from_url():
|
|
9
|
+
assert (
|
|
10
|
+
utils.load_file_from_url(DOGESEC_IDENTITY)["id"]
|
|
11
|
+
== "identity--9779a2db-f98c-5f4b-8d08-8ee04e02dbb5"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
with pytest.raises(Exception):
|
|
15
|
+
utils.load_file_from_url("https://gogle.cm/ojkskja")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_remove_duplicates():
|
|
19
|
+
assert (
|
|
20
|
+
len(
|
|
21
|
+
utils.remove_duplicates(
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
"id": "all-the-same",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "all-the-same",
|
|
28
|
+
},
|
|
29
|
+
{"id": "all-the-same", "a": 1},
|
|
30
|
+
{"id": "all-the-same", "a": 1, "_is_latest": True},
|
|
31
|
+
{"id": "all-the-same", "a": 2, "b": 1},
|
|
32
|
+
{"id": "all-the-same", "a": 2, "b": 1, "c": 1},
|
|
33
|
+
{"id": "all-the-same", "a": 2, "b": 1, "c": 1, "_is": 8},
|
|
34
|
+
]
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
== 4
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_get_embedded_refs():
|
|
42
|
+
assert utils.get_embedded_refs(
|
|
43
|
+
{
|
|
44
|
+
"abc_ref": "ref1",
|
|
45
|
+
"abcd_refs": ["ref1", "ref2"],
|
|
46
|
+
"abcde": [{"abcdef_ref": "ref7"}, {"abcd_efgh_ref": "ref8"}],
|
|
47
|
+
}
|
|
48
|
+
) == [
|
|
49
|
+
("abc", ["ref1"]),
|
|
50
|
+
("abcd", ["ref1", "ref2"]),
|
|
51
|
+
("abcde-abcdef", ["ref7"]),
|
|
52
|
+
("abcde-abcd-efgh", ["ref8"]),
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_get_embedded_refs__attributes_whitelist():
|
|
57
|
+
assert utils.get_embedded_refs(
|
|
58
|
+
{
|
|
59
|
+
"abc_ref": "ref1",
|
|
60
|
+
"abcd_refs": ["ref1", "ref2"],
|
|
61
|
+
"abcde": [{"abcdef_ref": "ref7"}, {"abcd_efgh_ref": "ref8"}],
|
|
62
|
+
},
|
|
63
|
+
attributes=["abcd_efgh_ref", "abc_ref"],
|
|
64
|
+
) == [
|
|
65
|
+
("abc", ["ref1"]),
|
|
66
|
+
(
|
|
67
|
+
"abcde-abcd-efgh",
|
|
68
|
+
["ref8"],
|
|
69
|
+
),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_get_vertex_and_edge_collection_names():
|
|
74
|
+
assert utils.get_vertex_and_edge_collection_names("ade") == (
|
|
75
|
+
"ade_vertex_collection",
|
|
76
|
+
"ade_edge_collection",
|
|
77
|
+
)
|
|
78
|
+
assert utils.get_vertex_and_edge_collection_names("ade_edge_collection") == (
|
|
79
|
+
"ade_vertex_collection",
|
|
80
|
+
"ade_edge_collection",
|
|
81
|
+
)
|
|
82
|
+
assert utils.get_vertex_and_edge_collection_names("ade_vertex_collection") == (
|
|
83
|
+
"ade_vertex_collection",
|
|
84
|
+
"ade_edge_collection",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_create_relationship__no_targets():
|
|
89
|
+
assert utils.create_relationship_obj(None, None, None, None, None, None) == []
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_create_relationships():
|
|
93
|
+
obj = {
|
|
94
|
+
"created": "2024-01-01T00:00:00.000000",
|
|
95
|
+
"modified": "2024-01-02T00:00:00.000000",
|
|
96
|
+
"object_marking_refs": ["marking--xyz"],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
source = "indicator--source"
|
|
100
|
+
targets = ["malware--target1", "software--target--2"]
|
|
101
|
+
relationship = "indicates"
|
|
102
|
+
insert_statement = []
|
|
103
|
+
bundle_id = "bundle--xyz"
|
|
104
|
+
extra_data = {"confidence": 80, "labels": ["example"]}
|
|
105
|
+
arango_obj = MagicMock()
|
|
106
|
+
arango_obj.identity_ref = {"id": "identity--abcd"}
|
|
107
|
+
arango_obj.core_collection_vertex = "vertices"
|
|
108
|
+
arango_obj.file = "/some/path/file.txt"
|
|
109
|
+
arango_obj.note = "This is a note"
|
|
110
|
+
|
|
111
|
+
utils.create_relationship_obj(
|
|
112
|
+
obj=obj,
|
|
113
|
+
source=source,
|
|
114
|
+
targets=targets,
|
|
115
|
+
relationship=relationship,
|
|
116
|
+
insert_statement=insert_statement,
|
|
117
|
+
bundle_id=bundle_id,
|
|
118
|
+
arango_obj=arango_obj,
|
|
119
|
+
extra_data=extra_data,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
assert len(insert_statement) == 2
|
|
123
|
+
assert insert_statement == [
|
|
124
|
+
{
|
|
125
|
+
"relationship_type": "indicates",
|
|
126
|
+
"created": "2024-01-01T00:00:00.000000",
|
|
127
|
+
"modified": "2024-01-02T00:00:00.000000",
|
|
128
|
+
"object_marking_refs": ["marking--xyz"],
|
|
129
|
+
"id": "relationship--8a86537f-d4bb-55bc-b06d-ddeabbd9899d",
|
|
130
|
+
"created_by_ref": "identity--abcd",
|
|
131
|
+
"source_ref": "indicator--source",
|
|
132
|
+
"target_ref": "malware--target1",
|
|
133
|
+
"_from": "vertices/indicator--source",
|
|
134
|
+
"_to": "vertices/malware--target1",
|
|
135
|
+
"_bundle_id": "bundle--xyz",
|
|
136
|
+
"_file_name": "file.txt",
|
|
137
|
+
"_stix2arango_note": "This is a note",
|
|
138
|
+
"_is_ref": True,
|
|
139
|
+
"type": "relationship",
|
|
140
|
+
"spec_version": "2.1",
|
|
141
|
+
"external_references": {
|
|
142
|
+
"source_name": "stix2arango",
|
|
143
|
+
"description": "embedded-relationship",
|
|
144
|
+
},
|
|
145
|
+
"confidence": 80,
|
|
146
|
+
"labels": ["example"],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"relationship_type": "indicates",
|
|
150
|
+
"created": "2024-01-01T00:00:00.000000",
|
|
151
|
+
"modified": "2024-01-02T00:00:00.000000",
|
|
152
|
+
"object_marking_refs": ["marking--xyz"],
|
|
153
|
+
"id": "relationship--fda071b0-e1e8-5831-a707-850f1b1a5a0e",
|
|
154
|
+
"created_by_ref": "identity--abcd",
|
|
155
|
+
"source_ref": "indicator--source",
|
|
156
|
+
"target_ref": "software--target--2",
|
|
157
|
+
"_from": "vertices/indicator--source",
|
|
158
|
+
"_to": "vertices/software--target--2",
|
|
159
|
+
"_bundle_id": "bundle--xyz",
|
|
160
|
+
"_file_name": "file.txt",
|
|
161
|
+
"_stix2arango_note": "This is a note",
|
|
162
|
+
"_is_ref": True,
|
|
163
|
+
"type": "relationship",
|
|
164
|
+
"spec_version": "2.1",
|
|
165
|
+
"external_references": {
|
|
166
|
+
"source_name": "stix2arango",
|
|
167
|
+
"description": "embedded-relationship",
|
|
168
|
+
},
|
|
169
|
+
"confidence": 80,
|
|
170
|
+
"labels": ["example"],
|
|
171
|
+
},
|
|
172
|
+
]
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
from stix2arango.stix2arango import Stix2Arango
|
|
3
|
-
|
|
4
|
-
def parse_bool(value: str):
|
|
5
|
-
value = value.lower()
|
|
6
|
-
# ["false", "no", "n"]
|
|
7
|
-
return value in ["yes", "y", "true", "1"]
|
|
8
|
-
|
|
9
|
-
def parse_arguments():
|
|
10
|
-
parser = argparse.ArgumentParser(description="Import STIX JSON into ArangoDB")
|
|
11
|
-
parser.add_argument("--file", required=True, help="Path to STIX JSON file")
|
|
12
|
-
parser.add_argument("--is_large_file", action="store_true", help="Use large file mode [Use this mode when the bundle is very large, this will enable you stix2arango to chunk before loading into memory]")
|
|
13
|
-
parser.add_argument("--database", required=True, help="ArangoDB database name")
|
|
14
|
-
parser.add_argument("--create_db", default=True, type=parse_bool, help="whether or not to skip the creation of database, requires admin permission")
|
|
15
|
-
parser.add_argument("--collection", required=True, help="ArangoDB collection name")
|
|
16
|
-
parser.add_argument("--stix2arango_note", required=False, help="Note for the import", default="")
|
|
17
|
-
parser.add_argument("--ignore_embedded_relationships", required=False, help="Ignore Embedded Relationship for the import", type=parse_bool, default=False)
|
|
18
|
-
parser.add_argument("--ignore_embedded_relationships_sro", required=False, help="Ignore Embedded Relationship for imported SROs", type=parse_bool, default=False)
|
|
19
|
-
parser.add_argument("--ignore_embedded_relationships_smo", required=False, help="Ignore Embedded Relationship for imported SMOs", type=parse_bool, default=False)
|
|
20
|
-
|
|
21
|
-
return parser.parse_args()
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def main():
|
|
25
|
-
args = parse_arguments()
|
|
26
|
-
stix_obj = Stix2Arango(args.database, args.collection, file=args.file, create_db=args.create_db, stix2arango_note=args.stix2arango_note, ignore_embedded_relationships=args.ignore_embedded_relationships, ignore_embedded_relationships_sro=args.ignore_embedded_relationships_sro, ignore_embedded_relationships_smo=args.ignore_embedded_relationships_smo, is_large_file=args.is_large_file)
|
|
27
|
-
stix_obj.run()
|
|
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.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-object-removed.json
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/files/stix2arango/embedded-ref-object-updated.json
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/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.2 → stix2arango-1.1.4}/tests/files/stix2arango/sigma-rule-bundle-another.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/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.2 → stix2arango-1.1.4}/tests/files/stix2arango/source-object-does-not-exist.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/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.2 → stix2arango-1.1.4}/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.2 → stix2arango-1.1.4}/tests/src/full_tests/test_18-testing-nested-embedded-ref.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_20-embedded-sro-update-for-sdo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_21-embedded-sro-update-for-sco.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_22-embedded-sro-update-for-smo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_23-embedded-sro-removed.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_24-test-hidden-properties.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/tests/src/full_tests/test_25-ignore-embedded-rels-smo.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/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
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_atlas.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_attack_ics.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_capec.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_cwe.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_disarm.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_locations.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_sigma_rules.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_tlp.py
RENAMED
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cti_processor/insert_archive_yara_rules.py
RENAMED
|
File without changes
|
|
File without changes
|
{stix2arango-1.1.2 → stix2arango-1.1.4}/utilities/arango_cve_processor/insert_archive_cve.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|