Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbb92949

Browse files
committed
Merge branch 'main' into gis-8639
# Conflicts:#uncoder-core/app/translator/platforms/elasticsearch/const.py#uncoder-core/app/translator/platforms/elasticsearch/mapping.py#uncoder-core/app/translator/platforms/elasticsearch/renders/esql.py#uncoder-core/app/translator/platforms/elasticsearch/str_value_manager.py
2 parentsd6bd1f9 +bf008fe commitbb92949

File tree

119 files changed

+4471
-532
lines changed

Some content is hidden

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

119 files changed

+4471
-532
lines changed

‎uncoder-core/app/translator/const.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99

1010
CTI_IOCS_PER_QUERY_LIMIT=25
1111

12-
DEFAULT_VALUE_TYPE=Union[int,str,StrValue,list[Union[int,str,StrValue]]]
12+
DEFAULT_VALUE_TYPE=Union[bool,int,str,StrValue,list[Union[int,str,StrValue]]]

‎uncoder-core/app/translator/core/exceptions/core.py‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
fromtypingimportOptional
22

33

4-
classNotImplementedException(BaseException):
5-
...
6-
7-
84
classBasePlatformException(BaseException):
95
...
106

@@ -21,6 +17,12 @@ def __init__(self, platform_name: str, fields: list[str], mapping: Optional[str]
2117
super().__init__(message)
2218

2319

20+
classUnsupportedMappingsException(BasePlatformException):
21+
def__init__(self,platform_name:str,mappings:list[str]):
22+
message=f"Platform{platform_name} does not support these mappings:{mappings}."
23+
super().__init__(message)
24+
25+
2426
classStrictPlatformFieldException(BasePlatformException):
2527
def__init__(self,platform_name:str,field_name:str):
2628
message=f"Source field `{field_name}` has no mapping for platform{platform_name}."
@@ -88,5 +90,9 @@ class InvalidJSONStructure(InvalidRuleStructure):
8890
rule_type:str="JSON"
8991

9092

93+
classInvalidTOMLStructure(InvalidRuleStructure):
94+
rule_type:str="TOML"
95+
96+
9197
classInvalidXMLStructure(InvalidRuleStructure):
9298
rule_type:str="XML"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ class FunctionRenderException(BaseRenderException):
1414

1515
classUnsupportedRenderMethod(BaseRenderException):
1616
def__init__(self,platform_name:str,method:str):
17-
message=f"Cannot translate.{platform_name} backend does not support{method}."
17+
message=f'Cannot translate.{platform_name} backend does not support"{method}".'
1818
super().__init__(message)

‎uncoder-core/app/translator/core/mapping.py‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
fromabcimportABC,abstractmethod
44
fromtypingimportTYPE_CHECKING,Optional,TypeVar,Union
55

6-
fromapp.translator.core.exceptions.coreimportStrictPlatformException
6+
fromapp.translator.core.exceptions.coreimportStrictPlatformException,UnsupportedMappingsException
77
fromapp.translator.core.models.platform_detailsimportPlatformDetails
88
fromapp.translator.mappings.utils.load_from_filesimportLoaderFileMappings
99

@@ -152,7 +152,7 @@ def prepare_fields_mapping(field_mapping: dict) -> FieldsMapping:
152152
defprepare_log_source_signature(self,mapping:dict)->LogSourceSignature:
153153
raiseNotImplementedError("Abstract method")
154154

155-
defget_suitable_source_mappings(
155+
defget_source_mappings_by_fields_and_log_sources(
156156
self,field_names:list[str],log_sources:dict[str,list[Union[int,str]]]
157157
)->list[SourceMapping]:
158158
by_log_sources_and_fields= []
@@ -170,6 +170,17 @@ def get_suitable_source_mappings(
170170

171171
returnby_log_sources_and_fieldsorby_fieldsor [self._source_mappings[DEFAULT_MAPPING_NAME]]
172172

173+
defget_source_mappings_by_ids(self,source_mapping_ids:list[str])->list[SourceMapping]:
174+
source_mappings= []
175+
forsource_mapping_idinsource_mapping_ids:
176+
ifsource_mapping:=self.get_source_mapping(source_mapping_id):
177+
source_mappings.append(source_mapping)
178+
179+
ifnotsource_mappings:
180+
source_mappings= [self.get_source_mapping(DEFAULT_MAPPING_NAME)]
181+
182+
returnsource_mappings
183+
173184
defget_source_mapping(self,source_id:str)->Optional[SourceMapping]:
174185
returnself._source_mappings.get(source_id)
175186

@@ -218,3 +229,18 @@ def prepare_mapping(self) -> dict[str, SourceMapping]:
218229
)
219230

220231
returnsource_mappings
232+
233+
234+
classBaseStrictLogSourcesPlatformMappings(ABC,BasePlatformMappings):
235+
defget_source_mappings_by_ids(self,source_mapping_ids:list[str])->list[SourceMapping]:
236+
source_mappings= []
237+
forsource_mapping_idinsource_mapping_ids:
238+
ifsource_mapping_id==DEFAULT_MAPPING_NAME:
239+
continue
240+
ifsource_mapping:=self.get_source_mapping(source_mapping_id):
241+
source_mappings.append(source_mapping)
242+
243+
ifnotsource_mappings:
244+
raiseUnsupportedMappingsException(platform_name=self.details.name,mappings=source_mapping_ids)
245+
246+
returnsource_mappings

‎uncoder-core/app/translator/core/mitre.py‎

Lines changed: 114 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,90 @@
33
importssl
44
importurllib.request
55
fromjsonimportJSONDecodeError
6-
fromtypingimportOptional
6+
fromtypingimportOptional,Union
77
fromurllib.errorimportHTTPError
88

99
fromapp.translator.core.models.query_containerimportMitreInfoContainer,MitreTacticContainer,MitreTechniqueContainer
1010
fromapp.translator.tools.singleton_metaimportSingletonMeta
1111
fromconstimportROOT_PROJECT_PATH
1212

1313

14+
classTrieNode:
15+
def__init__(self):
16+
self.children= {}
17+
self.is_end_of_word=False
18+
self.result=None
19+
20+
21+
classTrie:
22+
"""
23+
Trie (prefix tree) data structure for storing and searching Mitre ATT&CK Techniques and Tactics strings.
24+
25+
This class handles the insertion and searching of strings related to Mitre ATT&CK Techniques and Tactics, even when
26+
the strings have variations in spacing, case, or underscores. By normalizing the text—converting it to lowercase and
27+
removing spaces and underscores—different variations of the same logical string are treated as equivalent.
28+
29+
It means strings 'CredentialAccess', 'credential Access', and 'credential_access' will be processed identically,
30+
leading to the same result.
31+
"""
32+
33+
def__init__(self):
34+
self.root=TrieNode()
35+
36+
defnormalize_text(self,text:str)->str:
37+
returntext.replace(" ","").lower().replace("_","").lower()
38+
39+
definsert(self,text:str,result:Union[MitreTacticContainer,MitreTechniqueContainer])->None:
40+
node=self.root
41+
normalized_text=self.normalize_text(text)
42+
43+
forcharinnormalized_text:
44+
ifcharnotinnode.children:
45+
node.children[char]=TrieNode()
46+
node=node.children[char]
47+
48+
node.is_end_of_word=True
49+
node.result=result
50+
51+
52+
classTacticsTrie(Trie):
53+
def__init__(self):
54+
self.root=TrieNode()
55+
56+
defsearch(self,text:str)->Optional[MitreTacticContainer]:
57+
node:TrieNode=self.root
58+
normalized_text=self.normalize_text(text)
59+
60+
forcharinnormalized_text:
61+
ifcharnotinnode.children:
62+
return
63+
node=node.children[char]
64+
65+
ifnode.is_end_of_word:
66+
returnnode.result
67+
68+
69+
classTechniquesTrie(Trie):
70+
defsearch(self,text:str)->Optional[MitreTechniqueContainer]:
71+
node:TrieNode=self.root
72+
normalized_text=self.normalize_text(text)
73+
74+
forcharinnormalized_text:
75+
ifcharnotinnode.children:
76+
return
77+
node=node.children[char]
78+
79+
ifnode.is_end_of_word:
80+
returnnode.result
81+
82+
1483
classMitreConfig(metaclass=SingletonMeta):
1584
config_url:str="https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json"
1685
mitre_source_types:tuple= ("mitre-attack",)
1786

1887
def__init__(self,server:bool=False):
19-
self.tactics= {}
20-
self.techniques= {}
88+
self.tactics:TacticsTrie=TacticsTrie()
89+
self.techniques:TechniquesTrie=TechniquesTrie()
2190
ifnotserver:
2291
self.__load_mitre_configs_from_files()
2392

@@ -44,7 +113,6 @@ def update_mitre_config(self) -> None: # noqa: PLR0912
44113
return
45114

46115
tactic_map= {}
47-
technique_map= {}
48116

49117
# Map the tactics
50118
forentryinmitre_json["objects"]:
@@ -53,11 +121,12 @@ def update_mitre_config(self) -> None: # noqa: PLR0912
53121
forrefinentry["external_references"]:
54122
ifref["source_name"]=="mitre-attack":
55123
tactic_map[entry["x_mitre_shortname"]]=entry["name"]
56-
self.tactics[entry["name"].replace(" ","_").lower()]= {
57-
"external_id":ref["external_id"],
58-
"url":ref["url"],
59-
"tactic":entry["name"],
60-
}
124+
125+
tactic_data=MitreTacticContainer(
126+
external_id=ref["external_id"],url=ref["url"],name=entry["name"]
127+
)
128+
self.tactics.insert(entry["name"],tactic_data)
129+
61130
break
62131

63132
# Map the techniques
@@ -68,19 +137,15 @@ def update_mitre_config(self) -> None: # noqa: PLR0912
68137
continue
69138
forrefinentry["external_references"]:
70139
ifref["source_name"]inself.mitre_source_types:
71-
technique_map[ref["external_id"]]=entry["name"]
72140
sub_tactics= []
73-
# Get Mitre Tactics (Kill-Chains)
74141
fortacticinentry["kill_chain_phases"]:
75142
iftactic["kill_chain_name"]inself.mitre_source_types:
76-
# Map the short phase_name to tactic name
77143
sub_tactics.append(tactic_map[tactic["phase_name"]])
78-
self.techniques[ref["external_id"].lower()]= {
79-
"technique_id":ref["external_id"],
80-
"technique":entry["name"],
81-
"url":ref["url"],
82-
"tactic":sub_tactics,
83-
}
144+
145+
technique_data=MitreTechniqueContainer(
146+
technique_id=ref["external_id"],name=entry["name"],url=ref["url"],tactic=sub_tactics
147+
)
148+
self.techniques.insert(ref["external_id"],technique_data)
84149
break
85150

86151
# Map the sub-techniques
@@ -92,58 +157,60 @@ def update_mitre_config(self) -> None: # noqa: PLR0912
92157
ifref["source_name"]inself.mitre_source_types:
93158
sub_technique_id=ref["external_id"]
94159
sub_technique_name=entry["name"]
95-
parent_technique_name=technique_map[sub_technique_id.split(".")[0]]
96-
parent_tactics=self.techniques.get(sub_technique_id.split(".")[0].lower(), {}).get(
97-
"tactic", []
98-
)
99-
sub_technique_name=f"{parent_technique_name} :{sub_technique_name}"
100-
self.techniques[ref["external_id"].lower()]= {
101-
"technique_id":ref["external_id"],
102-
"technique":sub_technique_name,
103-
"url":ref["url"],
104-
"tactic":parent_tactics,
105-
}
160+
ifparent_technique:=self.techniques.search(sub_technique_id.split(".")[0]):
161+
sub_technique_name=f"{parent_technique.name} :{sub_technique_name}"
162+
sub_technique_data=MitreTechniqueContainer(
163+
technique_id=ref["external_id"],
164+
name=sub_technique_name,
165+
url=ref["url"],
166+
tactic=parent_technique.tactic,
167+
)
168+
self.techniques.insert(sub_technique_id,sub_technique_data)
106169
break
107170

108171
def__load_mitre_configs_from_files(self)->None:
109172
try:
110173
withopen(os.path.join(ROOT_PROJECT_PATH,"app/dictionaries/tactics.json"))asfile:
111-
self.tactics=json.load(file)
174+
loaded=json.load(file)
175+
176+
fortactic_name,tactic_datainloaded.items():
177+
tactic=MitreTacticContainer(
178+
external_id=tactic_data["external_id"],url=tactic_data["url"],name=tactic_data["tactic"]
179+
)
180+
self.tactics.insert(tactic_name,tactic)
112181
exceptJSONDecodeError:
113-
self.tactics= {}
182+
print("Unable to load MITRE Tactics")
114183

115184
try:
116185
withopen(os.path.join(ROOT_PROJECT_PATH,"app/dictionaries/techniques.json"))asfile:
117-
self.techniques=json.load(file)
186+
loaded=json.load(file)
187+
fortechnique_id,technique_datainloaded.items():
188+
technique=MitreTechniqueContainer(
189+
technique_id=technique_data["technique_id"],
190+
name=technique_data["technique"],
191+
url=technique_data["url"],
192+
tactic=technique_data.get("tactic", []),
193+
)
194+
self.techniques.insert(technique_id,technique)
118195
exceptJSONDecodeError:
119-
self.techniques= {}
196+
print("Unable to load MITRE Techniques")
120197

121198
defget_tactic(self,tactic:str)->Optional[MitreTacticContainer]:
122-
tactic=tactic.replace(".","_")
123-
iftactic_found:=self.tactics.get(tactic):
124-
returnMitreTacticContainer(
125-
external_id=tactic_found["external_id"],url=tactic_found["url"],name=tactic_found["tactic"]
126-
)
199+
returnself.tactics.search(tactic)
127200

128201
defget_technique(self,technique_id:str)->Optional[MitreTechniqueContainer]:
129-
iftechnique_found:=self.techniques.get(technique_id):
130-
returnMitreTechniqueContainer(
131-
technique_id=technique_found["technique_id"],
132-
name=technique_found["technique"],
133-
url=technique_found["url"],
134-
tactic=technique_found["tactic"],
135-
)
202+
returnself.techniques.search(technique_id)
136203

137204
defget_mitre_info(
138205
self,tactics:Optional[list[str]]=None,techniques:Optional[list[str]]=None
139206
)->MitreInfoContainer:
140207
tactics_list= []
141208
techniques_list= []
142209
fortacticintacticsor []:
143-
iftactic_found:=self.get_tactic(tactic=tactic.lower()):
210+
iftactic_found:=self.tactics.search(tactic):
144211
tactics_list.append(tactic_found)
145212
fortechniqueintechniquesor []:
146-
iftechnique_found:=self.get_technique(technique_id=technique.lower()):
213+
iftechnique_found:=self.techniques.search(technique):
147214
techniques_list.append(technique_found)
148215
returnMitreInfoContainer(
149216
tactics=sorted(tactics_list,key=lambdax:x.name),

‎uncoder-core/app/translator/core/mixins/rule.py‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
importjson
22
fromtypingimportUnion
33

4+
importtoml
45
importxmltodict
56
importyaml
67

7-
fromapp.translator.core.exceptions.coreimportInvalidJSONStructure,InvalidXMLStructure,InvalidYamlStructure
8+
fromapp.translator.core.exceptions.coreimport (
9+
InvalidJSONStructure,
10+
InvalidTOMLStructure,
11+
InvalidXMLStructure,
12+
InvalidYamlStructure,
13+
)
814
fromapp.translator.core.mitreimportMitreConfig,MitreInfoContainer
915

1016

@@ -50,3 +56,14 @@ def load_rule(text: Union[str, bytes]) -> dict:
5056
returnxmltodict.parse(text)
5157
exceptExceptionaserr:
5258
raiseInvalidXMLStructure(error=str(err))fromerr
59+
60+
61+
classTOMLRuleMixin:
62+
mitre_config:MitreConfig=MitreConfig()
63+
64+
@staticmethod
65+
defload_rule(text:str)->dict:
66+
try:
67+
returntoml.loads(text)
68+
excepttoml.TomlDecodeErroraserr:
69+
raiseInvalidTOMLStructure(error=str(err))fromerr

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp