devsecops-engine-tools 1.25.1__py3-none-any.whl → 1.26.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.

Files changed (33) hide show
  1. devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +6 -0
  2. devsecops_engine_tools/engine_core/src/domain/model/component.py +7 -0
  3. devsecops_engine_tools/engine_core/src/domain/model/gateway/sbom_manager.py +11 -0
  4. devsecops_engine_tools/engine_core/src/domain/model/gateway/vulnerability_management_gateway.py +6 -0
  5. devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py +125 -112
  6. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +73 -14
  7. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/syft/__init__.py +0 -0
  8. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/syft/syft.py +122 -0
  9. devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py +3 -1
  10. devsecops_engine_tools/engine_sast/engine_iac/src/domain/usecases/iac_scan.py +1 -1
  11. devsecops_engine_tools/engine_sast/engine_iac/src/infrastructure/driven_adapters/checkov/checkov_tool.py +0 -3
  12. devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/tool_gateway.py +1 -1
  13. devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py +17 -7
  14. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py +53 -3
  15. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py +48 -12
  16. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py +5 -4
  17. devsecops_engine_tools/engine_sca/engine_dependencies/src/applications/runner_dependencies_scan.py +6 -3
  18. devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/entry_points/entry_point_tool.py +31 -4
  19. devsecops_engine_tools/engine_utilities/defect_dojo/__init__.py +2 -1
  20. devsecops_engine_tools/engine_utilities/defect_dojo/applications/component.py +29 -0
  21. devsecops_engine_tools/engine_utilities/defect_dojo/domain/models/component.py +20 -0
  22. devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/component.py +11 -0
  23. devsecops_engine_tools/engine_utilities/defect_dojo/infraestructure/driver_adapters/component.py +52 -0
  24. devsecops_engine_tools/engine_utilities/sbom/__init__.py +0 -0
  25. devsecops_engine_tools/engine_utilities/sbom/deserealizator.py +24 -0
  26. devsecops_engine_tools/engine_utilities/sonarqube/src/infrastructure/entry_points/entry_point_report_sonar.py +32 -16
  27. devsecops_engine_tools/engine_utilities/utils/session_manager.py +4 -1
  28. devsecops_engine_tools/version.py +1 -1
  29. {devsecops_engine_tools-1.25.1.dist-info → devsecops_engine_tools-1.26.0.dist-info}/METADATA +1 -1
  30. {devsecops_engine_tools-1.25.1.dist-info → devsecops_engine_tools-1.26.0.dist-info}/RECORD +33 -23
  31. {devsecops_engine_tools-1.25.1.dist-info → devsecops_engine_tools-1.26.0.dist-info}/WHEEL +0 -0
  32. {devsecops_engine_tools-1.25.1.dist-info → devsecops_engine_tools-1.26.0.dist-info}/entry_points.txt +0 -0
  33. {devsecops_engine_tools-1.25.1.dist-info → devsecops_engine_tools-1.26.0.dist-info}/top_level.txt +0 -0
@@ -22,6 +22,7 @@ from devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.aws.s
22
22
  from devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.printer_pretty_table.printer_pretty_table import (
23
23
  PrinterPrettyTable,
24
24
  )
25
+ from devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.syft.syft import Syft
25
26
  import sys
26
27
  import argparse
27
28
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
@@ -115,6 +116,7 @@ def get_inputs_from_cli(args):
115
116
  choices=["true", "false"],
116
117
  type=str,
117
118
  required=False,
119
+ default="false",
118
120
  help="Use Secrets Manager to get the tokens",
119
121
  )
120
122
  parser.add_argument(
@@ -122,6 +124,7 @@ def get_inputs_from_cli(args):
122
124
  choices=["true", "false"],
123
125
  type=str,
124
126
  required=False,
127
+ default="false",
125
128
  help="Use Vulnerability Management to send the vulnerabilities to the platform",
126
129
  )
127
130
  parser.add_argument(
@@ -129,6 +132,7 @@ def get_inputs_from_cli(args):
129
132
  choices=["true", "false"],
130
133
  type=str,
131
134
  required=False,
135
+ default="false",
132
136
  help="Enable or Disable the send metrics to the driven adapter metrics",
133
137
  )
