Skip to content

Commit 7f0ecef

Browse files
authored
Merge pull request #26 from certego/update_check_value
Update check value
2 parents f70c81a + fc1d1f0 commit 7f0ecef

File tree

6 files changed

+115
-44
lines changed

6 files changed

+115
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
## 2.2.x
2+
### 2.2.9
3+
#### Bugfix
4+
* Fixed customer routing history
5+
#### Changes
6+
* Updated _check_value() method in filters
27
### 2.2.8
38
#### Bugfix
49
* Fixed a bug when an existing fields didn't match

routing_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ def test_routing_history(self):
124124
self.assertTrue("Workshop" in self.test_event_1["certego"]["routing_history"])
125125
self.assertTrue("TyreFit" in self.test_event_1["certego"]["routing_history"])
126126

127+
def test_routing_history_no_customer(self):
128+
self.routing.load_from_dicts([load_test_data("test_rule_24_routing_history"), load_test_data("test_customer_1")])
129+
self.routing.match(self.test_event_1)
130+
self.routing.match(self.test_event_1, type_="customers")
131+
self.assertTrue(self.test_event_1["certego"]["routing_history"]["Workshop"])
132+
self.assertNotIn("customer", self.test_event_1["certego"]["routing_history"])
133+
127134
def test_routing_history_stream_none(self):
128135
self.routing.load_from_dicts([load_test_data("test_rule_1_equals")])
129136
self.routing.match(self.test_event_1)

routingfilter/filters/filters.py

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
import re
33
from abc import ABC, abstractmethod
4-
from typing import Optional
4+
from typing import NoReturn, Optional
55

66
import macaddress
77
from IPy import IP
@@ -19,21 +19,25 @@ def __init__(self, key, value, **kwargs):
1919
def match(self, event: DictQuery) -> bool:
2020
return NotImplemented
2121

22-
def _check_value(self) -> Optional[Exception]:
22+
@abstractmethod
23+
def _check_value(self) -> Exception | NoReturn:
2324
"""
24-
Check if values in self._value are correct and raise an exception if they are incorrect.
25+
Check if values in self._value are correct and raise an exception if they are incorrect. If necessary, it converts value in lower case.
2526
2627
:return: no value or raise an exception
27-
:rtype: Optional[Exception]
28+
:rtype: NoReturn | Exception
2829
"""
29-
return None
30+
return NotImplemented
3031

3132

3233
class AllFilter(AbstractFilter):
3334
def __init__(self):
3435
key = value = []
3536
super().__init__(key, value)
3637

38+
def _check_value(self) -> Exception | NoReturn:
39+
return
40+
3741
def match(self, event: DictQuery) -> bool:
3842
"""
3943
Return always true.
@@ -51,6 +55,9 @@ def __init__(self, key):
5155
value = []
5256
super().__init__(key, value)
5357

58+
def _check_value(self) -> Exception | NoReturn:
59+
return
60+
5461
def match(self, event: DictQuery) -> bool:
5562
"""
5663
Return True if one of the key exists in the event.
@@ -83,6 +90,13 @@ class EqualFilter(AbstractFilter):
8390
def __init__(self, key, value):
8491
super().__init__(key, value)
8592

93+
def _check_value(self) -> Exception | NoReturn:
94+
tmp = []
95+
for value in self._value:
96+
value = value.lower() if isinstance(value, str) else str(value)
97+
tmp.append(value)
98+
self._value = tmp
99+
86100
def match(self, event: DictQuery):
87101
"""
88102
Check if at least a key matches at least one value.
@@ -92,16 +106,12 @@ def match(self, event: DictQuery):
92106
:return: true if event matches, false otherwise
93107
:rtype: bool
94108
"""
95-
filter_value = []
96-
for value in self._value:
97-
value = value.lower() if isinstance(value, str) else str(value)
98-
filter_value.append(value)
99109
for key in self._key:
100110
event_value = event.get(key, [])
101111
event_value = event_value if isinstance(event_value, list) else [event_value]
102112
for value in event_value:
103113
value = value.lower() if isinstance(value, str) else str(value)
104-
if value in filter_value:
114+
if value in self._value:
105115
return True
106116
return False
107117

@@ -120,6 +130,13 @@ def match(self, event: DictQuery) -> bool:
120130

121131

122132
class StartswithFilter(AbstractFilter):
133+
def _check_value(self) -> Exception | NoReturn:
134+
tmp = []
135+
for prefix in self._value:
136+
prefix = str(prefix).lower()
137+
tmp.append(prefix)
138+
self._value = tmp
139+
123140
def match(self, event: DictQuery) -> bool:
124141
"""
125142
Return True if at least one event value corresponding to a key starts with one of the value.
@@ -148,13 +165,19 @@ def _check_startswith(self, value: str) -> bool:
148165
"""
149166
value = value.lower()
150167
for prefix in self._value:
151-
prefix = str(prefix).lower()
152168
if value.startswith(prefix):
153169
return True
154170
return False
155171

