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

@@ -53,7 +53,7 @@ class GithubActions(DevopsPlatformGateway):
53
53
  return results.get(type)
54
54
 
55
55
  def get_source_code_management_uri(self):
56
- return f"{SystemVariables.github_server_url}/{SystemVariables.github_repository}"
56
+ return f"{SystemVariables.github_server_url.value()}/{SystemVariables.github_repository.value()}"
57
57
 
58
58
  def get_base_compact_remote_config_url(self, remote_config_repo):
59
59
  github_repository = SystemVariables.github_repository.value()
@@ -9,3 +9,7 @@ class ImagesGateway(metaclass=ABCMeta):
9
9
  @abstractmethod
10
10
  def get_base_image(self, image_to_scan) -> str:
11
11
  "get base image"
12
+
13
+ @abstractmethod
14
+ def validate_base_image_date(self, image_to_scan, referenced_date) -> str:
15
+ "validate base image date"
@@ -22,7 +22,8 @@ class ContainerScaScan:
22
22
  secret_tool,
23
23
  token_engine_container,
24
24
  image_to_scan,
25
- exclusions
25
+ exclusions,
26
+ pipeline_name,
26
27
  ):
27
28
  self.tool_run = tool_run
28
29
  self.remote_config = remote_config
@@ -33,6 +34,7 @@ class ContainerScaScan:
33
34
  self.token_engine_container = token_engine_container
34
35
  self.image_to_scan = image_to_scan
35
36
  self.exclusions = exclusions
37
+ self.pipeline_name = pipeline_name
36
38
 
37
39
  def get_image(self, image_to_scan):
38
40
  """
@@ -44,13 +46,13 @@ class ContainerScaScan:
44
46
  return self.tool_images.list_images(image_to_scan)
45
47
 
46
48
  def get_base_image(self, matching_image):
47
- """
49
+ """
48
50
  Process the base image.
49
51
 
50
52
  Returns:
51
53
  String: base image.
52
54
  """
53
- return self.tool_images.get_base_image(matching_image)
55
+ return self.tool_images.get_base_image(matching_image)
54
56
 
55
57
  def get_images_already_scanned(self):
56
58
  """
@@ -70,6 +72,17 @@ class ContainerScaScan:
70
72
  with open("scanned_images.txt", "a") as file:
71
73
  file.write(result_file + "\n")
72
74
 
75
+ def validate_base_image_date(self, matching_image, referenced_date):
76
+ """
77
+ Process the base image date validation.
78
+
79
+ Returns:
80
+ string: base image date.
81
+ """
82
+ return self.tool_images.validate_base_image_date(
83
+ matching_image, referenced_date
84
+ )
85
+
73
86
  def process(self):
74
87
  """
75
88
  Process SCA scanning.
@@ -80,8 +93,17 @@ class ContainerScaScan:
80
93
  base_image = None
81
94
  image_scanned = None
82
95
  matching_image = self.get_image(self.image_to_scan)
83
- if self.remote_config['GET_IMAGE_BASE']:
96
+ if self.remote_config["GET_IMAGE_BASE"]:
84
97
  base_image = self.get_base_image(matching_image)
98
+ if self.remote_config["VALIDATE_BASE_IMAGE_DATE"][
99
+ "ENABLED"
100
+ ] and not self.exclusions.get(self.pipeline_name, {}).get(
101
+ "VALIDATE_BASE_IMAGE_DATE"
102
+ ):
103
+ self.validate_base_image_date(
104
+ matching_image,
105
+ self.remote_config["VALIDATE_BASE_IMAGE_DATE"]["REFERENCE_IMAGE_DATE"],
106
+ )
85
107
  sbom_components = None
86
108
  generate_sbom = self.remote_config["SBOM"]["ENABLED"] and any(
87
109
  branch in str(self.branch)
@@ -98,7 +120,9 @@ class ContainerScaScan:
98
120
  self.secret_tool,
99
121
  self.token_engine_container,
100
122
  image_name,
101
- result_file, base_image, self.exclusions,
123
+ result_file,
124
+ base_image,
125
+ self.exclusions,
102
126
  generate_sbom,
103
127
  )
104
128
  self.set_image_scanned(image_name)
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.images_gateway import (
2
3
  ImagesGateway,
3
4
  )
@@ -33,18 +34,82 @@ class DockerImages(ImagesGateway):
33
34
  )
34
35
 
35
36
  def get_base_image(self, matching_image):