134
138
  parser.add_argument(
@@ -202,6 +206,7 @@ def application_core():
202
206
  }.get(args["platform_devops"])
203
207
  metrics_manager_gateway = S3Manager()
204
208
  printer_table_gateway = PrinterPrettyTable()
209
+ sbom_tool_gateway = Syft()
205
210
 
206
211
  init_engine_core(
207
212
  vulnerability_management_gateway,
@@ -209,6 +214,7 @@ def application_core():
209
214
  devops_platform_gateway,
210
215
  printer_table_gateway,
211
216
  metrics_manager_gateway,
217
+ sbom_tool_gateway,
212
218
  args,
213
219
  )
214
220
  except Exception as e:
@@ -0,0 +1,7 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class Component:
6
+ name: str
7
+ version: str
@@ -0,0 +1,11 @@
1
+ from abc import ABCMeta, abstractmethod
2
+ from devsecops_engine_tools.engine_core.src.domain.model.component import (
3
+ Component,
4
+ )
5
+
6
+ class SbomManagerGateway(metaclass=ABCMeta):
7
+ @abstractmethod
8
+ def get_components(
9
+ self, artifact, config, service_name
10
+ ) -> "list[Component]":
11
+ "get_components"
@@ -31,3 +31,9 @@ class VulnerabilityManagementGateway(metaclass=ABCMeta):
31
31
  self, engagement_name, dict_args, secret_tool, config_tool
32
32
  ):
33
33
  "get_active_engagements"
34
+
35
+ @abstractmethod
36
+ def send_sbom_components(
37
+ self, sbom_components, service, dict_args, secret_tool, config_tool
38
+ ):
39
+ "send_sbom_components"
@@ -19,6 +19,9 @@ from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform
19
19
  from devsecops_engine_tools.engine_core.src.domain.model.vulnerability_management import (
20
20
  VulnerabilityManagement,
21
21
  )
22
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.sbom_manager import (
23
+ SbomManagerGateway,
24
+ )
22
25
  from devsecops_engine_tools.engine_core.src.domain.model.input_core import InputCore
23
26
  from devsecops_engine_tools.engine_core.src.domain.model.level_vulnerability import (
24
27
  LevelVulnerability,
@@ -51,83 +54,12 @@ class HandleScan:
51
54
  vulnerability_management: VulnerabilityManagementGateway,
52
55
  secrets_manager_gateway: SecretsManagerGateway,
53
56
  devops_platform_gateway: DevopsPlatformGateway,
57
+ sbom_tool_gateway: SbomManagerGateway,
54
58
  ):
55
59
  self.vulnerability_management = vulnerability_management
56
60
  self.secrets_manager_gateway = secrets_manager_gateway
57
61
  self.devops_platform_gateway = devops_platform_gateway
58
-
59
- def _define_threshold_quality_vuln(
60
- self, input_core: InputCore, dict_args, secret_tool, config_tool
61
- ):
62
- quality_vulnerability_management = (
63
- input_core.threshold_defined.quality_vulnerability_management
64
- )
65
- if quality_vulnerability_management:
66
- product_type = self.vulnerability_management.get_product_type_service(
67
- input_core.scope_pipeline, dict_args, secret_tool, config_tool
68
- )
69
- if product_type:
70
- pt_name = product_type.name
71
- apply_qualitypt = next(
72
- filter(
73
- lambda qapt: pt_name in qapt,
74
- quality_vulnerability_management["PTS"],
75
- ),
76
- None,
77
- )
78
- if apply_qualitypt:
79
- pt_info = apply_qualitypt[pt_name]
80
- pt_profile = pt_info["PROFILE"]
81
- pt_apps = pt_info["APPS"]
82
-
83
- input_core.threshold_defined.vulnerability = (
84
- LevelVulnerability(quality_vulnerability_management[pt_profile])
85
- if pt_apps == "ALL"
86
- or any(map(lambda pd: pd in input_core.scope_pipeline, pt_apps))
87
- else input_core.threshold_defined.vulnerability
88
- )
89
-
90
- def _use_vulnerability_management(
91
- self, config_tool, input_core, dict_args, secret_tool, env
92
- ):
93
- try:
94
- self.vulnerability_management.send_vulnerability_management(
95
- VulnerabilityManagement(
96
- config_tool[dict_args["tool"].upper()]["TOOL"],
97
- input_core,
98
- dict_args,
99
- secret_tool,
100
- config_tool,
101
- self.devops_platform_gateway.get_source_code_management_uri(),
102
- self.devops_platform_gateway.get_base_compact_remote_config_url(
103
- dict_args["remote_config_repo"]
104
- ),
105
- self.devops_platform_gateway.get_variable("access_token"),
106
- self.devops_platform_gateway.get_variable("build_execution_id"),
107
- self.devops_platform_gateway.get_variable("build_id"),
108
- self.devops_platform_gateway.get_variable("branch_tag"),
109
- self.devops_platform_gateway.get_variable("commit_hash"),
110
- env,
111
- )
112
- )
113
-
114
- self._define_threshold_quality_vuln(
115
- input_core, dict_args, secret_tool, config_tool
116
- )
117
-
118
- except ExceptionVulnerabilityManagement as ex1:
119
- logger.error(str(ex1))
120
- try:
121
- input_core.totalized_exclusions.extend(
122
- self.vulnerability_management.get_findings_excepted(
123
- input_core.scope_pipeline,
124
- dict_args,
125
- secret_tool,
126
- config_tool,
127
- )
128
- )
129
- except ExceptionFindingsExcepted as ex2:
130
- logger.error(str(ex2))
62
+ self.sbom_tool_gateway = sbom_tool_gateway
131
63
 
