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

@@ -5,3 +5,7 @@ class ImagesGateway(metaclass=ABCMeta):
5
5
  @abstractmethod
6
6
  def list_images(self, image_to_scan) -> str:
7
7
  "get image to scan"
8
+
9
+ @abstractmethod
10
+ def get_base_image(self, image_to_scan) -> str:
11
+ "get base image"
@@ -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) -> str:
6
+ def run_tool_container_sca(self, dict_args, secret_tool, token_engine_container, scan_image, release, base_image, exclusions) -> str:
7
7
  "run tool container sca"
@@ -22,6 +22,7 @@ class ContainerScaScan:
22
22
  secret_tool,
23
23
  token_engine_container,
24
24
  image_to_scan,
25
+ exclusions
25
26
  ):
26
27
  self.tool_run = tool_run
27
28
  self.remote_config = remote_config
@@ -31,6 +32,7 @@ class ContainerScaScan:
31
32
  self.secret_tool = secret_tool
32
33
  self.token_engine_container = token_engine_container
33
34
  self.image_to_scan = image_to_scan
35
+ self.exclusions = exclusions
34
36
 
35
37
  def get_image(self, image_to_scan):
36
38
  """
@@ -41,6 +43,15 @@ class ContainerScaScan:
41
43
  """
42
44
  return self.tool_images.list_images(image_to_scan)
43
45
 
46
+ def get_base_image(self, matching_image):
47
+ """
48
+ Process the base image.
49
+
50
+ Returns:
51
+ String: base image.
52
+ """
53
+ return self.tool_images.get_base_image(matching_image)
54
+
44
55
  def get_images_already_scanned(self):
45
56
  """
46
57
  Create images scanned file if it does not exist and get the images that have already been scanned.
@@ -66,21 +77,24 @@ class ContainerScaScan:
66
77
  Returns:
67
78
  string: file scanning results name.
68
79
  """
69
- matching_image = self.get_image(self.image_to_scan)
80
+ base_image = None
70
81
  image_scanned = None
82
+ matching_image = self.get_image(self.image_to_scan)
83
+ if self.remote_config['GET_IMAGE_BASE']:
84
+ base_image = self.get_base_image(matching_image)
71
85
  if matching_image:
72
86
  image_name = matching_image.tags[0]
73
87
  result_file = image_name.replace("/","_") + "_scan_result.json"
74
88
  if image_name in self.get_images_already_scanned():
75
89
  print(f"The image {image_name} has already been scanned previously.")
76
- return image_scanned
90
+ return image_scanned, base_image
77
91
  image_scanned = self.tool_run.run_tool_container_sca(
78
- self.remote_config, self.secret_tool, self.token_engine_container, image_name, result_file
92
+ self.remote_config, self.secret_tool, self.token_engine_container, image_name, result_file, base_image, self.exclusions
79
93
  )
80
94
  self.set_image_scanned(image_name)
81
95
  else:
82
96
  print(f"'Not image found for {self.image_to_scan}'. Tool skipped.")
83
- return image_scanned
97
+ return image_scanned, base_image
84
98
 
85
99
  def deseralizator(self, image_scanned):
86
100
  """
@@ -12,25 +12,37 @@ class SetInputCore:
12
12
  self.tool = tool
13
13
  self.stage = stage
14
14
 
15
- def get_exclusions(self, exclusions_data, pipeline_name, tool):
16
- list_exclusions = [
17
- Exclusions(
18
- id=item.get("id", ""),
19
- where=item.get("where", ""),
20
- cve_id=item.get("cve_id", ""),
21
- create_date=item.get("create_date", ""),
22
- expired_date=item.get("expired_date", ""),
23
- severity=item.get("severity", ""),
24
- hu=item.get("hu", ""),
25
- reason=item.get("reason", "Risk acceptance"),
26
- )
27
- for key, value in exclusions_data.items()
28
- if key in {"All", pipeline_name} and value.get(tool)
29
- for item in value[tool]
30
- ]
15
+ def get_exclusions(self, exclusions_data, pipeline_name, tool, base_image):
16
+ list_exclusions = []
17
+ print("The base image used is:", base_image)
18
+ for key, value in exclusions_data.items():
19
+ if key not in {"All", pipeline_name} or not value.get(tool):
20
+ continue
21
+
22
+ for item in value[tool]:
23
+ if key == "All":
24
+ source_images = item.get("source_images", [])
25
+ if source_images and base_image is None:
26
+ continue
27
+ if source_images and not any(base_image in source for source in source_images):
28
+ continue
29
+
30
+ list_exclusions.append(
31
+ Exclusions(
32
+ id=item.get("id", ""),
33
+ where=item.get("where", ""),
34
+ cve_id=item.get("cve_id", ""),
35
+ create_date=item.get("create_date", ""),
36
+ expired_date=item.get("expired_date", ""),
37
+ severity=item.get("severity", ""),
38
+ hu=item.get("hu", ""),
39
+ reason=item.get("reason", "Risk acceptance"),
40
+ )
41
+ )
42
+
31
43
  return list_exclusions
32
44
 
33
- def set_input_core(self, image_scanned):
45
+ def set_input_core(self, image_scanned,base_image):
34
46
  """
