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

Files changed (35) hide show
  1. devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +2 -0
  2. devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py +19 -0
  3. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py +3 -6
  4. devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py +7 -47
  5. devsecops_engine_tools/engine_sca/engine_function/__init__.py +0 -0
  6. devsecops_engine_tools/engine_sca/engine_function/src/__init__.py +0 -0
  7. devsecops_engine_tools/engine_sca/engine_function/src/applications/__init__.py +0 -0
  8. devsecops_engine_tools/engine_sca/engine_function/src/applications/runner_function_scan.py +32 -0
  9. devsecops_engine_tools/engine_sca/engine_function/src/deployment/__init__.py +0 -0
  10. devsecops_engine_tools/engine_sca/engine_function/src/deployment/infrastructure/__init__.py +0 -0
  11. devsecops_engine_tools/engine_sca/engine_function/src/domain/__init__.py +0 -0
  12. devsecops_engine_tools/engine_sca/engine_function/src/domain/model/__init__.py +0 -0
  13. devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/__init__.py +0 -0
  14. devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/deserealizator_gateway.py +8 -0
  15. devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/tool_gateway.py +13 -0
  16. devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/__init__.py +0 -0
  17. devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/function_sca_scan.py +71 -0
  18. devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/handle_remote_config_patterns.py +73 -0
  19. devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/set_input_core.py +76 -0
  20. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/__init__.py +0 -0
  21. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/__init__.py +0 -0
  22. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/__init__.py +0 -0
  23. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py +175 -0
  24. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py +59 -0
  25. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/entry_points/__init__.py +0 -0
  26. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/entry_points/entry_point_tool.py +61 -0
  27. devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/helpers/__init__.py +0 -0
  28. devsecops_engine_tools/engine_utilities/twistcli_utils/__init__.py +0 -0
  29. devsecops_engine_tools/engine_utilities/twistcli_utils/twistcli_utils.py +44 -0
  30. devsecops_engine_tools/version.py +1 -1
  31. {devsecops_engine_tools-1.115.2.dist-info → devsecops_engine_tools-1.116.1.dist-info}/METADATA +1 -1
  32. {devsecops_engine_tools-1.115.2.dist-info → devsecops_engine_tools-1.116.1.dist-info}/RECORD +35 -10
  33. {devsecops_engine_tools-1.115.2.dist-info → devsecops_engine_tools-1.116.1.dist-info}/WHEEL +0 -0
  34. {devsecops_engine_tools-1.115.2.dist-info → devsecops_engine_tools-1.116.1.dist-info}/entry_points.txt +0 -0
  35. {devsecops_engine_tools-1.115.2.dist-info → devsecops_engine_tools-1.116.1.dist-info}/top_level.txt +0 -0
@@ -125,6 +125,7 @@ def get_inputs_from_cli(args):
125
125
  "engine_dependencies",
126
126
  "engine_container",
127
127
  "engine_risk",
128
+ "engine_function",
128
129
  ],
129
130
  type=str,
130
131
  required=True,
@@ -246,6 +247,7 @@ def get_inputs_from_cli(args):
246
247
  "engine_code": ["bearer", "kiuwan"],
247
248
  "engine_dast": ["nuclei"],
248
249
  "engine_risk": None,
250
+ "engine_function": ["prisma"],
249
251
  }
250
252
 
251
253
  args = parser.parse_args()
@@ -36,6 +36,9 @@ from devsecops_engine_tools.engine_sca.engine_container.src.applications.runner_
36
36
  from devsecops_engine_tools.engine_sca.engine_dependencies.src.applications.runner_dependencies_scan import (
37
37
  runner_engine_dependencies,
38
38
  )
39
+ from devsecops_engine_tools.engine_sca.engine_function.src.applications.runner_function_scan import (
40
+ runner_engine_function,
41
+ )
39
42
  from devsecops_engine_tools.engine_dast.src.applications.runner_dast_scan import (
40
43
  runner_engine_dast,
41
44
  )
@@ -100,6 +103,22 @@ class HandleScan:
100
103
  sbom_components,
101
104
  )
102
105
  return findings_list, input_core
106
+ elif "engine_function" in dict_args["module"]:
107
+ findings_list, input_core = runner_engine_function(
108
+ dict_args,
109
+ config_tool["ENGINE_FUNCTION"],
110
+ secret_tool,
111
+ self.devops_platform_gateway,
112
+ self.remote_config_source_gateway
113
+ )
114
+ self._use_vulnerability_management(
115
+ config_tool,
116
+ input_core,
117
+ dict_args,
118
+ secret_tool,
119
+ env
120
+ )
121
+ return findings_list, input_core
103
122
  elif "engine_dast" in dict_args["module"]:
104
123
  findings_list, input_core = runner_engine_dast(
105
124
  dict_args,
@@ -27,9 +27,7 @@ class PrinterPrettyTable(PrinterTableGateway):
27
27
  finding.description,
28
28
  finding.where,
29
29
  ]
30
- if (finding.module == "engine_container") or (
31
- finding.module == "engine_dependencies"
32
- ):
30
+ if finding.module in ("engine_container", "engine_dependencies", "engine_function"):
33
31
  row_data.append(finding.requirements)
34
32
  elif finding.module == "engine_code":
35
33
  row_data.append(finding.cvss)