156172

157173
class EndswithFilter(AbstractFilter):
174+
def _check_value(self) -> Exception | NoReturn:
175+
tmp = []
176+
for suffix in self._value:
177+
suffix = str(suffix).lower()
178+
tmp.append(suffix)
179+
self._value = tmp
180+
158181
def match(self, event: DictQuery) -> bool:
159182
"""
160183
Return True if at least one event value corresponding to a key ends with one of the value.
@@ -172,7 +195,7 @@ def match(self, event: DictQuery) -> bool:
172195
return True
173196
return False
174197

175-
def _check_endswith(self, value):
198+
def _check_endswith(self, value: str) -> bool:
176199
"""
177200
Check if the value end with one of the suffix given.
178201
@@ -183,13 +206,19 @@ def _check_endswith(self, value):
183206
"""
184207
value = value.lower()
185208
for suffix in self._value:
186-
suffix = str(suffix).lower()
187-
if str(value).endswith(suffix):
209+
if value.endswith(suffix):
188210
return True
189211
return False
190212

191213

192214
class KeywordFilter(AbstractFilter):
215+
def _check_value(self) -> Exception | NoReturn:
216+
tmp = []
217+
for keyword in self._value:
218+
keyword = str(keyword).lower()
219+
tmp.append(keyword)
220+
self._value = tmp
221+
193222
def match(self, event: DictQuery) -> bool:
194223
"""
195224
Return True if at least one value is present in the event value of corresponding key.
@@ -216,29 +245,28 @@ def _check_keyword(self, value: str) -> bool:
216245
:return: true or false
217246
:rtype: bool
218247
"""
219-
value = value.lower()
220248
for keyword in self._value:
221-
keyword = str(keyword).lower()
222-
if keyword in value:
249+
if keyword in value.lower():
223250
return True
224251
return False
225252

226253

227254
class RegexpFilter(AbstractFilter):
228-
def _check_value(self) -> Optional[Exception]:
255+
def _check_value(self) -> Exception | NoReturn:
229256
"""
230257
Check if values in self._value are valid regexes.
231258
232259
:return: none or error generated:
233260
:rtype: Optional[Exception]
234261
"""
262+
tmp = []
235263
for value in self._value:
236264
try:
237-
re.compile(value)
265+
tmp.append(re.compile(value))
238266
except re.error as e:
239267
self.logger.error(f"Invalid regex {value}, during check of value list {self._value}. Error message: {e}")
240268
raise ValueError(f"Regex check failed: error for value {value}. Error message: {e}")
241-
return None
269+
self._value = tmp
242270

243271
def match(self, event: DictQuery) -> bool:
244272
"""
@@ -267,7 +295,7 @@ def _check_regex(self, value: str) -> bool:
267295
:rtype: bool
268296
"""
269297
for regex in self._value:
270-
if re.search(regex, value):
298+
if regex.search(value):
271299
return True
272300
return False
273301

@@ -276,13 +304,14 @@ class NetworkFilter(AbstractFilter):
276304
def __init__(self, key, value):
277305
super().__init__(key, value)
278306

279-
def _check_value(self) -> Optional[Exception]:
307+
def _check_value(self) -> Exception | NoReturn:
280308
"""
281309
Check if the values in self._value are valid IP addresses.
282310
283311
:return: none or error generated
284312
:rtype: Optional[Exception]
285313
"""
314+
tmp = []
286315
for value in self._value:
287316
try:
288317
value = IP(value)
@@ -292,7 +321,8 @@ def _check_value(self) -> Optional[Exception]:
292321
except TypeError as e:
293322
self.logger.error(f"IP address (type error) error, during check of value {value} in list {self._value}. Error was: {e}.")
294323
raise ValueError(f"IP address check failed: type error for value {value}.")
295-
return None
324+
tmp.append(value)
325+
self._value = tmp
296326

297327
def match(self, event: DictQuery) -> bool:
298328
"""
@@ -323,7 +353,7 @@ def _check_network(self, ip_address: str) -> bool:
323353
try:
324354
ip_address = IP(ip_address)
325355
for value in self._value:
326-
if ip_address in IP(value):
356+
if ip_address in value:
327357
return True
328358
except ValueError as e:
329359
self.logger.debug(f"Error in parsing IP address (value error): {e}. ")
@@ -349,17 +379,20 @@ class DomainFilter(AbstractFilter):
349379
def __init__(self, key, value):
350380
super().__init__(key, value)
351381

