devsecops-engine-tools 1.32.5__py3-none-any.whl → 1.33.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of devsecops-engine-tools might be problematic. Click here for more details.

Files changed (26) hide show
  1. devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +8 -1
  2. devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py +13 -2
  3. devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +2 -1
  4. devsecops_engine_tools/engine_dast/src/applications/runner_dast_scan.py +100 -0
  5. devsecops_engine_tools/engine_dast/src/domain/model/api_config.py +13 -0
  6. devsecops_engine_tools/engine_dast/src/domain/model/api_operation.py +13 -0
  7. devsecops_engine_tools/engine_dast/src/domain/model/gateways/__init__.py +0 -0
  8. devsecops_engine_tools/engine_dast/src/domain/model/gateways/authentication_gateway.py +7 -0
  9. devsecops_engine_tools/engine_dast/src/domain/model/gateways/tool_gateway.py +9 -0
  10. devsecops_engine_tools/engine_dast/src/domain/model/wa_config.py +10 -0
  11. devsecops_engine_tools/engine_dast/src/domain/usecases/dast_scan.py +128 -0
  12. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/__init__.py +0 -0
  13. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_config.py +69 -0
  14. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_deserealizer.py +39 -0
  15. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_tool.py +145 -0
  16. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/__init__.py +0 -0
  17. devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/generic_oauth.py +70 -0
  18. devsecops_engine_tools/engine_dast/src/infrastructure/entry_points/entry_point_dast.py +15 -0
  19. devsecops_engine_tools/engine_dast/src/infrastructure/helpers/file_generator_tool.py +61 -0
  20. devsecops_engine_tools/engine_dast/src/infrastructure/helpers/json_handler.py +13 -0
  21. devsecops_engine_tools/version.py +1 -1
  22. {devsecops_engine_tools-1.32.5.dist-info → devsecops_engine_tools-1.33.0.dist-info}/METADATA +8 -2
  23. {devsecops_engine_tools-1.32.5.dist-info → devsecops_engine_tools-1.33.0.dist-info}/RECORD +26 -9
  24. {devsecops_engine_tools-1.32.5.dist-info → devsecops_engine_tools-1.33.0.dist-info}/WHEEL +0 -0
  25. {devsecops_engine_tools-1.32.5.dist-info → devsecops_engine_tools-1.33.0.dist-info}/entry_points.txt +0 -0
  26. {devsecops_engine_tools-1.32.5.dist-info → devsecops_engine_tools-1.33.0.dist-info}/top_level.txt +0 -0
@@ -170,6 +170,12 @@ def get_inputs_from_cli(args):
170
170
  required=False,
171
171
  help="Name of image to scan for engine_container",
172
172
  )
173
+ parser.add_argument(
174
+ "--dast_file_path",
175
+ required=False,
176
+ help="File path containing the configuration, structured according to the documentation, \
177
+ for the API or web application to be scanned by the DAST tool."
178
+ )
173
179
  args = parser.parse_args()
174
180
  return {
175
181
  "platform_devops": args.platform_devops,
@@ -187,7 +193,8 @@ def get_inputs_from_cli(args):
187
193
  "token_engine_dependencies": args.token_engine_dependencies,
188
194
  "token_external_checks": args.token_external_checks,
189
195
  "xray_mode": args.xray_mode,
190
- "image_to_scan": args.image_to_scan
196
+ "image_to_scan": args.image_to_scan,
197
+ "dast_file_path": args.dast_file_path
191
198
  }
192
199
 
193
200
 
@@ -36,10 +36,12 @@ 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_dast.src.applications.runner_dast_scan import (
40
+ runner_engine_dast
41
+ )
39
42
  from devsecops_engine_tools.engine_core.src.infrastructure.helpers.util import (
40
43
  define_env,
41
44
  )
42
-
43
45
  from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
44
46
  from devsecops_engine_tools.engine_utilities import settings
45
47
 
@@ -98,7 +100,16 @@ class HandleScan:
98
100
  )
99
101
  return findings_list, input_core
100
102
  elif "engine_dast" in dict_args["tool"]:
101
- print(MESSAGE_ENABLED)
103
+ findings_list, input_core = runner_engine_dast(
104
+ dict_args,
105
+ config_tool["ENGINE_DAST"],
106
+ secret_tool,
107
+ self.devops_platform_gateway
108
+ )
109
+ self._use_vulnerability_management(
110
+ config_tool, input_core, dict_args, secret_tool, env
111
+ )
112
+ return findings_list, input_core
102
113
  elif "engine_code" in dict_args["tool"]:
103
114
  findings_list, input_core = runner_engine_code(
104
115
  dict_args,
@@ -82,7 +82,8 @@ class DefectDojoPlatform(VulnerabilityManagementGateway):
82
82
  "BEARER": "Bearer CLI",
83
83
  "DEPENDENCY_CHECK": "Dependency Check Scan",
84
84
  "SONARQUBE": "SonarQube API Import",
85
- "GITLEAKS": "Gitleaks Scan"
85
+ "GITLEAKS": "Gitleaks Scan",
86
+ "NUCLEI": "Nuclei Scan"
86
87
  }
87
88
 