@@ -53,9 +51,8 @@ class PrinterPrettyTable(PrinterTableGateway):
53
51
  if (
54
52
  finding_list
55
53
  and (
56
- (finding_list[0].module == "engine_container")
57
- or (finding_list[0].module == "engine_dependencies")
58
- )
54
+ finding_list[0].module in ["engine_container","engine_dependencies", "engine_function"]
55
+ )
59
56
  ):
60
57
  headers = ["Severity", "ID", "Description", "Where", "Fixed in"]
61
58
  elif finding_list and finding_list[0].module == "engine_code":
@@ -1,10 +1,8 @@
1
- import stat
2
1
  import requests
3
2
  import os
4
3
  import subprocess
5
4
  import base64
6
5
  import json
7
- import platform
8
6
  from devsecops_engine_tools.engine_sca.engine_container.src.domain.model.gateways.tool_gateway import (
9
7
  ToolGateway,
10
8
  )
@@ -13,55 +11,18 @@ from devsecops_engine_tools.engine_utilities.sbom.deserealizator import (
13
11
  )
14
12
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
15
13
  from devsecops_engine_tools.engine_utilities import settings
14
+ from devsecops_engine_tools.engine_utilities.twistcli_utils.twistcli_utils import download_twistcli
16
15
 
17
16
  logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
18
17
 
19
18
 
20
19
  class PrismaCloudManagerScan(ToolGateway):
21
- def download_twistcli(
22
- self,
23
- file_path,
24
- prisma_key,
25
- prisma_console_url,
26
- prisma_api_version,
27
- ):
28
-
29
- machine = platform.machine()
30
- system = platform.system()
31
-
32
- base_url = f"{prisma_console_url}/api/{prisma_api_version}/util"
33
-
34
- os_mapping = {
35
- "Linux": "twistcli",
36
- "Windows": "windows/twistcli.exe",
37
- "Darwin": "osx/twistcli",
38
- }
39
-
40
- url = f"{base_url}/{os_mapping[system]}"
41
-
42
- if system == "Linux" and machine == "aarch64":
43
- url = f"{base_url}/arm64/twistcli"
44
- elif system == "Darwin" and machine == "aarch64":
45
- url = f"{base_url}/osx/arm64/twistcli"
46
-
47
- credentials = base64.b64encode(
48
- prisma_key.encode()
49
- ).decode()
50
- headers = {"Authorization": f"Basic {credentials}"}
51
- try:
52
- response = requests.get(url, headers=headers)
53
- response.raise_for_status()
54
-
55
- with open(file_path, "wb") as file:
56
- file.write(response.content)
57
-
58
- os.chmod(file_path, stat.S_IRWXU)
59
- logger.info(f"twistcli downloaded and saved to: {file_path}")
60
- return 0
61
-
62
- except Exception as e:
63
- raise ValueError(f"Error downloading twistcli: {e}")
64
-
20
+ def download_twistcli(self, file_path, prisma_key, prisma_console_url, prisma_api_version) -> int:
21
+ """
22
+ Método de instancia separado (lo que usan los tests),
23
+ delega en el util compat 'basic' para no romper aserciones.
24
+ """
25
+ return download_twistcli(file_path, prisma_key, prisma_console_url, prisma_api_version)
65
26
  def scan_image(
66
27
  self, file_path, image_name, result_file, remoteconfig, prisma_key, docker_address
67
28
  ):
@@ -168,7 +129,6 @@ class PrismaCloudManagerScan(ToolGateway):
168
129
  except Exception as e:
169
130
  logger.error(f"Error generating SBOM: {e}")
170
131
 
171
-
172
132
  def _split_prisma_token(self, prisma_key):
173
133
  try:
174
134
  access_prisma, token_prisma = prisma_key.split(":")
