devsecops-engine-tools 1.7.16__py3-none-any.whl → 1.7.17__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 (16) hide show
  1. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +1 -0
  2. devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py +39 -5
  3. devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py +2 -2
  4. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py +9 -2
  5. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py +51 -70
  6. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py +32 -33
  7. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py +47 -35
  8. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py +81 -89
  9. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py +5 -4
  10. devsecops_engine_tools/version.py +1 -1
  11. {devsecops_engine_tools-1.7.16.dist-info → devsecops_engine_tools-1.7.17.dist-info}/METADATA +1 -1
  12. {devsecops_engine_tools-1.7.16.dist-info → devsecops_engine_tools-1.7.17.dist-info}/RECORD +15 -16
  13. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/helpers/images_scanned.py +0 -16
  14. {devsecops_engine_tools-1.7.16.dist-info → devsecops_engine_tools-1.7.17.dist-info}/WHEEL +0 -0
  15. {devsecops_engine_tools-1.7.16.dist-info → devsecops_engine_tools-1.7.17.dist-info}/entry_points.txt +0 -0
  16. {devsecops_engine_tools-1.7.16.dist-info → devsecops_engine_tools-1.7.17.dist-info}/top_level.txt +0 -0
@@ -54,6 +54,7 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
54
54
  "PRISMA": "Twistlock Image Scan",
55
55
  "XRAY": "JFrog Xray On Demand Binary Scan",
56
56
  "TRUFFLEHOG": "Trufflehog Scan",
57
+ "TRIVY": "Trivy Scan",
57
58
  }
58
59
 
59
60
  if any(
@@ -8,6 +8,8 @@ from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateway
8
8
  DeseralizatorGateway,
9
9
  )
10
10
 
11
+ import os
12
+
11
13
 
12
14
  class ContainerScaScan:
13
15
  def __init__(
@@ -26,7 +28,7 @@ class ContainerScaScan:
26
28
  self.build_id = build_id
27
29
  self.token = token
28
30
 
29
- def scan_image(self):
31
+ def get_latest_image(self):
30
32
  """
31
33
  Process the list of images.
32
34
 
@@ -35,16 +37,48 @@ class ContainerScaScan:
35
37
  """
36
38
  return self.tool_images.list_images()
37
39
 
40
+ def get_images_already_scanned(self):
41
+ """
42
+ Create images scanned file if it does not exist and get the images that have already been scanned.
43
+ """
44
+ scanned_images_file = os.path.join(os.getcwd(), "scanned_images.txt")
45
+ if not os.path.exists(scanned_images_file):
46
+ open(scanned_images_file, "w").close()
47
+ with open(scanned_images_file, "r") as file:
48
+ images_scanned = file.read().splitlines()
49
+ return images_scanned
50
+
51
+ def set_image_scanned(self, result_file):
52
+ """
53
+ Write in scanned_images.txt the result file
54
+ """
55
+ with open("scanned_images.txt", "a") as file:
56
+ file.write(result_file + "\n")
57
+
38
58
  def process(self):
39
59
  """
40
60
  Process SCA scanning.
41
61
 
42
62
  Returns:
43
- dict: SCA scanning results.
63
+ string: file scanning results name.
44
64
  """
45
- return self.tool_run.run_tool_container_sca(
46
- self.remote_config, self.token, self.scan_image(), self.build_id
47
- )
65
+ latest_image = self.get_latest_image()
66
+ image_name = latest_image.tags[0]
67
+ image_scanned = None
68
+ if str(self.build_id) in image_name:
69
+ result_file = image_name + "_scan_result.json"
70
+ if result_file in self.get_images_already_scanned():
71
+ print(f"The image {image_name} has already been scanned previously.")
72
+ return image_scanned
73
+ image_scanned = self.tool_run.run_tool_container_sca(
74
+ self.remote_config, self.token, image_name, result_file
75
+ )
76
+ self.set_image_scanned(result_file)
77
+ else:
78
+ print(
79
+ f"'{image_name}' name does not contain build number '{self.build_id}'. Tool skipped."
80
+ )
81
+ return image_scanned
48
82
 
49
83
  def deseralizator(self, image_scanned):
50
84
  """
@@ -31,7 +31,7 @@ class SetInputCore:
31
31
  ]
32
32
  return list_exclusions
33
33
 
34
- def set_input_core(self, images_scanned):
34
+ def set_input_core(self, image_scanned):
35
35
  """
36
36
  Set the input core.
37
37
 
@@ -45,7 +45,7 @@ class SetInputCore:
45
45
  self.tool,
46
46
  ),