88
89
  if any(
@@ -0,0 +1,100 @@
1
+ from typing import List
2
+ from devsecops_engine_tools.engine_dast.src.infrastructure.entry_points.entry_point_dast import (
3
+ init_engine_dast,
4
+ )
5
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.nuclei.nuclei_tool import (
6
+ NucleiTool,
7
+ )
8
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.jwt.jwt_object import (
9
+ JwtObject,
10
+ )
11
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.jwt.jwt_tool import (
12
+ JwtTool,
13
+ )
14
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.oauth.generic_oauth import (
15
+ GenericOauth,
16
+ )
17
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.http.client.auth_client import (
18
+ AuthClientCredential,
19
+ )
20
+ from devsecops_engine_tools.engine_dast.src.domain.model.api_config import (
21
+ ApiConfig
22
+ )
23
+ from devsecops_engine_tools.engine_dast.src.domain.model.api_operation import (
24
+ ApiOperation
25
+ )
26
+ from devsecops_engine_tools.engine_dast.src.domain.model.wa_config import (
27
+ WaConfig
28
+ )
29
+ from devsecops_engine_tools.engine_dast.src.infrastructure.helpers.json_handler import (
30
+ load_json_file
31
+ )
32
+
33
+ def runner_engine_dast(dict_args, config_tool, secret_tool, devops_platform_gateway):
34
+ if config_tool["TOOL"].lower() == "nuclei": # tool_gateway is the main Tool
35
+ tool_run = NucleiTool()
36
+ extra_tools = []
37
+ target_config = None
38
+
39
+ # Filling operations list with adapters
40
+ data = load_json_file(dict_args["dast_file_path"])
41
+
42
+ try:
43
+ if "operations" in data: # Api
44
+ operations: List = []
45
+ for elem in data["operations"]:
46
+ security_type = elem["operation"]["security_auth"]["type"].lower()
47
+ if security_type == "jwt":
48
+ operations.append(
49
+ ApiOperation(
50
+ elem,
51
+ JwtObject(
52
+ elem["operation"]["security_auth"]
53
+ )
54
+ )
55
+ )
56
+ elif security_type == "oauth":
57
+ operations.append(
58
+ ApiOperation(
59
+ elem,
60
+ GenericOauth(
61
+ elem["operation"]["security_auth"],
62
+ data["endpoint"]
63
+ )
64
+ )
65
+ )
66
+ else:
67
+ operations.append(
68
+ ApiOperation(
69
+ elem,
70
+ AuthClientCredential(
71
+ elem["operation"]["security_auth"]
72
+ )
73
+ )
74
+ )
75
+ data["operations"] = operations
76
+ target_config = ApiConfig(data)
77
+ elif "WA" in data: # Web Application
78
+ if data["data"].get["security_auth"] == "oauth":
79
+ authentication_gateway = GenericOauth(
80
+ data["data"]["security_auth"]
81
+ )
82
+ target_config = WaConfig(data, authentication_gateway)
83
+ else:
84
+ raise ValueError("Can't match if the target type is an api or a web application")
85
+
86
+ if any((k.lower() == "jwt") for k in config_tool["EXTRA_TOOLS"]) and any(isinstance(operation.authentication_gateway, JwtObject) for operation in data["operations"] ):
87
+ extra_tools.append(JwtTool(target_config))
88
+
89
+ return init_engine_dast(
90
+ devops_platform_gateway=devops_platform_gateway,
91
+ tool_gateway=tool_run,
92
+ dict_args=dict_args,
93
+ secret_tool=secret_tool,
94
+ config_tool=config_tool,
95
+ extra_tools=extra_tools,
96
+ target_data=target_config
97
+ )
98
+ except Exception as e:
99
+ raise Exception(f"Error engine_dast: {e}")
100
+
@@ -0,0 +1,13 @@
1
+ from typing import List
2
+ from devsecops_engine_tools.engine_dast.src.domain.model.api_operation import ApiOperation
3
+
4
+
5
+ class ApiConfig():
6
+ def __init__(self, api_data: dict):
7
+ try:
8
+ self.target_type: str = "API"
9
+ self.endpoint: str = api_data["endpoint"]
10
+ self.rate_limit: str = api_data.get("rate_limit")
11
+ self.operations: "List[ApiOperation]" = api_data["operations"]
12
+ except KeyError:
13
+ raise KeyError("Missing configuration, validate the endpoint and every single operation")
@@ -0,0 +1,13 @@
1
+ from devsecops_engine_tools.engine_dast.src.domain.model.gateways.authentication_gateway import (
2
+ AuthenticationGateway
3
+ )
4
+ class ApiOperation():
5
+ def __init__(self, operation, authentication_gateway):
6
+ self.authentication_gateway: AuthenticationGateway = authentication_gateway
7
+ self.data: dict = operation
8
+ self.credentials = ("auth_header", "token")
9
+
10
+ def authenticate(self):
11
+ self.credentials = self.authentication_gateway.get_credentials()
12
+ if self.credentials is not None:
13
+ self.data["operation"]["headers"][f'{self.credentials[0]}'] = f'{self.credentials[1]}'
@@ -0,0 +1,7 @@
1
+ from abc import ABCMeta, abstractmethod
2
+
3
+
4
+ class AuthenticationGateway(metaclass=ABCMeta):
5
+ @abstractmethod
6
+ def get_credentials(self) -> dict:
7
+ "get_credentials"
@@ -0,0 +1,9 @@
1
+ from abc import ABCMeta, abstractmethod
2
+
3
+
4
+ class ToolGateway(metaclass=ABCMeta):
5
+ @abstractmethod
6
+ def run_tool(
7
+ self, target_data, config_tool, secret_tool, secret_external_checks, agent_work_folder
8
+ ) -> str:
9
+ "run_tool"
@@ -0,0 +1,10 @@
1
+ class WaConfig:
2
+ def __init__(self, data: dict, authentication_gateway):
3
+ self.target_type: str = "WA"
4
+ self.url: str = data["endpoint"]
5
+ self.data: dict = data.wa_data
6
+
7
+ def authenticate(self):
8
+ self.credentials = self.authentication_gateway.get_credentials()
9
+ if self.credentials is not None:
10
+ self.data["headers"][self.credentials[0]] = self.credentials[1]
@@ -0,0 +1,128 @@
1
+ from typing import (
2
+ List, Tuple, Any
3
+ )
4
+ from devsecops_engine_tools.engine_dast.src.domain.model.gateways.tool_gateway import (
5
+ ToolGateway,
6
+ )
7
+ from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import (
8
+ DevopsPlatformGateway,
9
+ )
10
+ from devsecops_engine_tools.engine_core.src.domain.model.input_core import (
11
+ InputCore,
12
+ )
13
+ from devsecops_engine_tools.engine_core.src.domain.model.exclusions import (
14
+ Exclusions,
15
+ )
16
+ from devsecops_engine_tools.engine_core.src.domain.model.threshold import Threshold
17
+
18
+ class DastScan:
19
+ def __init__(
20
+ self,
21
+ tool_gateway: ToolGateway,
22
+ devops_platform_gateway: DevopsPlatformGateway,
23
+ data_target,
24
+ aditional_tools: "List[ToolGateway]"
25
+ ):
26
+ self.tool_gateway = tool_gateway
27
+ self.devops_platform_gateway = devops_platform_gateway
28
+ self.data_target = data_target
29
+ self.other_tools = aditional_tools
30
+
31
+ def complete_config_tool(
32
+ self, data_file_tool, exclusions, tool
33
+ ) -> "Tuple[Any, Any]":
34
+
35
+ config_tool = data_file_tool
36
+
37
+ config_tool["SCOPE_PIPELINE"] = self.devops_platform_gateway.get_variable(
38
+ "pipeline_name"
39
+ )
40
+
41
+ config_tool["EXCLUSIONS"] = exclusions
42
+
43
+ config_exclusions = config_tool["EXCLUSIONS"]
44
+
45
+ if config_exclusions.get("All") is not None:
46
+ config_tool["EXCLUSIONS_ALL"] = config_exclusions.get("All").get(tool)
47
+ if config_exclusions.get(config_tool["SCOPE_PIPELINE"]) is not None:
48
+ config_tool["EXCLUSIONS_SCOPE"] = config_exclusions.get(
49
+ config_tool["SCOPE_PIPELINE"]
50
+ ).get(tool)
51
+
52
+ data_target_config = self.data_target
53
+ return config_tool, data_target_config
54
+
55
+ def process(
56
+ self, dict_args, secret_tool, config_tool
57
+ ) -> "Tuple[List, InputCore]":
58
+ init_config_tool = self.devops_platform_gateway.get_remote_config(
59
+ dict_args["remote_config_repo"], "engine_dast/ConfigTool.json"
60
+ )
61
+
62
+ exclusions = self.devops_platform_gateway.get_remote_config(
63
+ dict_args["remote_config_repo"],
64
+ "engine_dast/Exclusions.json"
65
+ )
66
+
67
+ agent_work_folder = self.devops_platform_gateway.get_variable("path_directory")
68
+
69
+ config_tool, data_target = self.complete_config_tool(
70
+ data_file_tool=init_config_tool,
71
+ exclusions=exclusions,
72
+ tool=config_tool["TOOL"],
73
+ )
74
+
75
+ finding_list, path_file_results = self.tool_gateway.run_tool(
76
+ target_data=data_target,
77
+ config_tool=config_tool,
78
+ secret_tool=secret_tool,
79
+ secret_external_checks=dict_args["token_external_checks"],
80
+ agent_work_folder=agent_work_folder
81
+ )
82
+
83
+ #Here execute other tools and append to finding list
84
+ if len(self.other_tools) > 0:
85
+ for i in range(len(self.other_tools)):
86
+ extra_config_tool, data_target = self.complete_config_tool(
87
+ data_file_tool=init_config_tool,
88
+ exclusions=exclusions,
89
+ tool=self.other_tools[i].TOOL
90
+ )
91
+ extra_finding_list = self.other_tools[i].run_tool(
92
+ target_data=data_target,
93
+ config_tool=extra_config_tool
94
+ )
95
+ if len(extra_finding_list) > 0:
96
+ finding_list.extend(extra_finding_list)
97
+
98
+ totalized_exclusions = []
99
+ (
100
+ totalized_exclusions.extend(
101
+ map(
102
+ lambda elem: Exclusions(**elem), config_tool.get("EXCLUSIONS_ALL")
103
+ )
104
+ )
105
+ if config_tool.get("EXCLUSIONS_ALL") is not None
106
+ else None
107
+ )
108
+ (
109
+ totalized_exclusions.extend(
110
+ map(
111
+ lambda elem: Exclusions(**elem),
112
+ config_tool.get("EXCLUSIONS_SCOPE"),
113
+ )
114
+ )
115
+ if config_tool.get("EXCLUSIONS_SCOPE") is not None
116
+ else None
117
+ )
118
+
119
+ input_core = InputCore(
120
+ totalized_exclusions=totalized_exclusions,
121
+ threshold_defined=Threshold(config_tool.get("THRESHOLD")),
122
+ path_file_results=path_file_results,
123
+ custom_message_break_build=config_tool.get("MESSAGE_INFO_DAST"),
124
+ scope_pipeline=config_tool.get("SCOPE_PIPELINE"),
125
+ stage_pipeline=self.devops_platform_gateway.get_variable("stage"),
126
+ )
127
+
128
+ return finding_list, input_core
@@ -0,0 +1,69 @@
1
+ from typing import List
2
+ import os
3
+ from ruamel.yaml import YAML
4
+ from json import dumps as json_dumps
5
+
6
+ class NucleiConfig:
7
+ def __init__(self, target_config):
8
+ self.url: str = target_config.endpoint
9
+ self.target_type: str = target_config.target_type.lower()
10
+ self.custom_templates_dir: str = ""
11
+ self.output_file: str = "result_dast_scan.json"
12
+ self.yaml = YAML()
13
+ if self.target_type == "api":
14
+ self.data: List = target_config.operations
15
+ elif self.target_type == "wa":
16
+ self.data: dict = target_config.data
17
+ else:
18
+ raise ValueError("ERROR: The objective is not an api or web application type")
19
+
20
+ def process_template_file(
21
+ self,
22
+ dest_folder: str,
23
+ template_name: str,
24
+ new_template_data: dict,
25
+ template_counter: int,
26
+ ) -> None:
27
+ new_template_name: str = "nuclei_template_" + str(template_counter) + ".yaml"
28
+ with open(template_name, "r") as template_file: # abrir archivo
29
+ template_data = self.yaml.load(template_file)
30
+ if "http" in template_data:
31
+ template_data["http"][0]["method"] = new_template_data["operation"]["method"]
32
+ template_data["http"][0]["path"] = [
33
+ "{{BaseURL}}" + new_template_data["operation"]["path"]
34
+ ]
35
+ if "headers" in template_data.get("http", [{}])[0]:
36
+ template_data["http"][0]["headers"] = new_template_data["operation"]["headers"]
37
+ if "payload" in new_template_data["operation"]:
38
+ body = json_dumps(new_template_data["operation"]["payload"])
39
+ template_data["http"][0]["body"] = body
40
+
41
+ new_template_path = os.path.join(dest_folder, new_template_name)
42
+
43
+ with open(new_template_path, "w") as nf:
44
+ self.yaml.dump(template_data, nf)
45
+
46
+ def process_templates_folder(self, base_folder: str) -> None:
47
+ if not os.path.exists(self.custom_templates_dir):
48
+ os.makedirs(self.custom_templates_dir)
49
+
50
+ t_counter = 0
51
+ for operation in self.data:
52
+ operation.authenticate() #Api Authentication
53
+ for root, _, files in os.walk(f"{base_folder}{os.sep}rules{os.sep}nuclei"):
54
+ for file in files:
55
+ if file.endswith(".yaml"):
56
+ self.process_template_file(
57
+ dest_folder=self.custom_templates_dir,
58
+ template_name=os.path.join(root, file),
59
+ new_template_data=operation.data,
60
+ template_counter=t_counter,
61
+ )
62
+ t_counter += 1
63
+
64
+ def customize_templates(self, directory: str) -> None:
65
+ if self.target_type == "api":
66
+ self.custom_templates_dir = f"{directory}{os.sep}customized-nuclei-templates"
67
+ self.process_templates_folder(
68
+ base_folder=directory
69
+ )
@@ -0,0 +1,39 @@
1
+ from dataclasses import (
2
+ dataclass,
3
+ )
4
+ from datetime import (
5
+ datetime,
6
+ )
7
+ from devsecops_engine_tools.engine_core.src.domain.model.finding import (
8
+ Category,
9
+ Finding,
10
+ )
11
+
12
+
13
+ @dataclass
14
+ class NucleiDesealizator:
15
+ @classmethod
16
+ def get_list_finding(
17
+ cls,
18
+ results_scan_list: "list[dict]",
19
+ ) -> "list[Finding]":
20
+ list_open_findings = []
21
+ if len(results_scan_list) > 0:
22
+ for scan in results_scan_list:
23
+ finding_open = Finding(
24
+ id=scan.get("template-id"),
25
+ cvss=scan["info"].get("classification", {}).get("cvss-score", ""),
26
+ where=scan.get("matched-at"),
27
+ description=scan["info"].get("description"),
28
+ severity=scan["info"].get("severity").lower() if scan["info"].get("severity").lower() != "info" else "low",
29
+ identification_date=datetime.now().strftime("%d%m%Y"),
30
+ module="engine_dast",
31
+ category=Category("vulnerability"),
32
+ requirements=scan["info"].get("remediation"),
33
+ tool="Nuclei",
34
+ published_date_cve=None
35
+ )
36
+ list_open_findings.append(finding_open)
37
+
38
+ return list_open_findings
39
+
@@ -0,0 +1,145 @@
1
+ import os
2
+ import subprocess
3
+ import json
4
+ import platform
5
+ import requests
6
+ import shutil
7
+ from devsecops_engine_tools.engine_dast.src.domain.model.gateways.tool_gateway import (
8
+ ToolGateway,
9
+ )
10
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.nuclei.nuclei_config import (
11
+ NucleiConfig,
12
+ )
13
+ from devsecops_engine_tools.engine_dast.src.infrastructure.driven_adapters.nuclei.nuclei_deserealizer import (
14
+ NucleiDesealizator,
15
+ )
16
+ from devsecops_engine_tools.engine_utilities.utils.utils import Utils
17
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
18
+ from devsecops_engine_tools.engine_utilities import settings
19
+ from devsecops_engine_tools.engine_utilities.utils.utils import Utils
20
+
21
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
22
+
23
+
24
+ class NucleiTool(ToolGateway):
25
+
26
+ """A class that wraps the nuclei scanner functionality"""
27
+
28
+ def __init__(self, target_config=None, data_config_cli=None):
29
+ """Initialize the class with the data from the config file and the cli"""
30
+ self.target_config = target_config
31
+ self.data_config_cli = data_config_cli
32
+ self.TOOL: str = "NUCLEI"
33
+
34
+ def download_tool(self, version):
35
+ try:
36
+ base_url = f"https://github.com/projectdiscovery/nuclei/releases/download/v{version}/"
37
+ os_type = platform.system().lower()
38
+
39
+ os_types = {"darwin": "macOS", "linux": "linux", "windows": "windows"}
40
+ if os_type in os_types:
41
+ curr_os = os_types[os_type]
42
+ else:
43
+ raise Exception(f"Error [101]: {os_type} is an unsupported OS type!")
44
+
45
+ file_name = f"nuclei_{version}_{curr_os}_amd64.zip"
46
+ url = f"{base_url}{file_name}"
47
+
48
+ response = requests.get(url, allow_redirects=True)
49
+ if response.status_code != 200:
50
+ raise Exception(f"Error [102]: Failed to download Nuclei version {version}. HTTP status code: {response.status_code}")
51
+
52
+ home_directory = os.path.expanduser("~")
53
+ zip_name = os.path.join(home_directory, file_name)
54
+ with open(zip_name, "wb") as f:
55
+ f.write(response.content)
56
+
57
+ Utils().unzip_file(zip_name, home_directory)
58
+ return 0
59
+ except Exception as e:
60
+ logger.error(f"Error [103]: An exception occurred during download: {e}")
61
+ return e
62
+
63
+ def install_tool(self, version):
64
+ try:
65
+ nuclei_path = shutil.which("nuclei")
66
+
67
+ if not nuclei_path:
68
+ download_result = self.download_tool(version)
69
+ if download_result != 0:
70
+ raise Exception(f"Error [104]: Download failed with error: {download_result}")
71
+
72
+ os_type = platform.system().lower()
73
+ home_directory = os.path.expanduser("~")
74
+
75
+ if nuclei_path:
76
+ executable_path = nuclei_path
77
+ elif os_type == "windows":
78
+ executable_path = os.path.join(home_directory, "nuclei.exe")
79
+ else:
80
+ executable_path = os.path.join(home_directory, "nuclei")
81
+
82
+ if os_type == "darwin" or os_type == "linux":
83
+ subprocess.run(["chmod", "+x", executable_path], check=True)
84
+ return {"status": 201, "path": executable_path} # Installation successful
85
+ elif os_type == "windows":
86
+ return {"status": 202, "path":executable_path}
87
+ else:
88
+ raise Exception(f"Error [105]: {os_type} is an unsupported OS type!")
89
+
90
+ except subprocess.CalledProcessError as e:
91
+ logger.error(f"Error [106]: Command execution failed: {e}")
92
+ return {"status": 106}
93
+ except Exception as e:
94
+ logger.error(f"Error [107]: An exception occurred during installation: {e}")
95
+ return {"status": 107}
96
+
97
+ def execute(self, command_prefix: str, target_config: NucleiConfig) -> dict:
98
+ """Interact with nuclei's core application"""
99
+
100
+ command = (
101
+ command_prefix
102
+ + " -u " # target URLs/hosts to scan
103
+ + target_config.url
104
+ + (f" -ud {target_config.custom_templates_dir}" if target_config.custom_templates_dir else "")
105
+ + " -ni " # disable interactsh server
106
+ + "-dc " # disable clustering of requests
107
+ + "-tags " # Excute only templates with the especified tag
108
+ + target_config.target_type
109
+ + " -je " # file to export results in JSON format
110
+ + str(target_config.output_file)
111
+ + " -sr"
112
+ )
113
+
114
+ if command is not None:
115
+ result = subprocess.run(
116
+ command,
117
+ shell=True,
118
+ capture_output=True,
119
+ )
120
+ error = result.stderr.decode().strip() if result.stderr else ""
121
+ if result.returncode != 0:
122
+ raise Exception(f"Error executing nuclei: {error}")
123
+ with open(target_config.output_file, "r") as f:
124
+ json_response = json.load(f)
125
+ return json_response
126
+
127
+ def run_tool(self,
128
+ target_data,
129
+ config_tool,
130
+ secret_tool,
131
+ secret_external_checks,
132
+ agent_work_folder
133
+ ):
134
+ result_install = self.install_tool(config_tool[self.TOOL]["VERSION"])
135
+ if result_install["status"] < 200:
136
+ return [], None
137
+
138
+ nuclei_config = NucleiConfig(target_data)
139
+ if config_tool[self.TOOL]["ENABLE_CUSTOM_RULES"]:
140
+ Utils().configurate_external_checks(self.TOOL, config_tool, secret_tool, secret_external_checks, agent_work_folder)
141
+ nuclei_config.customize_templates(agent_work_folder)
142
+
143
+ result_scans = self.execute(result_install["path"], nuclei_config)
144
+ findings_list = NucleiDesealizator().get_list_finding(result_scans)
145
+ return findings_list, nuclei_config.output_file
@@ -0,0 +1,70 @@
1
+ import requests
2
+ from devsecops_engine_tools.engine_dast.src.domain.model.gateways.authentication_gateway import (
3
+ AuthenticationGateway
4
+ )
5
+ from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger
6
+ from devsecops_engine_tools.engine_utilities import settings
7
+
8
+ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger()
9
+
10
+
11
+ class GenericOauth(AuthenticationGateway):
12
+ def __init__(self, data, endpoint):
13
+ self.data: dict = data
14
+ self.endpoint = endpoint
15
+ self.config = {}
16
+
17
+ def process_data(self):
18
+
19
+ self.config = {
20
+ "method": self.data.get("method", "POST"),
21
+ "path": self.data.get("path", ""),
22
+ "grant_type": self.data.get("grant_type",""),
23
+ "scope": self.data.get("scope", None),
24
+ "headers": self.data.get("headers", {}),
25
+ "client_secret": self.data.get("client_secret", ""),
26
+ "client_id": self.data.get("client_id", "")
27
+ }
28
+ return self.config
29
+
30
+ def get_access_token(self):
31
+ auth_config = self.process_data()
32
+
33
+ if auth_config["grant_type"].lower() == "client_credentials":
34
+ return self.get_access_token_client_credentials()
35
+ else:
36
+ raise ValueError("OAuth: Grant type is not supported yet")
37
+
38
+ def get_credentials(self):
39
+ return self.get_access_token()
40
+
41
+ def get_access_token_client_credentials(self):
42
+ """Obtain access token using client credentials flow."""
43
+ try:
44
+ required_keys = ["client_id", "client_secret"]
45
+ if not all(key in self.config for key in required_keys):
46
+ raise ValueError("One or more keys is missing in OAuth config")
47
+
48
+ data = {
49
+ "client_id": self.config["client_id"],
50
+ "client_secret": self.config["client_secret"],
51
+ "grant_type": "client_credentials",
52
+ "scope": self.config["scope"]
53
+ }
54
+
55
+ url = self.endpoint + self.config["path"]
56
+ headers = self.config["headers"]
57
+ response = requests.request(
58
+ self.config["method"], url, headers=headers, data=data, timeout=5
59
+ )
60
+ if 200 <= response.status_code < 300:
61
+ result = response.json()["access_token"]
62
+ return ("Authorization",f"Bearer {result}")
63
+ else:
64
+ print(
65
+ "OAuth: Can't obtain access token"
66
+ "token Unknown status "
67
+ "code {0}: -> {1}".format(response.status_code, response.text)
68
+ )
69
+ except (ConnectionError, ValueError, KeyError) as e:
70
+ logger.warning("OAuth: Can't obtain access token: {0}".format(e))
@@ -0,0 +1,15 @@
1
+ from devsecops_engine_tools.engine_dast.src.domain.usecases.dast_scan import (
2
+ DastScan,
3
+ )
4
+
5
+ def init_engine_dast(
6
+ devops_platform_gateway,
7
+ tool_gateway,
8
+ dict_args,
9
+ secret_tool,
10
+ config_tool,
11
+ extra_tools,
12
+ target_data
13
+ ):
14
+ dast_scan = DastScan(tool_gateway, devops_platform_gateway, target_data, extra_tools)
15
+ return dast_scan.process(dict_args, secret_tool, config_tool)
@@ -0,0 +1,61 @@
1
+ import json
2
+ import json
3
+ from datetime import datetime
4
+
5
+ def generate_file_from_tool(tool_name, result_scans, config_tool):
6
+ if tool_name == "JWT":
7
+ sarif_report = {
8
+ "version": "2.1.0",
9
+ "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
10
+ "runs": [
11
+ {
12
+ "tool": {
13
+ "driver": {
14
+ "name": tool_name,
15
+ "version": "1.0.0",
16
+ "rules": [
17
+ {
18
+ "id": rule_id,
19
+ "shortDescription": {"text": rule["description"]},
20
+ "helpUri": rule.get("helpUri", ""),
21
+ "properties": {
22
+ "severity": rule.get("severity", "medium"),
23
+ "cvss": rule.get("cvss", 0)
24
+ }
25
+ }
26
+ for rule_id, rule in config_tool.get("RULES", {}).items()
27
+ ]
28
+ }
29
+ },
30
+ "results": [
31
+ {
32
+ "ruleId": result["check_id"],
33
+ "message": {"text": result["description"]},
34
+ "locations": [
35
+ {
36
+ "physicalLocation": {
37
+ "artifactLocation": {
38
+ "uri": result["matched-at"]
39
+ }
40
+ }
41
+ }
42
+ ],
43
+ "properties": {
44
+ "severity": result["severity"],
45
+ "cvss": result["cvss"],
46
+ "remediation": result.get("remediation", "No remediation provided")
47
+ }
48
+ }
49
+ for result in result_scans
50
+ ]
51
+ }
52
+ ]
53
+ }
54
+
55
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
56
+ sarif_file_path = f"{tool_name}_report_{timestamp}.sarif"
57
+
58
+ with open(sarif_file_path, "w", encoding="utf-8") as sarif_file:
59
+ json.dump(sarif_report, sarif_file, indent=4)
60
+
61
+ return sarif_file_path
@@ -0,0 +1,13 @@
1
+ import json
2
+
3
+
4
+ def load_json_file(file_path: str):
5
+ try:
6
+ with open(file_path, 'r') as file:
7
+ return json.load(file)
8
+ except FileNotFoundError:
9
+ raise FileNotFoundError(f"Error: The file '{file_path}' was not found.")
10
+ except json.JSONDecodeError:
11
+ raise json.JSONDecodeError(f"Error: The file '{file_path}' does not contain valid JSON.")
12
+ except IOError as e:
13
+ raise IOError(f"I/O Error: {e}")
@@ -1 +1 @@
1
- version = '1.32.5'
1
+ version = '1.33.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: devsecops-engine-tools
3
- Version: 1.32.5
3
+ Version: 1.33.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
@@ -28,6 +28,9 @@ Requires-Dist: setuptools==72.1.0
28
28
  Requires-Dist: rich==13.9.4
29
29
  Requires-Dist: cpe==1.3.1
30
30
  Requires-Dist: packageurl-python==0.15.6
31
+ Requires-Dist: ruamel.yaml==0.18.6
32
+ Requires-Dist: Authlib==1.3.2
33
+ Requires-Dist: PyJWT==2.9.0
31
34
 
32
35
  # DevSecOps Engine Tools
33
36
 
@@ -71,7 +74,7 @@ pip3 install devsecops-engine-tools
71
74
  ### Scan running - flags (CLI)
72
75
 
73
76
  ```bash
74
- devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_config_repo ["remote_config_repo"] --remote_config_branch ["remote_config_branch"] --tool ["engine_iac", "engine_dast", "engine_secret", "engine_dependencies", "engine_container", "engine_risk", "engine_code"] --folder_path ["Folder path scan engine_iac, engine_code, engine_dependencies and engine_secret"] --platform ["k8s","cloudformation","docker", "openapi", "terraform"] --use_secrets_manager ["false", "true"] --use_vulnerability_management ["false", "true"] --send_metrics ["false", "true"] --token_cmdb ["token_cmdb"] --token_vulnerability_management ["token_vulnerability_management"] --token_engine_container ["token_engine_container"] --token_engine_dependencies ["token_engine_dependencies"] --token_external_checks ["token_external_checks"] --xray_mode ["scan", "audit"] --image_to_scan ["image_to_scan"]
77
+ devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_config_repo ["remote_config_repo"] --remote_config_branch ["remote_config_branch"] --tool ["engine_iac", "engine_dast", "engine_secret", "engine_dependencies", "engine_container", "engine_risk", "engine_code"] --folder_path ["Folder path scan engine_iac, engine_code, engine_dependencies and engine_secret"] --platform ["k8s","cloudformation","docker", "openapi", "terraform"] --use_secrets_manager ["false", "true"] --use_vulnerability_management ["false", "true"] --send_metrics ["false", "true"] --token_cmdb ["token_cmdb"] --token_vulnerability_management ["token_vulnerability_management"] --token_engine_container ["token_engine_container"] --token_engine_dependencies ["token_engine_dependencies"] --token_external_checks ["token_external_checks"] --xray_mode ["scan", "audit"] --image_to_scan ["image_to_scan"] --dast_file_path ["dast_file_path"]
75
78
  ```
76
79
 
77
80
  ### Structure Remote Config
@@ -83,6 +86,9 @@ devsecops-engine-tools --platform_devops ["local","azure","github"] --remote_con
83
86
  ┣ 📂engine_risk
84
87
  ┃ ┗ 📜ConfigTool.json
85
88
  ┃ ┗ 📜Exclusions.json
89
+ ┣ 📂engine_dast
90
+ ┃ ┗ 📜ConfigTool.json
91
+ ┃ ┗ 📜Exclusions.json
86
92
  ┣ 📂engine_sast
87
93
  ┃ ┗ 📂engine_iac
88
94
  ┃ ┗ 📜ConfigTool.json
@@ -1,9 +1,9 @@
1
1
  devsecops_engine_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- devsecops_engine_tools/version.py,sha256=RANDpLFXBeOMxUGB5T0M5F0OW8X34R26gytSNFGlps8,19
2
+ devsecops_engine_tools/version.py,sha256=slrJ8PjsmWhzds_t0aw7z9hMpKCAEOkgVl8LCAlXhwA,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
6
- devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py,sha256=poPtyIEmOWjkE2L0l8l01O50dRG84xkp3V33zXDxU6g,7779
6
+ devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py,sha256=PcYxH6NQIPkFPMkeOEUs5iw2k-gL0HKuOek2uhR4gIQ,8080
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=0JK4U5LGxzrLVZOw68j1PMxmLTDPru7Kts_-RtAG0jA,15965
30
30
  devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py,sha256=RirHqsW5AhGjV7ITa13bW_BfM6VE99DffrPASoB9SN0,9403
31
- devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py,sha256=q1RGSDT7LSpPn7NyA9Pl4QGeQLQ3kvawzqmXrVQIKTs,9694
31
+ devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py,sha256=XHLeVIVLrXv4oZF8GY6InEqWg0dszMb-0XBJFX7RZjY,10161
32
32
  devsecops_engine_tools/engine_core/src/domain/usecases/metrics_manager.py,sha256=Xi0iNnPrFgqd2cBdAA5E_tgouhxs-BTo016aolnGgv8,2413
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
@@ -38,7 +38,7 @@ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/aws/secret
38
38
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py,sha256=buCBJ6kAg-5b_7P-gWzem6NEMbk5lK9Hx0Zuf-BQfXQ,5090
40
40
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=zBfd4zI_5fAHsIX3ZKt-WJmESkHkfUeIzAZO3O6adHo,27789
41
+ devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py,sha256=QnAy_7jnjd7BGzmkSnfsbsajkJ4Ap2pEguRChASNvdk,27830
42
42
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py,sha256=KCg6tTDncasrRZbB20QiLZNE6TKYkfgQ9zP0wPd3xe0,3925
44
44
  devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/printer_pretty_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -57,15 +57,32 @@ devsecops_engine_tools/engine_core/src/infrastructure/helpers/util.py,sha256=lDt
57
57
  devsecops_engine_tools/engine_dast/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  devsecops_engine_tools/engine_dast/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  devsecops_engine_tools/engine_dast/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ devsecops_engine_tools/engine_dast/src/applications/runner_dast_scan.py,sha256=4RWkHfDm9WSzeLVE43XmQDC3osUoS4zwqhVo14piHxo,4004
60
61
  devsecops_engine_tools/engine_dast/src/deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
62
  devsecops_engine_tools/engine_dast/src/deployment/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
63
  devsecops_engine_tools/engine_dast/src/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
64
  devsecops_engine_tools/engine_dast/src/domain/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ devsecops_engine_tools/engine_dast/src/domain/model/api_config.py,sha256=9B-pSTT58Bb1ysK6MIOpAxsGrn_AdrevOnQYmsLyNvU,548
66
+ devsecops_engine_tools/engine_dast/src/domain/model/api_operation.py,sha256=mQbmTlB0UxCJGEmw21Z0c9ObQF72Gl8N1qK21H5H81o,621
67
+ devsecops_engine_tools/engine_dast/src/domain/model/wa_config.py,sha256=DovmiRO9l50P25N91lG3BpSwc6R9OVQIw89Nv1RpXcc,411
68
+ devsecops_engine_tools/engine_dast/src/domain/model/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
+ devsecops_engine_tools/engine_dast/src/domain/model/gateways/authentication_gateway.py,sha256=JSi2LAK8kPctqPmh3KfxIkXeDY5sSRsXoPWqudlmyYQ,175
70
+ devsecops_engine_tools/engine_dast/src/domain/model/gateways/tool_gateway.py,sha256=F9Xusc7bQo25GpRvCMWPPQ_hlILbGF1yZKMAnm15Axs,255
64
71
  devsecops_engine_tools/engine_dast/src/domain/usecases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
+ devsecops_engine_tools/engine_dast/src/domain/usecases/dast_scan.py,sha256=9zQhA8d9McGWNT2ZdvjmjWCIPN3UpST7RWve2QvyHu4,4693
65
73
  devsecops_engine_tools/engine_dast/src/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
74
  devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_config.py,sha256=TxjdA5_KDmn-RqZQsPkrrqyjd9zPMweKH37pwnxSV8Q,3090
77
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_deserealizer.py,sha256=qqoBMXr350ItzabSU6a_fD2-9kB6pAmtWioFP5AvCIE,1346
78
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_tool.py,sha256=Bk2JTwzTqrU9N84C_GTIf2vF_IpxuvLbvaygVIWOXdI,6066
79
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
+ devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/generic_oauth.py,sha256=Je82JrXrM28lBJ0Z5ShySj8dqS47pmlWQwLmxvk6UsQ,2806
67
81
  devsecops_engine_tools/engine_dast/src/infrastructure/entry_points/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
+ devsecops_engine_tools/engine_dast/src/infrastructure/entry_points/entry_point_dast.py,sha256=Cbl-PH4BL4mT7JMkFRd3G9xKL4VatGDox3uyCGjxsKc,419
68
83
  devsecops_engine_tools/engine_dast/src/infrastructure/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
+ devsecops_engine_tools/engine_dast/src/infrastructure/helpers/file_generator_tool.py,sha256=usSGuFYziitOj3aGa9ifvpfJ-J3qX4c0GXbPm3PmTnQ,2604
85
+ devsecops_engine_tools/engine_dast/src/infrastructure/helpers/json_handler.py,sha256=qQkSO0EXguVGZN6hSb356sB0HS0ZdcjfXsnPelfUnyg,444
69
86
  devsecops_engine_tools/engine_risk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
87
  devsecops_engine_tools/engine_risk/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
88
  devsecops_engine_tools/engine_risk/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -324,8 +341,8 @@ devsecops_engine_tools/engine_utilities/utils/name_conversion.py,sha256=ADJrRGax
324
341
  devsecops_engine_tools/engine_utilities/utils/printers.py,sha256=amYAr9YQfYgR6jK9a2l26z3oovFPQ3FAKmhq6BKhEBA,623
325
342
  devsecops_engine_tools/engine_utilities/utils/session_manager.py,sha256=Z0fdhB3r-dxU0nGSD9zW_B4r2Qol1rUnUCkhFR0U-HQ,487
326
343
  devsecops_engine_tools/engine_utilities/utils/utils.py,sha256=dAklY11OGNDODjZyt9dO68Xiwu9pLJmqLOslqQ7rXa8,6112
327
- devsecops_engine_tools-1.32.5.dist-info/METADATA,sha256=QUwi6wvkbITtiWwVHwlr6wGfPBw8f551jOmifzSvpUs,11378
328
- devsecops_engine_tools-1.32.5.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
329
- devsecops_engine_tools-1.32.5.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
330
- devsecops_engine_tools-1.32.5.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
331
- devsecops_engine_tools-1.32.5.dist-info/RECORD,,
344
+ devsecops_engine_tools-1.33.0.dist-info/METADATA,sha256=JjNGfCUCAgdfAXsGiI-nqwmOehCbPKRKPQVaWhD2cHc,11592
345
+ devsecops_engine_tools-1.33.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
346
+ devsecops_engine_tools-1.33.0.dist-info/entry_points.txt,sha256=MHCTFFs9bdNKo6YcWCcBW2_8X6yTisgLOlmVx-V8Rxc,276
347
+ devsecops_engine_tools-1.33.0.dist-info/top_level.txt,sha256=ge6y0X_xBAU1aG3EMWFtl9djbVyg5BxuSp2r2Lg6EQU,23
348
+ devsecops_engine_tools-1.33.0.dist-info/RECORD,,