132
64
  def process(self, dict_args: any, config_tool: any):
133
65
  secret_tool = None
@@ -145,28 +77,25 @@ class HandleScan:
145
77
  self.devops_platform_gateway,
146
78
  env,
147
79
  )
148
- if (
149
- dict_args["use_vulnerability_management"] == "true"
150
- and input_core.path_file_results
151
- ):
152
- self._use_vulnerability_management(
153
- config_tool, input_core, dict_args, secret_tool, env
154
- )
80
+ self._use_vulnerability_management(
81
+ config_tool, input_core, dict_args, secret_tool, env
82
+ )
155
83
  return findings_list, input_core
156
84
  elif "engine_container" in dict_args["tool"]:
157
- findings_list, input_core = runner_engine_container(
85
+ findings_list, input_core, sbom_components = runner_engine_container(
158
86
  dict_args,
159
87
  config_tool["ENGINE_CONTAINER"]["TOOL"],
160
88
  secret_tool,
161
89
  self.devops_platform_gateway,
162
90
  )
163
- if (
164
- dict_args["use_vulnerability_management"] == "true"
165
- and input_core.path_file_results
166
- ):
167
- self._use_vulnerability_management(
168
- config_tool, input_core, dict_args, secret_tool, env
169
- )
91
+ self._use_vulnerability_management(
92
+ config_tool,
93
+ input_core,
94
+ dict_args,
95
+ secret_tool,
96
+ env,
97
+ sbom_components,
98
+ )
170
99
  return findings_list, input_core
171
100
  elif "engine_dast" in dict_args["tool"]:
172
101
  print(MESSAGE_ENABLED)
@@ -176,39 +105,123 @@ class HandleScan:
176
105
  config_tool["ENGINE_CODE"]["TOOL"],
177
106
  self.devops_platform_gateway,
178
107
  )
179
- if (
180
- dict_args["use_vulnerability_management"] == "true"
181
- and input_core.path_file_results
182
- ):
183
- self._use_vulnerability_management(
184
- config_tool, input_core, dict_args, secret_tool, env
185
- )
108
+ self._use_vulnerability_management(
109
+ config_tool, input_core, dict_args, secret_tool, env
110
+ )
186
111
  return findings_list, input_core
187
112
  elif "engine_secret" in dict_args["tool"]:
188
113
  findings_list, input_core = runner_secret_scan(
189
114
  dict_args,
190
115
  config_tool["ENGINE_SECRET"]["TOOL"],
191
116
  self.devops_platform_gateway,
192
- secret_tool
117
+ secret_tool,
118
+ )
119
+ self._use_vulnerability_management(
120
+ config_tool, input_core, dict_args, secret_tool, env
193
121
  )
194
- if (
195
- dict_args["use_vulnerability_management"] == "true"
196
- and input_core.path_file_results
197
- ):
198
- self._use_vulnerability_management(
199
- config_tool, input_core, dict_args, secret_tool, env
200
- )
201
122
  return findings_list, input_core
