devsecops-engine-tools 1.60.0__py3-none-any.whl → 1.60.1__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.

Files changed (19) hide show
  1. devsecops_engine_tools/engine_sast/engine_iac/src/domain/model/context_iac.py +2 -1
  2. devsecops_engine_tools/engine_sast/engine_iac/src/domain/model/gateways/tool_gateway.py +4 -5
  3. devsecops_engine_tools/engine_sast/engine_iac/src/domain/usecases/iac_scan.py +14 -12
  4. devsecops_engine_tools/engine_sast/engine_iac/src/infrastructure/driven_adapters/checkov/checkov_deserealizator.py +11 -8
  5. devsecops_engine_tools/engine_sast/engine_iac/src/infrastructure/driven_adapters/checkov/checkov_tool.py +230 -206
  6. devsecops_engine_tools/engine_sast/engine_iac/src/infrastructure/driven_adapters/kics/kics_tool.py +123 -85
  7. devsecops_engine_tools/engine_sast/engine_iac/src/infrastructure/driven_adapters/kubescape/kubescape_tool.py +80 -65
  8. devsecops_engine_tools/engine_sca/engine_container/src/domain/model/context_container.py +2 -1
  9. devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/deserealizator_gateway.py +7 -2
  10. devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py +53 -52
  11. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py +3 -3
  12. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py +50 -31
  13. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py +9 -5
  14. devsecops_engine_tools/version.py +1 -1
  15. {devsecops_engine_tools-1.60.0.dist-info → devsecops_engine_tools-1.60.1.dist-info}/METADATA +1 -1
  16. {devsecops_engine_tools-1.60.0.dist-info → devsecops_engine_tools-1.60.1.dist-info}/RECORD +19 -19
  17. {devsecops_engine_tools-1.60.0.dist-info → devsecops_engine_tools-1.60.1.dist-info}/WHEEL +0 -0
  18. {devsecops_engine_tools-1.60.0.dist-info → devsecops_engine_tools-1.60.1.dist-info}/entry_points.txt +0 -0
  19. {devsecops_engine_tools-1.60.0.dist-info → devsecops_engine_tools-1.60.1.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,9 @@ import threading
9
9
  import json
10
10
  import shutil
11
11
  import platform
12
- from devsecops_engine_tools.engine_sast.engine_iac.src.domain.model.context_iac import ContextIac
12
+ from devsecops_engine_tools.engine_sast.engine_iac.src.domain.model.context_iac import (
13
+ ContextIac,
14
+ )
13
15
  from devsecops_engine_tools.engine_sast.engine_iac.src.domain.model.gateways.tool_gateway import (
14
16
  ToolGateway,
15
17
  )
@@ -30,7 +32,7 @@ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
30
32
 
31
33
 
32
34
  class CheckovTool(ToolGateway):
33
-
35
+
34
36
  CHECKOV_CONFIG_FILE = "checkov_config.yaml"
35
37
  TOOL_CHECKOV = "CHECKOV"
36
38
  framework_mapping = {
@@ -38,31 +40,123 @@ class CheckovTool(ToolGateway):
38
40
  "RULES_K8S": "kubernetes",
39
41
  "RULES_CLOUDFORMATION": "cloudformation",
40
42
  "RULES_OPENAPI": "openapi",
41
- "RULES_TERRAFORM": "terraform"
43
+ "RULES_TERRAFORM": "terraform",
42
44
  }
43
45
  framework_external_checks = [
44
46
  "RULES_K8S",
45
47
  "RULES_CLOUDFORMATION",
46
48
  "RULES_DOCKER",
47
49
  "RULES_OPENAPI",
48
- "RULES_TERRAFORM"
50
+ "RULES_TERRAFORM",
49
51
  ]
50
52
 
51
- def create_config_file(self, checkov_config: CheckovConfig):
52
- with open(
53
- checkov_config.path_config_file
54
- + checkov_config.config_file_name
55
- + self.CHECKOV_CONFIG_FILE,
56
- "w",
57
- ) as file:
58
- yaml.dump(checkov_config.dict_confg_file, file)
59
- file.close()
53
+ def run_tool(
54
+ self,
55
+ config_tool,
56
+ folders_to_scan,
57
+ environment,
58
+ platform_to_scan,
59
+ secret_tool,
60
+ secret_external_checks,
61
+ **kwargs,
62
+ ):
63
+ util = Utils()
64
+ agent_env = util.configurate_external_checks(
65
+ self.TOOL_CHECKOV, config_tool, secret_tool, secret_external_checks
66
+ )
67
+
68
+ install_type = config_tool[self.TOOL_CHECKOV].get("INSTALL_TYPE", "")
69
+
70
+ command_prefix = None
71
+
72
+ if install_type.casefold() == "remote-binary".casefold():
73
+ command_prefix = self._install_binary(config_tool[self.TOOL_CHECKOV])
74
+ else:
75
+ command_prefix = self._retryable_install_package(
76
+ "checkov", config_tool[self.TOOL_CHECKOV]["VERSION"]
77
+ )
78
+
79
+ if command_prefix is not None:
80
+ result_scans, rules_run = self._scan_folders(
81
+ folders_to_scan,
82
+ config_tool,
83
+ agent_env,
84
+ environment,
85
+ platform_to_scan,
86
+ command_prefix,
87
+ kwargs.get("dict_args"),
88
+ )
89
+
90
+ checkov_deserealizator = CheckovDeserealizator()
91
+ findings_list = checkov_deserealizator.get_list_finding(
92
+ result_scans,
93
+ rules_run,
94
+ config_tool[self.TOOL_CHECKOV]["DEFAULT_SEVERITY"],
95
+ config_tool[self.TOOL_CHECKOV]["DEFAULT_CATEGORY"],
96
+ )
97
+
98
+ return (
99
+ findings_list,
100
+ generate_file_from_tool(
101
+ self.TOOL_CHECKOV,
102
+ result_scans,
103
+ rules_run,
104
+ config_tool[self.TOOL_CHECKOV]["DEFAULT_SEVERITY"],
105
+ config_tool[self.TOOL_CHECKOV]["DEFAULT_CATEGORY"],
106
+ ),
107
+ )
108
+ else:
109
+ return [], None
110
+
111
+ def get_iac_context_from_results(self, path_file_results: str):
112
+ with open(path_file_results, "r") as file:
113
+ context_results_scan_list = json.load(file)
114
+ context_iac_list = []
115
+ failed_checks = context_results_scan_list.get("results", {}).get(
116
+ "failed_checks", []
117
+ )
118
+ for check in failed_checks:
119
+ file_line_range = check.get("file_line_range", ["unknown", "unknown"])
120
+ start_line = (
121
+ file_line_range[0] if len(file_line_range) > 0 else "unknown"
122
+ )
123
+ end_line = file_line_range[1] if len(file_line_range) > 1 else "unknown"
124
+ line_range_str = (
125
+ f"{start_line}-{end_line}"
126
+ if start_line != end_line
127
+ else str(start_line)
128
+ )
129
+
130
+ context_iac = ContextIac(
131
+ id=check.get("check_id", "unknown"),
132
+ check_name=check.get("check_name", "unknown"),
133
+ check_class=check.get("check_class", "unknown"),
134
+ severity=check.get("severity").lower(),
135
+ where=f"{check.get('repo_file_path', 'unknown')}: {check.get('resource', 'unknown')} (line {line_range_str})",
136
+ resource=check.get("resource", "unknown"),
137
+ description=check.get("check_name", "unknown"),
138
+ module="engine_iac",
139
+ tool="Checkov",
140
+ )
141
+
142
+ context_iac_list.append(context_iac)
143
+
144
+ print("===== BEGIN CONTEXT OUTPUT =====")
145
+ print(
146
+ json.dumps(
147
+ {"iac_context": [obj.__dict__ for obj in context_iac_list]},
148
+ indent=4,
149
+ )
150
+ )
151
+ print("===== END CONTEXT OUTPUT =====")
60
152
 
61
- def retryable_install_package(self, package: str, version: str) -> bool:
153
+ def _retryable_install_package(self, package: str, version: str) -> bool:
62
154
  MAX_RETRIES = 3
63
155
  RETRY_DELAY = 1 # in seconds
64
156
  INSTALL_SUCCESS_MSG = f"Installation of {package} successful"
65
- INSTALL_RETRY_MSG = f"Retrying installation of {package} in {RETRY_DELAY} seconds..."
157
+ INSTALL_RETRY_MSG = (
158
+ f"Retrying installation of {package} in {RETRY_DELAY} seconds..."
159
+ )
66
160
 
67
161
  installed = shutil.which(package)
68
162
  if installed:
@@ -77,10 +171,7 @@ class CheckovTool(ToolGateway):
77
171
  # Detect Python version
78
172
  try:
79
173
  result = subprocess.run(
80
- [python_path, "--version"],
81
- capture_output=True,
82
- text=True,
83
- check=True
174
+ [python_path, "--version"], capture_output=True, text=True, check=True
84
175
  )
85
176
  version_str = result.stdout.strip().split()[1]
86
177
  major, minor, *_ = map(int, version_str.split("."))
@@ -90,10 +181,16 @@ class CheckovTool(ToolGateway):
90
181
 
91
182
  # Prepare install command parts
92
183
  install_cmd_base = [
93
- python_path, "-m", "pip", "install", "-q",
184
+ python_path,
185
+ "-m",
186
+ "pip",
187
+ "install",
188
+ "-q",
94
189
  f"{package}=={version}",
95
- "--retries", str(MAX_RETRIES),
96
- "--timeout", str(RETRY_DELAY),
190
+ "--retries",
191
+ str(MAX_RETRIES),
192
+ "--timeout",
193
+ str(RETRY_DELAY),
97
194
  ]
98
195
 
99
196
  if (major, minor) >= (3, 11):
@@ -111,38 +208,89 @@ class CheckovTool(ToolGateway):
111
208
  logger.debug(INSTALL_SUCCESS_MSG)
112
209
  return "checkov"
113
210
  else:
114
- logger.error(f"Installation failed (attempt {attempt}): {result.stderr.decode().strip()}")
211
+ logger.error(
212
+ f"Installation failed (attempt {attempt}): {result.stderr.decode().strip()}"
213
+ )
115
214
  except Exception as e:
116
215
  logger.error(f"Error during installation (attempt {attempt}): {e}")
117
216
 
118
217
  retry(attempt)
119
218
 
120
219
  return None
121
-
122
- def execute(self, checkov_config: CheckovConfig, command_prefix):
123
- command = (
124
- f"{command_prefix} --config-file "
125
- + checkov_config.path_config_file
126
- + checkov_config.config_file_name
127
- + self.CHECKOV_CONFIG_FILE
128
- )
129
- env_modified = dict(os.environ)
130
- if checkov_config.env is not None:
131
- env_modified = {**dict(os.environ), **checkov_config.env}
132
- result = subprocess.run(
133
- command, capture_output=True, text=True, shell=True, env=env_modified
220
+
221
+ def _install_binary(self, config_tool):
222
+ os_platform = platform.system()
223
+ if os_platform == "Linux":
224
+ architecture = platform.machine()
225
+ if architecture == "aarch64":
226
+ url = config_tool["URL_FILE_LINUX_ARM64"]
227
+ else:
228
+ url = config_tool["URL_FILE_LINUX"]
229
+ file = os.path.basename(url)
230
+ self._install_tool_unix(file, url)
231
+ return "./checkov"
232
+ elif os_platform == "Darwin":
233
+ url = config_tool["URL_FILE_DARWIN"]
234
+ file = os.path.basename(url)
235
+ self._install_tool_unix(file, url)
236
+ return "./checkov"
237
+ elif os_platform == "Windows":
238
+ url = config_tool["URL_FILE_WINDOWS"]
239
+ file = os.path.basename(url)
240
+ self._install_tool_windows(file, url)
241
+ return "checkov.exe"
242
+ else:
243
+ logger.warning(f"{os_platform} is not supported.")
244
+ return None
245
+
246
+ def _install_tool_unix(self, file, url):
247
+ installed = subprocess.run(
248
+ ["which", "./checkov"],
249
+ stdout=subprocess.PIPE,
250
+ stderr=subprocess.PIPE,
134
251
  )
135
- output = result.stdout.strip()
136
- error = result.stderr.strip()
137
- return output
252
+ if installed.returncode == 1:
253
+ command = ["chmod", "+x", "./checkov"]
254
+ try:
255
+ self._download_tool(file, url)
256
+ with zipfile.ZipFile(file, "r") as zip_file:
257
+ zip_file.extract(member="dist/checkov")
258
+ source = os.path.join("dist", "checkov")
259
+ destination = "checkov"
260
+ shutil.move(source, destination)
261
+ subprocess.run(
262
+ command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
263
+ )
264
+ except Exception as e:
265
+ logger.error(f"Error installing Checkov: {e}")
138
266
 
139
- def async_scan(self, queue, checkov_config: CheckovConfig, command_prefix):
140
- result = []
141
- output = self.execute(checkov_config, command_prefix)
142
- result.append(json.loads(output))
143
- queue.put(result)
267
+ def _install_tool_windows(self, file, url):
268
+ try:
269
+ subprocess.run(
270
+ ["checkov.exe", "--version"],
271
+ stdout=subprocess.PIPE,
272
+ stderr=subprocess.PIPE,
273
+ )
274
+ except:
275
+ try:
276
+ self._download_tool(file, url)
277
+ with zipfile.ZipFile(file, "r") as zip_file:
278
+ zip_file.extract(member="dist/checkov.exe")
279
+ source = os.path.join("dist", "checkov.exe")
280
+ destination = "checkov.exe"
281
+ shutil.move(source, destination)
282
+ except Exception as e:
283
+ logger.error(f"Error installing Checkov: {e}")
144
284
 
145
- def scan_folders(
285
+ def _download_tool(self, file, url):
286
+ try:
287
+ response = requests.get(url, allow_redirects=True)
288
+ with open(file, "wb") as compress_file:
289
+ compress_file.write(response.content)
290
+ except Exception as e:
291
+ logger.error(f"Error downloading Checkov: {e}")
292
+
293
+ def _scan_folders(
146
294
  self,
147
295
  folders_to_scan,
148
296
  config_tool,
@@ -150,7 +298,7 @@ class CheckovTool(ToolGateway):
150
298
  environment,
151
299
  platform_to_scan,
152
300
  command_prefix,
153
- dict_args
301
+ dict_args,
154
302
  ):
155
303
  output_queue = queue.Queue()
156
304
  # Crea una lista para almacenar los hilos
@@ -163,7 +311,10 @@ class CheckovTool(ToolGateway):
163
311
  ):
164
312
  framework = [self.framework_mapping[rule]]
165
313
  repo_root = None
166
- if "terraform" in platform_to_scan or ("all" in platform_to_scan and self.framework_mapping[rule] == "terraform"):
314
+ if "terraform" in platform_to_scan or (
315
+ "all" in platform_to_scan
316
+ and self.framework_mapping[rule] == "terraform"
317
+ ):
167
318
  framework.append("terraform_plan")
168
319
  repo_root = dict_args.get("terraform_repo_root", None)
169
320
 
@@ -197,18 +348,14 @@ class CheckovTool(ToolGateway):
197
348
  else []
198
349
  ),
199
350
  repo_root_for_plan_enrichment=repo_root,
200
- deep_analysis=(
201
- True
202
- if repo_root
203
- else None
204
- )
351
+ deep_analysis=(True if repo_root else None),
205
352
  )
