txt2detection 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
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/__main__.py +8 -1
- txt2detection/ai_extractor/base.py +11 -1
- txt2detection/bundler.py +2 -2
- txt2detection/credential_checker.py +80 -0
- {txt2detection-1.0.1.dist-info → txt2detection-1.0.3.dist-info}/METADATA +25 -1
- {txt2detection-1.0.1.dist-info → txt2detection-1.0.3.dist-info}/RECORD +9 -8
- {txt2detection-1.0.1.dist-info → txt2detection-1.0.3.dist-info}/WHEEL +0 -0
- {txt2detection-1.0.1.dist-info → txt2detection-1.0.3.dist-info}/entry_points.txt +0 -0
- {txt2detection-1.0.1.dist-info → txt2detection-1.0.3.dist-info}/licenses/LICENSE +0 -0
txt2detection/__main__.py
CHANGED
|
@@ -13,6 +13,7 @@ import uuid
|
|
|
13
13
|
from stix2 import Identity
|
|
14
14
|
import yaml
|
|
15
15
|
|
|
16
|
+
from txt2detection import credential_checker
|
|
16
17
|
from txt2detection.ai_extractor.base import BaseAIExtractor
|
|
17
18
|
from txt2detection.models import TAG_PATTERN, DetectionContainer, Level, SigmaRuleDetection
|
|
18
19
|
from txt2detection.utils import validate_token_count
|
|
@@ -91,6 +92,7 @@ def parse_args():
|
|
|
91
92
|
file = mode.add_parser('file', help="process a file input using ai")
|
|
92
93
|
text = mode.add_parser('text', help="process a text argument using ai")
|
|
93
94
|
sigma = mode.add_parser('sigma', help="process a sigma file without ai")
|
|
95
|
+
check_credentials = mode.add_parser('check-credentials', help="show status of external services with respect to credentials")
|
|
94
96
|
|
|
95
97
|
for mode_parser in [file, text, sigma]:
|
|
96
98
|
mode_parser.add_argument('--report_id', type=uuid.UUID, help='report_id to use for generated report')
|
|
@@ -115,7 +117,10 @@ def parse_args():
|
|
|
115
117
|
sigma.add_argument('--level', help="If passed, will overwrite any existing `level` recorded in the rule", choices=Level._member_names_)
|
|
116
118
|
|
|
117
119
|
args: Args = parser.parse_args()
|
|
118
|
-
|
|
120
|
+
if args.mode == "check-credentials":
|
|
121
|
+
statuses = credential_checker.check_statuses(test_llms=True)
|
|
122
|
+
credential_checker.format_statuses(statuses)
|
|
123
|
+
sys.exit(0)
|
|
119
124
|
|
|
120
125
|
if args.mode != 'sigma':
|
|
121
126
|
assert args.ai_provider, "--ai_provider is required in file or txt mode"
|
|
@@ -129,6 +134,8 @@ def parse_args():
|
|
|
129
134
|
return args
|
|
130
135
|
|
|
131
136
|
|
|
137
|
+
|
|
138
|
+
|
|
132
139
|
def run_txt2detection(name, identity, tlp_level, input_text: str, labels: list[str], report_id: str|uuid.UUID, ai_provider: BaseAIExtractor, **kwargs) -> Bundler:
|
|
133
140
|
if sigma := kwargs.get('sigma_file'):
|
|
134
141
|
detection = get_sigma_detections(sigma)
|
|
@@ -54,4 +54,14 @@ class BaseAIExtractor():
|
|
|
54
54
|
|
|
55
55
|
@property
|
|
56
56
|
def extractor_name(self):
|
|
57
|
-
return f"{self.provider}:{self.llm.model}"
|
|
57
|
+
return f"{self.provider}:{self.llm.model}"
|
|
58
|
+
|
|
59
|
+
def check_credential(self):
|
|
60
|
+
try:
|
|
61
|
+
return "authorized" if self._check_credential() else "unauthorized"
|
|
62
|
+
except:
|
|
63
|
+
return "unknown"
|
|
64
|
+
|
|
65
|
+
def _check_credential(self):
|
|
66
|
+
self.llm.complete("say 'hi'")
|
|
67
|
+
return True
|
txt2detection/bundler.py
CHANGED
|
@@ -244,7 +244,7 @@ class Bundler:
|
|
|
244
244
|
|
|
245
245
|
headers = {}
|
|
246
246
|
if api_key := os.environ.get('CTIBUTLER_API_KEY'):
|
|
247
|
-
headers['
|
|
247
|
+
headers['API-KEY'] = api_key
|
|
248
248
|
|
|
249
249
|
return self._get_objects(endpoint, headers)
|
|
250
250
|
|
|
@@ -255,7 +255,7 @@ class Bundler:
|
|
|
255
255
|
endpoint = urljoin(os.environ['VULMATCH_BASE_URL'] + '/', f"v1/cve/objects/?cve_id="+','.join(cve_ids))
|
|
256
256
|
headers = {}
|
|
257
257
|
if api_key := os.environ.get('VULMATCH_API_KEY'):
|
|
258
|
-
headers['
|
|
258
|
+
headers['API-KEY'] = api_key
|
|
259
259
|
|
|
260
260
|
return self._get_objects(endpoint, headers)
|
|
261
261
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
import random
|
|
4
|
+
from urllib.parse import urljoin
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def check_llms():
|
|
10
|
+
from txt2detection.__main__ import parse_model
|
|
11
|
+
|
|
12
|
+
auth_info = dict()
|
|
13
|
+
for model_name in ["openai", "deepseek", "gemini", "openrouter", "anthropic"]:
|
|
14
|
+
try:
|
|
15
|
+
model = parse_model(model_name)
|
|
16
|
+
auth_info[model_name] = model.check_credential()
|
|
17
|
+
except argparse.ArgumentTypeError:
|
|
18
|
+
auth_info[model_name] = "unsupported"
|
|
19
|
+
except:
|
|
20
|
+
auth_info[model_name] = "unauthorized"
|
|
21
|
+
return auth_info
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def check_ctibutler_vulmatch(service):
|
|
25
|
+
session = requests.Session()
|
|
26
|
+
if service == 'vulmatch':
|
|
27
|
+
base_url = os.getenv('VULMATCH_BASE_URL')
|
|
28
|
+
url = urljoin(base_url, 'v1/cve/objects/vulnerability--f552f6f4-39da-48dc-8717-323772c99588/')
|
|
29
|
+
session.headers['API-KEY'] = os.environ.get('VULMATCH_API_KEY')
|
|
30
|
+
elif service == 'ctibutler':
|
|
31
|
+
base_url = os.getenv('CTIBUTLER_BASE_URL')
|
|
32
|
+
url = urljoin(base_url, 'v1/location/versions/available/')
|
|
33
|
+
session.headers['API-KEY'] = os.environ.get('CTIBUTLER_API_KEY')
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
resp = session.get(url)
|
|
37
|
+
match resp.status_code:
|
|
38
|
+
case 401 | 403:
|
|
39
|
+
return "unauthorized"
|
|
40
|
+
case 200:
|
|
41
|
+
return "authorized"
|
|
42
|
+
case _:
|
|
43
|
+
return "unknown"
|
|
44
|
+
except:
|
|
45
|
+
return "offline"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def check_statuses(test_llms=False):
|
|
49
|
+
statuses = dict(
|
|
50
|
+
ctibutler=check_ctibutler_vulmatch("ctibutler"),
|
|
51
|
+
vulmatch=check_ctibutler_vulmatch("vulmatch"),
|
|
52
|
+
)
|
|
53
|
+
if test_llms:
|
|
54
|
+
statuses.update(llms=check_llms())
|
|
55
|
+
return statuses
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def format_statuses(status_dict):
|
|
59
|
+
def get_marker(status):
|
|
60
|
+
"""Return a checkmark, cross, or dash based on status."""
|
|
61
|
+
match status.lower():
|
|
62
|
+
case "authorized":
|
|
63
|
+
return "✔"
|
|
64
|
+
case "unauthorized":
|
|
65
|
+
return "✖"
|
|
66
|
+
case "unknown" | "offline" | "unsupported":
|
|
67
|
+
return "–"
|
|
68
|
+
case _:
|
|
69
|
+
return "?"
|
|
70
|
+
|
|
71
|
+
print("============= Service Statuses ===============")
|
|
72
|
+
for key, value in status_dict.items():
|
|
73
|
+
if key == "llms" and isinstance(value, dict):
|
|
74
|
+
print(f"\n {key.upper()}:")
|
|
75
|
+
for llm_name, llm_status in value.items():
|
|
76
|
+
marker = get_marker(llm_status)
|
|
77
|
+
print(f" {llm_name:<12}: {llm_status:<15} {marker}")
|
|
78
|
+
else:
|
|
79
|
+
marker = get_marker(value)
|
|
80
|
+
print(f" {key:<12}: {value:<15} {marker}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: txt2detection
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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
|
|
@@ -100,6 +100,30 @@ cp .env.example .env
|
|
|
100
100
|
|
|
101
101
|
To see more information about how to set the variables, and what they do, read the `.env.markdown` file.
|
|
102
102
|
|
|
103
|
+
Then test your configoration
|
|
104
|
+
|
|
105
|
+
```shell
|
|
106
|
+
python3 txt2detection.py \
|
|
107
|
+
check-credentials
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
It will return a response to show what API keys are working
|
|
111
|
+
|
|
112
|
+
```txt
|
|
113
|
+
============= Service Statuses ===============
|
|
114
|
+
ctibutler : authorized ✔
|
|
115
|
+
vulmatch : authorized ✔
|
|
116
|
+
|
|
117
|
+
LLMS:
|
|
118
|
+
openai : authorized ✔
|
|
119
|
+
deepseek : unsupported –
|
|
120
|
+
gemini : unsupported –
|
|
121
|
+
openrouter : unsupported –
|
|
122
|
+
anthropic : unsupported –
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Not all services need to be configured, if you have no intention of using them.
|
|
126
|
+
|
|
103
127
|
### Run
|
|
104
128
|
|
|
105
129
|
```shell
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
txt2detection/__init__.py,sha256=Fc460P0q_eb2u3Xc89z-fwl-4ai3jrPqPNVwJQYNkNQ,89
|
|
2
|
-
txt2detection/__main__.py,sha256=
|
|
3
|
-
txt2detection/bundler.py,sha256=
|
|
2
|
+
txt2detection/__main__.py,sha256=R9TgWWGzA8rxF39rZr2MNOrQubhItdRAgP2nd8Tfb78,9337
|
|
3
|
+
txt2detection/bundler.py,sha256=rIvVTlLEHu9SMPqy8AyLbiJ3Cg0WNq7uWvGIXGoaPsg,10822
|
|
4
|
+
txt2detection/credential_checker.py,sha256=YoOe1ABjNfAJIcNE6PRAZtvznTybUKHNBB57DPQhZsU,2564
|
|
4
5
|
txt2detection/models.py,sha256=wDRL-Thme8XXuX1b850v_egTjL3mNYpdVmDvYwfzKI8,12000
|
|
5
6
|
txt2detection/observables.py,sha256=NNnwF_gOsPmAbfgk5fj1rcluMsShZOHssAGy2VJgvmo,6763
|
|
6
7
|
txt2detection/utils.py,sha256=wCol8_DBlvzJOV8VvjqvVR6FWWDQjmz8ItbxG8qbvnw,2755
|
|
7
8
|
txt2detection/ai_extractor/__init__.py,sha256=itcwTF0-S80mx-SuSvfrKazvcwsojR-QsBN-UvnSDwE,418
|
|
8
9
|
txt2detection/ai_extractor/anthropic.py,sha256=YOi2rHUeeoRMS4CFG6mX7xUU4q4rw9qNl72R74UN6ZM,420
|
|
9
|
-
txt2detection/ai_extractor/base.py,sha256=
|
|
10
|
+
txt2detection/ai_extractor/base.py,sha256=urZe_kpYu3BwXyKJsQ0GQIEtTasUQYp4dFzuz34Hai8,2336
|
|
10
11
|
txt2detection/ai_extractor/deepseek.py,sha256=2XehIYbWXG6Odq68nQX4CNtl5GdmBlAmjLP_lG2eEFo,660
|
|
11
12
|
txt2detection/ai_extractor/gemini.py,sha256=hlcKkiHGzQJ0dQECfIhjx2LfdhZoquAF9POwz61RAhw,557
|
|
12
13
|
txt2detection/ai_extractor/openai.py,sha256=e5Of3i-T2CvUSx1T_v7wHOuewHK2IoImxZXfXeZc3Ds,625
|
|
@@ -14,8 +15,8 @@ txt2detection/ai_extractor/openrouter.py,sha256=-KcdcyKPpaeiGfvqJB4L7vMmcXTDhml3
|
|
|
14
15
|
txt2detection/ai_extractor/prompts.py,sha256=ACYFWUafdHXHBXz7fq_RSooA4PJ-mBdaBzqsOOSFpVg,5918
|
|
15
16
|
txt2detection/ai_extractor/utils.py,sha256=SUxyPhkGp5yDbX_H_E018i93R8IbyLsQ00PIBDecfuc,540
|
|
16
17
|
txt2detection/config/detection_languages.yaml,sha256=dgQUJPxhDRJ_IiFEFOiH0yhEer3SkFSIhY4pS3BsX2c,287
|
|
17
|
-
txt2detection-1.0.
|
|
18
|
-
txt2detection-1.0.
|
|
19
|
-
txt2detection-1.0.
|
|
20
|
-
txt2detection-1.0.
|
|
21
|
-
txt2detection-1.0.
|
|
18
|
+
txt2detection-1.0.3.dist-info/METADATA,sha256=uObp1AT1iejmjazeIxZdB-EmY3tk087qnHxv-x1kj88,14213
|
|
19
|
+
txt2detection-1.0.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
20
|
+
txt2detection-1.0.3.dist-info/entry_points.txt,sha256=ep_rLlS2r1-kKE7S3iKf3SVwbCU9-FZhU9zUebitw7A,62
|
|
21
|
+
txt2detection-1.0.3.dist-info/licenses/LICENSE,sha256=BK8Ppqlc4pdgnNzIxnxde0taoQ1BgicdyqmBvMiNYgY,11364
|
|
22
|
+
txt2detection-1.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|