@@ -0,0 +1,32 @@
1
+ from devsecops_engine_tools.engine_sca.engine_function.src.infrastructure.entry_points.entry_point_tool import (
2
+ init_engine_sca_rm,
3
+ )
4
+ from devsecops_engine_tools.engine_sca.engine_function.src.infrastructure.driven_adapters.prisma_cloud.prisma_cloud_manager_scan import (
5
+ PrismaCloudManagerScan,
6
+ )
7
+ from devsecops_engine_tools.engine_sca.engine_function.src.infrastructure.driven_adapters.prisma_cloud.prisma_deserialize_output import (
8
+ PrismaDeserealizator,
9
+ )
10
+
11
+
12
+ def runner_engine_function(dict_args, config_tool, secret_tool, tool_remote, remote_config_source_gateway):
13
+ try:
14
+ if config_tool["TOOL"].lower() == "prisma":
15
+ tool_run = PrismaCloudManagerScan(config_tool, dict_args)
16
+ tool_deseralizator = PrismaDeserealizator()
17
+ return init_engine_sca_rm(
18
+ tool_run,
19
+ tool_remote,
20
+ remote_config_source_gateway,
21
+ tool_deseralizator,
22
+ dict_args,
23
+ secret_tool,
24
+ config_tool,
25
+ )
26
+
27
+ except Exception as e:
28
+ raise Exception(f"Error SCAN engine function : {str(e)}")
29
+
30
+
31
+ if __name__ == "__main__":
32
+ runner_engine_function()
@@ -0,0 +1,8 @@
1
+ from abc import ABCMeta, abstractmethod
2
+ from devsecops_engine_tools.engine_core.src.domain.model.finding import Finding
3
+
4
+
5
+ class DeseralizatorGateway(metaclass=ABCMeta):
6
+ @abstractmethod
7
+ def get_list_findings(self, results_scan_list: list) -> "list[Finding]":
8
+ "Deseralizator"
@@ -0,0 +1,13 @@
1
+ from abc import ABCMeta, abstractmethod
2
+
3
+
4
+ class ToolGateway(metaclass=ABCMeta):
5
+ @abstractmethod
6
+ def run_tool_function_sca(
7
+ self,
8
+ dict_args,
9
+ token:str=None,
10
+ skip_flag:bool=None,
11
+ ) -> str:
12
+
13
+ "run tool function sca"
@@ -0,0 +1,71 @@
1
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import (
2
+ DevopsPlatformGateway,
3
+ )
4
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.model.gateways.tool_gateway import (
5
+ ToolGateway,
6
+ )
7
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.model.gateways.deserealizator_gateway import (
8
+ DeseralizatorGateway,
9
+ )
10
+
11
+
12
+ class FunctionScaScan:
13
+ def __init__(
14
+ self,
15
+ tool_run: ToolGateway,
16
+ remote_config,
17
+ tool_remote: DevopsPlatformGateway,
18
+ tool_deseralizator: DeseralizatorGateway,
19
+ dict_args,
20
+ secret_tool,
21
+ token_engine_container
22
+ ):
23
+ self.tool_run = tool_run
24
+ self.remote_config = remote_config
25
+ self.tool_remote = tool_remote
26
+ self.tool_deseralizator = tool_deseralizator
27
+ self.dict_args = dict_args
28
+ self.secret_tool = secret_tool
29
+ self.token_engine_container = token_engine_container
30
+
31
+ def get_remote_config(self, file_path):
32
+ """
33
+ Get remote configuration.
34
+
35
+ Returns:
36
+ dict: Remote configuration.
37
+ """
38
+ return self.tool_remote.get_remote_config(self.dict_args["remote_config_repo"], file_path, self.dict_args["remote_config_branch"])
39
+
40
+
41
+ def get_variable(self, variable):
42
+ """
43
+ Get variable.
44
+
45
+ Returns:
46
+ dict: Remote variable.
47
+ """
48
+ return self.tool_remote.get_variable(variable)
49
+
50
+ def process(self):
51
+ """
52
+ Process SCA scanning.
53
+
54
+ Returns:
55
+ dict: SCA scanning results.
56
+ """
57
+
58
+ return self.tool_run.run_tool_function_sca(
59
+ self.get_remote_config("engine_sca/engine_function/ConfigTool.json"),
60
+ self.secret_tool,
61
+ self.token_engine_container,
62
+ )
63
+
64
+ def deseralizator(self, function_scanned):
65
+ """
66
+ Process the results deserializer.
67
+
68
+ Returns:
69
+ list: Deserialized list of findings.
70
+ """
71
+ return self.tool_deseralizator.get_list_findings(function_scanned)
@@ -0,0 +1,73 @@
1
+ import re
2
+
3
+ class HandleRemoteConfigPatterns:
4
+ def __init__(self, remote_config, exclusions, pipeline_name):
5
+ self.remote_config = remote_config
6
+ self.exclusions = exclusions
7
+ self.pipeline_name = pipeline_name
8
+
9
+ def get_remote_config(self, file_path):
10
+ """
11
+ Get remote configuration
12
+ Return: dict: Remote configuration
13
+ """
14
+ return self.tool_remote.get_remote_config(
15
+ self.dict_args["remote_config_repo"], file_path, self.dict_args["remote_config_branch"]
16
+ )
17
+
18
+ def get_variable(self, variable):
19
+ """
20
+ Get variable.
21
+
22
+ Returns:
23
+ dict: Remote variable.
24
+ """
25
+ return self.tool_remote.get_variable(variable)
26
+
27
+ def handle_skip_tool(self, exclusions, pipeline_name):
28
+ """
29
+ Handle skip tool.
30
+
31
+ Return: bool: True -> skip tool, False -> not skip tool.
32
+ """
33
+ if (pipeline_name in exclusions) and (
34
+ exclusions[pipeline_name].get("SKIP_TOOL", 0)
35
+ ):
36
+ return True
37
+ else:
38
+ return False
39
+
40
+ def process_handle_skip_tool(self):
41
+ """
42
+ Process handle skip tool.
43
+
44
+ Return: bool: True -> skip tool, False -> not skip tool.
45
+ """
46
+ return self.handle_skip_tool(
47
+ self.get_remote_config("engine_sca/engine_function/Exclusions.json"),
48
+ self.get_variable("pipeline_name"),
49
+ )
50
+
51
+ def ignore_analysis_pattern(self):
52
+ """
53
+ Handle analysis pattern.
54
+ Return: bool: False -> not scan, True -> scan.
55
+ """
56
+ ignore = self.remote_config["IGNORE_SEARCH_PATTERN"]
57
+ if re.match(ignore, self.pipeline_name, re.IGNORECASE):
58
+ return False
59
+ else:
60
+ return True
61
+
62
+ def skip_from_exclusion(self):
63
+ """
64
+ Handle skip tool.
65
+
66
+ Return: bool: True -> skip tool, False -> not skip tool.
67
+ """
68
+ if (self.pipeline_name in self.exclusions) and (
69
+ self.exclusions[self.pipeline_name].get("SKIP_TOOL", 0)
70
+ ):
71
+ return True
72
+ else:
73
+ return False
@@ -0,0 +1,76 @@
1
+ from devsecops_engine_tools.engine_core.src.domain.model.input_core import InputCore
2
+ from devsecops_engine_tools.engine_core.src.domain.model.threshold import Threshold
3
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import (
4
+ DevopsPlatformGateway,
5
+ )
6
+ from devsecops_engine_tools.engine_core.src.domain.model.exclusions import Exclusions
7
+
8
+
9
+ class SetInputCore:
10
+ def __init__(self, tool_remote: DevopsPlatformGateway, dict_args, config_tool):
11
+ self.tool_remote = tool_remote
12
+ self.dict_args = dict_args
13
+ self.config_tool = config_tool
14
+
15
+ def get_remote_config(self, file_path):
16
+ """
17
+ Get remote configuration.
18
+
19
+ Returns:
20
+ dict: Remote configuration.
21
+ """
22
+ return self.tool_remote.get_remote_config(self.dict_args["remote_config_repo"], file_path)
23
+
24
+ def get_variable(self, variable):
25
+ """
26
+ Get variable.
27
+
28
+ Returns:
29
+ dict: Remote variable.
30
+ """
31
+ return self.tool_remote.get_variable(variable)
32
+
33
+ def get_exclusions(self, exclusions_data, pipeline_name, tool):
34
+ list_exclusions = []
35
+ for key, value in exclusions_data.items():
36
+ if (key == "All") or (key == pipeline_name):
37
+ if value.get(tool, 0):
38
+ exclusions = [
39
+ Exclusions(
40
+ id=item.get("id", ""),
41
+ where=item.get("where", ""),
42
+ cve_id=item.get("cve_id", ""),
43
+ create_date=item.get("create_date", ""),
44
+ expired_date=item.get("expired_date", ""),
45
+ severity=item.get("severity", ""),
46
+ hu=item.get("hu", ""),
47
+ reason=item.get("reason", "DevSecOps policy"),
48
+ )
49
+ for item in value[tool]
50
+ ]
51
+ list_exclusions.extend(exclusions)
52
+ return list_exclusions
53
+
54
+ def set_input_core(self):
55
+ """
56
+ Set the input core.
57
+
58
+ Returns:
59
+ dict: Input core.
60
+ """
61
+
62
+ return InputCore(
63
+ self.get_exclusions(
64
+ self.get_remote_config("engine_sca/engine_function/Exclusions.json"),
65
+ self.get_variable("pipeline_name"),
66
+ self.config_tool["TOOL"],
67
+ ),
68
+ Threshold(
69
+ self.get_remote_config("engine_sca/engine_function/ConfigTool.json")["THRESHOLD"]
70
+ ),
71
+ None,
72
+ self.get_remote_config("engine_sca/engine_function/ConfigTool.json")["MESSAGE_INFO_ENGINE_FUNCTION"],
73
+ self.get_variable("pipeline_name"),
74
+ self.get_variable("pipeline_name"),
75
+ self.get_variable("stage"),
76
+ )
@@ -0,0 +1,175 @@
1
+ import os
2
+ import glob
3
+ import subprocess
4
+ import re
5
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.model.gateways.tool_gateway import (
6
+ ToolGateway,
7
+ )
8
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
9
+ from devsecops_engine_tools.engine_utilities import settings
10
+ from devsecops_engine_tools.engine_utilities.twistcli_utils.twistcli_utils import download_twistcli
11
+
12
+
13
+
14
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
15
+
16
+
17
+ class PrismaCloudManagerScan:
18
+ def __init__(
19
+ self,
20
+ tool_run: ToolGateway,
21
+ dict_args
22
+ ):
23
+ self.tool_run = tool_run
24
+ self.dict_args = dict_args
25
+
26
+ def run_tool_function_sca(
27
+ self,
28
+ remoteconfig,
29
+ secret_tool,
30
+ token_engine_container,
31
+ ):
32
+ prisma_key = (
33
+ f"{secret_tool['access_prisma']}:{secret_tool['token_prisma']}" if secret_tool else token_engine_container
34
+ )
35
+ file_path = os.path.join(
36
+ os.getcwd(), remoteconfig["PRISMA_CLOUD"]["TWISTCLI_PATH"]
37
+ )
38
+ if not os.path.exists(file_path):
39
+ self.download_twistcli(
40
+ file_path,
41
+ prisma_key,
42
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
43
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_API_VERSION"],
44
+ )
45
+ folder_path = self.dict_args["folder_path"]
46
+ function_scan = self._scan_function(
47
+ file_path,
48
+ folder_path,
49
+ remoteconfig,
50
+ prisma_key,
51
+ )
52
+
53
+ return function_scan
54
+
55
+ def _split_prisma_token(self, prisma_key):
56
+ try:
57
+ access_prisma, token_prisma = prisma_key.split(":")
58
+ return access_prisma, token_prisma
59
+ except ValueError:
60
+ raise ValueError("The string is not properly formatted. Make sure it contains a ':'.")
61
+
62
+ def _scan_function(self, file_path, folder_path, remoteconfig, prisma_key):
63
+ function_path = glob.glob(os.path.join(folder_path, "*.zip"))
64
+ if not function_path:
65
+ print("No .zip file found [Scanning skipped]")
66
+ return None
67
+ zip_name = os.path.basename(function_path[0])
68
+ command = (
69
+ file_path,
70
+ "serverless",
71
+ "scan",
72
+ "--address",
73
+ remoteconfig["PRISMA_CLOUD"]["PRISMA_CONSOLE_URL"],
74
+ "--user",
75
+ self._split_prisma_token(prisma_key)[0],
76
+ "--password",
77
+ self._split_prisma_token(prisma_key)[1],
78
+ "--details",
79
+ function_path[0],
80
+ )
81
+ try:
82
+ result = subprocess.run(
83
+ command,
84
+ check=True,
85
+ stdout=subprocess.PIPE,
86
+ stderr=subprocess.PIPE,
87
+ text=True,
88
+ errors="replace"
89
+ )
90
+ print(f"The function {zip_name} was scanned")
91
+ result = self._parse_scan_results(result.stdout)
92
+ return result
93
+
94
+ except subprocess.CalledProcessError as e:
95
+ logger.error(
96
+ f"Error during function scan of {zip_name}"
97
+ f"\n errorcode: {e.returncode}"
98
+ f"\n output: {e.output}"
99
+ )
100
+ def download_twistcli(self, file_path, prisma_key, prisma_console_url, prisma_api_version) -> int:
101
+ """
102
+ Método de instancia separado (lo que usan los tests),
103
+ delega en el util compat 'basic' para no romper aserciones.
104
+ """
105
+ return download_twistcli(file_path, prisma_key, prisma_console_url, prisma_api_version)
106
+
107
+ def _parse_scan_results(self, stdout: str) -> dict:
108
+ def extract_dist(pattern: str) -> dict:
109
+ match = re.search(pattern, stdout)
110
+ return {
111
+ "critical": int(match.group(2)),
112
+ "high": int(match.group(3)),
113
+ "medium": int(match.group(4)),
114
+ "low": int(match.group(5)),
115
+ "total": int(match.group(1))
116
+ } if match else {}
117
+
118
+ def clean_text(text) -> str:
119
+ cleaned_text = text.replace('\x1b[0m', '')
120
+ cleaned_text = cleaned_text.replace('\x1b[91;1m', '')
121
+ cleaned_text = cleaned_text.replace('\x1b[33;1m','')
122
+ return cleaned_text
123
+
124
+ def extract_table() -> list:
125
+ lines = stdout.splitlines()
126
+ table_start = [i for i, line in enumerate(lines) if 'CVE-' in line]
127
+ table_data = []
128
+ if table_start:
129
+ i = table_start[0]
130
+ while i < len(lines):
131
+ if "CVE-" in lines[i]:
132
+ row = lines[i]
133
+ desc_lines = []
134
+ i += 1
135
+ while i < len(lines) and not lines[i].strip().startswith("| CVE-") and not "+---" in lines[i]:
136
+ desc_lines.append(lines[i])
137
+ i += 1
138
+ full_row = row + "\n" + "\n".join(desc_lines)
139
+ table_data.append(full_row)
140
+ else:
141
+ i += 1
142
+
143
+ vulnerabilities = []
144
+ for row in table_data:
145
+ parts = [x.strip() for x in row.split("|")[1:-1]]
146
+ if len(parts) >= 9:
147
+ vuln = {
148
+ "id": clean_text(parts[0]),
149
+ "severity": clean_text(parts[1]),
150
+ "cvss": float(clean_text(parts[2])) if parts[2] else 0.0,
151
+ "packageName": clean_text(parts[3]),
152
+ "packageVersion": clean_text(parts[4]),
153
+ "status": clean_text(parts[5]),
154
+ "publishedDate": clean_text(parts[6]),
155
+ "discoveredDate": clean_text(parts[7]),
156
+ "description": clean_text(parts[8]).replace("u00a0", " ").strip(" .") + "..."
157
+ }
158
+ vulnerabilities.append(vuln)
159
+ return vulnerabilities
160
+
161
+ name_match = re.search(r"Scan results for: function (.+?)\s", stdout)
162
+ function_name = name_match.group(1) if name_match else "unknown.zip"
163
+
164
+ return {
165
+ "results": [
166
+ {
167
+ "name": function_name,
168
+ "complianceDistribution": extract_dist(r"Compliance found for function .*?: total - (\d+), critical - (\d+), high - (\d+), medium - (\d+), low - (\d+)"),
169
+ "complianceScanPassed": "Compliance threshold check results: PASS" in stdout,
170
+ "vulnerabilities": extract_table(),
171
+ "vulnerabilityDistribution": extract_dist(r"Vulnerabilities found for function .*?: total - (\d+), critical - (\d+), high - (\d+), medium - (\d+), low - (\d+)"),
172
+ "vulnerabilityScanPassed": "Vulnerability threshold check results: PASS" in stdout
173
+ }
174
+ ]
175
+ }
@@ -0,0 +1,59 @@
1
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.model.gateways.deserealizator_gateway import (
2
+ DeseralizatorGateway,
3
+ )
4
+ from devsecops_engine_tools.engine_core.src.domain.model.finding import (
5
+ Finding,
6
+ Category,
7
+ )
8
+ from datetime import datetime
9
+ from dataclasses import dataclass
10
+
11
+ @dataclass
12
+ class PrismaDeserealizator(DeseralizatorGateway):
13
+ def get_list_findings(self, function_scanned: dict) -> "list[Finding]":
14
+ if function_scanned is None:
15
+ return function_scanned
16
+
17
+ list_open_vulnerabilities = []
18
+ SEVERITY_MAP = {
19
+ "unimportant": "low",
20
+ "unassigned": "low",
21
+ "negligible": "low",
22
+ "not yet assigned": "low",
23
+ "low": "low",
24
+ "medium": "medium",
25
+ "moderate": "medium",
26
+ "high": "high",
27
+ "important": "high",
28
+ "critical": "critical",
29
+ }
30
+ vuls_data = function_scanned["results"][0]["vulnerabilities"]
31
+
32
+ if len(vuls_data) > 0:
33
+ vulnerabilities = [
34
+ Finding(
35
+ id=vul.get("id", ""),
36
+ cvss=float(vul.get("cvss", 0.0)),
37
+ where=vul.get("packageName", "")
38
+ + ":"
39
+ + vul.get("packageVersion", ""),
40
+ description=vul.get("description", "")[:150],
41
+ severity=SEVERITY_MAP.get(vul.get("severity", ""), ""),
42
+ identification_date=vul.get("discoveredDate", ""),
43
+ published_date_cve=vul.get("publishedDate", "").replace(
44
+ "Z", "+00:00"
45
+ ),
46
+ module="engine_function",
47
+ category=Category.VULNERABILITY,
48
+ requirements=vul.get("status", ""),
49
+ tool="PrismaCloud",
50
+ )
51
+ for vul in vuls_data
52
+ ]
53
+ else:
54
+ vulnerabilities = []
55
+
56
+ # Add the Vulnerability instances to the list
57
+ list_open_vulnerabilities.extend(vulnerabilities)
58
+
59
+ return list_open_vulnerabilities
@@ -0,0 +1,61 @@
1
+ import re
2
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.usecases.function_sca_scan import (
3
+ FunctionScaScan,
4
+ )
5
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.usecases.handle_remote_config_patterns import (
6
+ HandleRemoteConfigPatterns,
7
+ )
8
+ from devsecops_engine_tools.engine_sca.engine_function.src.domain.usecases.set_input_core import (
9
+ SetInputCore,
10
+ )
11
+
12
+
13
+ def init_engine_sca_rm(
14
+ tool_run,
15
+ tool_remote,
16
+ remote_config_source_gateway,
17
+ tool_deseralizator,
18
+ dict_args,
19
+ secret_tool,
20
+ config_tool,
21
+ ):
22
+ remote_config = remote_config_source_gateway.get_remote_config(
23
+ dict_args["remote_config_repo"],
24
+ "engine_sca/engine_function/ConfigTool.json",
25
+ dict_args["remote_config_branch"],
26
+ )
27
+ exclusions = remote_config_source_gateway.get_remote_config(
28
+ dict_args["remote_config_repo"],
29
+ "engine_sca/engine_function/Exclusions.json",
30
+ dict_args["remote_config_branch"],
31
+ )
32
+ pipeline_name = tool_remote.get_variable("pipeline_name")
33
+ regex_clean = remote_config.get("REGEX_CLEAN_END_PIPELINE_NAME")
34
+ if regex_clean:
35
+ pattern = re.compile(regex_clean)
36
+ match = pattern.match(pipeline_name)
37
+ if match:
38
+ pipeline_name= match.group(1)
39
+ handle_remote_config_patterns = HandleRemoteConfigPatterns(
40
+ remote_config, exclusions, pipeline_name
41
+ )
42
+ skip_flag = handle_remote_config_patterns.skip_from_exclusion()
43
+ scan_flag = handle_remote_config_patterns.ignore_analysis_pattern()
44
+ if scan_flag and not (skip_flag):
45
+ function_sca_scan = FunctionScaScan(
46
+ tool_run,
47
+ remote_config,
48
+ tool_remote,
49
+ tool_deseralizator,
50
+ dict_args,
51
+ secret_tool,
52
+ dict_args["token_engine_container"],
53
+ )
54
+ else:
55
+ print("Tool skipped by DevSecOps policy")
56
+ dict_args["send_metrics"] = "false"
57
+ dict_args["use_vulnerability_management"] = "false"
58
+ input_core = SetInputCore(tool_remote, dict_args, config_tool)
59
+ function_scan = function_sca_scan.process()
60
+
61
+ return function_sca_scan.deseralizator(function_scan), input_core.set_input_core()
@@ -0,0 +1,44 @@
1
+ # tools/devsecops_engine_tools/engine_utilities/twistcli_utils/twistcli_utils.py
2
+ import os
3
+ import stat
4
+ import base64
5
+ import platform
6
+ import logging
7
+ import requests
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ def download_twistcli(file_path: str, prisma_key: str, prisma_console_url: str, prisma_api_version: str) -> int:
12
+ machine = platform.machine()
13
+ system = platform.system()
14
+
15
+ base_url = f"{prisma_console_url}/api/{prisma_api_version}/util"
16
+
17
+ os_mapping = {
18
+ "Linux": "twistcli",
19
+ "Windows": "windows/twistcli.exe",
20
+ "Darwin": "osx/twistcli",
21
+ }
22
+
23
+ url = f"{base_url}/{os_mapping.get(system, 'twistcli')}"
24
+
25
+ if system == "Linux" and machine == "aarch64":
26
+ url = f"{base_url}/arm64/twistcli"
27
+ elif system == "Darwin" and machine == "aarch64":
28
+ url = f"{base_url}/osx/arm64/twistcli"
29
+
30
+ credentials = base64.b64encode(prisma_key.encode()).decode()
31
+ headers = {"Authorization": f"Basic {credentials}"}
32
+
33
+ try:
34
+ resp = requests.get(url, headers=headers)
35
+ resp.raise_for_status()
36
+
37
+ with open(file_path, "wb") as fh:
38
+ fh.write(resp.content)
39
+
40
+ os.chmod(file_path, stat.S_IRWXU)
41
+ logger.info("twistcli downloaded and saved to: %s", file_path)
42
+ return 0
43
+ except Exception as e:
44
+ raise ValueError(f"Error downloading twistcli: {e}")
@@ -1 +1 @@
1
- version = '1.115.2'
1
+ version = '1.116.1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devsecops-engine-tools
3
- Version: 1.115.2
3
+ Version: 1.116.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,9 +1,9 @@
1
1
  devsecops_engine_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- devsecops_engine_tools/version.py,sha256=G0FaCPC9BsNo6rIbflyFI_gSlVpN5Z4gG3VYTTSKWaY,20
2
+ devsecops_engine_tools/version.py,sha256=7JkAWunAxlTrOsrHQoxSGbRen6fwMohUIdsQ-egEUik,20
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
6
- devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py,sha256=SZwFPlpNNlfQTDZiDgB1Vy4qY323aSjFh5p0RTeVEvs,11343
6
+ devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py,sha256=Z5s0yezXAL2TqgBKIGJta_kEUTPM9A3qFdm7ymbKlEg,11413
7
7
  devsecops_engine_tools/engine_core/src/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  devsecops_engine_tools/engine_core/src/deployment/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  devsecops_engine_tools/engine_core/src/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -28,7 +28,7 @@ devsecops_engine_tools/engine_core/src/domain/model/gateway/vulnerability_manage
28
28
  devsecops_engine_tools/engine_core/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  devsecops_engine_tools/engine_core/src/domain/usecases/break_build.py,sha256=XAhykpsiRRIWfDy6Z3VDIMLExIev1bQbRHKFVF_f9cg,12176
30
30
  devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py,sha256=_vTTHOKBHsWQFPmL4j41fMonp6DLu8U4FCylDsw5-1Q,10053
31
- devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py,sha256=ML5FscQMlkEexAq3srivpjn2VQkJVsxHApZ5_I8T8Fg,11761
31
+ devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py,sha256=78uXAfVs1soYvuZUJQNOYIl283mshwmyM_QA24BvROk,12466
32
32
  devsecops_engine_tools/engine_core/src/domain/usecases/metrics_manager.py,sha256=xfaGrDf9rnN32qG_zOD9NN-a62reqQ5KOd2bP6xoRnw,2417