352-
def _check_value(self) -> Optional[Exception]:
382+
def _check_value(self) -> Exception | NoReturn:
353383
"""
354384
Check if values in self._value are string.
355385
356386
:return: none or error generated
357387
:rtype: bool
358388
"""
359-
for value in self._value:
360-
if not isinstance(value, str):
361-
raise ValueError(f"Domain check failed: value {value} is not a string.")
362-
return None
389+
tmp = []
390+
for domain in self._value:
391+
if not isinstance(domain, str):
392+
raise ValueError(f"Domain check failed: value {domain} is not a string.")
393+
domain = str(domain).lower()
394+
tmp.append(domain)
395+
self._value = tmp
363396

364397
def match(self, event: DictQuery) -> bool:
365398
"""
@@ -388,8 +421,7 @@ def _check_domain(self, value: str) -> bool:
388421
"""
389422
value = value.lower()
390423
for domain in self._value:
391-
domain = str(domain).lower()
392-
if value == domain or str(value).endswith(f".{domain}"):
424+
if value == domain or value.endswith(f".{domain}"):
393425
return True
394426
return False
395427

@@ -400,32 +432,32 @@ def __init__(self, key, value, comparator_type):
400432
self._check_comparator_type()
401433
super().__init__(key, value)
402434

403-
def _check_value(self) -> Optional[Exception]:
435+
def _check_value(self) -> Exception | NoReturn:
404436
"""
405437
Check if values in self._value are float.
406438
407439
:return: none or error generated
408-
:rtype: Optional[Exception]
440+
:rtype: Exception | NoReturn
409441
"""
442+
tmp = []
410443
for value in self._value:
411444
try:
412-
float(value)
445+
tmp.append(float(value))
413446
except ValueError:
414447
self.logger.error(f"Comparator check failed: value {value} of list {self._value} is not a float")
415448
raise ValueError(f"Comparator check failed: value {value} is not a float")
416-
return None
449+
self._value = tmp
417450

418-
def _check_comparator_type(self) -> Optional[Exception]:
451+
def _check_comparator_type(self) -> Exception | NoReturn:
419452
"""
420453
Check if comparator is valid.
421454
422455
:return: none or error generated
423-
:rtype: Optional[Exception]
456+
:rtype: Exception | NoReturn
424457
"""
425458
if self._comparator_type not in ["GREATER", "LESS", "GREATER_EQ", "LESS_EQ"]:
426459
self.logger.error(f"Comparator check failed: value {self._comparator_type} is not valid.")
427460
raise ValueError(f"Comparator type check failed. {self._comparator_type} is not a valid comparator.")
428-
return None
429461

430462
def match(self, event: DictQuery) -> bool:
431463
"""
@@ -455,7 +487,6 @@ def _compare(self, value: float) -> bool:
455487
"""
456488
for term in self._value:
457489
try:
458-
term = float(term)
459490
value = float(value)
460491
except ValueError as e:
461492
self.logger.debug(f"Error in parsing value to float in comparator filter: {e}. ")
@@ -480,19 +511,22 @@ class TypeofFilter(AbstractFilter):
480511
def __init__(self, key, value):
481512
super().__init__(key, value)
482513

483-
def _check_value(self) -> Optional[Exception]:
514+
def _check_value(self) -> Exception | NoReturn:
484515
"""
485516
Check if value is a correct type.
486517
487518
:return: no value or raised an exception
488-
:rtype: Optional[Exception]
519+
:rtype: NoReturn | Exception
489520
"""
490521
valid_type = ["str", "int", "float", "bool", "list", "dict", "ip", "mac"]
522+
tmp = []
491523
for value in self._value:
524+
value = str(value).lower()
492525
if value not in valid_type:
493526
self.logger.error(f"Type check failed: value {value} of list {self._value} is invalid.")
494527
raise ValueError(f"Type check failed: value {value} is invalid.")
495-
return None
528+
tmp.append(value)
529+
self._value = tmp
496530

497531
def match(self, event: DictQuery) -> bool:
498532
"""

routingfilter/filters/rule.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ def match(self, event: DictQuery) -> Results | None:
4848
if key in routing_history:
4949
output_copy.pop(key)
5050
else:
51-
routing_history.update({key: now})
51+
if key != "customer":
52+
routing_history.update({key: now})
5253
results = Results(rules=self.uid, output=output_copy)
5354
return results
5455

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="routingfilter",
8-
version="2.2.8",
8+
version="2.2.9",
99
packages=find_packages(include=["routingfilter", "routingfilter.*"]),
1010
include_package_data=True,
1111
install_requires=["IPy~=1.1", "macaddress~=2.0.2"],

0 commit comments

Comments
 (0)