Skip to content

Commit d87ec76

Browse files
committed
gis-8825 added sentinel one power query render
1 parent 9231d12 commit d87ec76

File tree

6 files changed

+179
-1
lines changed

6 files changed

+179
-1
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
from app.translator.platforms.sentinel_one.renders.s1_cti import S1EventsCTI # noqa: F401
2+
from app.translator.platforms.sentinel_one.renders.sentinel_one_power_query import (
3+
SentinelOnePowerQueryRender, # noqa: F401
4+
)

uncoder-core/app/translator/platforms/sentinel_one/const.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from app.translator.core.models.platform_details import PlatformDetails
22

3-
43
PLATFORM_DETAILS = {"group_id": "sentinel-one", "group_name": "SentinelOne"}
54

65
SENTINEL_ONE_EVENTS_QUERY_DETAILS = {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from typing import ClassVar
2+
3+
from app.translator.core.custom_types.values import ValueType
4+
from app.translator.core.escape_manager import EscapeManager
5+
from app.translator.core.models.escape_details import EscapeDetails
6+
7+
8+
class SentinelOnePowerQueryEscapeManager(EscapeManager):
9+
escape_map: ClassVar[dict[str, list[EscapeDetails]]] = {
10+
ValueType.value: [EscapeDetails(pattern=r"\\", escape_symbols=r"\\\\")],
11+
ValueType.regex_value: [EscapeDetails(pattern=r"\\", escape_symbols=r"\\\\")],
12+
}
13+
14+
15+
sentinel_one_power_query_escape_manager = SentinelOnePowerQueryEscapeManager()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from app.translator.core.mapping import BasePlatformMappings, LogSourceSignature
2+
from app.translator.platforms.sentinel_one.const import sentinel_one_power_query_details
3+
4+
5+
class SentinelOnePowerQueryLogSourceSignature(LogSourceSignature):
6+
def is_suitable(self) -> bool:
7+
return True
8+
9+
def __str__(self) -> str:
10+
return ""
11+
12+
13+
class SentinelOnePowerQueryMappings(BasePlatformMappings):
14+
def prepare_log_source_signature(self, mapping: dict) -> SentinelOnePowerQueryLogSourceSignature:
15+
...
16+
17+
18+
sentinel_one_power_query_query_mappings = SentinelOnePowerQueryMappings(
19+
platform_dir="sentinel_one", platform_details=sentinel_one_power_query_details
20+
)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from typing import Union, Optional
2+
3+
from app.translator.const import DEFAULT_VALUE_TYPE
4+
from app.translator.core.custom_types.values import ValueType
5+
from app.translator.core.mapping import LogSourceSignature
6+
from app.translator.core.models.platform_details import PlatformDetails
7+
from app.translator.core.render import BaseFieldValueRender, PlatformQueryRender
8+
from app.translator.core.str_value_manager import StrValueManager
9+
from app.translator.managers import render_manager
10+
from app.translator.platforms.sentinel_one.const import sentinel_one_power_query_details
11+
from app.translator.platforms.sentinel_one.mapping import (
12+
SentinelOnePowerQueryMappings,
13+
sentinel_one_power_query_query_mappings,
14+
)
15+
from app.translator.platforms.sentinel_one.str_value_manager import sentinel_one_power_query_str_value_manager
16+
17+
18+
class SentinelOnePowerQueryFieldValue(BaseFieldValueRender):
19+
details: PlatformDetails = sentinel_one_power_query_details
20+
str_value_manager: StrValueManager = sentinel_one_power_query_str_value_manager
21+
list_token = ", "
22+
23+
@staticmethod
24+
def _wrap_str_value(value: str) -> str:
25+
return f'"{value}"'
26+
27+
def equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
28+
if isinstance(value, list):
29+
values = self.list_token.join(
30+
self._pre_process_value(field, v, value_type=ValueType.value, wrap_str=True) for v in value
31+
)
32+
return f"{field} in ({values})"
33+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True)
34+
return f"{field} = {value}"
35+
36+
def less_modifier(self, field: str, value: Union[int, str]) -> str:
37+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True, wrap_int=True)
38+
return f"{field} < {value}"
39+
40+
def less_or_equal_modifier(self, field: str, value: Union[int, str]) -> str:
41+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True, wrap_int=True)
42+
return f"{field} <= {value}"
43+
44+
def greater_modifier(self, field: str, value: Union[int, str]) -> str:
45+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True, wrap_int=True)
46+
return f"{field} > {value}"
47+
48+
def greater_or_equal_modifier(self, field: str, value: Union[int, str]) -> str:
49+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True, wrap_int=True)
50+
return f"{field} >= {value}"
51+
52+
def not_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
53+
if isinstance(value, list):
54+
values = self.list_token.join(
55+
self._pre_process_value(field, v, value_type=ValueType.value, wrap_str=True, wrap_int=True)
56+
for v in value
57+
)
58+
return f"{field} != ({values})"
59+
value = self._pre_process_value(field, value, value_type=ValueType.value, wrap_str=True, wrap_int=True)
60+
return f"{field} != {value}"
61+
62+
def contains_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
63+
if isinstance(value, list):
64+
values = self.list_token.join(
65+
self._pre_process_value(field, v, value_type=ValueType.value, wrap_str=True, wrap_int=True)
66+
for v in value
67+
)
68+
return f"{field} contains ({values})"
69+
value = self._pre_process_value(field, value, value_type=ValueType.value)
70+
return f"{field} contains {value}"
71+
72+
def endswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
73+
return self.contains_modifier(field, value)
74+
75+
def startswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
76+
return self.contains_modifier(field, value)
77+
78+
def regex_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
79+
if isinstance(value, list):
80+
values = self.list_token.join(
81+
self.str_value_manager.escape_manager.escape(
82+
self._pre_process_value(field, v, value_type=ValueType.regex_value, wrap_str=True, wrap_int=True),
83+
ValueType.regex_value,
84+
)
85+
for v in value
86+
)
87+
return f"{field} matches ({values})"
88+
value = self._pre_process_value(field, value, value_type=ValueType.regex_value, wrap_str=True, wrap_int=True)
89+
value = self.str_value_manager.escape_manager.escape(value, ValueType.regex_value)
90+
return f"{field} matches {value}"
91+
92+
def is_none(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: # noqa: ARG002
93+
return f'not ({field} matches "\\.*")'
94+
95+
def is_not_none(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: # noqa: ARG002
96+
return f'{field} matches "\\.*"'
97+
98+
99+
@render_manager.register
100+
class SentinelOnePowerQueryRender(PlatformQueryRender):
101+
details: PlatformDetails = sentinel_one_power_query_details
102+
mappings: SentinelOnePowerQueryMappings = sentinel_one_power_query_query_mappings
103+
or_token = "or"
104+
and_token = "and"
105+
not_token = "not"
106+
comment_symbol = "//"
107+
field_value_render = SentinelOnePowerQueryFieldValue(or_token=or_token)
108+
109+
def generate_prefix(self, log_source_signature: Optional[LogSourceSignature], functions_prefix: str = "") -> str:
110+
return "| columns "
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Uncoder IO Community Edition License
3+
-----------------------------------------------------------------
4+
Copyright (c) 2024 SOC Prime, Inc.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
-----------------------------------------------------------------
18+
"""
19+
20+
from app.translator.core.str_value_manager import StrValueManager
21+
from app.translator.platforms.sentinel_one.escape_manager import (
22+
SentinelOnePowerQueryEscapeManager,
23+
sentinel_one_power_query_escape_manager,
24+
)
25+
26+
27+
class SentinelOnePowerQueryStrValueManager(StrValueManager):
28+
escape_manager: SentinelOnePowerQueryEscapeManager = sentinel_one_power_query_escape_manager
29+
30+
31+
sentinel_one_power_query_str_value_manager = SentinelOnePowerQueryStrValueManager()

0 commit comments

Comments
 (0)