33
33
  devsecops_engine_tools/engine_core/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -44,7 +44,7 @@ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_doj
44
44
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py,sha256=Mt3ejrNHhkk8HIhQunMDnSW8Sn-65-yyXHGrFpaN744,4649
46
46
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=0p-7HTT6FtW5DpJyGAauYLM1Oso4hPgKLFnLqXNPjbo,5724
47
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/printer_pretty_table.py,sha256=bzY0jNR1nlGn08UNIQ2OOvDMscKKgdxJ25sRdCF376Y,5658
48
48
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_rich_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_rich_table/printer_rich_table.py,sha256=LPr3xSv0I7ENEdu1xj8ve5PXzpUohs7hbQvHjDSaUuE,3028
50
50
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -226,7 +226,7 @@ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_ada
226
226
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
227
227
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/docker/docker_images.py,sha256=SbPuZbhIIIN2w84iTZ8eOChwjqOt8jXIe5rEjEgvb9g,6365
228
228
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
229
- devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=o0QfawD1p2D9emIXarXyl3pgecAAdOc8Fai-EW_QYoA,8030
229
+ devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=kQyKQlfw_43tZKBplqjO6dS4vkuEP4WmeRbtZbCdsqw,7106
230
230
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=FXb0jUReJVUdZq_H_Zz-gCueMmWf0AwMiwJB-Ceqv2A,2695
231
231
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
232
  devsecops_engine_tools/engine_sca/engine_container/src/infrastructure/driven_adapters/trivy_tool/trivy_manager_scan.py,sha256=r4_f-18fVgZelonjfxQ-9bsHVOzhI8LUxlu5A0UUuaw,3855