202
123
  elif "engine_dependencies" in dict_args["tool"]:
203
- findings_list, input_core = runner_engine_dependencies(
204
- dict_args, config_tool, secret_tool, self.devops_platform_gateway
124
+ findings_list, input_core, sbom_components = runner_engine_dependencies(
125
+ dict_args, config_tool, secret_tool, self.devops_platform_gateway, self.sbom_tool_gateway
205
126
  )
127
+ self._use_vulnerability_management(
128
+ config_tool,
129
+ input_core,
130
+ dict_args,
131
+ secret_tool,
132
+ env,
133
+ sbom_components
134
+ )
135
+ return findings_list, input_core
136
+
137
+ def _define_threshold_quality_vuln(
138
+ self, input_core: InputCore, dict_args, secret_tool, config_tool
139
+ ):
140
+ quality_vulnerability_management = (
141
+ input_core.threshold_defined.quality_vulnerability_management
142
+ )
143
+ if quality_vulnerability_management:
144
+ product_type = self.vulnerability_management.get_product_type_service(
145
+ input_core.scope_pipeline, dict_args, secret_tool, config_tool
146
+ )
147
+ if product_type:
148
+ pt_name = product_type.name
149
+ apply_qualitypt = next(
150
+ filter(
151
+ lambda qapt: pt_name in qapt,
152
+ quality_vulnerability_management["PTS"],
153
+ ),
154
+ None,
155
+ )
156
+ if apply_qualitypt:
157
+ pt_info = apply_qualitypt[pt_name]
158
+ pt_profile = pt_info["PROFILE"]
159
+ pt_apps = pt_info["APPS"]
206
160
 
207
- if (
208
- dict_args["use_vulnerability_management"] == "true"
209
- and input_core.path_file_results
210
- ):
211
- self._use_vulnerability_management(
212
- config_tool, input_core, dict_args, secret_tool, env
161
+ input_core.threshold_defined.vulnerability = (
162
+ LevelVulnerability(quality_vulnerability_management[pt_profile])
163
+ if pt_apps == "ALL"
164
+ or any(map(lambda pd: pd in input_core.scope_pipeline, pt_apps))
165
+ else input_core.threshold_defined.vulnerability
166
+ )
167
+
168
+ def _use_vulnerability_management(
169
+ self,
170
+ config_tool,
171
+ input_core: InputCore,
172
+ dict_args,
173
+ secret_tool,
174
+ env,
175
+ sbom_components=None,
176
+ ):
177
+ if dict_args["use_vulnerability_management"] == "true":
178
+ try:
179
+ if input_core.path_file_results:
180
+ self.vulnerability_management.send_vulnerability_management(
181
+ VulnerabilityManagement(
182
+ config_tool[dict_args["tool"].upper()]["TOOL"],
183
+ input_core,
184
+ dict_args,
185
+ secret_tool,
186
+ config_tool,
187
+ self.devops_platform_gateway.get_source_code_management_uri(),
188
+ self.devops_platform_gateway.get_base_compact_remote_config_url(
189
+ dict_args["remote_config_repo"]
190
+ ),
191
+ self.devops_platform_gateway.get_variable("access_token"),
192
+ self.devops_platform_gateway.get_variable(
193
+ "build_execution_id"
194
+ ),
195
+ self.devops_platform_gateway.get_variable("build_id"),
196
+ self.devops_platform_gateway.get_variable("branch_tag"),
197
+ self.devops_platform_gateway.get_variable("commit_hash"),
198
+ env,
199
+ )
200
+ )
201
+
202
+ if sbom_components:
203
+ self.vulnerability_management.send_sbom_components(
204
+ sbom_components,
205
+ input_core.scope_pipeline,
206
+ dict_args,
207
+ secret_tool,
208
+ config_tool,
209
+ )
210
+
211
+ self._define_threshold_quality_vuln(
212
+ input_core, dict_args, secret_tool, config_tool
213
213
  )
214
- return findings_list, input_core
214
+
215
+ except ExceptionVulnerabilityManagement as ex1:
216
+ logger.error(str(ex1))
217
+ try:
218
+ input_core.totalized_exclusions.extend(
219
+ self.vulnerability_management.get_findings_excepted(
220
+ input_core.scope_pipeline,
221
+ dict_args,
222
+ secret_tool,
223
+ config_tool,
224
+ )
225
+ )
226
+ except ExceptionFindingsExcepted as ex2:
227
+ logger.error(str(ex2))
@@ -5,9 +5,6 @@ from devsecops_engine_tools.engine_core.src.domain.model.gateway.vulnerability_m
5
5
  from devsecops_engine_tools.engine_core.src.domain.model.vulnerability_management import (
6
6
  VulnerabilityManagement,
7
7
  )
8
- from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import (
9
- DevopsPlatformGateway
10
- )
11
8
  from devsecops_engine_tools.engine_utilities.defect_dojo import (
12
9
  DefectDojo,
13
10
  ImportScanRequest,
@@ -15,6 +12,7 @@ from devsecops_engine_tools.engine_utilities.defect_dojo import (
15
12
  Finding,
16
13
  Engagement,
17
14
  Product,
15
+ Component,
18
16
  )
19
17
  from devsecops_engine_tools.engine_core.src.domain.model.exclusions import Exclusions
20
18
  from devsecops_engine_tools.engine_core.src.domain.model.report import Report
@@ -33,6 +31,7 @@ from functools import partial
33
31
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
34
32
  from devsecops_engine_tools.engine_utilities import settings
35
33
  import time
34
+ import concurrent.futures
36
35
 
37
36
  logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
38
37
 
@@ -76,14 +75,14 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
76
75
  "KICS": "KICS Scanner",
77
76
  "BEARER": "Bearer CLI",
78
77
  "DEPENDENCY_CHECK": "Dependency Check Scan",
79
- "SONARQUBE": "SonarQube API Import"
78
+ "SONARQUBE": "SonarQube API Import",
80
79
  }
81
80
 
82
81
  if any(
83
82
  branch in str(vulnerability_management.branch_tag)
84
83
  for branch in vulnerability_management.config_tool[
85
84
  "VULNERABILITY_MANAGER"
86
- ]["BRANCH_FILTER"].split(",")
85
+ ]["BRANCH_FILTER"]
87
86
  ) or (vulnerability_management.dict_args["tool"] == "engine_secret"):
88
87
  tags = vulnerability_management.dict_args["tool"]
89
88
  if vulnerability_management.dict_args["tool"] == "engine_iac":
@@ -178,7 +177,11 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
178
177
  "prefetch": "prod_type",
179
178
  },
