Skip to content

Commit a749460

Browse files
authored
Merge pull request #220 from UncoderIO/gis-9071
GIS 9071 Added new platform Falco
2 parents 4c4f244 + cca40d9 commit a749460

File tree

9 files changed

+249
-0
lines changed

9 files changed

+249
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
platform: Falco
2+
source: aws_cloudtrail
3+
4+
field_mapping:
5+
eventSource: ct.src
6+
eventName: ct.name
7+
errorCode: ct.error
8+
RequestParameters: json.value[/requestParameters]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
platform: Falco
2+
source: default
3+
4+
5+
field_mapping:
6+
{}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from app.translator.platforms.falco.renders.falco import FalcoRuleRender # noqa: F401
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from app.translator.core.models.platform_details import PlatformDetails
2+
3+
FALCO_RULE_DETAILS = {
4+
"platform_id": "falco-yaml-rule",
5+
"name": "Falco YAML Rule",
6+
"platform_name": "Rule (YAML)",
7+
"group_id": "falco",
8+
"group_name": "Falco",
9+
}
10+
11+
falco_rule_details = PlatformDetails(**FALCO_RULE_DETAILS)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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 FalcoRuleEscapeManager(EscapeManager):
9+
escape_map: ClassVar[dict[str, list[EscapeDetails]]] = {
10+
ValueType.regex_value: [
11+
EscapeDetails(pattern=r"([$^*+()\[\]{}|.?\-\\])", escape_symbols=r"\\\1"),
12+
EscapeDetails(pattern=r"(')", escape_symbols=r"'\1"),
13+
]
14+
}
15+
16+
17+
falco_rule_escape_manager = FalcoRuleEscapeManager()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from app.translator.core.mapping import BaseStrictLogSourcesPlatformMappings, LogSourceSignature
2+
from app.translator.platforms.falco.const import falco_rule_details
3+
4+
5+
class FalcoRuleLogSourceSignature(LogSourceSignature):
6+
def __str__(self) -> str:
7+
return ""
8+
9+
def is_suitable(self) -> bool:
10+
return True
11+
12+
13+
class FalcoRuleMappings(BaseStrictLogSourcesPlatformMappings):
14+
def prepare_log_source_signature(self, mapping: dict) -> FalcoRuleLogSourceSignature: # noqa: ARG002
15+
return FalcoRuleLogSourceSignature()
16+
17+
18+
falco_rule_mappings = FalcoRuleMappings(platform_dir="falco", platform_details=falco_rule_details)

uncoder-core/app/translator/platforms/falco/renders/__init__.py