37
+ image_details = self.get_image_details(matching_image.id)
38
+ if not image_details:
39
+ return None
40
+
41
+ labels = image_details.get("Config", {}).get("Labels", {})
42
+ return self.extract_base_image_from_labels(labels, matching_image)
43
+
44
+ def validate_base_image_date(self, matching_image, referenced_date):
45
+ image_details = self.get_image_details(matching_image.id)
46
+ if not image_details:
47
+ return False
48
+
49
+ labels = image_details.get("Config", {}).get("Labels", {})
50
+ baseline_date = labels.get("x86.baseline.date")
51
+
52
+ if baseline_date:
53
+ date_image = self.parse_date(baseline_date)
54
+ else:
55
+ base_image = self.extract_base_image_from_labels(labels)
56
+ date_image = self.extract_date_from_image(base_image)
57
+
58
+ return self.validate_date(date_image, referenced_date)
59
+
60
+ def get_image_details(self, image_id):
36
61
  try:
37
62
  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("x86.image.name")
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}'.")
63
+ return client.api.inspect_image(image_id)
64
+ except Exception as e:
65
+ logger.error(f"Error obtaining image details for '{image_id}': {e}")
46
66
  return None
47
67
 
68
+ def extract_base_image_from_labels(self, labels, matching_image=None):
69
+ try:
70
+ source_image = labels.get("x86.image.name") or labels.get(
71
+ "image.base.ref.name"
72
+ )
73
+ if not source_image:
74
+ source_image = labels.get("source_images") or labels.get("source-image")
75
+
76
+ if source_image and matching_image:
77
+ logger.info(f"Base image for '{matching_image}' found: {source_image}")
78
+ elif matching_image:
79
+ logger.warning(f"Base image not found for '{matching_image}'.")
80
+
81
+ return source_image
48
82
  except Exception as e:
49
- logger.error(f"Error getting base image: {e}")
50
- return None
83
+ logger.error(f"Error extracting base image from labels: {e}")
84
+ return None
85
+
86
+ def extract_date_from_image(self, image_name):
87
+ if not image_name:
88
+ return None
89
+ try:
90
+ date = image_name.split("_")[-1]
91
+ return self.parse_date(date)
92
+ except Exception as e:
93
+ logger.error(f"Error extracting date from image name '{image_name}': {e}")
94
+ return None
95
+
96
+ def parse_date(self, date_str):
97
+ try:
98
+ return datetime.strptime(date_str, "%Y%m%d")
99
+ except ValueError:
100
+ logger.error(f"Invalid date format: {date_str}")
101
+ return None
102
+
103
+ def validate_date(self, date, referenced_date):
104
+ if not date:
105
+ raise ValueError("Cannot validate date: Invalid or missing date.")
106
+
107
+ reference_date = self.parse_date(referenced_date)
108
+ if not reference_date:
109
+ raise ValueError("Cannot validate date: Referenced date is invalid.")
110
+
111
+ if date < reference_date:
112
+ raise ValueError(
113
+ f"Compliance issue: the source base image date ({date.strftime('%Y-%m-%d')}) is older than the referenced date ({reference_date.strftime('%Y-%m-%d')})."
114
+ )
115
+ return True
@@ -52,7 +52,8 @@ def init_engine_sca_rm(
52
52
  secret_tool,
53
53
  dict_args["token_engine_container"],
54
54
  image_to_scan,
55
- exclusions
55
+ exclusions,
56
+ pipeline_name
56
57
  )
57
58
  image_scanned, base_image, sbom_components = container_sca_scan.process()
58
59
  if image_scanned:
@@ -1 +1 @@
1
- version = '1.42.3'
1
+ version = '1.43.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devsecops-engine-tools
3
- Version: 1.42.3
3
+ Version: 1.43.0
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=qzzHq7sSQn1Shj9yLpQ0xtfFSp9OLCxD3g-f8vYp3ig,19
2
+ devsecops_engine_tools/version.py,sha256=rgVE2760niT3XN1VMw-ZEBrUP7L5heut-fiAjEx9JwA,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
@@ -40,7 +40,7 @@ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azur
40
40
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=ptzqoY7BkNO4jlna7Uw30mreKZfspwBRqEZMAbhRka4,29969
42
42
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py,sha256=cn9VGDaD9gUnJrLn9vEkQvfqYHIJftGE9ZACHEUOUxo,4132
43
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py,sha256=RbZS__LXeeztxumSKZ0aqmkQwKL39q1xdkJDVV_QSMU,4148
44
44
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=NkXu7JYoCHXIx0HzHl4DhdLGEpocPMIqs2L0ADS-RcI,5369
46
46
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_rich_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -198,16 +198,16 @@ devsecops_engine_tools/engine_sca/engine_container/src/domain/__init__.py,sha256
198
198
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
199
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
200
200
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/deserealizator_gateway.py,sha256=sE7-GnNSNLWbA1H0mvTwXmxcOJXl8uvw-0hxMyX4oMc,290
201
- devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/images_gateway.py,sha256=cXafS4v7tflUAaqf9t468gL8P6Wa9hY09BTNzKIuAWQ,277
201
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/images_gateway.py,sha256=U72tVbOdR75FlitYGp4Wrj7_ZPz0WRsSTRA48goG3Ec,411
202
202
  devsecops_engine_tools/engine_sca/engine_container/src/domain/model/gateways/tool_gateway.py,sha256=2fT2DFb4IPqQczCrAI0qEuWQUb3XsqFhI5M0OzNYalo,286
203
203
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
204
- devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=N61PjZAecSqhGTYc2HcyuBqdhDTFZ6ZpQMmOQH17h9Y,4122
204
+ devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/container_sca_scan.py,sha256=GvXsT-umEqB-2itAZiwlKIR581w78DbIJNknJ0o7EPw,4925
205
205
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/handle_remote_config_patterns.py,sha256=4wgBTQSDE-C5v01C3Vxzeq0DJKZUSqQ5TVLG7yPZPKs,926
206
206
  devsecops_engine_tools/engine_sca/engine_container/src/domain/usecases/set_input_core.py,sha256=2Q-20WqZUCTO5QQxEQnOX8fGlErgOMgiLBCDXBp3xFE,2634
207
207
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
208
208
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
209
209
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=kJfJbbsHgwmN1NWJ0lb4HhWNcadaFuSnLzr5xUV7QoM,1857
210
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=_p-JPfVBrDJBkAxWZHySLc54sMIEe9v1Ut77uTrqlOo,4316
211
211
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
212
212
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=tf33YFYB47th4Zu0WtWpsrAm5I6_xCON4yOwFacTQLA,6758
213
213
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=oK0NKuPODm38qDgQjf6w40lfNG6NFJS43p5k44wDoMA,2562
@@ -215,7 +215,7 @@ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_ada
215
215
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_deserialize_output.py,sha256=LGqnO10Zt-0-TxUW6F1S46jVktlIwxWSYATKSVblCWI,2535
216
216
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=7hGrUU37ZqZKHfkiNX2YrhIlDna8XnhJ3F7ONhneexs,5105
217
217
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=D80_Qns1OYGkCh7pKO1NbVq8Upp-Gn3gLdxtFQbUzsw,2567
218
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/entry_points/entry_point_tool.py,sha256=zCHhb0dFbvPl4kueKroaJfjhra8RWQXxuSOqVOZmg7o,2595
219
219
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
220
  devsecops_engine_tools/engine_sca/engine_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
221
  devsecops_engine_tools/engine_sca/engine_dependencies/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -347,8 +347,8 @@ devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGax
347
347
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=amYAr9YQfYgR6jK9a2l26z3oovFPQ3FAKmhq6BKhEBA,623
348
348
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=Z0fdhB3r-dxU0nGSD9zW_B4r2Qol1rUnUCkhFR0U-HQ,487
349
349
  devsecops_engine_tools/engine_utilities/utils/utils.py,sha256=XFap4yOK7ItLWsqbwDhvLd7NpDhs7i-UGJAMD6jjd7w,6687
350
- devsecops_engine_tools-1.42.3.dist-info/METADATA,sha256=r3wnjrTX8oIVaWN_HXA8kr3LQZFD26Cctk7PXJww0hg,11750
351
- devsecops_engine_tools-1.42.3.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
352
- devsecops_engine_tools-1.42.3.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
353
- devsecops_engine_tools-1.42.3.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
354
- devsecops_engine_tools-1.42.3.dist-info/RECORD,,
350
+ devsecops_engine_tools-1.43.0.dist-info/METADATA,sha256=MlWUkXgNemUz4PZ-NRmIWTGmsuWeWYzJj0q5TNOw6XI,11750
351
+ devsecops_engine_tools-1.43.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
352
+ devsecops_engine_tools-1.43.0.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
353
+ devsecops_engine_tools-1.43.0.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
354
+ devsecops_engine_tools-1.43.0.dist-info/RECORD,,