Skip to content

Commit 5fd269c

Browse files
committed
predefined field class
1 parent c1dddc7 commit 5fd269c

File tree

8 files changed

+75
-23
lines changed

8 files changed

+75
-23
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from app.translator.tools.custom_enum import CustomEnum
2+
3+
4+
class IPLocationType(CustomEnum):
5+
asn = "ip_loc_asn"
6+
asn_org = "ip_loc_asn_org"
7+
city = "ip_loc_city"
8+
continent = "ip_loc_continent"
9+
country = "ip_loc_country"
10+
lat_lon = "ip_loc_lat_lon"
11+
region = "ip_loc_region"
12+
timezone = "ip_loc_timezone"

uncoder-core/app/translator/core/models/field.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def set_generic_names_map(self, source_mappings: list[SourceMapping], default_ma
3737
self.__generic_names_map = generic_names_map
3838

3939

40+
class PredefinedField:
41+
def __init__(self, name: str):
42+
self.name = name
43+
44+
4045
class FieldField:
4146
def __init__(
4247
self,
@@ -46,10 +51,10 @@ def __init__(
4651
is_alias_left: bool = False,
4752
is_alias_right: bool = False,
4853
):
49-
self.field_left = Field(source_name=source_name_left)
54+
self.field_left = Field(source_name=source_name_left) if not is_alias_left else None
5055
self.alias_left = Alias(name=source_name_left) if is_alias_left else None
5156
self.operator = operator
52-
self.field_right = Field(source_name=source_name_right)
57+
self.field_right = Field(source_name=source_name_right) if not is_alias_right else None
5358
self.alias_right = Alias(name=source_name_right) if is_alias_right else None
5459

5560

@@ -60,11 +65,14 @@ def __init__(
6065
operator: Identifier,
6166
value: Union[int, str, StrValue, list, tuple],
6267
is_alias: bool = False,
68+
is_predefined_field: bool = False,
6369
):
64-
self.field = Field(source_name=source_name)
65-
self.alias = None
66-
if is_alias:
67-
self.alias = Alias(name=source_name)
70+
# mapped by platform fields mapping
71+
self.field = Field(source_name=source_name) if not (is_alias or is_predefined_field) else None
72+
# not mapped
73+
self.alias = Alias(name=source_name) if is_alias else None
74+
# mapped by platform predefined fields mapping
75+
self.predefined_field = PredefinedField(name=source_name) if is_predefined_field else None
6876

6977
self.operator = operator
7078
self.values = []
@@ -96,10 +104,13 @@ def __add_value(self, value: Optional[Union[int, str, StrValue, list, tuple]]) -
96104
self.values.append(value)
97105

98106
def __repr__(self):
99-
if self.field:
100-
return f"{self.field.source_name} {self.operator.token_type} {self.values}"
107+
if self.alias:
108+
return f"{self.alias.name} {self.operator.token_type} {self.values}"
109+
110+
if self.predefined_field:
111+
return f"{self.predefined_field.name} {self.operator.token_type} {self.values}"
101112

102-
return f"{self.alias.name} {self.operator.token_type} {self.values}"
113+
return f"{self.field.source_name} {self.operator.token_type} {self.values}"
103114

104115

105116
class Keyword:

uncoder-core/app/translator/core/render.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from app.translator.core.exceptions.parser import UnsupportedOperatorException
3232
from app.translator.core.functions import PlatformFunctions
3333
from app.translator.core.mapping import DEFAULT_MAPPING_NAME, BasePlatformMappings, LogSourceSignature, SourceMapping
34-
from app.translator.core.models.field import Field, FieldField, FieldValue, Keyword
34+
from app.translator.core.models.field import Field, FieldField, FieldValue, Keyword, PredefinedField
3535
from app.translator.core.models.functions.base import Function, RenderedFunctions
3636
from app.translator.core.models.identifier import Identifier
3737
from app.translator.core.models.platform_details import PlatformDetails
@@ -218,7 +218,8 @@ class PlatformQueryRender(QueryRender):
218218
field_field_render = BaseFieldFieldRender()
219219
field_value_render = BaseFieldValueRender(or_token=or_token)
220220

221-
raw_log_field_pattern_map: ClassVar[dict[str, str]] = None
221+
predefined_fields_map: ClassVar[dict[str, str]] = {}
222+
raw_log_field_patterns_map: ClassVar[dict[str, str]] = {}
222223

223224
def __init__(self):
224225
super().__init__()
@@ -248,9 +249,23 @@ def map_field(self, field: Field, source_mapping: SourceMapping) -> list[str]:
248249

249250
return mapped_field if mapped_field else [generic_field_name] if generic_field_name else [field.source_name]
250251

252+
def map_predefined_field(self, predefined_field: PredefinedField) -> str:
253+
if not (mapped_predefined_field_name := self.predefined_fields_map.get(predefined_field.name)):
254+
if self.is_strict_mapping:
255+
raise StrictPlatformException(field_name=predefined_field.name, platform_name=self.details.name)
256+
257+
return predefined_field.name
258+
259+
return mapped_predefined_field_name
260+
251261
def apply_token(self, token: Union[FieldValue, Keyword, Identifier], source_mapping: SourceMapping) -> str:
252262
if isinstance(token, FieldValue):
253-
mapped_fields = [token.alias.name] if token.alias else self.map_field(token.field, source_mapping)
263+
if token.alias:
264+
mapped_fields = [token.alias.name]
265+
elif token.predefined_field:
266+
mapped_fields = [self.map_predefined_field(token.predefined_field)]
267+
else:
268+
mapped_fields = self.map_field(token.field, source_mapping)
254269
joined = self.logical_operators_map[LogicalOperatorType.OR].join(
255270
[
256271
self.field_value_render.apply_field_value(field=field, operator=token.operator, value=token.value)
@@ -365,7 +380,7 @@ def generate_from_raw_query_container(self, query_container: RawQueryContainer)
365380
)
366381

367382
def process_raw_log_field(self, field: str, field_type: str) -> Optional[str]:
368-
if raw_log_field_pattern := self.raw_log_field_pattern_map.get(field_type):
383+
if raw_log_field_pattern := self.raw_log_field_patterns_map.get(field_type):
369384
return raw_log_field_pattern.format(field=field)
370385

371386
def process_raw_log_field_prefix(self, field: str, source_mapping: SourceMapping) -> Optional[list]:
@@ -379,7 +394,7 @@ def process_raw_log_field_prefix(self, field: str, source_mapping: SourceMapping
379394
return [self.process_raw_log_field(field=field, field_type=raw_log_field_type)]
380395

381396
def generate_raw_log_fields(self, fields: list[Field], source_mapping: SourceMapping) -> str:
382-
if self.raw_log_field_pattern_map is None:
397+
if not self.raw_log_field_patterns_map:
383398
return ""
384399
defined_raw_log_fields = []
385400
for field in fields:

uncoder-core/app/translator/core/tokenizer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,12 @@ def get_field_tokens_from_func_args( # noqa: PLR0912
332332
if isinstance(arg, Field):
333333
result.append(arg)
334334
elif isinstance(arg, FieldField):
335-
if not arg.alias_left or arg.alias_left.name != arg.field_left.source_name:
335+
if arg.field_left:
336336
result.append(arg.field_left)
337-
if not arg.alias_right or arg.alias_right.name != arg.field_right.source_name:
337+
if arg.field_right:
338338
result.append(arg.field_right)
339339
elif isinstance(arg, FieldValue):
340-
if not arg.alias or arg.alias.name != arg.field.source_name:
340+
if arg.field:
341341
result.append(arg.field)
342342
elif isinstance(arg, GroupByFunction):
343343
result.extend(self.get_field_tokens_from_func_args(args=arg.args))

uncoder-core/app/translator/platforms/logrhythm_axon/renders/logrhythm_axon_query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def generate_prefix(self, log_source_signature: LogSourceSignature, functions_pr
219219
return str(log_source_signature)
220220

221221
def apply_token(self, token: Union[FieldValue, Keyword, Identifier], source_mapping: SourceMapping) -> str:
222-
if isinstance(token, FieldValue):
222+
if isinstance(token, FieldValue) and token.field:
223223
try:
224224
mapped_fields = self.map_field(token.field, source_mapping)
225225
except StrictPlatformException:

uncoder-core/app/translator/platforms/opensearch/renders/opensearch_rule.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def finalize_query(
7979
return self.wrap_with_not_supported_functions(rule_str, not_supported_functions)
8080

8181
def apply_token(self, token: Union[FieldValue, Keyword, Identifier], source_mapping: SourceMapping) -> str:
82-
if isinstance(token, FieldValue):
82+
if isinstance(token, FieldValue) and token.field:
8383
for field in self.map_field(token.field, source_mapping):
8484
self.fields.update({field: f"{{ctx.results.0.hits.hits.0._source.{field}}}"})
8585
return super().apply_token(token, source_mapping)

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from app.translator.core.custom_types.predefined_fields import IPLocationType
12
from app.translator.core.models.platform_details import PlatformDetails
23

34
PLATFORM_DETAILS = {"group_id": "cortex", "group_name": "Palo Alto Cortex XSIAM"}
@@ -10,3 +11,15 @@
1011
}
1112

1213
cortex_xql_query_details = PlatformDetails(**CORTEX_XSIAM_XQL_QUERY_DETAILS)
14+
15+
16+
PREDEFINED_FIELDS_MAP = {
17+
IPLocationType.asn: "loc_asn",
18+
IPLocationType.asn_org: "loc_asn_org",
19+
IPLocationType.city: "loc_city",
20+
IPLocationType.continent: "loc_continent",
21+
IPLocationType.country: "loc_country",
22+
IPLocationType.lat_lon: "loc_latlon",
23+
IPLocationType.region: "loc_region",
24+
IPLocationType.timezone: "loc_timezone",
25+
}

uncoder-core/app/translator/platforms/palo_alto/renders/cortex_xsiam.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from app.translator.core.render import BaseFieldFieldRender, BaseFieldValueRender, PlatformQueryRender
3131
from app.translator.core.str_value_manager import StrValue
3232
from app.translator.managers import render_manager
33-
from app.translator.platforms.palo_alto.const import cortex_xql_query_details
33+
from app.translator.platforms.palo_alto.const import PREDEFINED_FIELDS_MAP, cortex_xql_query_details
3434
from app.translator.platforms.palo_alto.functions import CortexXQLFunctions, cortex_xql_functions
3535
from app.translator.platforms.palo_alto.mapping import (
3636
CortexXQLLogSourceSignature,
@@ -167,7 +167,8 @@ class CortexXQLQueryRender(PlatformQueryRender):
167167
details: PlatformDetails = cortex_xql_query_details
168168
mappings: CortexXQLMappings = cortex_xql_mappings
169169
is_strict_mapping = True
170-
raw_log_field_pattern_map: ClassVar[dict[str, str]] = {
170+
predefined_fields_map = PREDEFINED_FIELDS_MAP
171+
raw_log_field_patterns_map: ClassVar[dict[str, str]] = {
171172
"regex": '| alter {field} = regextract(to_json_string(action_evtlog_data_fields)->{field}{{}}, "\\"(.*)\\"")',
172173
"object": '| alter {field_name} = json_extract_scalar({field_object} , "$.{field_path}")',
173174
"list": '| alter {field_name} = arraystring(json_extract_array({field_object} , "$.{field_path}")," ")',
@@ -189,7 +190,7 @@ def init_platform_functions(self) -> None:
189190
self.platform_functions.platform_query_render = self
190191

191192
def process_raw_log_field(self, field: str, field_type: str) -> Optional[str]:
192-
raw_log_field_pattern = self.raw_log_field_pattern_map.get(field_type)
193+
raw_log_field_pattern = self.raw_log_field_patterns_map.get(field_type)
193194
if raw_log_field_pattern is None:
194195
return
195196
if field_type == "regex":
@@ -206,7 +207,7 @@ def generate_prefix(self, log_source_signature: CortexXQLLogSourceSignature, fun
206207
return f"{functions_prefix}{log_source_str}"
207208

208209
def apply_token(self, token: Union[FieldValue, Keyword, Identifier], source_mapping: SourceMapping) -> str:
209-
if isinstance(token, FieldValue):
210+
if isinstance(token, FieldValue) and token.field:
210211
field_name = token.field.source_name
211212
if values_map := SOURCE_MAPPING_TO_FIELD_VALUE_MAP.get(source_mapping.source_id, {}).get(field_name):
212213
values_to_update = []

0 commit comments

Comments
 (0)