Whitespace-only changes.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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+
from typing import ClassVar, Optional
20+
21+
import yaml
22+
23+
from app.translator.const import DEFAULT_VALUE_TYPE
24+
from app.translator.core.custom_types.values import ValueType
25+
from app.translator.core.mapping import LogSourceSignature, SourceMapping
26+
from app.translator.core.models.platform_details import PlatformDetails
27+
from app.translator.core.models.query_container import MetaInfoContainer
28+
from app.translator.core.models.query_tokens.field import Field
29+
from app.translator.core.render import BaseFieldValueRender, PlatformQueryRender
30+
from app.translator.core.str_value_manager import StrValueManager
31+
from app.translator.managers import render_manager
32+
from app.translator.platforms.falco.const import falco_rule_details
33+
from app.translator.platforms.falco.mapping import FalcoRuleMappings, falco_rule_mappings
34+
from app.translator.platforms.falco.str_value_manager import falco_rule_str_value_manager
35+
36+
37+
class FalcoRuleFieldValueRender(BaseFieldValueRender):
38+
details = falco_rule_details
39+
str_value_manager: StrValueManager = falco_rule_str_value_manager
40+
41+
@staticmethod
42+
def _wrap_str_value(value: str) -> str:
43+
return f'"{value}"'
44+
45+
@staticmethod
46+
def _wrap_int_value(value: str) -> str:
47+
return f'"{value}"'
48+
49+
def equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
50+
if isinstance(value, list):
51+
return f"({self.or_token.join([self.equal_modifier(field=field, value=v) for v in value])})"
52+
return f"{field} = {self._pre_process_value(field, value, wrap_str=True)}"
53+
54+
def not_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
55+
if isinstance(value, list):
56+
return f"({self.or_token.join([self.not_equal_modifier(field=field, value=v) for v in value])})"
57+
return f"{field} != {self._pre_process_value(field, value, wrap_str=True)}"
58+
59+
def less_modifier(self, field: str, value: int) -> str:
60+
return f"{field} < {self._pre_process_value(field, value)}"
61+
62+
def less_or_equal_modifier(self, field: str, value: int) -> str:
63+
return f"{field} <= {self._pre_process_value(field, value)}"
64+
65+
def greater_modifier(self, field: str, value: int) -> str:
66+
return f"{field} > {self._pre_process_value(field, value)}"
67+
68+
def greater_or_equal_modifier(self, field: str, value: int) -> str:
69+
return f"{field} >= {self._pre_process_value(field, value)}"
70+
71+
def contains_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
72+
if isinstance(value, list):
73+
return f"({self.or_token.join([self.contains_modifier(field=field, value=v) for v in value])})"
74+
value = self._pre_process_value(field, value, wrap_str=True, wrap_int=True)
75+
return f"{field} contains {value}"
76+
77+
def endswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
78+
if isinstance(value, list):
79+
return f"({self.or_token.join([self.endswith_modifier(field=field, value=v) for v in value])})"
80+
value = self._pre_process_value(field, value, wrap_str=True, wrap_int=True)
81+
return f"{field} endswith {value}"
82+
83+
def startswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
84+
if isinstance(value, list):
85+
return f"({self.or_token.join([self.startswith_modifier(field=field, value=v) for v in value])})"
86+
value = self._pre_process_value(field, value, wrap_str=True, wrap_int=True)
87+
return f"{field} startswith {value}"
88+
89+
def regex_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
90+
if isinstance(value, list):
91+
return f"({self.or_token.join(self.regex_modifier(field=field, value=v) for v in value)})"
92+
regex_str = self._pre_process_value(field, value, value_type=ValueType.regex_value)
93+
return f"{field} regex '{regex_str}'"
94+
95+
def is_none(self, field: str, value: DEFAULT_VALUE_TYPE) -> str:
96+
if isinstance(value, list):
97+
return f"({self.or_token.join(self.is_none(field=field, value=v) for v in value)})"
98+
return f"{field} exists"
99+
100+
101+
@render_manager.register
102+
class FalcoRuleRender(PlatformQueryRender):
103+
details: PlatformDetails = falco_rule_details
104+
mappings: FalcoRuleMappings = falco_rule_mappings
105+
106+
or_token = "or"
107+
and_token = "and"
108+
not_token = "not"
109+
110+
comment_symbol = "//"
111+
112+
field_value_render = FalcoRuleFieldValueRender(or_token=or_token)
113+
114+
priority_map: ClassVar[dict[str, str]] = {
115+
"unspecified": "NOTICE",
116+
"info": "INFORMATIONAL",
117+
"low": "WARNING",
118+
"medium": "ERROR",
119+
"high": "ERROR",
120+
"critical": "CRITICAL",
121+
}
122+
123+
def generate_prefix(self, log_source_signature: Optional[LogSourceSignature], functions_prefix: str = "") -> str: # noqa: ARG002
124+
return ""
125+
126+
def generate_output(self, fields: list[Field], unmapped_fields: list[str], source_mapping: SourceMapping) -> str:
127+
extra_fields = []
128+
for field in fields:
129+
if field.source_name in unmapped_fields:
130+
extra_fields.append(field.source_name)
131+
elif generic_field_name := field.get_generic_field_name(source_mapping.source_id):
132+
extra_field = source_mapping.fields_mapping.get_platform_field_name(generic_field_name)
133+
if extra_field:
134+
extra_fields.append(extra_field)
135+
extra_fields = [f"{field.replace('.', '_')}=%{field}" for field in extra_fields]
136+
return f"shell in a container (container_name=%container.name {' '.join(extra_fields)})"
137+
138+
def finalize_query(
139+
self,
140+
prefix: str,
141+
query: str,
142+
functions: str,
143+
meta_info: Optional[MetaInfoContainer] = None,
144+
source_mapping: Optional[SourceMapping] = None,
145+
not_supported_functions: Optional[list] = None,
146+
unmapped_fields: Optional[list[str]] = None,
147+
*args, # noqa: ARG002
148+
**kwargs, # noqa: ARG002
149+
) -> str:
150+
query = self._join_query_parts(prefix, query, functions)
151+
rule = {
152+
"rule": meta_info.title or "Falco Rule",
153+
"condition": query,
154+
"desc": meta_info.description or "Falco Rule",
155+
"output": self.generate_output(meta_info.query_fields, unmapped_fields or [], source_mapping),
156+
"priority": self.priority_map.get(meta_info.severity or "medium"),
157+
}
158+
rule_str = yaml.dump(rule, default_flow_style=False, sort_keys=False)
159+
rule_str = self.wrap_with_meta_info(rule_str, meta_info)
160+
rule_str = self.wrap_with_unmapped_fields(rule_str, unmapped_fields)
161+
return self.wrap_with_not_supported_functions(rule_str, not_supported_functions)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
from app.translator.core.str_value_manager import StrValueManager
20+
from app.translator.platforms.falco.escape_manager import FalcoRuleEscapeManager, falco_rule_escape_manager
21+
22+
23+
class FalcoRuleStrValueManager(StrValueManager):
24+
escape_manager: FalcoRuleEscapeManager = falco_rule_escape_manager
25+
26+
27+
falco_rule_str_value_manager = FalcoRuleStrValueManager()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy