txt2detection 1.0.7__tar.gz → 1.0.9__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 txt2detection might be problematic. Click here for more details.
- {txt2detection-1.0.7 → txt2detection-1.0.9}/PKG-INFO +7 -8
- {txt2detection-1.0.7 → txt2detection-1.0.9}/README.md +5 -7
- {txt2detection-1.0.7 → txt2detection-1.0.9}/pyproject.toml +2 -1
- txt2detection-1.0.9/tests/files/sigma-rule-attack-enterprise.yml +27 -0
- txt2detection-1.0.9/tests/files/sigma-rule-attack-flow.yml +25 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-custom-tags.yml +1 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-master.yml +1 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-description.yml +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-level.yml +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-license.yml +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-status.yml +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-observables.yml +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/manual-tests/README.md +30 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_bundler.py +57 -12
- txt2detection-1.0.9/txt2detection/__main__.py +347 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/base.py +41 -13
- txt2detection-1.0.9/txt2detection/ai_extractor/models.py +34 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/openai.py +1 -3
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/openrouter.py +4 -4
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/prompts.py +130 -3
- txt2detection-1.0.9/txt2detection/attack_flow.py +233 -0
- txt2detection-1.0.9/txt2detection/bundler.py +370 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/credential_checker.py +11 -9
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/models.py +86 -49
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/observables.py +0 -1
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/utils.py +24 -12
- txt2detection-1.0.7/txt2detection/__main__.py +0 -196
- txt2detection-1.0.7/txt2detection/bundler.py +0 -283
- {txt2detection-1.0.7 → txt2detection-1.0.9}/.env.example +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/.env.markdown +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/.github/workflows/create-release.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/.github/workflows/run-tests.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/.gitignore +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/LICENSE +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/config/detection_languages.yaml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/docs/README.md +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/docs/txt2detection.png +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/requirements.txt +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/CVE-2024-56520.txt +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/EC2-exfil.txt +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/observables.txt +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-existing-related.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-author.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-date.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-tags.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-no-title.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/files/sigma-rule-one-date.yml +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/__init__.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/requirements.txt +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_main.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_main_run_txt2detction.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_models.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_observables.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/tests/src/test_utils.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/__init__.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/__init__.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/anthropic.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/deepseek.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/gemini.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection/ai_extractor/utils.py +0 -0
- {txt2detection-1.0.7 → txt2detection-1.0.9}/txt2detection.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: txt2detection
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9
|
|
4
4
|
Summary: A command line tool that takes a txt file containing threat intelligence and turns it into a detection rule.
|
|
5
5
|
Project-URL: Homepage, https://github.com/muchdogesec/txt2detection
|
|
6
6
|
Project-URL: Issues, https://github.com/muchdogesec/txt2detection/issues
|
|
@@ -21,6 +21,7 @@ Requires-Dist: python-slugify
|
|
|
21
21
|
Requires-Dist: pyyaml
|
|
22
22
|
Requires-Dist: requests>=2.31.0; python_version >= '3.7'
|
|
23
23
|
Requires-Dist: stix2
|
|
24
|
+
Requires-Dist: stix2extensions
|
|
24
25
|
Requires-Dist: tqdm>=4.66.4; python_version >= '3.7'
|
|
25
26
|
Requires-Dist: validators>=0.34.0
|
|
26
27
|
Provides-Extra: anthropic
|
|
@@ -71,12 +72,6 @@ txt2detection allows a user to enter some threat intelligence as a file to consi
|
|
|
71
72
|
2. Based on the user input, AI prompts structured and sent to produce an intelligence rule
|
|
72
73
|
3. Rules converted into STIX objects
|
|
73
74
|
|
|
74
|
-
## tl;dr
|
|
75
|
-
|
|
76
|
-
[](https://www.youtube.com/watch?v=uJWXYKyu3Xg)
|
|
77
|
-
|
|
78
|
-
[Watch the demo](https://www.youtube.com/watch?v=uJWXYKyu3Xg).
|
|
79
|
-
|
|
80
75
|
## Usage
|
|
81
76
|
|
|
82
77
|
### Setup
|
|
@@ -161,12 +156,14 @@ Use this mode to generate a set of rules from an input text file;
|
|
|
161
156
|
* `--license` (optional): [License of the rule according the SPDX ID specification](https://spdx.org/licenses/). Will be added to the rule.
|
|
162
157
|
* `--reference_urls` (optional): A list of URLs to be added as `references` in the Sigma Rule property and in the `external_references` property of the Indicator and Report STIX object created. e.g `"https://www.google.com/" "https://www.facebook.com/"`
|
|
163
158
|
* `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
|
|
164
|
-
*
|
|
159
|
+
* `--ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
|
|
165
160
|
* Provider (env var required `OPENROUTER_API_KEY`): `openrouter:`, providers/models `openai/gpt-4o`, `deepseek/deepseek-chat` ([More here](https://openrouter.ai/models))
|
|
166
161
|
* Provider (env var required `OPENAI_API_KEY`): `openai:`, models e.g.: `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `gpt-4` ([More here](https://platform.openai.com/docs/models))
|
|
167
162
|
* Provider (env var required `ANTHROPIC_API_KEY`): `anthropic:`, models e.g.: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`, `claude-3-opus-latest` ([More here](https://docs.anthropic.com/en/docs/about-claude/models))
|
|
168
163
|
* Provider (env var required `GOOGLE_API_KEY`): `gemini:models/`, models: `gemini-1.5-pro-latest`, `gemini-1.5-flash-latest` ([More here](https://ai.google.dev/gemini-api/docs/models/gemini))
|
|
169
164
|
* Provider (env var required `DEEPSEEK_API_KEY`): `deepseek:`, models `deepseek-chat` ([More here](https://api-docs.deepseek.com/quick_start/pricing))
|
|
165
|
+
* `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
|
|
166
|
+
* `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
|
|
170
167
|
|
|
171
168
|
Note, in this mode, the following values will be automatically assigned to the rule
|
|
172
169
|
|
|
@@ -193,6 +190,8 @@ Note, in this mode you should be aware of a few things;
|
|
|
193
190
|
* `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
|
|
194
191
|
* `status` (optional): either `stable`, `test`, `experimental`, `deprecated`, `unsupported`. If passed, will overwrite any existing `status` recorded in the rule
|
|
195
192
|
* `level` (optional): either `informational`, `low`, `medium`, `high`, `critical`. If passed, will overwrite any existing `level` recorded in the rule
|
|
193
|
+
* `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
|
|
194
|
+
* `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
|
|
196
195
|
|
|
197
196
|
### A note on observable extraction
|
|
198
197
|
|
|
@@ -31,12 +31,6 @@ txt2detection allows a user to enter some threat intelligence as a file to consi
|
|
|
31
31
|
2. Based on the user input, AI prompts structured and sent to produce an intelligence rule
|
|
32
32
|
3. Rules converted into STIX objects
|
|
33
33
|
|
|
34
|
-
## tl;dr
|
|
35
|
-
|
|
36
|
-
[](https://www.youtube.com/watch?v=uJWXYKyu3Xg)
|
|
37
|
-
|
|
38
|
-
[Watch the demo](https://www.youtube.com/watch?v=uJWXYKyu3Xg).
|
|
39
|
-
|
|
40
34
|
## Usage
|
|
41
35
|
|
|
42
36
|
### Setup
|
|
@@ -121,12 +115,14 @@ Use this mode to generate a set of rules from an input text file;
|
|
|
121
115
|
* `--license` (optional): [License of the rule according the SPDX ID specification](https://spdx.org/licenses/). Will be added to the rule.
|
|
122
116
|
* `--reference_urls` (optional): A list of URLs to be added as `references` in the Sigma Rule property and in the `external_references` property of the Indicator and Report STIX object created. e.g `"https://www.google.com/" "https://www.facebook.com/"`
|
|
123
117
|
* `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
|
|
124
|
-
*
|
|
118
|
+
* `--ai_provider` (required): defines the `provider:model` to be used to generate the rule. Select one option. Currently supports:
|
|
125
119
|
* Provider (env var required `OPENROUTER_API_KEY`): `openrouter:`, providers/models `openai/gpt-4o`, `deepseek/deepseek-chat` ([More here](https://openrouter.ai/models))
|
|
126
120
|
* Provider (env var required `OPENAI_API_KEY`): `openai:`, models e.g.: `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `gpt-4` ([More here](https://platform.openai.com/docs/models))
|
|
127
121
|
* Provider (env var required `ANTHROPIC_API_KEY`): `anthropic:`, models e.g.: `claude-3-5-sonnet-latest`, `claude-3-5-haiku-latest`, `claude-3-opus-latest` ([More here](https://docs.anthropic.com/en/docs/about-claude/models))
|
|
128
122
|
* Provider (env var required `GOOGLE_API_KEY`): `gemini:models/`, models: `gemini-1.5-pro-latest`, `gemini-1.5-flash-latest` ([More here](https://ai.google.dev/gemini-api/docs/models/gemini))
|
|
129
123
|
* Provider (env var required `DEEPSEEK_API_KEY`): `deepseek:`, models `deepseek-chat` ([More here](https://api-docs.deepseek.com/quick_start/pricing))
|
|
124
|
+
* `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
|
|
125
|
+
* `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
|
|
130
126
|
|
|
131
127
|
Note, in this mode, the following values will be automatically assigned to the rule
|
|
132
128
|
|
|
@@ -153,6 +149,8 @@ Note, in this mode you should be aware of a few things;
|
|
|
153
149
|
* `--external_refs` (optional): txt2detection will automatically populate the `external_references` of the report object it creates for the input. You can use this value to add additional objects to `external_references`. Note, you can only add `source_name` and `external_id` values currently. Pass as `source_name=external_id`. e.g. `--external_refs txt2stix=demo1 source=id` would create the following objects under the `external_references` property: `{"source_name":"txt2stix","external_id":"demo1"},{"source_name":"source","external_id":"id"}`
|
|
154
150
|
* `status` (optional): either `stable`, `test`, `experimental`, `deprecated`, `unsupported`. If passed, will overwrite any existing `status` recorded in the rule
|
|
155
151
|
* `level` (optional): either `informational`, `low`, `medium`, `high`, `critical`. If passed, will overwrite any existing `level` recorded in the rule
|
|
152
|
+
* `--ai_create_attack_flow` (boolean): passing this flag will also prompt the AI model (the same entered for `--ai_provider`, default `false`) to generate an [Attack Flow](https://center-for-threat-informed-defense.github.io/attack-flow/) for the MITRE ATT&CK tags to define the logical order in which they are being described. Note, Sigma currently supports ATT&CK Enterprise only.
|
|
153
|
+
* `--ai_create_attack_navigator_layer` (boolean, default `false`): passing this flag will generate a [MITRE ATT&CK Navigator layer](https://mitre-attack.github.io/attack-navigator/) for MITRE ATT&CK tags. Note, Sigma currently supports ATT&CK Enterprise only. You don't need to pass this if `--ai_create_attack_flow` is set to `true` (as this mode relies on this setting being true)
|
|
156
154
|
|
|
157
155
|
### A note on observable extraction
|
|
158
156
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "txt2detection"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.9"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name = "dogesec" }
|
|
10
10
|
]
|
|
@@ -31,6 +31,7 @@ dependencies = [
|
|
|
31
31
|
"validators>=0.34.0",
|
|
32
32
|
"llama-index-core>=0.12.42",
|
|
33
33
|
'llama-index-llms-openai>=0.4.5',
|
|
34
|
+
'stix2extensions',
|
|
34
35
|
]
|
|
35
36
|
[project.urls]
|
|
36
37
|
Homepage = "https://github.com/muchdogesec/txt2detection"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
title: Attack Navigator Enterprise
|
|
2
|
+
id: a18e76d1-f152-4b87-a552-d46f41afd637
|
|
3
|
+
status: test
|
|
4
|
+
description: Build an Attack Enterprise Navigator layer
|
|
5
|
+
references:
|
|
6
|
+
- https://www.dogesec.com
|
|
7
|
+
author: dogesec
|
|
8
|
+
date: 2020-01-01
|
|
9
|
+
modified: 2020-01-02
|
|
10
|
+
tags:
|
|
11
|
+
- tlp.clear
|
|
12
|
+
- attack.t1547
|
|
13
|
+
- attack.t1671
|
|
14
|
+
- attack.t1025
|
|
15
|
+
- attack.command-and-control
|
|
16
|
+
- attack.t1661 # will fail is mobile
|
|
17
|
+
logsource:
|
|
18
|
+
product: okta
|
|
19
|
+
service: okta
|
|
20
|
+
detection:
|
|
21
|
+
selection:
|
|
22
|
+
eventtype:
|
|
23
|
+
- policy.lifecycle.update
|
|
24
|
+
- policy.lifecycle.delete
|
|
25
|
+
condition: selection
|
|
26
|
+
level: low
|
|
27
|
+
license: MIT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
title: Attack Flow demo
|
|
2
|
+
id: 7894eba6-b0e5-48d9-be52-26bf5a556e45
|
|
3
|
+
status: test
|
|
4
|
+
description: Build an Attack Flow from a Sigma Rule
|
|
5
|
+
references:
|
|
6
|
+
- https://www.dogesec.com
|
|
7
|
+
author: dogesec
|
|
8
|
+
date: 2020-01-01
|
|
9
|
+
modified: 2020-01-02
|
|
10
|
+
tags:
|
|
11
|
+
- tlp.clear
|
|
12
|
+
- attack.t1547
|
|
13
|
+
- attack.t1671
|
|
14
|
+
- attack.t1025
|
|
15
|
+
logsource:
|
|
16
|
+
product: okta
|
|
17
|
+
service: okta
|
|
18
|
+
detection:
|
|
19
|
+
selection:
|
|
20
|
+
eventtype:
|
|
21
|
+
- policy.lifecycle.update
|
|
22
|
+
- policy.lifecycle.delete
|
|
23
|
+
condition: selection
|
|
24
|
+
level: low
|
|
25
|
+
license: MIT
|
|
@@ -445,4 +445,33 @@ python3 txt2detection.py sigma \
|
|
|
445
445
|
--name "Overwrite status" \
|
|
446
446
|
--status unsupported \
|
|
447
447
|
--report_id d2d01afa-dc55-4a80-8d62-15d154450112
|
|
448
|
-
```
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
## Attack Flow
|
|
452
|
+
|
|
453
|
+
```shell
|
|
454
|
+
python3 txt2detection.py sigma \
|
|
455
|
+
--sigma_file tests/files/sigma-rule-attack-flow.yml \
|
|
456
|
+
--name "Create ATT&CK Flow" \
|
|
457
|
+
--report_id 330e2030-1dc2-45e6-be13-9342b102621b \
|
|
458
|
+
--ai_provider openai:gpt-5 \
|
|
459
|
+
--ai_create_attack_flow
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
## Attack Navigator
|
|
463
|
+
|
|
464
|
+
### Enterprise
|
|
465
|
+
|
|
466
|
+
```shell
|
|
467
|
+
python3 txt2detection.py sigma \
|
|
468
|
+
--sigma_file tests/files/sigma-rule-attack-enterprise.yml \
|
|
469
|
+
--name "Attack Navigator Enterprise" \
|
|
470
|
+
--report_id a18e76d1-f152-4b87-a552-d46f41afd637 \
|
|
471
|
+
--ai_provider openai:gpt-5 \
|
|
472
|
+
--ai_create_attack_navigator_layer
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Mobile / ICS
|
|
476
|
+
|
|
477
|
+
Not currently supported by Sigma.
|
|
@@ -16,9 +16,9 @@ def dummy_detection():
|
|
|
16
16
|
detection = SigmaRuleDetection(
|
|
17
17
|
title="Test Detection",
|
|
18
18
|
description="Detects something suspicious.",
|
|
19
|
-
detection=dict(condition="selection1", selection1=dict(ip=
|
|
19
|
+
detection=dict(condition="selection1", selection1=dict(ip="1.1.1.1")),
|
|
20
20
|
tags=["tlp.red", "sigma.execution"],
|
|
21
|
-
id=
|
|
21
|
+
id="cd7ff0b1-fbf3-4c2d-ba70-5d127eb8b4be",
|
|
22
22
|
external_references=[],
|
|
23
23
|
logsource=dict(
|
|
24
24
|
category="network-connection",
|
|
@@ -28,15 +28,6 @@ def dummy_detection():
|
|
|
28
28
|
return detection
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
@pytest.fixture
|
|
32
|
-
def bundler_instance():
|
|
33
|
-
return Bundler(
|
|
34
|
-
name="Test Report",
|
|
35
|
-
identity=None,
|
|
36
|
-
tlp_level="red",
|
|
37
|
-
description="This is a test report.",
|
|
38
|
-
labels=["tlp.red", "test.test-var"],
|
|
39
|
-
)
|
|
40
31
|
|
|
41
32
|
|
|
42
33
|
def test_bundler_initialization(bundler_instance):
|
|
@@ -229,7 +220,7 @@ def test_bundler_generates_valid_bundle(dummy_detection):
|
|
|
229
220
|
|
|
230
221
|
def test_bundle_detections(dummy_detection, bundler_instance):
|
|
231
222
|
container = DetectionContainer(success=False, detections=[])
|
|
232
|
-
with patch.object(Bundler,
|
|
223
|
+
with patch.object(Bundler, "add_rule_indicator") as mock_add_rule_indicator:
|
|
233
224
|
bundler_instance.bundle_detections(container)
|
|
234
225
|
mock_add_rule_indicator.assert_not_called()
|
|
235
226
|
mock_add_rule_indicator.reset_mock()
|
|
@@ -238,3 +229,57 @@ def test_bundle_detections(dummy_detection, bundler_instance):
|
|
|
238
229
|
container.success = True
|
|
239
230
|
bundler_instance.bundle_detections(container)
|
|
240
231
|
mock_add_rule_indicator.assert_called_once_with(detection)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_bundle_detections__creates_log_source(dummy_detection, bundler_instance):
|
|
235
|
+
dummy_detection.detection_id = "d73e1632-c541-4b09-8281-95dc7f9c5782"
|
|
236
|
+
bundler_instance.add_rule_indicator(dummy_detection)
|
|
237
|
+
objects = [
|
|
238
|
+
obj
|
|
239
|
+
for obj in bundler_instance.bundle_dict["objects"]
|
|
240
|
+
if obj["id"]
|
|
241
|
+
in (
|
|
242
|
+
"data-source--f078a18f-0f04-5fde-b6cd-a5af90b6346b",
|
|
243
|
+
"relationship--fe0a3715-6a21-5472-840f-39ea9c61ee83",
|
|
244
|
+
)
|
|
245
|
+
]
|
|
246
|
+
assert objects == [
|
|
247
|
+
{
|
|
248
|
+
"type": "data-source",
|
|
249
|
+
"spec_version": "2.1",
|
|
250
|
+
"id": "data-source--f078a18f-0f04-5fde-b6cd-a5af90b6346b",
|
|
251
|
+
"category": "network-connection",
|
|
252
|
+
"product": "firewall",
|
|
253
|
+
"extensions": {
|
|
254
|
+
"extension-definition--afeeb724-bce2-575e-af3d-d705842ea84b": {
|
|
255
|
+
"extension_type": "new-sco"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"type": "relationship",
|
|
261
|
+
"spec_version": "2.1",
|
|
262
|
+
"id": "relationship--fe0a3715-6a21-5472-840f-39ea9c61ee83",
|
|
263
|
+
"created_by_ref": "identity--a4d70b75-6f4a-5d19-9137-da863edd33d7",
|
|
264
|
+
"created": "2025-01-01T00:00:00.000Z",
|
|
265
|
+
"modified": "2025-01-01T00:00:00.000Z",
|
|
266
|
+
"relationship_type": "related-to",
|
|
267
|
+
"description": "Test Detection is created from log-source {category=network-connection, product=firewall}",
|
|
268
|
+
"source_ref": "indicator--d73e1632-c541-4b09-8281-95dc7f9c5782",
|
|
269
|
+
"target_ref": "data-source--f078a18f-0f04-5fde-b6cd-a5af90b6346b",
|
|
270
|
+
"object_marking_refs": [
|
|
271
|
+
"marking-definition--e828b379-4e03-4974-9ac4-e53a884c97c1",
|
|
272
|
+
"marking-definition--a4d70b75-6f4a-5d19-9137-da863edd33d7",
|
|
273
|
+
],
|
|
274
|
+
},
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
def test_get_attack_objects(bundler_instance):
|
|
278
|
+
retval = bundler_instance.get_attack_objects(['T1190', 'T1547'])
|
|
279
|
+
print({r['id'] for r in retval})
|
|
280
|
+
assert {r['id'] for r in retval} == {'attack-pattern--1ecb2399-e8ba-4f6b-8ba7-5c27d49405cf', 'attack-pattern--3f886f2a-874f-4333-b794-aa6075009b1c'}
|
|
281
|
+
|
|
282
|
+
def test_get_cve_objects(bundler_instance):
|
|
283
|
+
cves = ['CVE-2025-1234', 'CVE-2024-1234']
|
|
284
|
+
retval = bundler_instance.get_cve_objects(cves)
|
|
285
|
+
assert {r['name'] for r in retval} == set(cves)
|