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
@@ -21,6 +21,7 @@ def init_engine_core(
21
21
  devops_platform_gateway: any,
22
22
  print_table_gateway: any,
23
23
  metrics_manager_gateway: any,
24
+ sbom_tool_gateway: any,
24
25
  args: any
25
26
  ):
26
27
  config_tool = devops_platform_gateway.get_remote_config(
@@ -28,7 +29,7 @@ def init_engine_core(
28
29
  )
29
30
  Printers.print_logo_tool(config_tool["BANNER"])
30
31
 
31
- if config_tool[args["tool"].upper()]["ENABLED"] == "true":
32
+ if config_tool[args["tool"].upper()]["ENABLED"]:
32
33
  if args["tool"] == "engine_risk":
33
34
  results, input_core = HandleRisk(
34
35
  vulnerability_management_gateway,
@@ -42,6 +43,7 @@ def init_engine_core(
42
43
  vulnerability_management_gateway,
43
44
  secrets_manager_gateway,
44
45
  devops_platform_gateway,
46
+ sbom_tool_gateway
45
47
  ).process(args, config_tool)
46
48
 
47
49
  results = BreakBuild(devops_platform_gateway, print_table_gateway).process(
@@ -115,7 +115,7 @@ class IacScan:
115
115
 
116
116
  if dict_args["folder_path"]:
117
117
  if (
118
- config_tool.update_service_file_name_cft == "True"
118
+ config_tool.update_service_file_name_cft
119
119
  and "cloudformation" in dict_args["platform"]
120
120
  ):
121
121
  files = os.listdir(os.path.join(os.getcwd(), dict_args["folder_path"]))
@@ -2,7 +2,6 @@ import yaml
2
2
  import subprocess
3
3
  import time
4
4
  import os
5
- import platform
6
5
  import queue
7
6
  import threading
8
7
  import json
@@ -171,7 +170,6 @@ class CheckovTool(ToolGateway):
171
170
  f"{config_tool[self.TOOL_CHECKOV]['EXTERNAL_CHECKS_GIT']}/{self.framework_mapping[rule]}"
172
171
  ]
173
172
  if config_tool[self.TOOL_CHECKOV]["USE_EXTERNAL_CHECKS_GIT"]
174
- == "True"
175
173
  and agent_env is not None
176
174
  and rule in self.framework_external_checks
177
175
  else []
@@ -180,7 +178,6 @@ class CheckovTool(ToolGateway):
180
178
  external_checks_dir=(
181
179
  f"/tmp/rules/{self.framework_mapping[rule]}"
182
180
  if config_tool[self.TOOL_CHECKOV]["USE_EXTERNAL_CHECKS_DIR"]
183
- == "True"
184
181
  and rule in self.framework_external_checks
185
182
  else []
186
183
  ),
@@ -3,5 +3,5 @@ from abc import ABCMeta, abstractmethod
3
3
 
4
4
  class ToolGateway(metaclass=ABCMeta):
5
5
  @abstractmethod
6
- def run_tool_container_sca(self, dict_args, secret_tool, token_engine_container, scan_image, release, base_image, exclusions) -> str:
6
+ def run_tool_container_sca(self, dict_args, secret_tool, token_engine_container, scan_image, release, base_image, exclusions, generate_sbom):
7
7
  "run tool container sca"
@@ -18,7 +18,7 @@ class ContainerScaScan:
18
18
  remote_config,
19
19
  tool_images: ImagesGateway,
20
20
  tool_deseralizator: DeseralizatorGateway,
21
- build_id,
21
+ branch,
22
22
  secret_tool,
23
23
  token_engine_container,
24
24
  image_to_scan,
@@ -28,7 +28,7 @@ class ContainerScaScan:
28
28
  self.remote_config = remote_config
29
29
  self.tool_images = tool_images
30
30
  self.tool_deseralizator = tool_deseralizator
31
- self.build_id = build_id
31
+ self.branch = branch
32
32
  self.secret_tool = secret_tool
33
33
  self.token_engine_container = token_engine_container
34
34
  self.image_to_scan = image_to_scan
@@ -82,19 +82,29 @@ class ContainerScaScan:
82
82
  matching_image = self.get_image(self.image_to_scan)
83
83
  if self.remote_config['GET_IMAGE_BASE']:
84
84
  base_image = self.get_base_image(matching_image)
85
+ sbom_components = None
86
+ generate_sbom = self.remote_config["SBOM"]["ENABLED"] and any(
87
+ branch in str(self.branch)
88
+ for branch in self.remote_config["SBOM"]["BRANCH_FILTER"]
89
+ )
85
90
  if matching_image:
86
91
  image_name = matching_image.tags[0]
87
- result_file = image_name.replace("/","_") + "_scan_result.json"
92
+ result_file = image_name.replace("/", "_") + "_scan_result.json"
88
93
  if image_name in self.get_images_already_scanned():
89
94
  print(f"The image {image_name} has already been scanned previously.")
90
- return image_scanned, base_image
91
- image_scanned = self.tool_run.run_tool_container_sca(
92
- self.remote_config, self.secret_tool, self.token_engine_container, image_name, result_file, base_image, self.exclusions
95
+ return image_scanned, base_image, sbom_components
96
+ image_scanned, sbom_components = self.tool_run.run_tool_container_sca(
97
+ self.remote_config,
98
+ self.secret_tool,
99
+ self.token_engine_container,
100
+ image_name,
101
+ result_file, base_image, self.exclusions,
102
+ generate_sbom,
93
103
  )
94
104
  self.set_image_scanned(image_name)
95
105
  else:
96
106
  print(f"'Not image found for {self.image_to_scan}'. Tool skipped.")
97
- return image_scanned, base_image
107
+ return image_scanned, base_image, sbom_components
98
108
 
99
109
  def deseralizator(self, image_scanned):
100
110
  """
@@ -8,6 +8,9 @@ import json
8
8
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.tool_gateway import (
9
9
  ToolGateway,
10
10
  )
11
+ from devsecops_engine_tools.engine_utilities.sbom.deserealizator import (
12
+ get_list_component,
13
+ )
11
14
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
12
15
  from devsecops_engine_tools.engine_utilities import settings
13
16
 
@@ -97,13 +100,53 @@ class PrismaCloudManagerScan(ToolGateway):
97
100
  except subprocess.CalledProcessError as e:
98
101
  logger.error(f"Error during write image base of {base_image}: {e.stderr}")
99
102
 
103
+ def _generate_sbom(self, image_scanned, remoteconfig, prisma_secret_key, image_name):
104
+
105
+ url = f"{remoteconfig['PRISMA_CLOUD']['PRISMA_CONSOLE_URL']}/api/{remoteconfig['PRISMA_CLOUD']['PRISMA_API_VERSION']}/sbom/download/cli-images"
106
+ credentials = base64.b64encode(
107
+ f"{remoteconfig['PRISMA_CLOUD']['PRISMA_ACCESS_KEY']}:{prisma_secret_key}".encode()
108
+ ).decode()
109
+ headers = {"Authorization": f"Basic {credentials}"}
110
+ try:
111
+
112
+ with open(image_scanned, "rb") as file:
113
+ image_object = file.read()
114
+ json_data = json.loads(image_object)
115
+
116
+ if not json_data["results"]:
117
+ print("No results found in the scan, SBOM not generated")
118
+ return None
119
+
120
+ response = requests.get(
121
+ url,
122
+ headers=headers,
123
+ params={
124
+ "id": json_data["results"][0]["scanID"],
125
+ "sbomFormat": remoteconfig["PRISMA_CLOUD"]["SBOM_FORMAT"],
126
+ },
127
+ )
128
+ response.raise_for_status()
129
+
130
+ result_sbom = f"{image_name.replace('/', '_')}_SBOM.json"
131
+ with open(result_sbom, "wb") as file:
132
+ file.write(response.content)
133
+
134
+ print(f"SBOM generated and saved to: {result_sbom}")
135
+
136
+ return get_list_component(result_sbom, remoteconfig["PRISMA_CLOUD"]["SBOM_FORMAT"])
137
+ except Exception as e:
138
+ logger.error(f"Error generating SBOM: {e}")
139
+
100
140
  def run_tool_container_sca(
101
- self, remoteconfig, secret_tool, token_engine_container, image_name, result_file, base_image, exclusions
141
+ self, remoteconfig, secret_tool, token_engine_container, image_name, result_file, base_image, exclusions, generate_sbom
102
142
  ):
103
- prisma_secret_key = secret_tool["token_prisma_cloud"] if secret_tool else token_engine_container
143
+ prisma_secret_key = (
144
+ secret_tool["token_prisma_cloud"] if secret_tool else token_engine_container
145
+ )
104
146
  file_path = os.path.join(
105
147
  os.getcwd(), remoteconfig["PRISMA_CLOUD"]["TWISTCLI_PATH"]
106
148
  )
149
+ sbom_components = None
107
150
 
108
151
  if not os.path.exists(file_path):
109
152
  self.download_twistcli(
@@ -122,5 +165,12 @@ class PrismaCloudManagerScan(ToolGateway):
122
165
  )
123
166
  if base_image:
124
167
  self._write_image_base(result_file, base_image, exclusions)
168
+ if generate_sbom:
169
+ sbom_components = self._generate_sbom(
170
+ image_scanned,
171
+ remoteconfig,
172
+ prisma_secret_key,
173
+ image_name
174
+ )
125
175
 
126
- return image_scanned
176
+ return image_scanned, sbom_components
@@ -12,6 +12,10 @@ import json
12
12
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
13
13
  from devsecops_engine_tools.engine_utilities import settings
14
14
 
15
+ from devsecops_engine_tools.engine_utilities.sbom.deserealizator import (
16
+ get_list_component,
17
+ )
18
+
15
19
  logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
16
20
 
17
21
 
@@ -24,9 +28,9 @@ class TrivyScan(ToolGateway):
24
28
  except Exception as e:
25
29
  logger.error(f"Error downloading trivy: {e}")
26
30
 
27
- def install_tool(self, file, url):
31
+ def install_tool(self, file, url, command_prefix):
28
32
  installed = subprocess.run(
29
- ["which", "./trivy"],
33
+ ["which", command_prefix],
30
34
  stdout=subprocess.PIPE,
31
35
  stderr=subprocess.PIPE,
32
36
  )
@@ -35,21 +39,26 @@ class TrivyScan(ToolGateway):
35
39
  self.download_tool(file, url)
36
40
  with tarfile.open(file, 'r:gz') as tar_file:
37
41
  tar_file.extract(member=tar_file.getmember("trivy"))
42
+ return "./trivy"
38
43
  except Exception as e:
39
44
  logger.error(f"Error installing trivy: {e}")
45
+ else:
46
+ return installed.stdout.decode().strip()
40
47
 
41
- def install_tool_windows(self, file, url):
48
+ def install_tool_windows(self, file, url, command_prefix):
42
49
  try:
43
50
  subprocess.run(
44
- ["./trivy.exe", "--version"],
51
+ [command_prefix, "--version"],
45
52
  stdout=subprocess.PIPE,
46
53
  stderr=subprocess.PIPE,
47
54
  )
55
+ return command_prefix
48
56
  except:
49
57
  try:
50
58
  self.download_tool(file, url)
51
59
  with zipfile.ZipFile(file, 'r') as zip_file:
52
60
  zip_file.extract(member="trivy.exe")
61
+ return "./trivy.exe"
53
62
  except Exception as e:
54
63
  logger.error(f"Error installing trivy: {e}")
55
64
 
@@ -79,24 +88,49 @@ class TrivyScan(ToolGateway):
79
88
  except Exception as e:
80
89
  logger.error(f"Error during image scan of {image_name}: {e}")
81
90
 
82
- def run_tool_container_sca(self, remoteconfig, secret_tool, token_engine_container, image_name, result_file ,base_image, exclusions):
91
+ def _generate_sbom(self, prefix, image_name, remoteconfig):
92
+ result_sbom = f"{image_name.replace('/', '_')}_SBOM.json"
93
+ command = [
94
+ prefix,
95
+ "image",
96
+ "--format",
97
+ remoteconfig["TRIVY"]["SBOM_FORMAT"],
98
+ "--output",
99
+ result_sbom
100
+ ]
101
+ command.extend(["--quiet", image_name])
102
+ try:
103
+ subprocess.run(
104
+ command,
105
+ check=True,
106
+ stdout=subprocess.PIPE,
107
+ stderr=subprocess.PIPE,
108
+ text=True,
109
+ )
110
+ print(f"SBOM generated and saved to: {result_sbom}")
111
+
112
+ return get_list_component(result_sbom, remoteconfig["TRIVY"]["SBOM_FORMAT"])
113
+
114
+ except Exception as e:
115
+ logger.error(f"Error generating SBOM: {e}")
116
+
117
+ def run_tool_container_sca(self, remoteconfig, secret_tool, token_engine_container, image_name, result_file, base_image, exclusions, generate_sbom):
83
118
  trivy_version = remoteconfig["TRIVY"]["TRIVY_VERSION"]
84
119
  os_platform = platform.system()
85
120
  arch_platform = platform.architecture()[0]
86
121
  base_url = f"https://github.com/aquasecurity/trivy/releases/download/v{trivy_version}/"
122
+ sbom_components = None
87
123
 
124
+ command_prefix = "trivy"
88
125
  if os_platform == "Linux":
89
126
  file=f"trivy_{trivy_version}_Linux-{arch_platform}.tar.gz"
90
- self.install_tool(file, base_url+file)
91
- command_prefix = "./trivy"
127
+ command_prefix = self.install_tool(file, base_url+file, "trivy")
92
128
  elif os_platform == "Darwin":
93
129
  file=f"trivy_{trivy_version}_macOS-{arch_platform}.tar.gz"
94
- self.install_tool(file, base_url+file)
95
- command_prefix = "./trivy"
130
+ command_prefix = self.install_tool(file, base_url+file, "trivy")
96
131
  elif os_platform == "Windows":
97
132
  file=f"trivy_{trivy_version}_windows-{arch_platform}.zip"
98
- self.install_tool_windows(file, base_url+file)
99
- command_prefix = "./trivy.exe"
133
+ command_prefix = self.install_tool_windows(file, base_url+file, "trivy.exe")
100
134
  else:
101
135
  logger.warning(f"{os_platform} is not supported.")
102
136
  return None
@@ -104,5 +138,7 @@ class TrivyScan(ToolGateway):
104
138
  image_scanned = (
105
139
  self.scan_image(command_prefix, image_name, result_file, base_image)
106
140
  )
141
+ if generate_sbom:
142
+ sbom_components = self._generate_sbom(command_prefix, image_name, remoteconfig)
107
143
 
108
- return image_scanned
144
+ return image_scanned, sbom_components
@@ -34,11 +34,12 @@ def init_engine_sca_rm(
34
34
  )
35
35
  skip_flag = handle_remote_config_patterns.skip_from_exclusion()
36
36
  scan_flag = handle_remote_config_patterns.ignore_analysis_pattern()
37
- build_id = tool_remote.get_variable("build_id")
37
+ branch = tool_remote.get_variable("branch_tag")
38
38
  stage = tool_remote.get_variable("stage")
39
39
  image_to_scan = dict_args["image_to_scan"]
40
40
  image_scanned = None
41
41
  base_image = None
42
+ sbom_components = None
42
43
  deseralized = []
43
44
  input_core = SetInputCore(remote_config, exclusions, pipeline_name, tool, stage)
44
45
  if scan_flag and not (skip_flag):
@@ -47,13 +48,13 @@ def init_engine_sca_rm(
47
48
  remote_config,
48
49
  tool_images,
49
50
  tool_deseralizator,
50
- build_id,
51
+ branch,
51
52
  secret_tool,
52
53
  dict_args["token_engine_container"],
53
54
  image_to_scan,
54
55
  exclusions
55
56
  )
56
- image_scanned,base_image = container_sca_scan.process()
57
+ image_scanned, base_image, sbom_components = container_sca_scan.process()
57
58
  if image_scanned:
58
59
  deseralized = container_sca_scan.deseralizator(image_scanned)
59
60
  else:
@@ -61,4 +62,4 @@ def init_engine_sca_rm(
61
62
  dict_args["send_metrics"] = "false"
62
63
  core_input = input_core.set_input_core(image_scanned,base_image)
63
64
 
64
- return deseralized, core_input
65
+ return deseralized, core_input, sbom_components
@@ -16,20 +16,22 @@ from devsecops_engine_tools.engine_sca.engine_dependencies.src.infrastructure.en
16
16
 
17
17
 
18
18
  def runner_engine_dependencies(
19
- dict_args, config_tool, secret_tool, devops_platform_gateway
19
+ dict_args, config_tool, secret_tool, devops_platform_gateway, sbom_tool_gateway
20
20
  ):
21
21
  try:
22
22
  tools_mapping = {
23
- "XRAY": {"tool_run": XrayScan, "tool_deserializator": XrayDeserializator},
23
+ "XRAY": {"tool_run": XrayScan, "tool_deserializator": XrayDeserializator, "tool_sbom": sbom_tool_gateway},
24
24
  "DEPENDENCY_CHECK": {
25
25
  "tool_run": DependencyCheckTool,
26
26
  "tool_deserializator": DependencyCheckDeserialize,
27
+ "tool_sbom": sbom_tool_gateway
27
28
  },
28
29
  }
29
30
 
30
31
  selected_tool = config_tool["ENGINE_DEPENDENCIES"]["TOOL"]
31
32
  tool_run = tools_mapping[selected_tool]["tool_run"]()
32
33
  tool_deserializator = tools_mapping[selected_tool]["tool_deserializator"]()
34
+ tool_sbom = tools_mapping[selected_tool]["tool_sbom"]
33
35
 
34
36
  return init_engine_dependencies(
35
37
  tool_run,
@@ -37,7 +39,8 @@ def runner_engine_dependencies(
37
39
  tool_deserializator,
38
40
  dict_args,
39
41
  secret_tool,
40
- config_tool["ENGINE_DEPENDENCIES"]["TOOL"],
42
+ config_tool,
43
+ tool_sbom
41
44
  )
42
45
 
43
46
  except Exception as e:
@@ -7,9 +7,14 @@ from devsecops_engine_tools.engine_sca.engine_dependencies.src.domain.usecases.s
7
7
  from devsecops_engine_tools.engine_sca.engine_dependencies.src.domain.usecases.handle_remote_config_patterns import (
8
8
  HandleRemoteConfigPatterns,
9
9
  )
10
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import (
11
+ DevopsPlatformGateway,
12
+ )
13
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.sbom_manager import (
14
+ SbomManagerGateway,
15
+ )
10
16
 
11
17
  import os
12
- import sys
13
18
 
14
19
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
15
20
  from devsecops_engine_tools.engine_utilities import settings
@@ -18,7 +23,13 @@ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
18
23
 
19
24
 
20
25
  def init_engine_dependencies(
21
- tool_run, tool_remote, tool_deserializator, dict_args, secret_tool, tool
26
+ tool_run,
27
+ tool_remote: DevopsPlatformGateway,
28
+ tool_deserializator,
29
+ dict_args,
30
+ secret_tool,
31
+ config_tool,
32
+ tool_sbom: SbomManagerGateway,
22
33
  ):
23
34
  remote_config = tool_remote.get_remote_config(
24
35
  dict_args["remote_config_repo"],
@@ -40,7 +51,14 @@ def init_engine_dependencies(
40
51
 
41
52
  dependencies_scanned = None
42
53
  deserialized = []
43
- input_core = SetInputCore(remote_config, exclusions, pipeline_name, tool)
54
+ sbom_components = None
55
+ config_sbom = config_tool["SBOM_MANAGER"]
56
+ input_core = SetInputCore(
57
+ remote_config,
58
+ exclusions,
59
+ pipeline_name,
60
+ config_tool["ENGINE_DEPENDENCIES"]["TOOL"],
61
+ )
44
62
 
45
63
  if scan_flag and not (skip_flag):
46
64
  to_scan = dict_args["folder_path"] if dict_args["folder_path"] else os.getcwd()
@@ -55,6 +73,15 @@ def init_engine_dependencies(
55
73
  to_scan,
56
74
  secret_tool,
57
75
  )
76
+ if config_sbom["ENABLED"] and any(
77
+ branch in str(tool_remote.get_variable("branch_tag"))
78
+ for branch in config_sbom["BRANCH_FILTER"]
79
+ ):
80
+ sbom_components = tool_sbom.get_components(
81
+ to_scan,
82
+ config_sbom,
83
+ pipeline_name
84
+ )
58
85
  dependencies_scanned = dependencies_sca_scan.process()
59
86
  deserialized = (
60
87
  dependencies_sca_scan.deserializator(dependencies_scanned)
@@ -69,4 +96,4 @@ def init_engine_dependencies(
69
96
 
70
97
  core_input = input_core.set_input_core(dependencies_scanned)
71
98
 
72
- return deserialized, core_input
99
+ return deserialized, core_input, sbom_components
@@ -4,4 +4,5 @@ from .applications.defect_dojo import DefectDojo
4
4
  from .applications.finding import Finding
5
5
  from .applications.connect import Connect
6
6
  from .applications.engagement import Engagement
7
- from .applications.product import Product
7
+ from .applications.product import Product
8
+ from .applications.component import Component
@@ -0,0 +1,29 @@
1
+ from devsecops_engine_tools.engine_utilities.utils.api_error import ApiError
2
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
3
+ from devsecops_engine_tools.engine_utilities.defect_dojo.infraestructure.driver_adapters.component import ComponentRestConsumer
4
+ from devsecops_engine_tools.engine_utilities.defect_dojo.domain.user_case.component import ComponentUserCase
5
+ from devsecops_engine_tools.engine_utilities.settings import SETTING_LOGGER
6
+
7
+ logger = MyLogger.__call__(**SETTING_LOGGER).get_logger()
8
+
9
+ class Component:
10
+
11
+ @staticmethod
12
+ def get_component(session, request: dict):
13
+ try:
14
+ rest_component = ComponentRestConsumer(session=session)
15
+ uc = ComponentUserCase(rest_component)
16
+ return uc.get(request)
17
+ except ApiError as e:
18
+ logger.error(f"Error during get component: {e}")
19
+ raise e
20
+
21
+ @staticmethod
22
+ def create_component(session, request):
23
+ try:
24
+ rest_component = ComponentRestConsumer(session=session)
25
+ uc = ComponentUserCase(rest_component)
26
+ return uc.post(request)
27
+ except ApiError as e:
28
+ logger.error(f"Error during create component: {e}")
29
+ raise e
@@ -0,0 +1,20 @@
1
+ import dataclasses
2
+ from typing import List
3
+ from devsecops_engine_tools.engine_utilities.utils.dataclass_classmethod import FromDictMixin
4
+
5
+
6
+ @dataclasses.dataclass
7
+ class Component(FromDictMixin):
8
+ id: int = 0
9
+ name: str = ""
10
+ version: str = ""
11
+ date: str = ""
12
+ Component_id: int = 0
13
+
14
+
15
+ @dataclasses.dataclass
16
+ class ComponentList(FromDictMixin):
17
+ count: int = 0
18
+ next = None
19
+ previous = None
20
+ results: List[Component] = dataclasses.field(default_factory=list)
@@ -0,0 +1,11 @@
1
+ from devsecops_engine_tools.engine_utilities.defect_dojo.infraestructure.driver_adapters.component import ComponentRestConsumer
2
+
3
+ class ComponentUserCase:
4
+ def __init__(self, rest_component: ComponentRestConsumer):
5
+ self.__rest_component = rest_component
6
+
7
+ def get(self, request):
8
+ return self.__rest_component.get_component(request)
9
+
10
+ def post(self, request):
11
+ return self.__rest_component.post_component(request)
@@ -0,0 +1,52 @@
1
+ import json
2
+ from devsecops_engine_tools.engine_utilities.utils.api_error import ApiError
3
+ from devsecops_engine_tools.engine_utilities.defect_dojo.infraestructure.driver_adapters.settings.settings import VERIFY_CERTIFICATE
4
+ from devsecops_engine_tools.engine_utilities.utils.session_manager import SessionManager
5
+ from devsecops_engine_tools.engine_utilities.settings import SETTING_LOGGER
6
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
7
+
8
+ from devsecops_engine_tools.engine_utilities.defect_dojo.domain.models.component import ComponentList, Component
9
+
10
+ logger = MyLogger.__call__(**SETTING_LOGGER).get_logger()
11
+
12
+
13
+ class ComponentRestConsumer:
14
+ def __init__(self, session: SessionManager):
15
+ self.__token = session._token
16
+ self.__host = session._host
17
+ self.__session = session._instance
18
+
19
+ def get_component(self, request):
20
+ url = f"{self.__host}/api/v2/components/"
21
+ headers = {
22
+ "Authorization": f"Token {self.__token}",
23
+ "Content-Type": "application/json",
24
+ }
25
+ try:
26
+ response = self.__session.get(
27
+ url=url, headers=headers, params=request, verify=VERIFY_CERTIFICATE
28
+ )
29
+ if response.status_code != 200:
30
+ logger.error(response.json())
31
+ raise ApiError(response.json())
32
+ components = ComponentList().from_dict(response.json())
33
+ except Exception as e:
34
+ raise ApiError(e)
35
+ return components
36
+
37
+ def post_component(self, request):
38
+ url = f"{self.__host}/api/v2/components/"
39
+ headers = {
40
+ "Authorization": f"Token {self.__token}",
41
+ "Content-Type": "application/json",
42
+ }
43
+ try:
44
+ response = self.__session.post(
45
+ url=url, headers=headers, data=json.dumps(request), verify=VERIFY_CERTIFICATE
46
+ )
47
+ if response.status_code != 201:
48
+ raise ApiError(response.json())
49
+ response = Component.from_dict(response.json())
50
+ except Exception as e:
51
+ raise ApiError(e)
52
+ return response
@@ -0,0 +1,24 @@
1
+ import json
2
+
3
+ from devsecops_engine_tools.engine_core.src.domain.model.component import Component
4
+
5
+
6
+ def get_list_component(result_sbom, format) -> "list[Component]":
7
+ list_components = []
8
+
9
+ with open(result_sbom, "rb") as file:
10
+ sbom_object = file.read()
11
+ json_data = json.loads(sbom_object)
12
+
13
+ if "cyclonedx" in format:
14
+ for component in json_data.get("components", []):
15
+ if component.get("version") != "UNKNOWN":
16
+ component_name = (
17
+ f"{component.get('group','')}_{component.get('name')}"
18
+ if component.get("group")
19
+ else component.get("name")
20
+ )
21
+ list_components.append(
22
+ Component(component_name, component.get("version"))
23
+ )
24
+ return list_components