180
179
  )
181
- return response.prefetch.prod_type[str(response.results[0].prod_type)] if response.prefetch else None
180
+ return (
181
+ response.prefetch.prod_type[str(response.results[0].prod_type)]
182
+ if response.prefetch
183
+ else None
184
+ )
182
185
 
183
186
  return self._retries_requests(request_func, dd_max_retries, retry_delay=5)
184
187
 
@@ -282,12 +285,14 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
282
285
  "limit": config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"][
283
286
  "LIMITS_QUERY"
284
287
  ],
285
- "duplicate": "false"
288
+ "duplicate": "false",
286
289
  }
287
290
  max_retries = config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"][
288
291
  "MAX_RETRIES_QUERY"
289
292
  ]
290
- host_dd = config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"]["HOST_DEFECT_DOJO"]
293
+ host_dd = config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"][
294
+ "HOST_DEFECT_DOJO"
295
+ ]
291
296
 
292
297
  findings = self._get_findings(
293
298
  self._get_session_manager(dict_args, secret_tool, config_tool),
@@ -337,7 +342,9 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
337
342
 
338
343
  engagements = Engagement.get_engagements(request_is, request_active).results
339
344
 
340
- host_dd = config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"]["HOST_DEFECT_DOJO"]
345
+ host_dd = config_tool["VULNERABILITY_MANAGER"]["DEFECT_DOJO"][
346
+ "HOST_DEFECT_DOJO"
347
+ ]
341
348
 
342
349
  for engagement in engagements:
343
350
  engagement.vm_url = f"{host_dd}/engagement/{engagement.id}/finding/open"
@@ -349,6 +356,53 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
349
356
  "Error getting engagements with the following error: {0} ".format(ex)
350
357
  )
351
358
 
359
+ def send_sbom_components(
360
+ self, sbom_components, service, dict_args, secret_tool, config_tool
361
+ ):
362
+ try:
363
+ engagements = self.get_active_engagements(
364
+ service, dict_args, secret_tool, config_tool
365
+ )
366
+ engagement = [
367
+ engagement for engagement in engagements if engagement.name == service
368
+ ]
369
+ session_manager = self._get_session_manager(
370
+ dict_args, secret_tool, config_tool
371
+ )
372
+
373
+ with concurrent.futures.ThreadPoolExecutor(max_workers=25) as executor:
374
+ _ = [
375
+ executor.submit(
376
+ self._process_component,
377
+ sbom_component,
378
+ session_manager,
379
+ engagement,
380
+ )
381
+ for sbom_component in sbom_components
382
+ ]
383
+
384
+ except Exception as ex:
385
+ raise ExceptionVulnerabilityManagement(
386
+ "Error sending components sbom to vulnerability management with the following error: {0} ".format(
387
+ ex
388
+ )
389
+ )
390
+
391
+ def _process_component(self, component_sbom, session_manager, engagement):
392
+ request = {
393
+ "name": component_sbom.name,
394
+ "version": component_sbom.version,
395
+ "engagement_id": engagement[0].id,
396
+ }
397
+ components = Component.get_component(session=session_manager, request=request)
398
+ if components.results == []:
399
+ response = Component.create_component(
400
+ session=session_manager, request=request
401
+ )
402
+ logger.info(
403
+ f"Component created: {response.name} - {response.version} found with id: {response.id}"
404
+ )
405
+
352
406
  def _get_session_manager(self, dict_args, secret_tool, config_tool):
353
407
  token_dd = dict_args.get("token_vulnerability_management") or secret_tool.get(
354
408
  "token_defect_dojo"
@@ -382,7 +436,11 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
382
436
  elif finding.risk_status == "Transfer Accepted":
383
437
  exclusions.append(
384
438
  self._create_report_exclusion(
385
- finding, date_fn, "engine_risk", self.TRANSFERRED_FINDING, host_dd
439
+ finding,
440
+ date_fn,
441
+ "engine_risk",
442
+ self.TRANSFERRED_FINDING,
443
+ host_dd,
386
444
  )
387
445
  )
388
446
  return exclusions
@@ -433,7 +491,6 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
433
491
 
434
492
  return create_date, expired_date
435
493
 
436
-
437
494
  def _create_exclusion(self, finding, date_fn, tool, reason):
438
495
  create_date, expired_date = self._date_reason_based(finding, date_fn, reason)
439
496
 
@@ -445,7 +502,7 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
445
502
  severity=finding.severity,
446
503
  reason=reason,
447
504
  )
448
-
505
+
449
506
  def _create_report_exclusion(self, finding, date_fn, tool, reason, host_dd):
450
507
  create_date, expired_date = self._date_reason_based(finding, date_fn, reason)
451
508
 
@@ -493,7 +550,7 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
493
550
  false_p=finding.false_p,
494
551
  out_of_scope=finding.out_of_scope,
495
552
  service=finding.service,
496
- unique_id_from_tool=finding.unique_id_from_tool
553
+ unique_id_from_tool=finding.unique_id_from_tool,
497
554
  )
498
555
 
499
556
  def _format_date_to_dd_format(self, date_string):
@@ -504,7 +561,9 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
504
561
  )
505
562
 
506
563
  def _get_where(self, finding, tool):
507
- if tool in ["engine_container", "engine_dependencies"]:
564
+ if tool == "engine_dependencies":
565
+ return finding.component_name.replace("_", ":") + ":" + finding.component_version
566
+ elif tool == "engine_container":
508
567
  return finding.component_name + ":" + finding.component_version
509
568
  elif tool == "engine_dast":
510
569
  return finding.endpoints
@@ -0,0 +1,122 @@
1
+ from dataclasses import dataclass
2
+ import requests
3
+ import subprocess
4
+ import tarfile
5
+ import zipfile
6
+ import platform
7
+
8
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.sbom_manager import (
9
+ SbomManagerGateway,
10
+ )
11
+ from devsecops_engine_tools.engine_utilities.sbom.deserealizator import (
12
+ get_list_component,
13
+ )
14
+ from devsecops_engine_tools.engine_core.src.domain.model.component import (
15
+ Component,
16
+ )
17
+
18
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
19
+ from devsecops_engine_tools.engine_utilities import settings
20
+
21
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
22
+
23
+
24
+ @dataclass
25
+ class Syft(SbomManagerGateway):
26
+
27
+ def get_components(self, artifact, config, service_name) -> "list[Component]":
28
+ try:
29
+ syft_version = config["SYFT"]["SYFT_VERSION"]
30
+ os_platform = platform.system()
31
+ base_url = (
32
+ f"https://github.com/anchore/syft/releases/download/v{syft_version}/"
33
+ )
34
+
35
+ command_prefix = "syft"
36
+ if os_platform == "Linux":
37
+ file = f"syft_{syft_version}_linux_amd64.tar.gz"
38
+ command_prefix = self._install_tool_unix(
39
+ file, base_url + file, command_prefix
40
+ )
41
+ elif os_platform == "Darwin":
42
+ file = f"syft_{syft_version}_darwin_amd64.tar.gz"
43
+ command_prefix = self._install_tool_unix(
44
+ file, base_url + file, command_prefix
45
+ )
46
+ elif os_platform == "Windows":
47
+ file = f"syft_{syft_version}_windows_amd64.zip"
48
+ command_prefix = self._install_tool_windows(
49
+ file, base_url + file, "syft.exe"
50
+ )
51
+ else:
52
+ logger.warning(f"{os_platform} is not supported.")
53
+ return None
54
+
55
+ result_sbom = self._run_syft(command_prefix, artifact, config, service_name)
56
+ return get_list_component(result_sbom, config["SYFT"]["OUTPUT_FORMAT"])
57
+ except Exception as e:
58
+ logger.error(f"Error generating SBOM: {e}")
59
+ return None
60
+
61
+ def _run_syft(self, command_prefix, artifact, config, service_name):
62
+ result_file = f"{service_name}_SBOM.json"
63
+ command = [
64
+ command_prefix,
65
+ artifact,
66
+ "-o",
67
+ f"{config['SYFT']['OUTPUT_FORMAT']}={result_file}",
68
+ ]
69
+ try:
70
+ subprocess.run(
71
+ command,
72
+ check=True,
73
+ stdout=subprocess.PIPE,
74
+ stderr=subprocess.PIPE,
75
+ text=True,
76
+ )
77
+ print(f"SBOM generated and saved to: {result_file}")
78
+ return result_file
79
+ except Exception as e:
80
+ logger.error(f"Error running syft: {e}")
81
+
82
+ def _install_tool_unix(self, file, url, command_prefix):
83
+ installed = subprocess.run(
84
+ ["which", command_prefix],
85
+ stdout=subprocess.PIPE,
86
+ stderr=subprocess.PIPE,
87
+ )
88
+ if installed.returncode == 1:
89
+ try:
90
+ self._download_tool(file, url)
91
+ with tarfile.open(file, "r:gz") as tar_file:
92
+ tar_file.extract(member=tar_file.getmember("syft"))
93
+ return "./syft"
94
+ except Exception as e:
95
+ logger.error(f"Error installing syft: {e}")
96
+ else:
97
+ return installed.stdout.decode("utf-8").strip()
98
+
99
+ def _install_tool_windows(self, file, url, command_prefix):
100
+ try:
101
+ installed = subprocess.run(
102
+ [command_prefix, "--version"],
103
+ stdout=subprocess.PIPE,
104
+ stderr=subprocess.PIPE,
105
+ )
106
+ return installed.stdout.decode("utf-8").strip()
107
+ except:
108
+ try:
109
+ self._download_tool(file, url)
110
+ with zipfile.ZipFile(file, "r") as zip_file:
111
+ zip_file.extract(member="syft.exe")
112
+ return "./syft.exe"
113
+ except Exception as e:
114
+ logger.error(f"Error installing syft: {e}")
115
+
116
+ def _download_tool(self, file, url):
117
+ try:
118
+ response = requests.get(url, allow_redirects=True)
119
+ with open(file, "wb") as compress_file:
120
+ compress_file.write(response.content)
121
+ except Exception as e:
122
+ logger.error(f"Error downloading syft: {e}")