47
47
  Threshold(self.remote_config["THRESHOLD"]),
48
- images_scanned[-1] if images_scanned else None,
48
+ image_scanned,
49
49
  self.remote_config["MESSAGE_INFO_ENGINE_CONTAINER"],
50
50
  self.pipeline_name,
51
51
  self.stage.capitalize(),
@@ -4,6 +4,11 @@ from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateway
4
4
  )
5
5
  import docker
6
6
 
7
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
8
+ from devsecops_engine_tools.engine_utilities import settings
9
+
10
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
11
+
7
12
 
8
13
  class DockerImages(ImagesGateway):
9
14
  def list_images(self):
@@ -18,5 +23,7 @@ class DockerImages(ImagesGateway):
18
23
  print("Tag last image:", latest_image.tags)
19
24
  print("Created date last image:", latest_image.attrs["Created"])
20
25
  return latest_image
21
- except subprocess.CalledProcessError as e:
22
- raise ValueError(f"Error listing images:{e.stderr}")
26
+ except Exception as e:
27
+ logger.error(
28
+ f"Error listing images, docker must be running and added to PATH: {e}"
29
+ )
@@ -4,9 +4,6 @@ import os
4
4
  import subprocess
5
5
  import logging
6
6
  import base64
7
- from devsecops_engine_tools.engine_sca.engine_container.src.infrastructure.helpers.images_scanned import (
8
- ImagesScanned,
9
- )
10
7
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.tool_gateway import (
11
8
  ToolGateway,
12
9
  )
@@ -44,76 +41,60 @@ class PrismaCloudManagerScan(ToolGateway):
44
41
  except Exception as e:
45
42
  raise ValueError(f"Error downloading twistcli: {e}")
46
43
 
47
- def scan_image(self, file_path, image, remoteconfig, prisma_secret_key, build_id):
48
- file_name = "scanned_images.txt"
49
- image_name = f"{image.tags[0]}"
50
- result_file = f"{image_name}" + "_scan_result.json"
51
- images_scanned = []
52
-
53
- if (result_file) in ImagesScanned.get_images_already_scanned(file_name):
54
- print(f"The image {image_name} has already been scanned previously.")
55
- else:
56
- if build_id in image_name:
57
- command = (
58
- file_path,
59
- "images",
60
- "scan",
61
- "--address",
62
- remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
63
- "--user",
64
- remoteconfig["PRISMA_CLOUD"]["PRISMA_ACCESS_KEY"],
65
- "--password",
66
- prisma_secret_key,
67
- "--output-file",
68
- result_file,
69
- "--details",
70
- image_name,
71
- )
72
- try:
73
- subprocess.run(
74
- command,
75
- check=True,
76
- stdout=subprocess.PIPE,
77
- stderr=subprocess.PIPE,
78
- text=True,
79
- )
80
- images_scanned.append(result_file)
81
- print(f"The image {image_name} was scanned")
82
- with open(file_name, "a") as file:
83
- file.write(result_file + "\n")
84
- except subprocess.CalledProcessError as e:
85
- logger.error(f"Error during image scan of {image_name}: {e.stderr}")
86
-
87
- return images_scanned
88
-
89
- def run_tool_container_sca(self, remoteconfig, prisma_secret_key, image, build_id):
90
- images_scanned = []
44
+ def scan_image(
45
+ self, file_path, image_name, result_file, remoteconfig, prisma_secret_key
46
+ ):
47
+ command = (
48
+ file_path,
49
+ "images",
50
+ "scan",
51
+ "--address",
52
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
53
+ "--user",
54
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_ACCESS_KEY"],
55
+ "--password",
56
+ prisma_secret_key,
57
+ "--output-file",
58
+ result_file,
59
+ "--details",
60
+ image_name,
61
+ )
91
62
  try:
92
- file_path = os.path.join(
93
- os.getcwd(), remoteconfig["PRISMA_CLOUD"]["TWISTCLI_PATH"]
63
+ subprocess.run(
64
+ command,
65
+ check=True,
66
+ stdout=subprocess.PIPE,
67
+ stderr=subprocess.PIPE,
68
+ text=True,
94
69
  )
70
+ print(f"The image {image_name} was scanned")
95
71
 
96
- if not os.path.exists(file_path):
97
- self.download_twistcli(
98
- file_path,
99
- remoteconfig["PRISMA_CLOUD"]["PRISMA_ACCESS_KEY"],
100
- prisma_secret_key,
101
- remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
102
- remoteconfig["PRISMA_CLOUD"]["PRISMA_API_VERSION"],
103
- )
104
- images_scanned.extend(
105
- self.scan_image(
106
- file_path,
107
- image,
108
- remoteconfig,
109
- prisma_secret_key,
110
- build_id,
111
- )
112
- )
72
+ return result_file
73
+
74
+ except subprocess.CalledProcessError as e:
75
+ logger.error(f"Error during image scan of {image_name}: {e.stderr}")
113
76
 
114
- return images_scanned
77
+ def run_tool_container_sca(
78
+ self, remoteconfig, prisma_secret_key, image_name, result_file
79
+ ):
80
+ file_path = os.path.join(
81
+ os.getcwd(), remoteconfig["PRISMA_CLOUD"]["TWISTCLI_PATH"]
82
+ )
115
83
 
116
- except Exception as ex:
117
- logger.error(f"An overall error occurred: {ex}")
84
+ if not os.path.exists(file_path):
85
+ self.download_twistcli(
86
+ file_path,
87
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_ACCESS_KEY"],
88
+ prisma_secret_key,
89
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
90
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_API_VERSION"],
91
+ )
92
+ image_scanned = self.scan_image(
93
+ file_path,
94
+ image_name,
95
+ result_file,
96
+ remoteconfig,
97
+ prisma_secret_key,
98
+ )
118
99
 
119
- return images_scanned
100
+ return image_scanned
@@ -12,7 +12,7 @@ import json
12
12
 
13
13
  @dataclass
14
14
  class PrismaDeserealizator(DeseralizatorGateway):
15
- def get_list_findings(self, images_scanned: list) -> "list[Finding]":
15
+ def get_list_findings(self, image_scanned) -> "list[Finding]":
16
16
  list_open_vulnerabilities = []
17
17
  SEVERITY_MAP = {
18
18
  "unimportant": "low",
@@ -26,40 +26,39 @@ class PrismaDeserealizator(DeseralizatorGateway):
26
26
  "important": "high",
27
27
  "critical": "critical",
28
28
  }
29
- for image in images_scanned:
30
- with open(image, "rb") as file:
31
- image_object = file.read()
29
+ with open(image_scanned, "rb") as file:
30
+ image_object = file.read()
32
31
 
33
- json_data = json.loads(image_object)
34
- vulnerabilities_data = (
35
- json_data["results"][0]["vulnerabilities"]
36
- if "vulnerabilities" in json_data["results"][0]
37
- else []
38
- )
32
+ json_data = json.loads(image_object)
33
+ vulnerabilities_data = (
34
+ json_data["results"][0]["vulnerabilities"]
35
+ if "vulnerabilities" in json_data["results"][0]
36
+ else []
37
+ )
39
38
 
40
- # Create a list of findings instances from the JSON data
41
- vulnerabilities = [
42
- Finding(
43
- id=vul.get("id", ""),
44
- cvss=float(vul.get("cvss", 0.0)),
45
- where=vul.get("packageName", "")
46
- + ":"
47
- + vul.get("packageVersion", ""),
48
- description=vul.get("description", "")[:150],
49
- severity=SEVERITY_MAP.get(vul.get("severity", ""), ""),
50
- identification_date=datetime.strptime(
51
- vul.get("discoveredDate", ""), "%Y-%m-%dT%H:%M:%S%z"
52
- ),
53
- published_date_cve=vul.get("publishedDate", None),
54
- module="engine_container",
55
- category=Category.VULNERABILITY,
56
- requirements=vul.get("status", ""),
57
- tool="PrismaCloud",
58
- )
59
- for vul in vulnerabilities_data
60
- ]
39
+ # Create a list of findings instances from the JSON data
40
+ vulnerabilities = [
41
+ Finding(
42
+ id=vul.get("id", ""),
43
+ cvss=float(vul.get("cvss", 0.0)),
44
+ where=vul.get("packageName", "")
45
+ + ":"
46
+ + vul.get("packageVersion", ""),
47
+ description=vul.get("description", "")[:150],
48
+ severity=SEVERITY_MAP.get(vul.get("severity", ""), ""),
49
+ identification_date=datetime.strptime(
50
+ vul.get("discoveredDate", ""), "%Y-%m-%dT%H:%M:%S%z"
51
+ ),
52
+ published_date_cve=vul.get("publishedDate", "").replace("Z", "+00:00"),
53
+ module="engine_container",
54
+ category=Category.VULNERABILITY,
55
+ requirements=vul.get("status", ""),
56
+ tool="PrismaCloud",
57
+ )
58
+ for vul in vulnerabilities_data
59
+ ]
61
60
 
62
- # Add the Vulnerability instances to the list
63
- list_open_vulnerabilities.extend(vulnerabilities)
61
+ # Add the Vulnerability instances to the list
62
+ list_open_vulnerabilities.extend(vulnerabilities)
64
63
 
65
64
  return list_open_vulnerabilities
@@ -7,45 +7,57 @@ from devsecops_engine_tools.engine_core.src.domain.model.finding import (
7
7
  )
8
8
  from dataclasses import dataclass
9
9
  import json
10
- from datetime import datetime
10
+ from datetime import datetime, timezone
11
11
 
12
12
 
13
13
  @dataclass
14
14
  class TrivyDeserializator(DeseralizatorGateway):
15
- def get_list_findings(self, images_scanned: list) -> "list[Finding]":
15
+ def check_date_format(self, vul):
16
+ try:
17
+ published_date_cve=datetime.strptime(
18
+ vul.get("PublishedDate"),
19
+ "%Y-%m-%dT%H:%M:%S.%fZ"
20
+ ).replace(tzinfo=timezone.utc).isoformat()
21
+ except:
22
+ published_date_cve=datetime.strptime(
23
+ vul.get("PublishedDate"),
24
+ "%Y-%m-%dT%H:%M:%SZ"
25
+ ).replace(tzinfo=timezone.utc).isoformat()
26
+ return published_date_cve
27
+
28
+ def get_list_findings(self, image_scanned) -> "list[Finding]":
16
29
  list_open_vulnerabilities = []
17
- for image in images_scanned:
18
- with open(image, "rb") as file:
19
- image_object = file.read()
20
- json_data = json.loads(image_object)
21
- vulnerabilities_data = json_data["Results"][0]["Vulnerabilities"]
22
- vulnerabilities = [
23
- Finding(
24
- id=vul.get("VulnerabilityID", ""),
25
- cvss=next(
26
- (
27
- v["V3Score"]
28
- for v in vul["CVSS"].values()
29
- if "V3Score" in v
30
- ),
31
- None,
32
- ),
33
- where=vul.get("PkgName", "")
34
- + " "
35
- + vul.get("InstalledVersion", ""),
36
- description=vul.get("Description", "").replace("\n", ""),
37
- severity=vul.get("Severity", "").lower(),
38
- identification_date=datetime.now().strftime(
39
- "%d-%m-%Y %H:%M:%S"
30
+ with open(image_scanned, "rb") as file:
31
+ image_object = file.read()
32
+ json_data = json.loads(image_object)
33
+ vulnerabilities_data = json_data["Results"][0].get("Vulnerabilities", [])
34
+ vulnerabilities = [
35
+ Finding(
36
+ id=vul.get("VulnerabilityID", ""),
37
+ cvss=str(next(
38
+ (
39
+ v["V3Score"]
40
+ for v in vul["CVSS"].values()
41
+ if "V3Score" in v
40
42
  ),
41
- published_date_cve=vul.get("PublishedDate", ""),
42
- module="engine_container",
43
- category=Category.VULNERABILITY,
44
- requirements=vul.get("FixedVersion") or vul.get("Status", ""),
45
- tool="Trivy",
46
- )
47
- for vul in vulnerabilities_data
48
- if "CVSS" in vul
49
- ]
50
- list_open_vulnerabilities.extend(vulnerabilities)
43
+ None,
44
+ )),
45
+ where=vul.get("PkgName", "")
46
+ + " "
47
+ + vul.get("InstalledVersion", ""),
48
+ description=vul.get("Description", "").replace("\n", "")[:150],
49
+ severity=vul.get("Severity", "").lower(),
50
+ identification_date=datetime.now().strftime(
51
+ "%Y-%m-%dT%H:%M:%S%z"
52
+ ),
53
+ published_date_cve=self.check_date_format(vul),
54
+ module="engine_container",
55
+ category=Category.VULNERABILITY,
56
+ requirements=vul.get("FixedVersion") or vul.get("Status", ""),
57
+ tool="Trivy",
58
+ )
59
+ for vul in vulnerabilities_data
60
+ if vul.get("CVSS") and vul.get("PublishedDate")
61
+ ]
62
+ list_open_vulnerabilities.extend(vulnerabilities)
51
63
  return list_open_vulnerabilities
@@ -1,13 +1,12 @@
1
- import subprocess
2
- import re
3
-
4
1
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.tool_gateway import (
5
2
  ToolGateway,
6
3
  )
7
4
 
8
- from devsecops_engine_tools.engine_sca.engine_container.src.infrastructure.helpers.images_scanned import (
9
- ImagesScanned,
10
- )
5
+ import subprocess
6
+ import platform
7
+ import requests
8
+ import tarfile
9
+ import zipfile
11
10
 
12
11
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
13
12
  from devsecops_engine_tools.engine_utilities import settings
@@ -16,99 +15,92 @@ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
16
15
 
17
16
 
18
17
  class TrivyScan(ToolGateway):
19
- def install_tool(self, version):
18
+ def download_tool(self, file, url):
19
+ try:
20
+ response = requests.get(url, allow_redirects=True)
21
+ with open(file, "wb") as compress_file:
22
+ compress_file.write(response.content)
23
+ except Exception as e:
24
+ logger.error(f"Error downloading trivy: {e}")
25
+
26
+ def install_tool(self, file, url):
20
27
  installed = subprocess.run(
21
- ["which", "trivy"],
28
+ ["which", "./trivy"],
22
29
  stdout=subprocess.PIPE,
23
30
  stderr=subprocess.PIPE,
24
31
  )
25
32
  if installed.returncode == 1:
26
33
  try:
27
- command1 = [
28
- "wget",
29
- "https://github.com/aquasecurity/trivy/releases/download/v"
30
- + version
31
- + "/trivy_"
32
- + version
33
- + "_Linux-64bit.deb",
34
- ]
35
- subprocess.run(
36
- command1, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
37
- )
38
- command2 = [
39
- "sudo",
40
- "dpkg",
41
- "-i",
42
- "trivy_" + version + "_Linux-64bit.deb",
43
- ]
44
- subprocess.run(
45
- command2, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
46
- )
47
- except subprocess.CalledProcessError as error:
48
- raise RuntimeError(f"Error al instalar trivy: {error}")
49
-
50
- def scan_image(self, repository, tag, remoteconfig, release):
51
- file_name = "scanned_images.txt"
52
- repo = repository.split("/")[1] if len(repository.split("/")) >= 2 else ""
53
- image_name = f"{repository}:{tag}"
54
- result_file = f"{repo}:{tag}" + "_scan_result.json"
55
- images_scanned = []
34
+ self.download_tool(file, url)
35
+ with tarfile.open(file, 'r:gz') as tar_file:
36
+ tar_file.extract(member=tar_file.getmember("trivy"))
37
+ except Exception as e:
38
+ logger.error(f"Error installing trivy: {e}")
39
+
40
+ def install_tool_windows(self, file, url):
41
+ try:
42
+ subprocess.run(
43
+ ["./trivy.exe", "--version"],
44
+ stdout=subprocess.PIPE,
45
+ stderr=subprocess.PIPE,
46
+ )
47
+ except:
48
+ try:
49
+ self.download_tool(file, url)
50
+ with zipfile.ZipFile(file, 'r') as zip_file:
51
+ zip_file.extract(member="trivy.exe")
52
+ except Exception as e:
53
+ logger.error(f"Error installing trivy: {e}")
56
54
 
57
- if not ((result_file) in ImagesScanned.get_images_already_scanned(file_name)):
58
- pattern = remoteconfig["REGEX_EXPRESSION_PROJECTS"]
59
- match = re.match(pattern, repo.upper())
60
- if match:
61
- if match.group() in release.upper():
62
- command1 = ["trivy", "image", "--download-db-only"]
63
- command2 = [
64
- "trivy",
65
- "--scanners",
66
- "vuln",
67
- "-f",
68
- "json",
69
- "-o",
70
- result_file,
71
- ]
72
- command2.extend(["--quiet", "image", image_name])
73
- try:
74
- subprocess.run(
75
- command1,
76
- check=True,
77
- stdout=subprocess.PIPE,
78
- stderr=subprocess.PIPE,
79
- )
80
- subprocess.run(
81
- command2,
82
- check=True,
83
- stdout=subprocess.PIPE,
84
- stderr=subprocess.PIPE,
85
- text=True,
86
- )
87
- images_scanned.append(result_file)
88
- with open(file_name, "a") as file:
89
- file.write(result_file + "\n")
90
- except subprocess.CalledProcessError as e:
91
- logger.error(
92
- f"Error during image scan of {repository}: {e.stderr}"
93
- )
55
+ def scan_image(self, prefix, image_name, result_file):
56
+ command = [
57
+ prefix,
58
+ "--scanners",
59
+ "vuln",
60
+ "-f",
61
+ "json",
62
+ "-o",
63
+ result_file,
64
+ ]
65
+ command.extend(["--quiet", "image", image_name])
66
+ try:
67
+ subprocess.run(
68
+ command,
69
+ check=True,
70
+ stdout=subprocess.PIPE,
71
+ stderr=subprocess.PIPE,
72
+ text=True,
73
+ )
74
+ print(f"The image {image_name} was scanned")
94
75
 
95
- return images_scanned
76
+ return result_file
96
77
 
97
- def run_tool_container_sca(self, remoteconfig, token, scan_image, release):
98
- try:
99
- trivy_version = remoteconfig["TRIVY"]["TRIVY_VERSION"]
100
- self.install_tool(trivy_version)
101
- images_scanned = []
78
+ except Exception as e:
79
+ logger.error(f"Error during image scan of {image_name}: {e}")
102
80
 
103
- for image in scan_image:
104
- repository, tag = image["Repository"], image["Tag"]
105
- images_scanned.extend(
106
- self.scan_image(repository, tag, remoteconfig, release)
107
- )
81
+ def run_tool_container_sca(self, remoteconfig, token, image_name, result_file):
82
+ trivy_version = remoteconfig["TRIVY"]["TRIVY_VERSION"]
83
+ os_platform = platform.system()
84
+ base_url = f"https://github.com/aquasecurity/trivy/releases/download/v{trivy_version}/"
108
85
 
109
- return images_scanned
86
+ if os_platform == "Linux":
87
+ file=f"trivy_{trivy_version}_Linux-64bit.tar.gz"
88
+ self.install_tool(file, base_url+file)
89
+ command_prefix = "./trivy"
90
+ elif os_platform == "Darwin":
91
+ file=f"trivy_{trivy_version}_macOS-64bit.tar.gz"
92
+ self.install_tool(file, base_url+file)
93
+ command_prefix = "./trivy"
94
+ elif os_platform == "Windows":
95
+ file=f"trivy_{trivy_version}_windows-64bit.zip"
96
+ self.install_tool_windows(file, base_url+file)
97
+ command_prefix = "./trivy.exe"
98
+ else:
99
+ logger.warning(f"{os_platform} is not supported.")
100
+ return None
110
101
 
111
- except Exception as ex:
112
- logger.error(f"An overall error occurred: {ex}")
102
+ image_scanned = (
103
+ self.scan_image(command_prefix, image_name, result_file)
104
+ )
113
105
 
114
- return 0
106
+ return image_scanned
@@ -36,7 +36,7 @@ def init_engine_sca_rm(
36
36
  scan_flag = handle_remote_config_patterns.ignore_analysis_pattern()
37
37
  build_id = tool_remote.get_variable("build_id")
38
38
  stage = tool_remote.get_variable("stage")
39
- images_scanned = []
39
+ image_scanned = None
40
40
  deseralized = []
41
41
  input_core = SetInputCore(remote_config, exclusions, pipeline_name, tool, stage)
42
42
  if scan_flag and not (skip_flag):
@@ -48,11 +48,12 @@ def init_engine_sca_rm(
48
48
  build_id,
49
49
  token,
50
50
  )
51
- images_scanned = container_sca_scan.process()
52
- deseralized = container_sca_scan.deseralizator(images_scanned)
51
+ image_scanned = container_sca_scan.process()
52
+ if image_scanned:
53
+ deseralized = container_sca_scan.deseralizator(image_scanned)
53
54
  else:
54
55
  print("Tool skipped by DevSecOps policy")
55
56
  logger.info("Tool skipped by DevSecOps policy")
56
- core_input = input_core.set_input_core(images_scanned)
57
+ core_input = input_core.set_input_core(image_scanned)
57
58
 
58
59
  return deseralized, core_input
@@ -1 +1 @@
1
- version = '1.7.16'
1
+ version = '1.7.17'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devsecops-engine-tools
3
- Version: 1.7.16
3
+ Version: 1.7.17
4
4
  Summary: Tool for DevSecOps strategy
5
5
  Home-page: https://github.com/bancolombia/devsecops-engine-tools
6
6
  Author: Bancolombia DevSecOps Team
@@ -1,5 +1,5 @@
1
1
  devsecops_engine_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- devsecops_engine_tools/version.py,sha256=vVlXeXuVsZX9q82mpgg-l8td6DNWeMF45zXX4TerVqA,18
2
+ devsecops_engine_tools/version.py,sha256=CetXeOFaV4Pn_xtCRH2tc2R90KqylDgNgYCAiNFxVlY,18
3
3
  devsecops_engine_tools/engine_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  devsecops_engine_tools/engine_core/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  devsecops_engine_tools/engine_core/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -36,7 +36,7 @@ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/aws/secret
36
36
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py,sha256=Ot1j5my-iEpU-ZYy9yNXkwmwLOmJ3f95JyyAUcpFN5g,4967
38
38
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=fnyexfnIfFyP4iCLTeMwWa6OaEP_VYcnPg8roANIKGs,10864
39
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=qOqipt7P6THEjoaBwpIPO8OEN9OKpW6u_X_c4DeGhx8,10903
40
40
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=Tz056qYuIKrdYGKyoPo7xFdOpfN3A0YMd3cCSAGVrYQ,3828
42
42
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -138,23 +138,22 @@ devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/des
138
138
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/images_gateway.py,sha256=szx-9iO1eSDedr3rw605Mx3jYBEFwRKBM0ts5zImgx0,158
139
139
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/tool_gateway.py,sha256=ADZjrl8u8CQ0hWoVhbnHFcjvyUmUeleffwmhtlg8s30,224
140
140
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
- devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=zwlYQSmtn7_ms9x5-Dhr3WTilLM5cXdAyslgWRh5xdc,1635
141
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=bJrQr-e_mEQci_cT3a3fWGbCAryX1lFLJbrY8rd-Qg8,3054
142
142
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/handle_remote_config_patterns.py,sha256=4wgBTQSDE-C5v01C3Vxzeq0DJKZUSqQ5TVLG7yPZPKs,926
143
- devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py,sha256=Jw2sjrgRS8kjIFLt2nEBXQpF2-Ncm_ltgc6Q7ZIZKw0,1840
143
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py,sha256=DdKyKnLzqswHt619B3s1GTB5u_RyUixCambDkBuu7y4,1806
144
144
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
145
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
146
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=tdZeW5KbZcLxSMM37-GdmkLItpRDUlR0eAyew6bI2ts,816
147
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=XoF6PtMNIdycuBQbRl7NjBPaqUr80-S8KxV93iEpFNA,1067
148
148
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=3KyqbuLSFHMAUO5n9ruLMU8nhiP9BuGeXchN9PHW3M0,4369
150
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=k6j6ajlHFVfKdxIdvWVak0eryhIknT0IyTvyI2e3gz0,2514
149
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=DUq-cs3DuKpwfKVcu_zCiydLD-OZihbtRiQhVw0Dl1M,3213
150
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=Q6jPGjAO-oY0YeHZYmmD_in-nA8R6oa4_cBGbNs1oy8,2375
151
151
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py,sha256=v0XU-KJfnt4BFmoLbpc3IE0RxDVsYN5dzftfJiWR2Fs,2169
153
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=IBd3fOQmHPDeVud54DQtw0x2o4jm31iwRoiBDTpkqdc,4284
152
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py,sha256=LGqnO10Zt-0-TxUW6F1S46jVktlIwxWSYATKSVblCWI,2535
153
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=dAjnif-4CVYWrEpsMeAP97p-vsqtcZooxTBKeW8dzOY,3611
154
154
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=BM8XJI_tlFxurdhBz2N5R33z4WGNLN_mkaG2npYBTiM,2212
155
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=RrpGnDSAL_YnRmONRkOKjWk5JbCOi_vG9dvlz5E_67U,2241
156
156
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/helpers/images_scanned.py,sha256=V_wE9maXdGlQbYIe6qVgOqEtiWrh-icd8V4dpWDQrXg,590
158
157
  devsecops_engine_tools/engine_sca/engine_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
159
158
  devsecops_engine_tools/engine_sca/engine_dependencies/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
159
  devsecops_engine_tools/engine_sca/engine_dependencies/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -242,8 +241,8 @@ devsecops_engine_tools/engine_utilities/utils/logger_info.py,sha256=4Mz8Bwlm9Mku
242
241
  devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGaxYSDe0ZRh6VHRf53H4sXPcb-vNP_i81PUn3I,307
243
242
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=GAslbWaBpwP3mP6fBsgVl07TTBgcCggQTy8h2M9ibeo,612
244
243
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=yNtlT-8Legz1sHbGPH8LNYjL-LgDUE0zXG2rYjiab7U,290
245
- devsecops_engine_tools-1.7.16.dist-info/METADATA,sha256=BwG-ipv7ziTvAqeXg3xPytZqTQ0lpI3wch50ZHysRLw,4840
246
- devsecops_engine_tools-1.7.16.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
247
- devsecops_engine_tools-1.7.16.dist-info/entry_points.txt,sha256=9IjXF_7Zpgowq_SY6OSmsA9vZze18a8_AeHwkQVrgKk,131
248
- devsecops_engine_tools-1.7.16.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
249
- devsecops_engine_tools-1.7.16.dist-info/RECORD,,
244
+ devsecops_engine_tools-1.7.17.dist-info/METADATA,sha256=vnb5zKm0jaudK0eUDqplO_WKDQpgFdx5dfWjmE2Nc1U,4840
245
+ devsecops_engine_tools-1.7.17.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
246
+ devsecops_engine_tools-1.7.17.dist-info/entry_points.txt,sha256=9IjXF_7Zpgowq_SY6OSmsA9vZze18a8_AeHwkQVrgKk,131
247
+ devsecops_engine_tools-1.7.17.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
248
+ devsecops_engine_tools-1.7.17.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- import os
2
-
3
-
4
- class ImagesScanned:
5
- @staticmethod
6
- def get_images_already_scanned(file_name):
7
- """
8
- Create images scanned file if it does not exist and get the images that have already been scanned.
9
- """
10
- scanned_images_file = os.path.join(os.getcwd(), file_name)
11
- # Check if the file exists; if not, create it
12
- if not os.path.exists(scanned_images_file):
13
- open(scanned_images_file, "w").close()
14
- with open(scanned_images_file, "r") as file:
15
- images_scanned = file.read().splitlines()
16
- return images_scanned