35
47
  Set the input core.
36
48
 
@@ -42,6 +54,7 @@ class SetInputCore:
42
54
  self.exclusions,
43
55
  self.pipeline_name,
44
56
  self.tool,
57
+ base_image
45
58
  ),
46
59
  Utils.update_threshold(
47
60
  self,
@@ -31,3 +31,20 @@ class DockerImages(ImagesGateway):
31
31
  logger.error(
32
32
  f"Error listing images, docker must be running and added to PATH: {e}"
33
33
  )
34
+
35
+ def get_base_image(self, matching_image):
36
+ try:
37
+ client = docker.from_env()
38
+ image_details = client.api.inspect_image(matching_image.id)
39
+ labels = image_details.get("Config", {}).get("Labels", {})
40
+ source_image = labels.get("source-image")
41
+ if source_image:
42
+ logger.info(f"Base image for '{matching_image}' from source-image label: {source_image}")
43
+ return source_image
44
+
45
+ logger.warning(f"Base image not found for '{matching_image}'.")
46
+ return None
47
+
48
+ except Exception as e:
49
+ logger.error(f"Error getting base image: {e}")
50
+ return None
@@ -4,6 +4,7 @@ import os
4
4
  import subprocess
5
5
  import logging
6
6
  import base64
7
+ import json
7
8
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.tool_gateway import (
8
9
  ToolGateway,
9
10
  )
@@ -68,14 +69,36 @@ class PrismaCloudManagerScan(ToolGateway):
68
69
  text=True,
69
70
  )
70
71
  print(f"The image {image_name} was scanned")
71
-
72
72
  return result_file
73
73
 
74
74
  except subprocess.CalledProcessError as e:
75
75
  logger.error(f"Error during image scan of {image_name}: {e.stderr}")
76
76
 
77
+ def _write_image_base(self, result_file, base_image, exclusions_data):
78
+ try:
79
+ with open(result_file, "r") as file:
80
+ data = json.load(file)
81
+
82
+ prisma_exclusions = exclusions_data.get("All", {}).get("PRISMA", [])
83
+ modified = False
84
+ for result in data.get("results", []):
85
+ for vulnerability in result.get("vulnerabilities", []):
86
+ for exclusion in prisma_exclusions:
87
+ if (
88
+ vulnerability.get("id") == exclusion.get("id") and
89
+ any(image.startswith(base_image) for image in exclusion.get("source_images", []))
90
+ ):
91
+ vulnerability["baseImage"] = base_image
92
+ modified = True
93
+
94
+ if modified:
95
+ with open(result_file, "w") as file:
96
+ json.dump(data, file, indent=4)
97
+ except subprocess.CalledProcessError as e:
98
+ logger.error(f"Error during write image base of {base_image}: {e.stderr}")
99
+
77
100
  def run_tool_container_sca(
78
- self, remoteconfig, secret_tool, token_engine_container, image_name, result_file
101
+ self, remoteconfig, secret_tool, token_engine_container, image_name, result_file, base_image, exclusions
79
102
  ):
80
103
  prisma_secret_key = secret_tool["token_prisma_cloud"] if secret_tool else token_engine_container