@@ -263,6 +263,29 @@ devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/entry_p
263
263
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/entry_points/entry_point_tool.py,sha256=aXK8sDJ9RMy3WwNiZuxFeYNRTAxG-klPD3XvE4yNROE,3940
264
264
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
265
265
  devsecops_engine_tools/engine_sca/engine_dependencies/src/infrastructure/helpers/get_artifacts.py,sha256=ECczGxi-neekJAJkMBaRCE_1NTqmcv-5tB90F3GKz7w,5234
266
+ devsecops_engine_tools/engine_sca/engine_function/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
267
+ devsecops_engine_tools/engine_sca/engine_function/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
268
+ devsecops_engine_tools/engine_sca/engine_function/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
269
+ devsecops_engine_tools/engine_sca/engine_function/src/applications/runner_function_scan.py,sha256=AN7XCaAzaSTJ_q8T3l6AF6orQh57tubIkkp9O7xpnJ8,1161
270
+ devsecops_engine_tools/engine_sca/engine_function/src/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
271
+ devsecops_engine_tools/engine_sca/engine_function/src/deployment/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
272
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
273
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
274
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
275
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/deserealizator_gateway.py,sha256=sE7-GnNSNLWbA1H0mvTwXmxcOJXl8uvw-0hxMyX4oMc,290
276
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/model/gateways/tool_gateway.py,sha256=Pg7YCTRKUCrb1RCXRbfWPrOepjeHC_V912tMvxdEMhQ,272
277
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/function_sca_scan.py,sha256=s2Fw2hS4wSYd77w0NkV88L_Hx6iFc_qiaeaHwaxpquo,2078
279
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/handle_remote_config_patterns.py,sha256=JGjtREInEadXCRskhFnlvTqYeDkGNAePR478e_A6JBw,2130
280
+ devsecops_engine_tools/engine_sca/engine_function/src/domain/usecases/set_input_core.py,sha256=h18O2bNba2wOQNoqjBrxf2Z9HLlDrzdxFOQkJ5Bo-QU,2864
281
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
282
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
283
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
284
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/prisma_cloud_manager_scan.py,sha256=sKHshGZZ3RxNrlzw-3MpHeWYarLb8KVTpyqJ6AkfUZM,6937
285
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/driven_adapters/prisma_cloud/prisma_deserialize_output.py,sha256=ZmTV4-7M5VX-pjruvcnzrAeuOJrdqzoZnvPtyN-oGRI,2126
286
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/entry_points/entry_point_tool.py,sha256=rW-TaEMZB5tXD8pUiNNg4HV8mYxgqYjIsyXfYJcN6T4,2210
288
+ devsecops_engine_tools/engine_sca/engine_function/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
266
289
  devsecops_engine_tools/engine_utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