206
353
 
207
354
  checkov_config.create_config_dict()
208
- self.create_config_file(checkov_config)
355
+ self._create_config_file(checkov_config)
209
356
  rules_run.update(config_tool[self.TOOL_CHECKOV]["RULES"][rule])
210
357
  t = threading.Thread(
211
- target=self.async_scan,
358
+ target=self._async_scan,
212
359
  args=(output_queue, checkov_config, command_prefix),
213
360
  )
214
361
  t.start()
@@ -223,158 +370,35 @@ class CheckovTool(ToolGateway):
223
370
  result_scans.extend(result)
224
371
  return result_scans, rules_run
225
372
 
226
- def run_tool(
227
- self,
228
- config_tool,
229
- folders_to_scan,
230
- environment,
231
- platform_to_scan,
232
- secret_tool,
233
- secret_external_checks,
234
- **kwargs
235
- ):
236
- util = Utils()
237
- agent_env = util.configurate_external_checks(self.TOOL_CHECKOV,config_tool, secret_tool,secret_external_checks)
238
-
239
-
240
- install_type = config_tool[self.TOOL_CHECKOV].get("INSTALL_TYPE", "")
241
-
242
- command_prefix = None
243
-
244
- if install_type.casefold() == "remote-binary".casefold():
245
- command_prefix = self.install_binary(config_tool[self.TOOL_CHECKOV])
246
- else:
247
- command_prefix = self.retryable_install_package(
248
- "checkov", config_tool[self.TOOL_CHECKOV]["VERSION"]
249
- )
250
-
251
- if command_prefix is not None:
252
- result_scans, rules_run = self.scan_folders(
253
- folders_to_scan, config_tool, agent_env, environment, platform_to_scan, command_prefix, kwargs.get("dict_args")
254
- )
255
-
256
- checkov_deserealizator = CheckovDeserealizator()
257
- findings_list = checkov_deserealizator.get_list_finding(
258
- result_scans,
259
- rules_run,
260
- config_tool[self.TOOL_CHECKOV]["DEFAULT_SEVERITY"],
261
- config_tool[self.TOOL_CHECKOV]["DEFAULT_CATEGORY"]
262
- )
263
-
264
- return (
265
- findings_list,
266
- generate_file_from_tool(
267
- self.TOOL_CHECKOV,
268
- result_scans,
269
- rules_run,
270
- config_tool[self.TOOL_CHECKOV]["DEFAULT_SEVERITY"],
271
- config_tool[self.TOOL_CHECKOV]["DEFAULT_CATEGORY"]
272
- ),
273
- )
274
- else:
275
- return [], None
276
-
277
- def get_iac_context_from_results(
278
- self, path_file_results: str
279
- ):
280
- with open(path_file_results, "r") as file:
281
- context_results_scan_list = json.load(file)
282
- context_iac_list = []
283
- failed_checks = context_results_scan_list.get("results", {}).get("failed_checks", [])
284
- for check in failed_checks:
285
- file_line_range = check.get("file_line_range", ["unknown", "unknown"])
286
- start_line = file_line_range[0] if len(file_line_range) > 0 else "unknown"
287
- end_line = file_line_range[1] if len(file_line_range) > 1 else "unknown"
288
- line_range_str = f"{start_line}-{end_line}" if start_line != end_line else str(start_line)
289
-
290
- context_iac = ContextIac(
291
- id=check.get("check_id", "unknown"),
292
- check_name=check.get("check_name", "unknown"),
293
- check_class=check.get("check_class", "unknown"),
294
- severity=check.get("severity").lower(),
295
- where=f"{check.get('repo_file_path', 'unknown')}: {check.get('resource', 'unknown')} (line {line_range_str})",
296
- resource=check.get("resource", "unknown"),
297
- description=check.get("check_name", "unknown"),
298
- module="engine_iac",
299
- tool="Checkov"
300
- )
301
-
302
- context_iac_list.append(context_iac)
303
-
304
- print("===== BEGIN CONTEXT OUTPUT =====")
305
- print(json.dumps({"iac_context": [obj.__dict__ for obj in context_iac_list]}, indent=4))
306
- print("===== END CONTEXT OUTPUT =====")
307
-
373
+ def _create_config_file(self, checkov_config: CheckovConfig):
374
+ with open(
375
+ checkov_config.path_config_file
376
+ + checkov_config.config_file_name
377
+ + self.CHECKOV_CONFIG_FILE,
378
+ "w",
379
+ ) as file:
380
+ yaml.dump(checkov_config.dict_confg_file, file)
381
+ file.close()
308
382
 
