Skip to content

Commit fe2aa2f

Browse files
authored
Merge pull request #107 from UncoderIO/gis-7683
platforms init refactoring
2 parents b0a757f + 15bd579 commit fe2aa2f

File tree

95 files changed

+299
-159
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+299
-159
lines changed

uncoder-core/app/translator/cti_translator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class CTITranslator:
13-
renders: RenderCTIManager = render_cti_manager
13+
render_manager: RenderCTIManager = render_cti_manager
1414

1515
def __init__(self):
1616
self.logger = logging.getLogger("cti_translator")
@@ -38,7 +38,7 @@ def __parse_iocs_from_string(
3838

3939
@handle_translation_exceptions
4040
def __render_translation(self, parsed_data: dict, platform_data: CTIPlatform, iocs_per_query: int) -> list[str]:
41-
render_cti = self.renders.get(platform_data.id)
41+
render_cti = self.render_manager.get(platform_data.id)
4242

4343
chunked_iocs = self.__get_iocs_chunk(
4444
chunks_size=iocs_per_query, data=parsed_data, mapping=render_cti.default_mapping
@@ -85,4 +85,4 @@ def __get_iocs_chunk(
8585

8686
@classmethod
8787
def get_renders(cls) -> list:
88-
return cls.renders.get_platforms_details
88+
return cls.render_manager.get_platforms_details

uncoder-core/app/translator/managers.py

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
from abc import ABC
2+
from functools import cached_property
23

34
from app.models.translation import TranslatorPlatform
45
from app.translator.core.exceptions.core import UnsupportedRootAParser
5-
from app.translator.platforms import __ALL_PARSERS as PARSERS
6-
from app.translator.platforms import __ALL_RENDERS as RENDERS
7-
from app.translator.platforms import __ALL_RENDERS_CTI as RENDERS_CTI
86

97

108
class Manager(ABC):
11-
platforms_class = ()
9+
platforms = {}
1210

13-
@property
14-
def platforms(self) -> dict:
15-
return {platform.details.platform_id: platform for platform in self.platforms_class}
11+
def register(self, cls):
12+
self.platforms[cls.details.platform_id] = cls()
13+
return cls
1614

1715
def get(self, platform_id: str): # noqa: ANN201
1816
if platform := self.platforms.get(platform_id):
1917
return platform
2018
raise UnsupportedRootAParser(parser=platform_id)
2119

2220
def all_platforms(self) -> list:
23-
return list(self.platforms)
21+
return list(self.platforms.keys())
2422

25-
@property
23+
@cached_property
2624
def get_platforms_details(self) -> list[TranslatorPlatform]:
2725
platforms = [
2826
TranslatorPlatform(
@@ -37,21 +35,59 @@ def get_platforms_details(self) -> list[TranslatorPlatform]:
3735
alt_platform=platform.details.alt_platform,
3836
first_choice=platform.details.first_choice,
3937
)
40-
for platform in self.platforms_class
38+
for platform in self.platforms.values()
4139
]
4240
return sorted(platforms, key=lambda platform: platform.group_name)
4341

4442

45-
class RenderManager(Manager):
46-
platforms_class = RENDERS
43+
class ParserManager(Manager):
44+
platforms = {}
45+
supported_by_roota_platforms = {}
46+
main_platforms = {}
4747

48+
def get_supported_by_roota(self, platform_id: str): # noqa: ANN201
49+
if platform := self.supported_by_roota_platforms.get(platform_id):
50+
return platform
51+
raise UnsupportedRootAParser(parser=platform_id)
4852

49-
class ParserManager(Manager):
50-
platforms_class = PARSERS
53+
def register_supported_by_roota(self, cls):
54+
parser = cls()
55+
self.supported_by_roota_platforms[cls.details.platform_id] = parser
56+
self.platforms[cls.details.platform_id] = parser
57+
return cls
58+
59+
def register_main(self, cls):
60+
parser = cls()
61+
self.main_platforms[cls.details.platform_id] = parser
62+
self.platforms[cls.details.platform_id] = parser
63+
return cls
64+
65+
@cached_property
66+
def get_platforms_details(self) -> list[TranslatorPlatform]:
67+
platforms = [
68+
TranslatorPlatform(
69+
id=platform.details.platform_id,
70+
name=platform.details.name,
71+
code=platform.details.platform_id,
72+
group_name=platform.details.group_name,
73+
group_id=platform.details.group_id,
74+
platform_name=platform.details.platform_name,
75+
platform_id=platform.details.platform_id,
76+
alt_platform_name=platform.details.alt_platform_name,
77+
alt_platform=platform.details.alt_platform,
78+
first_choice=platform.details.first_choice,
79+
)
80+
for platform in self.platforms.values()
81+
]
82+
return sorted(platforms, key=lambda platform: platform.group_name)
83+
84+
85+
class RenderManager(Manager):
86+
platforms = {}
5187

5288

5389
class RenderCTIManager(Manager):
54-
platforms_class = RENDERS_CTI
90+
platforms = {}
5591

5692

5793
parser_manager = ParserManager()
Lines changed: 13 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,17 @@
1-
from app.translator.platforms.athena.parsers.athena import AthenaQueryParser
2-
from app.translator.platforms.athena.renders.athena import AthenaQueryRender
3-
from app.translator.platforms.athena.renders.athena_cti import AthenaCTI
4-
from app.translator.platforms.carbonblack.renders.carbonblack_cti import CarbonBlackCTI
5-
from app.translator.platforms.chronicle.parsers.chronicle import ChronicleQueryParser
6-
from app.translator.platforms.chronicle.parsers.chronicle_rule import ChronicleRuleParser
7-
from app.translator.platforms.chronicle.renders.chronicle import ChronicleQueryRender
8-
from app.translator.platforms.chronicle.renders.chronicle_cti import ChronicleQueryCTI
9-
from app.translator.platforms.chronicle.renders.chronicle_rule import ChronicleSecurityRuleRender
10-
from app.translator.platforms.crowdstrike.parsers.crowdstrike import CrowdStrikeQueryParser
11-
from app.translator.platforms.crowdstrike.renders.crowdstrike import CrowdStrikeQueryRender
12-
from app.translator.platforms.crowdstrike.renders.crowdstrike_cti import CrowdStrikeCTI
13-
from app.translator.platforms.elasticsearch.parsers.detection_rule import ElasticSearchRuleParser
14-
from app.translator.platforms.elasticsearch.parsers.elasticsearch import ElasticSearchQueryParser
15-
from app.translator.platforms.elasticsearch.renders.detection_rule import ElasticSearchRuleRender
16-
from app.translator.platforms.elasticsearch.renders.elast_alert import ElastAlertRuleRender
17-
from app.translator.platforms.elasticsearch.renders.elasticsearch import ElasticSearchQueryRender
18-
from app.translator.platforms.elasticsearch.renders.elasticsearch_cti import ElasticsearchCTI
19-
from app.translator.platforms.elasticsearch.renders.kibana import KibanaRuleRender
20-
from app.translator.platforms.elasticsearch.renders.xpack_watcher import XPackWatcherRuleRender
21-
from app.translator.platforms.fireeye_helix.renders.fireeye_helix_cti import FireeyeHelixCTI
22-
from app.translator.platforms.forti_siem.renders.forti_siem_rule import FortiSiemRuleRender
23-
from app.translator.platforms.graylog.parsers.graylog import GraylogQueryParser
24-
from app.translator.platforms.graylog.renders.graylog import GraylogQueryRender
25-
from app.translator.platforms.graylog.renders.graylog_cti import GraylogCTI
26-
from app.translator.platforms.logpoint.renders.logpoint_cti import LogpointCTI
27-
from app.translator.platforms.logrhythm_axon.renders.logrhythm_axon_query import LogRhythmAxonQueryRender
28-
from app.translator.platforms.logrhythm_axon.renders.logrhythm_axon_rule import LogRhythmAxonRuleRender
29-
from app.translator.platforms.logscale.parsers.logscale import LogScaleQueryParser
30-
from app.translator.platforms.logscale.parsers.logscale_alert import LogScaleAlertParser
31-
from app.translator.platforms.logscale.renders.logscale import LogScaleQueryRender
32-
from app.translator.platforms.logscale.renders.logscale_alert import LogScaleAlertRender
33-
from app.translator.platforms.logscale.renders.logscale_cti import LogScaleCTI
34-
from app.translator.platforms.microsoft.parsers.microsoft_defender import MicrosoftDefenderQueryParser
35-
from app.translator.platforms.microsoft.parsers.microsoft_sentinel import MicrosoftSentinelQueryParser
36-
from app.translator.platforms.microsoft.parsers.microsoft_sentinel_rule import MicrosoftSentinelRuleParser
37-
from app.translator.platforms.microsoft.renders.microsoft_defender import MicrosoftDefenderQueryRender
38-
from app.translator.platforms.microsoft.renders.microsoft_defender_cti import MicrosoftDefenderCTI
39-
from app.translator.platforms.microsoft.renders.microsoft_sentinel import MicrosoftSentinelQueryRender
40-
from app.translator.platforms.microsoft.renders.microsoft_sentinel_cti import MicrosoftSentinelCTI
41-
from app.translator.platforms.microsoft.renders.microsoft_sentinel_rule import MicrosoftSentinelRuleRender
42-
from app.translator.platforms.opensearch.parsers.opensearch import OpenSearchQueryParser
43-
from app.translator.platforms.opensearch.renders.opensearch import OpenSearchQueryRender
44-
from app.translator.platforms.opensearch.renders.opensearch_cti import OpenSearchCTI
45-
from app.translator.platforms.opensearch.renders.opensearch_rule import OpenSearchRuleRender
46-
from app.translator.platforms.palo_alto.renders.cortex_xsiam import CortexXQLQueryRender
47-
from app.translator.platforms.qradar.parsers.qradar import QradarQueryParser
48-
from app.translator.platforms.qradar.renders.qradar import QradarQueryRender
49-
from app.translator.platforms.qradar.renders.qradar_cti import QRadarCTI
50-
from app.translator.platforms.qualys.renders.qualys_cti import QualysCTI
51-
from app.translator.platforms.rsa_netwitness.renders.rsa_netwitness_cti import RSANetwitnessCTI
52-
from app.translator.platforms.securonix.renders.securonix_cti import SecuronixCTI
53-
from app.translator.platforms.sentinel_one.renders.s1_cti import S1EventsCTI
54-
from app.translator.platforms.sigma.parsers.sigma import SigmaParser
55-
from app.translator.platforms.sigma.renders.sigma import SigmaRender
56-
from app.translator.platforms.snowflake.renders.snowflake_cti import SnowflakeCTI
57-
from app.translator.platforms.splunk.parsers.splunk import SplunkQueryParser
58-
from app.translator.platforms.splunk.parsers.splunk_alert import SplunkAlertParser
59-
from app.translator.platforms.splunk.renders.splunk import SplunkQueryRender
60-
from app.translator.platforms.splunk.renders.splunk_alert import SplunkAlertRender
61-
from app.translator.platforms.splunk.renders.splunk_cti import SplunkCTI
62-
from app.translator.platforms.sumo_logic.renders.sumologic_cti import SumologicCTI
1+
import importlib.util
2+
import os
633

64-
__ALL_RENDERS = (
65-
SigmaRender(),
66-
MicrosoftSentinelQueryRender(),
67-
MicrosoftSentinelRuleRender(),
68-
MicrosoftDefenderQueryRender(),
69-
QradarQueryRender(),
70-
CrowdStrikeQueryRender(),
71-
SplunkQueryRender(),
72-
SplunkAlertRender(),
73-
ChronicleQueryRender(),
74-
ChronicleSecurityRuleRender(),
75-
AthenaQueryRender(),
76-
ElasticSearchQueryRender(),
77-
LogRhythmAxonQueryRender(),
78-
LogRhythmAxonRuleRender(),
79-
LogScaleQueryRender(),
80-
LogScaleAlertRender(),
81-
ElasticSearchRuleRender(),
82-
ElastAlertRuleRender(),
83-
KibanaRuleRender(),
84-
XPackWatcherRuleRender(),
85-
OpenSearchQueryRender(),
86-
OpenSearchRuleRender(),
87-
GraylogQueryRender(),
88-
FortiSiemRuleRender(),
89-
CortexXQLQueryRender(),
90-
)
4+
from const import PLATFORMS_PATH
915

92-
__ALL_PARSERS = (
93-
AthenaQueryParser(),
94-
ChronicleQueryParser(),
95-
ChronicleRuleParser(),
96-
SplunkQueryParser(),
97-
SplunkAlertParser(),
98-
SigmaParser(),
99-
QradarQueryParser(),
100-
MicrosoftSentinelQueryParser(),
101-
MicrosoftSentinelRuleParser(),
102-
MicrosoftDefenderQueryParser(),
103-
CrowdStrikeQueryParser(),
104-
LogScaleQueryParser(),
105-
LogScaleAlertParser(),
106-
ElasticSearchQueryParser(),
107-
ElasticSearchRuleParser(),
108-
OpenSearchQueryParser(),
109-
GraylogQueryParser(),
110-
)
1116

7+
def init_platforms():
8+
for platform in [f for f in os.listdir(PLATFORMS_PATH) if os.path.isdir(os.path.join(PLATFORMS_PATH, f))]:
9+
if not platform.startswith("__") and not platform.endswith("__"):
10+
# Platforms __init__.py execution
11+
init_path = f"{PLATFORMS_PATH}/{platform}/__init__.py"
12+
spec = importlib.util.spec_from_file_location("__init__", init_path)
13+
init_module = importlib.util.module_from_spec(spec)
14+
spec.loader.exec_module(init_module)
11215

113-
__ALL_RENDERS_CTI = (
114-
MicrosoftSentinelCTI(),
115-
MicrosoftDefenderCTI(),
116-
QRadarCTI(),
117-
SplunkCTI(),
118-
ChronicleQueryCTI(),
119-
CrowdStrikeCTI(),
120-
SumologicCTI(),
121-
ElasticsearchCTI(),
122-
LogScaleCTI(),
123-
OpenSearchCTI(),
124-
FireeyeHelixCTI(),
125-
CarbonBlackCTI(),
126-
GraylogCTI(),
127-
LogpointCTI(),
128-
QualysCTI(),
129-
RSANetwitnessCTI(),
130-
S1EventsCTI(),
131-
SecuronixCTI(),
132-
SnowflakeCTI(),
133-
AthenaCTI(),
134-
)
16+
17+
init_platforms()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from app.translator.platforms.arcsight.renders.arcsight_cti import ArcsightKeyword
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from app.translator.core.models.platform_details import PlatformDetails
2+
from app.translator.core.render_cti import RenderCTI
3+
from app.translator.managers import render_cti_manager
4+
from app.translator.platforms.arcsight.const import ARCSIGHT_QUERY_DETAILS
5+
from app.translator.platforms.arcsight.mappings.arcsight_cti import DEFAULT_ARCSIGHT_MAPPING
6+
7+
8+
@render_cti_manager.register
9+
class ArcsightKeyword(RenderCTI):
10+
details: PlatformDetails = PlatformDetails(**ARCSIGHT_QUERY_DETAILS)
11+
12+
default_mapping = DEFAULT_ARCSIGHT_MAPPING
13+
field_value_template: str = "{key} = {value}"
14+
or_operator: str = " OR "
15+
group_or_operator: str = " OR "
16+
or_group: str = "{or_group}"
17+
result_join: str = ""
18+
final_result_for_many: str = '({result}) AND type != 2 | rex field = flexString1 mode=sed "s//Sigma: None/g"\n'
19+
final_result_for_one: str = '{result} AND type != 2 | rex field = flexString1 mode=sed "s//Sigma: None/g"\n'
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from app.translator.platforms.athena.parsers.athena import AthenaQueryParser
2+
from app.translator.platforms.athena.renders.athena import AthenaQueryRender
3+
from app.translator.platforms.athena.renders.athena_cti import AthenaCTI

uncoder-core/app/translator/platforms/athena/parsers/athena.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@
2222
from app.translator.core.models.platform_details import PlatformDetails
2323
from app.translator.core.models.query_container import RawQueryContainer, TokenizedQueryContainer
2424
from app.translator.core.parser import PlatformQueryParser
25+
from app.translator.managers import parser_manager
2526
from app.translator.platforms.athena.const import athena_details
2627
from app.translator.platforms.athena.mapping import AthenaMappings, athena_mappings
2728
from app.translator.platforms.athena.tokenizer import AthenaTokenizer
2829

2930

31+
@parser_manager.register_supported_by_roota
3032
class AthenaQueryParser(PlatformQueryParser):
3133
details: PlatformDetails = athena_details
3234
mappings: AthenaMappings = athena_mappings

uncoder-core/app/translator/platforms/athena/renders/athena.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from app.translator.core.mapping import LogSourceSignature
2424
from app.translator.core.models.platform_details import PlatformDetails
2525
from app.translator.core.render import BaseQueryFieldValue, PlatformQueryRender
26+
from app.translator.managers import render_manager
2627
from app.translator.platforms.athena.const import athena_details
2728
from app.translator.platforms.athena.mapping import AthenaMappings, athena_mappings
2829

@@ -76,6 +77,7 @@ def keywords(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: # noqa: ARG00
7677
raise UnsupportedRenderMethod(platform_name=self.details.name, method="Keywords")
7778

7879

80+
@render_manager.register
7981
class AthenaQueryRender(PlatformQueryRender):
8082
details: PlatformDetails = athena_details
8183
mappings: AthenaMappings = athena_mappings

uncoder-core/app/translator/platforms/athena/renders/athena_cti.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
from app.translator.core.models.platform_details import PlatformDetails
2121
from app.translator.core.render_cti import RenderCTI
22+
from app.translator.managers import render_cti_manager
2223
from app.translator.platforms.athena.const import athena_details
2324
from app.translator.platforms.athena.mappings.athena_cti import DEFAULT_ATHENA_MAPPING
2425

2526

27+
@render_cti_manager.register
2628
class AthenaCTI(RenderCTI):
2729
details: PlatformDetails = athena_details
2830

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from app.translator.platforms.carbonblack.renders.carbonblack_cti import CarbonBlackCTI

0 commit comments

Comments
 (0)