267
290
  devsecops_engine_tools/engine_utilities/settings.py,sha256=CPnDndwVeRgQNml3HVzvytVruDd8dTd1ICHbkMDSgTM,2144
268
291
  devsecops_engine_tools/engine_utilities/azuredevops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -374,6 +397,8 @@ devsecops_engine_tools/engine_utilities/trivy_utils/infrastructure/__init__.py,s
374
397
  devsecops_engine_tools/engine_utilities/trivy_utils/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
398
  devsecops_engine_tools/engine_utilities/trivy_utils/infrastructure/driven_adapters/trivy_deserialize_output.py,sha256=Y2X4B9qgNRn1GdRfDHv-rb-v7dNP2Aifmqzq7R3BZFA,5512
376
399
  devsecops_engine_tools/engine_utilities/trivy_utils/infrastructure/driven_adapters/trivy_manager_scan_utils.py,sha256=9bUT0V-EFhdik8aNuGTI2i4OnT1YvFT7s7xu5M5sejM,2888
400
+ devsecops_engine_tools/engine_utilities/twistcli_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
401
+ devsecops_engine_tools/engine_utilities/twistcli_utils/twistcli_utils.py,sha256=OzgLbt6HIdx87Lm_4qS6s84mkHc_UcGb9DKRo5C9dr4,1351
377
402
  devsecops_engine_tools/engine_utilities/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