309
- def install_binary(self,config_tool):
310
- os_platform = platform.system()
311
- if os_platform == "Linux":
312
- architecture = platform.machine()
313
- if architecture == "aarch64":
314
- url = config_tool["URL_FILE_LINUX_ARM64"]
315
- else:
316
- url = config_tool["URL_FILE_LINUX"]
317
- file = os.path.basename(url)
318
- self.install_tool_unix(file, url)
319
- return "./checkov"
320
- elif os_platform == "Darwin":
321
- url = config_tool["URL_FILE_DARWIN"]
322
- file = os.path.basename(url)
323
- self.install_tool_unix(file, url)
324
- return "./checkov"
325
- elif os_platform == "Windows":
326
- url = config_tool["URL_FILE_WINDOWS"]
327
- file = os.path.basename(url)
328
- self.install_tool_windows(file, url)
329
- return "checkov.exe"
330
- else:
331
- logger.warning(f"{os_platform} is not supported.")
332
- return None
333
-
334
-
335
- def download_tool(self, file, url):
336
- try:
337
- response = requests.get(url, allow_redirects=True)
338
- with open(file, "wb") as compress_file:
339
- compress_file.write(response.content)
340
- except Exception as e:
341
- logger.error(f"Error downloading Checkov: {e}")
383
+ def _async_scan(self, queue, checkov_config: CheckovConfig, command_prefix):
384
+ result = []
385
+ output = self._execute(checkov_config, command_prefix)
386
+ result.append(json.loads(output))
387
+ queue.put(result)
342
388
 
