devsecops-engine-tools 1.101.1__py3-none-any.whl → 1.103.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of devsecops-engine-tools might be problematic. Click here for more details.
- devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +19 -4
- devsecops_engine_tools/engine_core/src/domain/model/finding.py +9 -1
- devsecops_engine_tools/engine_core/src/domain/usecases/break_build.py +11 -7
- devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py +4 -1
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py +3 -1
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +88 -74
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py +3 -1
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py +14 -7
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py +1 -0
- devsecops_engine_tools/engine_sast/engine_code/src/applications/runner_engine_code.py +17 -1
- devsecops_engine_tools/engine_sast/engine_code/src/domain/model/gateways/tool_gateway.py +24 -11
- devsecops_engine_tools/engine_sast/engine_code/src/domain/usecases/code_scan.py +100 -37
- devsecops_engine_tools/engine_sast/engine_code/src/infrastructure/driven_adapters/bearer/bearer_deserealizator.py +9 -4
- devsecops_engine_tools/engine_sast/engine_code/src/infrastructure/driven_adapters/kiuwan/__init__.py +0 -0
- devsecops_engine_tools/engine_sast/engine_code/src/infrastructure/driven_adapters/kiuwan/kiuwan_deserealizator.py +59 -0
- devsecops_engine_tools/engine_sast/engine_code/src/infrastructure/driven_adapters/kiuwan/kiuwan_tool.py +537 -0
- devsecops_engine_tools/engine_sast/engine_secret/src/infrastructure/driven_adapters/gitleaks/gitleaks_tool.py +1 -1
- devsecops_engine_tools/engine_utilities/azuredevops/models/AzurePredefinedVariables.py +3 -0
- devsecops_engine_tools/engine_utilities/github/models/GithubPredefinedVariables.py +3 -0
- devsecops_engine_tools/version.py +1 -1
- {devsecops_engine_tools-1.101.1.dist-info → devsecops_engine_tools-1.103.0.dist-info}/METADATA +1 -1
- {devsecops_engine_tools-1.101.1.dist-info → devsecops_engine_tools-1.103.0.dist-info}/RECORD +25 -22
- {devsecops_engine_tools-1.101.1.dist-info → devsecops_engine_tools-1.103.0.dist-info}/WHEEL +0 -0
- {devsecops_engine_tools-1.101.1.dist-info → devsecops_engine_tools-1.103.0.dist-info}/entry_points.txt +0 -0
- {devsecops_engine_tools-1.101.1.dist-info → devsecops_engine_tools-1.103.0.dist-info}/top_level.txt +0 -0
devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py
CHANGED
|
@@ -76,5 +76,6 @@ class RuntimeLocal(DevopsPlatformGateway):
|
|
|
76
76
|
"vm_product_type_name" : "DET_VM_PRODUCT_TYPE_NAME",
|
|
77
77
|
"vm_product_name" : "DET_VM_PRODUCT_NAME",
|
|
78
78
|
"vm_product_description" : "DET_VM_PRODUCT_DESCRIPTION",
|
|
79
|
+
"build_task": "DET_APPLICATION_BUILD_TASK",
|
|
79
80
|
}
|
|
80
81
|
return os.environ.get(env_variables[variable], None)
|
|
@@ -7,13 +7,29 @@ from devsecops_engine_tools.engine_sast.engine_code.src.infrastructure.driven_ad
|
|
|
7
7
|
from devsecops_engine_tools.engine_utilities.git_cli.infrastructure.git_run import (
|
|
8
8
|
GitRun
|
|
9
9
|
)
|
|
10
|
+
from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
|
|
11
|
+
from devsecops_engine_tools.engine_utilities import settings
|
|
12
|
+
from devsecops_engine_tools.engine_sast.engine_code.src.infrastructure.driven_adapters.kiuwan.kiuwan_tool import get_kiuwan_instance
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
|
|
10
16
|
|
|
11
17
|
def runner_engine_code(dict_args, tool, devops_platform_gateway, remote_config_source_gateway):
|
|
12
18
|
try:
|
|
19
|
+
logger.info("Selecting tool...")
|
|
13
20
|
tool_gateway = None
|
|
14
21
|
git_gateway = GitRun()
|
|
15
22
|
if (tool == "BEARER"):
|
|
23
|
+
logger.info("Bearer tool selected...")
|
|
16
24
|
tool_gateway = BearerTool()
|
|
25
|
+
elif (tool == "KIUWAN"):
|
|
26
|
+
logger.info("Kiuwan tool selected...")
|
|
27
|
+
tool_gateway = get_kiuwan_instance(
|
|
28
|
+
dict_args=dict_args,
|
|
29
|
+
devops_platform_gateway=devops_platform_gateway,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
logger.info("Tool has been selected successfully")
|
|
17
33
|
|
|
18
34
|
return init_engine_sast_code(
|
|
19
35
|
devops_platform_gateway=devops_platform_gateway,
|
|
@@ -29,4 +45,4 @@ def runner_engine_code(dict_args, tool, devops_platform_gateway, remote_config_s
|
|
|
29
45
|
|
|
30
46
|
|
|
31
47
|
if __name__ == "__main__":
|
|
32
|
-
runner_engine_code()
|
|
48
|
+
runner_engine_code()
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
from abc import ABCMeta, abstractmethod
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
)
|
|
2
|
+
from typing import List, Optional, Any, Tuple
|
|
3
|
+
from devsecops_engine_tools.engine_sast.engine_code.src.domain.model.config_tool import ConfigTool
|
|
5
4
|
|
|
6
5
|
class ToolGateway(metaclass=ABCMeta):
|
|
7
|
-
|
|
8
6
|
@abstractmethod
|
|
9
|
-
def run_tool(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
def run_tool(
|
|
8
|
+
self,
|
|
9
|
+
folder_to_scan: str,
|
|
10
|
+
pull_request_files: List[str],
|
|
11
|
+
agent_work_folder: str,
|
|
12
|
+
repository: str,
|
|
13
|
+
config_tool: ConfigTool
|
|
14
|
+
) -> Tuple[List[Any], Optional[str]]:
|
|
15
|
+
"""
|
|
16
|
+
Run the code scan tool.
|
|
17
|
+
Args:
|
|
18
|
+
folder_to_scan: Path to the folder to scan
|
|
19
|
+
pull_request_files: List of files modified in the pull request
|
|
20
|
+
agent_work_folder: Directory for storing temporary files
|
|
21
|
+
repository: Name of the repository
|
|
22
|
+
config_tool: Configuration object for the tool
|
|
23
|
+
Returns:
|
|
24
|
+
Tuple containing:
|
|
25
|
+
- List of findings (vulnerabilities or defects).
|
|
26
|
+
- Path to the results file, or None if no file is generated.
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
from typing import Any, Dict, List, Tuple
|
|
2
3
|
from devsecops_engine_tools.engine_sast.engine_code.src.domain.model.gateways.tool_gateway import (
|
|
3
4
|
ToolGateway,
|
|
4
5
|
)
|
|
@@ -33,9 +34,9 @@ class CodeScan:
|
|
|
33
34
|
self.remote_config_source_gateway = remote_config_source_gateway
|
|
34
35
|
self.git_gateway = git_gateway
|
|
35
36
|
|
|
36
|
-
def set_config_tool(self, dict_args):
|
|
37
|
+
def set_config_tool(self, dict_args: Dict[str, Any], config_tool_path: str):
|
|
37
38
|
init_config_tool = self.remote_config_source_gateway.get_remote_config(
|
|
38
|
-
dict_args["remote_config_repo"],
|
|
39
|
+
dict_args["remote_config_repo"], config_tool_path, dict_args["remote_config_branch"]
|
|
39
40
|
)
|
|
40
41
|
scope_pipeline = self.devops_platform_gateway.get_variable("pipeline_name")
|
|
41
42
|
return ConfigTool(json_data=init_config_tool, scope=scope_pipeline)
|
|
@@ -88,35 +89,112 @@ class CodeScan:
|
|
|
88
89
|
return True
|
|
89
90
|
return False
|
|
90
91
|
|
|
91
|
-
def
|
|
92
|
-
|
|
92
|
+
def _get_config_tool_and_exclusions_data(self, dict_args, tool) -> Tuple[Dict[str, Any], Dict[str, str]]:
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
Get the information related to configuracion and exclusiones for the selected tool.
|
|
96
|
+
|
|
97
|
+
Parameters:
|
|
98
|
+
dict_args: Dictionary with properties setting up from the extension.
|
|
99
|
+
tool: String name of the tool that will be used to run scan.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
config_tool: Dictionary with the configuration of the tool.
|
|
103
|
+
excusions_data: Dictionary with the exclusions configured for an specific tool and pipelines.
|
|
104
|
+
"""
|
|
105
|
+
logger.info("Getting engine_code config tool and exclusions...")
|
|
106
|
+
config_tool = self.set_config_tool(dict_args, "engine_sast/engine_code/ConfigTool.json")
|
|
93
107
|
exclusions_data = self.remote_config_source_gateway.get_remote_config(
|
|
94
|
-
dict_args["remote_config_repo"], "engine_sast/engine_code/Exclusions.json"
|
|
108
|
+
dict_args["remote_config_repo"], "engine_sast/engine_code/Exclusions.json", dict_args["remote_config_branch"]
|
|
109
|
+
)
|
|
110
|
+
return config_tool, exclusions_data
|
|
111
|
+
|
|
112
|
+
def _get_filtered_pr_files(self, dict_args: Dict[str,str], config_tool: Dict[str, Any]) -> List[str]:
|
|
113
|
+
"""
|
|
114
|
+
Retrieve and filter pull request files based on exclusion rules.
|
|
115
|
+
|
|
116
|
+
Parameters:
|
|
117
|
+
config_tool: Configuration dictionary for the SAST tool.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
List of filtered pull request file paths.
|
|
121
|
+
"""
|
|
122
|
+
pull_request_files = []
|
|
123
|
+
if not dict_args["folder_path"]:
|
|
124
|
+
pull_request_files = self.get_pull_request_files(
|
|
125
|
+
config_tool.target_branches
|
|
126
|
+
)
|
|
127
|
+
pull_request_files = [
|
|
128
|
+
pf
|
|
129
|
+
for pf in pull_request_files
|
|
130
|
+
if not self.apply_exclude_path(
|
|
131
|
+
config_tool.exclude_folder,
|
|
132
|
+
config_tool.ignore_search_pattern,
|
|
133
|
+
pf,
|
|
134
|
+
)
|
|
135
|
+
]
|
|
136
|
+
return pull_request_files
|
|
137
|
+
|
|
138
|
+
def _create_input_core(self, list_exclusions: List[str], config_tool: Dict[str, Any], exclusions_data: Dict[str, str], path_file_results: str) -> 'InputCore':
|
|
139
|
+
"""
|
|
140
|
+
Create an InputCore object with pipeline and tool configuration.
|
|
141
|
+
|
|
142
|
+
Parameters:
|
|
143
|
+
list_exclusions: List of excluded files or patterns.
|
|
144
|
+
config_tool: Configuration dictionary for the SAST tool.
|
|
145
|
+
exclusions_data: Exclusion data for the tool.
|
|
146
|
+
path_file_results: Path to the results file.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
InputCore object with pipeline and tool configuration.
|
|
150
|
+
"""
|
|
151
|
+
return InputCore(
|
|
152
|
+
totalized_exclusions=list_exclusions,
|
|
153
|
+
threshold_defined=Utils.update_threshold(
|
|
154
|
+
self,
|
|
155
|
+
config_tool.threshold,
|
|
156
|
+
exclusions_data,
|
|
157
|
+
config_tool.scope_pipeline,
|
|
158
|
+
),
|
|
159
|
+
path_file_results=path_file_results,
|
|
160
|
+
custom_message_break_build=config_tool.message_info_engine_code,
|
|
161
|
+
scope_pipeline=config_tool.scope_pipeline,
|
|
162
|
+
scope_service=config_tool.scope_pipeline,
|
|
163
|
+
stage_pipeline=self.devops_platform_gateway.get_variable("stage").capitalize(),
|
|
95
164
|
)
|
|
165
|
+
|
|
166
|
+
def process(self, dict_args, tool):
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
This function process the request to a new scan code.
|
|
170
|
+
|
|
171
|
+
Parameters:
|
|
172
|
+
dict_args: Dictionary with properties setting up from the extension.
|
|
173
|
+
tool: String name of the tool that will be used to run scan.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
findings_list: List with the defects founded during analysis.
|
|
177
|
+
input_core: InputCore instance with properties related to scan proccess.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
# Retrieve the config tool and exclusions data for the tool used during scan
|
|
181
|
+
config_tool, exclusions_data = self._get_config_tool_and_exclusions_data(
|
|
182
|
+
dict_args, tool
|
|
183
|
+
)
|
|
184
|
+
|
|
96
185
|
list_exclusions, skip_tool = self.get_exclusions(tool, exclusions_data)
|
|
97
186
|
findings_list, path_file_results = [], ""
|
|
98
187
|
|
|
99
188
|
if not skip_tool:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
config_tool.target_branches
|
|
104
|
-
)
|
|
105
|
-
pull_request_files = [
|
|
106
|
-
pf
|
|
107
|
-
for pf in pull_request_files
|
|
108
|
-
if not self.apply_exclude_path(
|
|
109
|
-
config_tool.exclude_folder,
|
|
110
|
-
config_tool.ignore_search_pattern,
|
|
111
|
-
pf,
|
|
112
|
-
)
|
|
113
|
-
]
|
|
189
|
+
# Retrieve the pull requests files
|
|
190
|
+
# If folder path was not added in dict args, the pr files will be downloaded excluding the paths excluded
|
|
191
|
+
pull_request_files = self._get_filtered_pr_files(dict_args, config_tool)
|
|
114
192
|
|
|
115
193
|
findings_list, path_file_results = self.tool_gateway.run_tool(
|
|
116
194
|
dict_args["folder_path"],
|
|
117
195
|
pull_request_files,
|
|
118
196
|
self.devops_platform_gateway.get_variable("path_directory"),
|
|
119
|
-
self.devops_platform_gateway.get_variable("repository"),
|
|
197
|
+
dict_args.get("repo_name", False) if dict_args.get("repo_name", False) else self.devops_platform_gateway.get_variable("repository"),
|
|
120
198
|
config_tool,
|
|
121
199
|
)
|
|
122
200
|
|
|
@@ -125,21 +203,6 @@ class CodeScan:
|
|
|
125
203
|
dict_args["send_metrics"] = "false"
|
|
126
204
|
dict_args["use_vulnerability_management"] = "false"
|
|
127
205
|
|
|
128
|
-
input_core =
|
|
129
|
-
totalized_exclusions=list_exclusions,
|
|
130
|
-
threshold_defined=Utils.update_threshold(
|
|
131
|
-
self,
|
|
132
|
-
config_tool.threshold,
|
|
133
|
-
exclusions_data,
|
|
134
|
-
config_tool.scope_pipeline,
|
|
135
|
-
),
|
|
136
|
-
path_file_results=path_file_results,
|
|
137
|
-
custom_message_break_build=config_tool.message_info_engine_code,
|
|
138
|
-
scope_pipeline=config_tool.scope_pipeline,
|
|
139
|
-
scope_service=config_tool.scope_pipeline,
|
|
140
|
-
stage_pipeline=self.devops_platform_gateway.get_variable(
|
|
141
|
-
"stage"
|
|
142
|
-
).capitalize(),
|
|
143
|
-
)
|
|
206
|
+
input_core = self._create_input_core(list_exclusions, config_tool, exclusions_data, path_file_results)
|
|
144
207
|
|
|
145
|
-
return findings_list, input_core
|
|
208
|
+
return findings_list, input_core
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from devsecops_engine_tools.engine_core.src.domain.model.finding import (
|
|
2
2
|
Category,
|
|
3
|
-
|
|
3
|
+
EngineCodeFinding,
|
|
4
4
|
)
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from dataclasses import dataclass
|
|
@@ -12,7 +12,7 @@ class BearerDeserealizator:
|
|
|
12
12
|
@classmethod
|
|
13
13
|
def get_list_finding(cls,
|
|
14
14
|
scan_result_path,
|
|
15
|
-
agent_work_folder) -> "list[
|
|
15
|
+
agent_work_folder) -> "list[EngineCodeFinding]":
|
|
16
16
|
findings = []
|
|
17
17
|
with open(scan_result_path, encoding='utf-8') as arc:
|
|
18
18
|
try:
|
|
@@ -30,7 +30,7 @@ class BearerDeserealizator:
|
|
|
30
30
|
chunks = [description[i : i + 70] for i in range(0, len(description), 70)]
|
|
31
31
|
formatted_description = "\n".join(chunks) + "\n"
|
|
32
32
|
|
|
33
|
-
finding =
|
|
33
|
+
finding = EngineCodeFinding(
|
|
34
34
|
id=vul["id"],
|
|
35
35
|
cvss="",
|
|
36
36
|
where=vul["full_filename"].replace(agent_work_folder, "").replace("/copy_files_bearer", ""),
|
|
@@ -41,7 +41,12 @@ class BearerDeserealizator:
|
|
|
41
41
|
module="engine_code",
|
|
42
42
|
category=Category.VULNERABILITY,
|
|
43
43
|
requirements="",
|
|
44
|
-
tool="Bearer"
|
|
44
|
+
tool="Bearer",
|
|
45
|
+
analysis_url=None,
|
|
46
|
+
analysis_code=None,
|
|
47
|
+
label=None,
|
|
48
|
+
application_business_value=None,
|
|
49
|
+
defect_type=None
|
|
45
50
|
)
|
|
46
51
|
findings.append(finding)
|
|
47
52
|
|
devsecops_engine_tools/engine_sast/engine_code/src/infrastructure/driven_adapters/kiuwan/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Dict, Any, List
|
|
3
|
+
|
|
4
|
+
from devsecops_engine_tools.engine_core.src.domain.model.finding import Category, EngineCodeFinding
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class KiuwanDeserealizator:
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This class has the functions to deserealize the defects found in kiuwan analysis scan.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def get_findings(
|
|
15
|
+
last_analysis: Dict[str, Any],
|
|
16
|
+
defects_data: Dict[str, Any],
|
|
17
|
+
analysis_code: str,
|
|
18
|
+
severity_mapper: Dict[str,str],
|
|
19
|
+
) -> List[EngineCodeFinding]:
|
|
20
|
+
"""
|
|
21
|
+
Map Kiuwan defects to KiuwanFinding objects.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
last_analysis: Dictionary containing the last analysis data.
|
|
25
|
+
defects_data: Dictionary containing the defects data.
|
|
26
|
+
analysis_code: The code of the analysis.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
List of KiuwanFinding objects representing the mapped defects.
|
|
30
|
+
"""
|
|
31
|
+
analysis_date = last_analysis.get("date", datetime.now().strftime("%d/%m/%Y"))
|
|
32
|
+
application_business_value = last_analysis.get("applicationBusinessValue", "")
|
|
33
|
+
|
|
34
|
+
findings = []
|
|
35
|
+
for defect in defects_data.get("defects", []):
|
|
36
|
+
# Mapear characteristic a Category
|
|
37
|
+
characteristic = defect.get("characteristic", "").lower()
|
|
38
|
+
|
|
39
|
+
finding = EngineCodeFinding(
|
|
40
|
+
id=str(defect.get("defectId", "")),
|
|
41
|
+
cvss=defect.get("ruleCode", ""),
|
|
42
|
+
where=f"{defect.get('file', '')}:{defect.get('line', '')}",
|
|
43
|
+
description=defect.get("rule", ""),
|
|
44
|
+
severity=severity_mapper.get(defect.get("priority", ""), "Undefined"),
|
|
45
|
+
identification_date=analysis_date,
|
|
46
|
+
published_date_cve="",
|
|
47
|
+
module="engine_code",
|
|
48
|
+
category=Category.VULNERABILITY if characteristic == "security" else Category.COMPLIANCE,
|
|
49
|
+
requirements="",
|
|
50
|
+
tool="kiuwan",
|
|
51
|
+
analysis_url=last_analysis.get("analysisURL", "No available"),
|
|
52
|
+
analysis_code=analysis_code,
|
|
53
|
+
label=defect.get("label", ""),
|
|
54
|
+
application_business_value=application_business_value,
|
|
55
|
+
defect_type=characteristic
|
|
56
|
+
)
|
|
57
|
+
findings.append(finding)
|
|
58
|
+
|
|
59
|
+
return findings
|