devsecops-engine-tools 1.32.4__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.
- devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +8 -1
- devsecops_engine_tools/engine_core/src/domain/usecases/handle_scan.py +13 -2
- devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py +2 -1
- devsecops_engine_tools/engine_dast/src/applications/runner_dast_scan.py +100 -0
- devsecops_engine_tools/engine_dast/src/domain/model/api_config.py +13 -0
- devsecops_engine_tools/engine_dast/src/domain/model/api_operation.py +13 -0
- devsecops_engine_tools/engine_dast/src/domain/model/gateways/__init__.py +0 -0
- devsecops_engine_tools/engine_dast/src/domain/model/gateways/authentication_gateway.py +7 -0
- devsecops_engine_tools/engine_dast/src/domain/model/gateways/tool_gateway.py +9 -0
- devsecops_engine_tools/engine_dast/src/domain/model/wa_config.py +10 -0
- devsecops_engine_tools/engine_dast/src/domain/usecases/dast_scan.py +128 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/__init__.py +0 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_config.py +69 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_deserealizer.py +39 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_tool.py +145 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/__init__.py +0 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/oauth/generic_oauth.py +70 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/entry_points/entry_point_dast.py +15 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/helpers/file_generator_tool.py +61 -0
- devsecops_engine_tools/engine_dast/src/infrastructure/helpers/json_handler.py +13 -0
- devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/import_scan.py +1 -1
- devsecops_engine_tools/version.py +1 -1
- {devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/METADATA +8 -2
- {devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/RECORD +27 -10
- {devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/WHEEL +0 -0
- {devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/entry_points.txt +0 -0
- {devsecops_engine_tools-1.32.4.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
|
-
|
|
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,
|
devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/defect_dojo/defect_dojo.py
CHANGED
|
@@ -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]}'
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|
|
@@ -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
|
+
)
|
devsecops_engine_tools/engine_dast/src/infrastructure/driven_adapters/nuclei/nuclei_deserealizer.py
ADDED
|
@@ -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
|
|
File without changes
|
|
@@ -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}")
|
|
@@ -43,7 +43,7 @@ class ImportScanUserCase:
|
|
|
43
43
|
raise ApiError(log)
|
|
44
44
|
|
|
45
45
|
logger.info(f"Match {request.scan_type}")
|
|
46
|
-
products = self.__rest_product.get_products({"name":request.
|
|
46
|
+
products = self.__rest_product.get_products({"name":request.product_name})
|
|
47
47
|
if len(products.results) > 0:
|
|
48
48
|
product_id = products.results[0].id
|
|
49
49
|
request.product_name = products.results[0].name
|
|
@@ -1 +1 @@
|
|
|
1
|
-
version = '1.
|
|
1
|
+
version = '1.33.0'
|
{devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devsecops-engine-tools
|
|
3
|
-
Version: 1.
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
@@ -263,7 +280,7 @@ devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/component.p
|
|
|
263
280
|
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/engagement.py,sha256=SVX-weFRPT3DK7w6IBrLuWS4L6vboMuZtwXAQmIHfEE,406
|
|
264
281
|
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/finding.py,sha256=TjfpdJtaBwQvT8XNJKBf6tuOASOAw7ZiOxJbqsKadaA,1689
|
|
265
282
|
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/finding_exclusion.py,sha256=VqdwBiQGc9XFpatvbXGL837LtTxkWlfhWH46W1cTbCg,455
|
|
266
|
-
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/import_scan.py,sha256=
|
|
283
|
+
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/import_scan.py,sha256=2Hjhquy_tAwww3YOVY_EuO7S3YSN8DAKH8Q4uEmzDIk,6931
|
|
267
284
|
devsecops_engine_tools/engine_utilities/defect_dojo/domain/user_case/product.py,sha256=6f6eABdC79zOopMe_Rif3XoGG-yFfq9x_EOkevTuGDY,368
|
|
268
285
|
devsecops_engine_tools/engine_utilities/defect_dojo/infraestructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
269
286
|
devsecops_engine_tools/engine_utilities/defect_dojo/infraestructure/driver_adapters/__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.
|
|
328
|
-
devsecops_engine_tools-1.
|
|
329
|
-
devsecops_engine_tools-1.
|
|
330
|
-
devsecops_engine_tools-1.
|
|
331
|
-
devsecops_engine_tools-1.
|
|
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,,
|
|
File without changes
|
{devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{devsecops_engine_tools-1.32.4.dist-info → devsecops_engine_tools-1.33.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|