378
403
  devsecops_engine_tools/engine_utilities/utils/api_error.py,sha256=yRbad5gNUHh5nALBKkRDi-d98JPmqAhw-QJEGW4psrw,528
379
404
  devsecops_engine_tools/engine_utilities/utils/dataclass_classmethod.py,sha256=S-w6pybVKlyVBhV3HE3IGDvO4ByXxiVePP1JaMnISgM,4302
@@ -383,8 +408,8 @@ devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGax
383
408
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=amYAr9YQfYgR6jK9a2l26z3oovFPQ3FAKmhq6BKhEBA,623
384
409
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=Z0fdhB3r-dxU0nGSD9zW_B4r2Qol1rUnUCkhFR0U-HQ,487
385
410
  devsecops_engine_tools/engine_utilities/utils/utils.py,sha256=HCjS900TBoNcHrC4LaiP-Kf9frVdtagF130qOUgnO2M,6757
386
- devsecops_engine_tools-1.115.2.dist-info/METADATA,sha256=WsgwnYL8DfGejyuZ2zb962MvO_sR9kX0wErPrPAFWFE,3429
387
- devsecops_engine_tools-1.115.2.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
388
- devsecops_engine_tools-1.115.2.dist-info/entry_points.txt,sha256=OWAww5aBsGeMv0kWhSgVNB0ySKKpYuJd4dly0ikFPkc,283
389
- devsecops_engine_tools-1.115.2.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
390
- devsecops_engine_tools-1.115.2.dist-info/RECORD,,
411
+ devsecops_engine_tools-1.116.1.dist-info/METADATA,sha256=82r4HO801zvv99mFWa_nYtQ4DvVe3vnh3cvPc0Nhh6A,3429
412
+ devsecops_engine_tools-1.116.1.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
413
+ devsecops_engine_tools-1.116.1.dist-info/entry_points.txt,sha256=OWAww5aBsGeMv0kWhSgVNB0ySKKpYuJd4dly0ikFPkc,283
414
+ devsecops_engine_tools-1.116.1.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
415
+ devsecops_engine_tools-1.116.1.dist-info/RECORD,,