tellaro-query-language 0.2.16__py3-none-any.whl → 0.2.17__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.
- {tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/METADATA +1 -1
- {tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/RECORD +7 -7
- tql/mutators/__init__.py +29 -1
- tql/mutators/encoding.py +197 -0
- {tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/WHEEL +0 -0
- {tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/entry_points.txt +0 -0
- {tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,10 +22,10 @@ tql/exceptions.py,sha256=GVssdBp9134Wyk1bWbcLQFU9U8yQKl5zzquTTrM22A0,5620
|
|
|
22
22
|
tql/field_type_inference.py,sha256=KOazjp8CK6s9vwOcFkQrdOwcazOwHqSIhYgX8hWCiDo,9700
|
|
23
23
|
tql/geoip_normalizer.py,sha256=tvie-5xevJEeLp2KmjoXDjYdND8AvyVE7lCO8qgUzGY,10486
|
|
24
24
|
tql/mutator_analyzer.py,sha256=OWx3k5lK5aFHWU9Ez6DaIhenEZDxj9CbB0vM71xqUTw,55670
|
|
25
|
-
tql/mutators/__init__.py,sha256=
|
|
25
|
+
tql/mutators/__init__.py,sha256=Y33ugaBdXoYIH2O1AqgTvaHR-DaHDXbgcEOLuB9w4Lk,7609
|
|
26
26
|
tql/mutators/base.py,sha256=4Ze_x1sTO11OILXfcF2XN7ttyHcZ4gwn96UXFMMaC6M,2523
|
|
27
27
|
tql/mutators/dns.py,sha256=F0xlDLTRlkE-4j_1QUsaXWP_AnmBsLk1KdOyuRnu6ZI,15593
|
|
28
|
-
tql/mutators/encoding.py,sha256=
|
|
28
|
+
tql/mutators/encoding.py,sha256=Ne2vCyrFax80eq_0S7m3-zhmm-iFMLAx30ZCw5A11Mo,15090
|
|
29
29
|
tql/mutators/geo.py,sha256=H-_5oDvuYaAG8Re17RkGjzCc6Z07YHd7Cr95g6JbnyE,16188
|
|
30
30
|
tql/mutators/list.py,sha256=949ZrKKhL4INkH2Od8bq7Ey80kFX_23PEfRKueG82cU,7084
|
|
31
31
|
tql/mutators/network.py,sha256=1lZpmKt1GoTfNxiXUmSXkTwJIzPQZnQEgU7ojpBSm3A,5458
|
|
@@ -52,8 +52,8 @@ tql/stats_evaluator.py,sha256=2qnjeH5Qx14qpHDS_YJn9jRPeoPUfkeiYJabBagdfRs,36126
|
|
|
52
52
|
tql/stats_transformer.py,sha256=MT-4rDWZSySgn4Fuq9H0c-mvwFYLM6FqWpPv2rHX-rE,7588
|
|
53
53
|
tql/streaming_file_processor.py,sha256=cftWhYcvUo984P3ALf2CO3FoCQPJPe_2s2HLcXTp5UQ,12437
|
|
54
54
|
tql/validators.py,sha256=e9MlX-zQ_O3M8YP8vXyMjKU8iiJMTh6mMK0iv0_4gTY,3771
|
|
55
|
-
tellaro_query_language-0.2.
|
|
56
|
-
tellaro_query_language-0.2.
|
|
57
|
-
tellaro_query_language-0.2.
|
|
58
|
-
tellaro_query_language-0.2.
|
|
59
|
-
tellaro_query_language-0.2.
|
|
55
|
+
tellaro_query_language-0.2.17.dist-info/METADATA,sha256=EUmPRjAdMbUKsTM8V7GQY1kkdjIcvQYSJzGDqGTSPl0,21892
|
|
56
|
+
tellaro_query_language-0.2.17.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
57
|
+
tellaro_query_language-0.2.17.dist-info/entry_points.txt,sha256=D0lbIGUYuDyfcYeqju1rWcMBFzft4sZtfIlw5uPNx5g,181
|
|
58
|
+
tellaro_query_language-0.2.17.dist-info/licenses/LICENSE,sha256=eWf8lkuXlVX_8WiDpUgQvzxc1cxCeVne_e6P-pVJpwM,3038
|
|
59
|
+
tellaro_query_language-0.2.17.dist-info/RECORD,,
|
tql/mutators/__init__.py
CHANGED
|
@@ -13,7 +13,15 @@ from ..cache import CacheManager, LocalCacheManager, RedisCacheManager
|
|
|
13
13
|
# Import all mutator classes
|
|
14
14
|
from .base import BaseMutator, append_to_result
|
|
15
15
|
from .dns import NSLookupMutator
|
|
16
|
-
from .encoding import
|
|
16
|
+
from .encoding import (
|
|
17
|
+
Base64DecodeMutator,
|
|
18
|
+
Base64EncodeMutator,
|
|
19
|
+
HexDecodeMutator,
|
|
20
|
+
HexEncodeMutator,
|
|
21
|
+
Md5Mutator,
|
|
22
|
+
Sha256Mutator,
|
|
23
|
+
URLDecodeMutator,
|
|
24
|
+
)
|
|
17
25
|
from .geo import GeoIPLookupMutator, GeoIPResolver
|
|
18
26
|
from .list import (
|
|
19
27
|
AllMutator,
|
|
@@ -44,6 +52,10 @@ __all__ = [
|
|
|
44
52
|
"Base64EncodeMutator",
|
|
45
53
|
"Base64DecodeMutator",
|
|
46
54
|
"URLDecodeMutator",
|
|
55
|
+
"HexEncodeMutator",
|
|
56
|
+
"HexDecodeMutator",
|
|
57
|
+
"Md5Mutator",
|
|
58
|
+
"Sha256Mutator",
|
|
47
59
|
# Security mutators
|
|
48
60
|
"RefangMutator",
|
|
49
61
|
"DefangMutator",
|
|
@@ -91,6 +103,10 @@ ALLOWED_MUTATORS: Dict[str, Optional[Dict[str, type]]] = {
|
|
|
91
103
|
"b64encode": {"field": str},
|
|
92
104
|
"b64decode": {"field": str},
|
|
93
105
|
"urldecode": {"field": str},
|
|
106
|
+
"hexencode": {"field": str},
|
|
107
|
+
"hexdecode": {"field": str},
|
|
108
|
+
"md5": {"field": str},
|
|
109
|
+
"sha256": {"field": str},
|
|
94
110
|
# List evaluation mutators
|
|
95
111
|
"any": None,
|
|
96
112
|
"all": None,
|
|
@@ -124,6 +140,10 @@ ENRICHMENT_MUTATORS = {
|
|
|
124
140
|
"b64encode",
|
|
125
141
|
"b64decode",
|
|
126
142
|
"urldecode",
|
|
143
|
+
"hexencode",
|
|
144
|
+
"hexdecode",
|
|
145
|
+
"md5",
|
|
146
|
+
"sha256",
|
|
127
147
|
}
|
|
128
148
|
|
|
129
149
|
|
|
@@ -180,6 +200,14 @@ def create_mutator(name: str, params: Optional[List[List[Any]]] = None) -> BaseM
|
|
|
180
200
|
return Base64DecodeMutator(params_dict)
|
|
181
201
|
elif key == "urldecode":
|
|
182
202
|
return URLDecodeMutator(params_dict)
|
|
203
|
+
elif key == "hexencode":
|
|
204
|
+
return HexEncodeMutator(params_dict)
|
|
205
|
+
elif key == "hexdecode":
|
|
206
|
+
return HexDecodeMutator(params_dict)
|
|
207
|
+
elif key == "md5":
|
|
208
|
+
return Md5Mutator(params_dict)
|
|
209
|
+
elif key == "sha256":
|
|
210
|
+
return Sha256Mutator(params_dict)
|
|
183
211
|
elif key == "is_private":
|
|
184
212
|
return IsPrivateMutator(params_dict)
|
|
185
213
|
elif key == "is_global":
|
tql/mutators/encoding.py
CHANGED
|
@@ -216,3 +216,200 @@ class URLDecodeMutator(BaseMutator):
|
|
|
216
216
|
else:
|
|
217
217
|
# Return the decoded value directly
|
|
218
218
|
return decoded_value
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class HexEncodeMutator(BaseMutator):
|
|
222
|
+
"""
|
|
223
|
+
Mutator that encodes string values to hexadecimal.
|
|
224
|
+
|
|
225
|
+
Converts strings to their hexadecimal representation.
|
|
226
|
+
Supports encoding individual strings or lists of strings.
|
|
227
|
+
|
|
228
|
+
Parameters:
|
|
229
|
+
field: Optional field to store the encoded value
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
def __init__(self, params: Optional[Dict[str, Any]] = None) -> None:
|
|
233
|
+
super().__init__(params)
|
|
234
|
+
self.is_enrichment = True
|
|
235
|
+
|
|
236
|
+
def apply(self, field_name: str, record: Dict[str, Any], value: Any) -> Any:
|
|
237
|
+
"""Apply the hex encode transformation."""
|
|
238
|
+
append_field = self.params.get("field")
|
|
239
|
+
|
|
240
|
+
# Handle different input types
|
|
241
|
+
encoded_value: Any
|
|
242
|
+
if value is None:
|
|
243
|
+
encoded_value = None
|
|
244
|
+
elif isinstance(value, str):
|
|
245
|
+
encoded_value = value.encode("utf-8").hex()
|
|
246
|
+
elif isinstance(value, bytes):
|
|
247
|
+
encoded_value = value.hex()
|
|
248
|
+
elif isinstance(value, list):
|
|
249
|
+
encoded_value = []
|
|
250
|
+
for item in value:
|
|
251
|
+
if isinstance(item, str):
|
|
252
|
+
encoded_value.append(item.encode("utf-8").hex())
|
|
253
|
+
elif isinstance(item, bytes):
|
|
254
|
+
encoded_value.append(item.hex())
|
|
255
|
+
elif item is None:
|
|
256
|
+
encoded_value.append(None)
|
|
257
|
+
else:
|
|
258
|
+
encoded_value.append(str(item).encode("utf-8").hex())
|
|
259
|
+
else:
|
|
260
|
+
encoded_value = str(value).encode("utf-8").hex()
|
|
261
|
+
|
|
262
|
+
# If field is specified, add to record and return original value
|
|
263
|
+
if append_field:
|
|
264
|
+
append_to_result(record, append_field, encoded_value)
|
|
265
|
+
return value
|
|
266
|
+
return encoded_value
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class HexDecodeMutator(BaseMutator):
|
|
270
|
+
"""
|
|
271
|
+
Mutator that decodes hexadecimal string values.
|
|
272
|
+
|
|
273
|
+
Converts hexadecimal strings back to their original string representation.
|
|
274
|
+
Supports decoding individual strings or lists of strings.
|
|
275
|
+
|
|
276
|
+
Parameters:
|
|
277
|
+
field: Optional field to store the decoded value
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
def __init__(self, params: Optional[Dict[str, Any]] = None) -> None:
|
|
281
|
+
super().__init__(params)
|
|
282
|
+
self.is_enrichment = True
|
|
283
|
+
|
|
284
|
+
def apply(self, field_name: str, record: Dict[str, Any], value: Any) -> Any: # noqa: C901
|
|
285
|
+
"""Apply the hex decode transformation."""
|
|
286
|
+
append_field = self.params.get("field")
|
|
287
|
+
|
|
288
|
+
def _decode_hex(s: str) -> Optional[str]:
|
|
289
|
+
"""Decode a hex string, returning None on failure."""
|
|
290
|
+
try:
|
|
291
|
+
return bytes.fromhex(s).decode("utf-8")
|
|
292
|
+
except (ValueError, UnicodeDecodeError): # noqa: B014
|
|
293
|
+
return None
|
|
294
|
+
|
|
295
|
+
# Handle different input types
|
|
296
|
+
decoded_value: Any
|
|
297
|
+
if value is None:
|
|
298
|
+
decoded_value = None
|
|
299
|
+
elif isinstance(value, str):
|
|
300
|
+
decoded_value = _decode_hex(value)
|
|
301
|
+
elif isinstance(value, list):
|
|
302
|
+
decoded_value = []
|
|
303
|
+
for item in value:
|
|
304
|
+
if isinstance(item, str):
|
|
305
|
+
decoded_value.append(_decode_hex(item))
|
|
306
|
+
else:
|
|
307
|
+
decoded_value.append(item)
|
|
308
|
+
else:
|
|
309
|
+
decoded_value = _decode_hex(str(value))
|
|
310
|
+
|
|
311
|
+
# If field is specified, add to record and return original value
|
|
312
|
+
if append_field:
|
|
313
|
+
append_to_result(record, append_field, decoded_value)
|
|
314
|
+
return value
|
|
315
|
+
return decoded_value
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class Md5Mutator(BaseMutator):
|
|
319
|
+
"""
|
|
320
|
+
Mutator that calculates MD5 hash of string values.
|
|
321
|
+
|
|
322
|
+
Computes the MD5 hash (as a hexadecimal string) of the input.
|
|
323
|
+
Supports hashing individual strings or lists of strings.
|
|
324
|
+
|
|
325
|
+
Parameters:
|
|
326
|
+
field: Optional field to store the hash value
|
|
327
|
+
"""
|
|
328
|
+
|
|
329
|
+
def __init__(self, params: Optional[Dict[str, Any]] = None) -> None:
|
|
330
|
+
super().__init__(params)
|
|
331
|
+
self.is_enrichment = True
|
|
332
|
+
|
|
333
|
+
def apply(self, field_name: str, record: Dict[str, Any], value: Any) -> Any:
|
|
334
|
+
"""Apply the MD5 hash transformation."""
|
|
335
|
+
import hashlib
|
|
336
|
+
|
|
337
|
+
append_field = self.params.get("field")
|
|
338
|
+
|
|
339
|
+
# Handle different input types
|
|
340
|
+
hashed_value: Any
|
|
341
|
+
if value is None:
|
|
342
|
+
hashed_value = None
|
|
343
|
+
elif isinstance(value, str):
|
|
344
|
+
hashed_value = hashlib.md5(value.encode("utf-8")).hexdigest()
|
|
345
|
+
elif isinstance(value, bytes):
|
|
346
|
+
hashed_value = hashlib.md5(value).hexdigest()
|
|
347
|
+
elif isinstance(value, list):
|
|
348
|
+
hashed_value = []
|
|
349
|
+
for item in value:
|
|
350
|
+
if isinstance(item, str):
|
|
351
|
+
hashed_value.append(hashlib.md5(item.encode("utf-8")).hexdigest())
|
|
352
|
+
elif isinstance(item, bytes):
|
|
353
|
+
hashed_value.append(hashlib.md5(item).hexdigest())
|
|
354
|
+
elif item is None:
|
|
355
|
+
hashed_value.append(None)
|
|
356
|
+
else:
|
|
357
|
+
hashed_value.append(hashlib.md5(str(item).encode("utf-8")).hexdigest())
|
|
358
|
+
else:
|
|
359
|
+
hashed_value = hashlib.md5(str(value).encode("utf-8")).hexdigest()
|
|
360
|
+
|
|
361
|
+
# If field is specified, add to record and return original value
|
|
362
|
+
if append_field:
|
|
363
|
+
append_to_result(record, append_field, hashed_value)
|
|
364
|
+
return value
|
|
365
|
+
return hashed_value
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class Sha256Mutator(BaseMutator):
|
|
369
|
+
"""
|
|
370
|
+
Mutator that calculates SHA256 hash of string values.
|
|
371
|
+
|
|
372
|
+
Computes the SHA256 hash (as a hexadecimal string) of the input.
|
|
373
|
+
Supports hashing individual strings or lists of strings.
|
|
374
|
+
|
|
375
|
+
Parameters:
|
|
376
|
+
field: Optional field to store the hash value
|
|
377
|
+
"""
|
|
378
|
+
|
|
379
|
+
def __init__(self, params: Optional[Dict[str, Any]] = None) -> None:
|
|
380
|
+
super().__init__(params)
|
|
381
|
+
self.is_enrichment = True
|
|
382
|
+
|
|
383
|
+
def apply(self, field_name: str, record: Dict[str, Any], value: Any) -> Any:
|
|
384
|
+
"""Apply the SHA256 hash transformation."""
|
|
385
|
+
import hashlib
|
|
386
|
+
|
|
387
|
+
append_field = self.params.get("field")
|
|
388
|
+
|
|
389
|
+
# Handle different input types
|
|
390
|
+
hashed_value: Any
|
|
391
|
+
if value is None:
|
|
392
|
+
hashed_value = None
|
|
393
|
+
elif isinstance(value, str):
|
|
394
|
+
hashed_value = hashlib.sha256(value.encode("utf-8")).hexdigest()
|
|
395
|
+
elif isinstance(value, bytes):
|
|
396
|
+
hashed_value = hashlib.sha256(value).hexdigest()
|
|
397
|
+
elif isinstance(value, list):
|
|
398
|
+
hashed_value = []
|
|
399
|
+
for item in value:
|
|
400
|
+
if isinstance(item, str):
|
|
401
|
+
hashed_value.append(hashlib.sha256(item.encode("utf-8")).hexdigest())
|
|
402
|
+
elif isinstance(item, bytes):
|
|
403
|
+
hashed_value.append(hashlib.sha256(item).hexdigest())
|
|
404
|
+
elif item is None:
|
|
405
|
+
hashed_value.append(None)
|
|
406
|
+
else:
|
|
407
|
+
hashed_value.append(hashlib.sha256(str(item).encode("utf-8")).hexdigest())
|
|
408
|
+
else:
|
|
409
|
+
hashed_value = hashlib.sha256(str(value).encode("utf-8")).hexdigest()
|
|
410
|
+
|
|
411
|
+
# If field is specified, add to record and return original value
|
|
412
|
+
if append_field:
|
|
413
|
+
append_to_result(record, append_field, hashed_value)
|
|
414
|
+
return value
|
|
415
|
+
return hashed_value
|
|
File without changes
|
{tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{tellaro_query_language-0.2.16.dist-info → tellaro_query_language-0.2.17.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|