81
104
  file_path = os.path.join(
@@ -95,7 +118,9 @@ class PrismaCloudManagerScan(ToolGateway):
95
118
  image_name,
96
119
  result_file,
97
120
  remoteconfig,
98
- prisma_secret_key,
121
+ prisma_secret_key
99
122
  )
123
+ if base_image:
124
+ self._write_image_base(result_file, base_image, exclusions)
100
125
 
101
126
  return image_scanned
@@ -7,6 +7,7 @@ import platform
7
7
  import requests
8
8
  import tarfile
9
9
  import zipfile
10
+ import json
10
11
 
11
12
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
12
13
  from devsecops_engine_tools.engine_utilities import settings
@@ -52,7 +53,7 @@ class TrivyScan(ToolGateway):
52
53
  except Exception as e:
53
54
  logger.error(f"Error installing trivy: {e}")
54
55
 
55
- def scan_image(self, prefix, image_name, result_file):
56
+ def scan_image(self, prefix, image_name, result_file, base_image):
56
57
  command = [
57
58
  prefix,
58
59
  "--scanners",
@@ -78,7 +79,7 @@ class TrivyScan(ToolGateway):
78
79
  except Exception as e:
79
80
  logger.error(f"Error during image scan of {image_name}: {e}")
80
81
 
81
- def run_tool_container_sca(self, remoteconfig, secret_tool, token_engine_container, image_name, result_file):
82
+ def run_tool_container_sca(self, remoteconfig, secret_tool, token_engine_container, image_name, result_file ,base_image, exclusions):
82
83
  trivy_version = remoteconfig["TRIVY"]["TRIVY_VERSION"]
83
84
  os_platform = platform.system()
84
85
  arch_platform = platform.architecture()[0]
@@ -101,7 +102,7 @@ class TrivyScan(ToolGateway):
101
102
  return None
102
103
 
103
104
  image_scanned = (
104
- self.scan_image(command_prefix, image_name, result_file)
105
+ self.scan_image(command_prefix, image_name, result_file, base_image)
105
106
  )
106
107
 
107
108
  return image_scanned
@@ -38,6 +38,7 @@ def init_engine_sca_rm(
38
38
  stage = tool_remote.get_variable("stage")
39
39
  image_to_scan = dict_args["image_to_scan"]
40
40
  image_scanned = None
41
+ base_image = None
41
42
  deseralized = []
42
43
  input_core = SetInputCore(remote_config, exclusions, pipeline_name, tool, stage)
43
44
  if scan_flag and not (skip_flag):
@@ -50,13 +51,14 @@ def init_engine_sca_rm(
50
51
  secret_tool,
51
52
  dict_args["token_engine_container"],
52
53
  image_to_scan,
54
+ exclusions
53
55
  )
54
- image_scanned = container_sca_scan.process()
56
+ image_scanned,base_image = container_sca_scan.process()
55
57
  if image_scanned:
56
58
  deseralized = container_sca_scan.deseralizator(image_scanned)
57
59
  else:
58
60
  print("Tool skipped by DevSecOps policy")
59
61
  dict_args["send_metrics"] = "false"
60
- core_input = input_core.set_input_core(image_scanned)
62
+ core_input = input_core.set_input_core(image_scanned,base_image)
61
63
 
62
64
  return deseralized, core_input
@@ -1 +1 @@
1
- version = '1.25.0'
1
+ version = '1.25.1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devsecops-engine-tools
3
- Version: 1.25.0
3
+ Version: 1.25.1
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=H5emCtCaqtHr-9dLv_SG9PwZ_mJKNcZ0wZ2S_f-TQHQ,19
2
+ devsecops_engine_tools/version.py,sha256=qfAYf9RsqCPGpf2oH5qMg1YfoP33JS4SDFWM3eS8bUU,19
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
@@ -169,24 +169,24 @@ devsecops_engine_tools/engine_sca/engine_container/src/domain/__init__.py,sha256
169
169
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
170
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
171
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/deserealizator_gateway.py,sha256=sE7-GnNSNLWbA1H0mvTwXmxcOJXl8uvw-0hxMyX4oMc,290
172
- devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/images_gateway.py,sha256=4I0x7qT97mT1kuyIYMWHz7KH_XEMwNm9_eB0SUcEKrE,179
173
- devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/tool_gateway.py,sha256=oMeCeSjAjT-efISOAjAfRv85fRhsX6ZNszrKraHAdTE,254
172
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/images_gateway.py,sha256=cXafS4v7tflUAaqf9t468gL8P6Wa9hY09BTNzKIuAWQ,277
173
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/tool_gateway.py,sha256=hQ_4Qmcx9tebf-2Mvu4EeZHwaobVl-hUuzU7vB0U5lw,278
174
174
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
175
- devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=SXwMqqUSjaJlFUkfnLJp_2o2kJn4zVUXM0oNTP8cJ-k,3250
175
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=8h4qV_xbH9InocBhk3oWkLuma-RWhkZDhjt_lrjTd8E,3749
176
176
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/handle_remote_config_patterns.py,sha256=4wgBTQSDE-C5v01C3Vxzeq0DJKZUSqQ5TVLG7yPZPKs,926
177
- devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py,sha256=-X4wIUAMF3ru1HBEfNz9JhrCg6tcgX40FBKdmamDEIU,2020
177
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py,sha256=n-SjcDl6YPAnUWqkOYXsVr-mTiS4rGxj4sS2YkXo6xw,2632
178
178
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
179
179
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
180
180
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=DtjjScV0WYDRme2JgCjGf3BB8btqcJObWMu-xvHZgNY,1173
181
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=99-KEv62RoHAkY-S2mR7GjuHsMF0ELt_x4mW5ZMKubE,1855
182
182
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=vGQUGbYUzab_TvLHmH8lkb9jf2ZNCY3IiuhhYAz8lN0,3337
183
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=UA-tU1ppfWpEUh_QZLBX3IJxRQPkC6f91dpeRI31EXg,4597
184
184
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=oK0NKuPODm38qDgQjf6w40lfNG6NFJS43p5k44wDoMA,2562
185
185
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
186
186
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py,sha256=LGqnO10Zt-0-TxUW6F1S46jVktlIwxWSYATKSVblCWI,2535
187
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=LWiCQsL7BukEJPCoPkC_zYDfYQMLo2LNYwMbIIXBGfs,3722
187
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=RG8H9pYcqo554VQGXWZUYsLPQkanERscs3MVQOQ_vc8,3782
188
188
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=HSDhub6kPcbSfAo5uJOxY8Pc4kyZ8VszJmwH-p8vkx4,2437
189
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=OSXZs45XmuhGMOMJUa0AZKmsLi2jqPP93GI1FaJP5Ug,2506
190
190
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
191
191
  devsecops_engine_tools/engine_sca/engine_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
192
192
  devsecops_engine_tools/engine_sca/engine_dependencies/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -308,8 +308,8 @@ devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGax
308
308
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=amYAr9YQfYgR6jK9a2l26z3oovFPQ3FAKmhq6BKhEBA,623
309
309
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=yNtlT-8Legz1sHbGPH8LNYjL-LgDUE0zXG2rYjiab7U,290
310
310
  devsecops_engine_tools/engine_utilities/utils/utils.py,sha256=yvCbPKAWa7wxk5S-s_Xkvx9VtnIpv9eWUMG8wtlmrhs,5870
311
- devsecops_engine_tools-1.25.0.dist-info/METADATA,sha256=oJKPtxsdfGzrdqYgZg1sokubbszwx1AceewY7AJkqWg,11010
312
- devsecops_engine_tools-1.25.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
313
- devsecops_engine_tools-1.25.0.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
314
- devsecops_engine_tools-1.25.0.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
315
- devsecops_engine_tools-1.25.0.dist-info/RECORD,,
311
+ devsecops_engine_tools-1.25.1.dist-info/METADATA,sha256=DniDER-9_UQl3ajfi-gEheUEb7Ec-aDbHrSW_WyVcWU,11010
312
+ devsecops_engine_tools-1.25.1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
313
+ devsecops_engine_tools-1.25.1.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
314
+ devsecops_engine_tools-1.25.1.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
315
+ devsecops_engine_tools-1.25.1.dist-info/RECORD,,