343
- def install_tool_unix(self, file, url):
344
- installed = subprocess.run(
345
- ["which", "./checkov"],
346
- stdout=subprocess.PIPE,
347
- stderr=subprocess.PIPE,
389
+ def _execute(self, checkov_config: CheckovConfig, command_prefix):
390
+ command = (
391
+ f"{command_prefix} --config-file "
392
+ + checkov_config.path_config_file
393
+ + checkov_config.config_file_name
394
+ + self.CHECKOV_CONFIG_FILE
348
395
  )
349
- if installed.returncode == 1:
350
- command = ["chmod", "+x", "./checkov"]
351
- try:
352
- self.download_tool(file, url)
353
- with zipfile.ZipFile(file, 'r') as zip_file:
354
- zip_file.extract(member="dist/checkov")
355
- source = os.path.join("dist", "checkov")
356
- destination = "checkov"
357
- shutil.move(source, destination)
358
- subprocess.run(
359
- command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
360
- )
361
- except Exception as e:
362
- logger.error(f"Error installing Checkov: {e}")
363
-
364
- def install_tool_windows(self, file, url):
365
- try:
366
- subprocess.run(
367
- ["checkov.exe", "--version"],
368
- stdout=subprocess.PIPE,
369
- stderr=subprocess.PIPE,
370
- )
371
- except:
372
- try:
373
- self.download_tool(file, url)
374
- with zipfile.ZipFile(file, 'r') as zip_file:
375
- zip_file.extract(member="dist/checkov.exe")
376
- source = os.path.join("dist", "checkov.exe")
377
- destination = "checkov.exe"
378
- shutil.move(source, destination)
379
- except Exception as e:
380
- logger.error(f"Error installing Checkov: {e}")
396
+ env_modified = dict(os.environ)
397
+ if checkov_config.env is not None:
398
+ env_modified = {**dict(os.environ), **checkov_config.env}
399
+ result = subprocess.run(
400
+ command, capture_output=True, text=True, shell=True, env=env_modified
401
+ )
402
+ output = result.stdout.strip()
403
+ error = result.stderr.strip()
404
+ return output