mantis_api_client 5.3.0__tar.gz → 5.4.0__tar.gz
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.
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/PKG-INFO +1 -1
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/account_parser.py +55 -13
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/attack_parser.py +3 -3
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/bas_parser.py +19 -6
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/basebox_parser.py +3 -3
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/scenario_parser.py +3 -3
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/topology_parser.py +3 -3
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/user_api.py +2 -2
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/pyproject.toml +1 -1
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/AUTHORS +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/LICENSE +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/README.md +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/__init__.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/dataset_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/lab_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/labs_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/log_collector_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/redteam_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/signature_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/user_parser.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/config.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/dataset_api.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/exceptions.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/mantis.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/oidc.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/scenario_api.py +0 -0
- {mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/utils.py +0 -0
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/account_parser.py
RENAMED
|
@@ -32,7 +32,7 @@ from mantis_api_client.utils import colored
|
|
|
32
32
|
class Version:
|
|
33
33
|
def __init__(self, str_vers: str) -> None:
|
|
34
34
|
try:
|
|
35
|
-
self.major, self.minor, self.patch = str_vers.split(".")
|
|
35
|
+
self.major, self.minor, self.patch = str_vers.split(".", 2)
|
|
36
36
|
except Exception as e:
|
|
37
37
|
raise Exception(
|
|
38
38
|
"Bad version format for '{}': 'X.Y.Z' expected. Error: {}".format(
|
|
@@ -123,6 +123,31 @@ def status_handler(args: Any) -> None: # noqa: C901
|
|
|
123
123
|
)
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
+
# User API
|
|
127
|
+
print(" [+] Backoffice API")
|
|
128
|
+
print(" [+] address: {}".format(mantis_api_client_config.user_api_url))
|
|
129
|
+
try:
|
|
130
|
+
user_api_version = user_api.get_version()
|
|
131
|
+
user_vers = Version(str_vers=user_api_version)
|
|
132
|
+
except requests.exceptions.ConnectionError:
|
|
133
|
+
exit_code = 1
|
|
134
|
+
print(" [-] API status: " + colored("not running !", "white", "on_red"))
|
|
135
|
+
else:
|
|
136
|
+
print(" [+] API status: " + colored("OK", "grey", "on_green"))
|
|
137
|
+
print(" [+] version: {}".format(user_api_version))
|
|
138
|
+
if user_vers.major != client_vers.major:
|
|
139
|
+
exit_code = 1
|
|
140
|
+
print(
|
|
141
|
+
" [-] "
|
|
142
|
+
+ colored(
|
|
143
|
+
"Error: User API major version ({}) mismatchs with mantis_api_client major version ({})".format(
|
|
144
|
+
user_vers.major, client_vers.major
|
|
145
|
+
),
|
|
146
|
+
"white",
|
|
147
|
+
"on_red",
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
126
151
|
if exit_code != 0:
|
|
127
152
|
sys.exit(exit_code)
|
|
128
153
|
|
|
@@ -144,25 +169,42 @@ def info_handler(args: Any) -> None: # noqa: C901
|
|
|
144
169
|
access_token = jwt.get_unverified_claims(active_tokens["access_token"])
|
|
145
170
|
id_token = jwt.get_unverified_claims(active_tokens["id_token"])
|
|
146
171
|
|
|
147
|
-
|
|
148
|
-
|
|
172
|
+
sub_orgs = user_api.fetch_current_seats()
|
|
173
|
+
sub_membership: dict[str, list[dict]] = {}
|
|
174
|
+
sub_default_ws = get_oidc_client().get_default_workspace()
|
|
149
175
|
# Handle case where the user pertains to an organization
|
|
150
|
-
if
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
176
|
+
if sub_orgs:
|
|
177
|
+
sub_wss = user_api.fetch_current_workspaces()
|
|
178
|
+
for sub_org in sub_orgs:
|
|
179
|
+
sub_org_wss: list[dict] = []
|
|
180
|
+
sub_membership[sub_org["name"]] = sub_org_wss
|
|
181
|
+
for sub_ws in sub_wss:
|
|
182
|
+
if sub_org["id"] == sub_ws["organization_id"]:
|
|
183
|
+
sub_org_wss.append(sub_ws)
|
|
158
184
|
|
|
159
185
|
sorted_scopes = ", ".join(sorted(access_token["scope"].split()))
|
|
160
186
|
|
|
161
187
|
print(f"[+] Connected to {active_profile_domain}")
|
|
162
188
|
print(f" [+] Username: {id_token['preferred_username']}")
|
|
163
189
|
print(f" [+] Email: {id_token.get('email', 'N/A')}")
|
|
164
|
-
if
|
|
165
|
-
|
|
190
|
+
if sub_orgs:
|
|
191
|
+
|
|
192
|
+
def hl_activated_ws(ws: dict) -> str:
|
|
193
|
+
if ws["id"] == sub_default_ws:
|
|
194
|
+
return f"[bold]{ws['name']}[/bold]"
|
|
195
|
+
return ws["name"]
|
|
196
|
+
|
|
197
|
+
rprint(
|
|
198
|
+
r" \[+] Organization membership: {}".format(
|
|
199
|
+
", ".join(
|
|
200
|
+
"{} ({})".format(
|
|
201
|
+
org,
|
|
202
|
+
", ".join(map(hl_activated_ws, org_wss)),
|
|
203
|
+
)
|
|
204
|
+
for org, org_wss in sub_membership.items()
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
)
|
|
166
208
|
print(f" [+] Scopes: {sorted_scopes}")
|
|
167
209
|
|
|
168
210
|
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/attack_parser.py
RENAMED
|
@@ -95,7 +95,7 @@ def _attack_create_or_run_lab(args: Any, do_run: bool = True):
|
|
|
95
95
|
|
|
96
96
|
# Retrieve associated group id
|
|
97
97
|
if workspace_id is None:
|
|
98
|
-
print(colored("
|
|
98
|
+
print(colored("You have to specify a workspace with --workspace", "yellow"))
|
|
99
99
|
sys.exit(1)
|
|
100
100
|
|
|
101
101
|
# Safety checks
|
|
@@ -246,7 +246,7 @@ def add_attack_parser(root_parser: argparse.ArgumentParser, subparsers: Any) ->
|
|
|
246
246
|
help="Allows to define the unit scenario to create_lab for a unit attack",
|
|
247
247
|
)
|
|
248
248
|
parser_attack_create_lab.add_argument(
|
|
249
|
-
"--
|
|
249
|
+
"--workspace",
|
|
250
250
|
dest="workspace_id",
|
|
251
251
|
help="The group name that have ownership on lab",
|
|
252
252
|
)
|
|
@@ -280,7 +280,7 @@ def add_attack_parser(root_parser: argparse.ArgumentParser, subparsers: Any) ->
|
|
|
280
280
|
help="Allows to define the unit scenario to run for a unit attack",
|
|
281
281
|
)
|
|
282
282
|
parser_attack_run_lab.add_argument(
|
|
283
|
-
"--
|
|
283
|
+
"--workspace",
|
|
284
284
|
dest="workspace_id",
|
|
285
285
|
help="The group name that have ownership on lab",
|
|
286
286
|
)
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/bas_parser.py
RENAMED
|
@@ -13,7 +13,6 @@ from mantis_scenario_model.api_scenario_model import LabListReply
|
|
|
13
13
|
from mantis_scenario_model.lab_config_model import ContentType
|
|
14
14
|
from mantis_scenario_model.lab_config_model import LabConfig
|
|
15
15
|
from mantis_scenario_model.lab_model import Lab
|
|
16
|
-
from mantis_scenario_model.lab_model import ScenarioExecutionStatus
|
|
17
16
|
|
|
18
17
|
from cr_api_client import redteam_api
|
|
19
18
|
from mantis_api_client import scenario_api
|
|
@@ -113,7 +112,6 @@ def bas_create_handler(args: Any) -> None:
|
|
|
113
112
|
wait_lab(
|
|
114
113
|
lab_id,
|
|
115
114
|
quiet=True,
|
|
116
|
-
exit_on_status=[ScenarioExecutionStatus.scenario_execution],
|
|
117
115
|
)
|
|
118
116
|
|
|
119
117
|
except Exception as e:
|
|
@@ -129,7 +127,7 @@ def bas_create_handler(args: Any) -> None:
|
|
|
129
127
|
unset_current_lab()
|
|
130
128
|
|
|
131
129
|
print(
|
|
132
|
-
f"[hint]
|
|
130
|
+
f"[hint] Once an agent has been executed, retrieve its session with: '$ mantis bas info {lab_id}'"
|
|
133
131
|
)
|
|
134
132
|
|
|
135
133
|
|
|
@@ -239,7 +237,7 @@ def show_available_attacks(session_id: str, filter_tactic: str, filter_technique
|
|
|
239
237
|
for attack in attacks:
|
|
240
238
|
|
|
241
239
|
# Check if the attack is runnable
|
|
242
|
-
if attack["status"]
|
|
240
|
+
if attack["status"] not in ["runnable", "failed"]:
|
|
243
241
|
continue
|
|
244
242
|
|
|
245
243
|
# Check if the attack is BAS compatible
|
|
@@ -308,8 +306,14 @@ def show_available_attacks(session_id: str, filter_tactic: str, filter_technique
|
|
|
308
306
|
)
|
|
309
307
|
mitre_attack_infos = f"{technique_id} [{mitre_attack_tactics}]"
|
|
310
308
|
|
|
309
|
+
# Retrieve potential attack parameters that user can control
|
|
310
|
+
parameters = ""
|
|
311
|
+
attack_info = scenario_api.fetch_attack_by_name(attack['worker']['name'])
|
|
312
|
+
if attack_info.options:
|
|
313
|
+
parameters = f" - \033[1mparameters\033[0m: {', '.join(attack_info.options)}"
|
|
314
|
+
|
|
311
315
|
print(
|
|
312
|
-
f" - \033[
|
|
316
|
+
f" - \033[1mname\033[0m: {attack['worker']['name']:<30} - \033[1mATT&CK\033[0m: {mitre_attack_infos:<18} - \033[1mdescription\033[0m: {attack['worker']['title']:<30} - \033[1mvalues\033[0m:{attack_values}{parameters}"
|
|
313
317
|
)
|
|
314
318
|
|
|
315
319
|
|
|
@@ -523,6 +527,15 @@ def bas_attack_run_handler(args: Any) -> None:
|
|
|
523
527
|
|
|
524
528
|
params = parse_vars(params)
|
|
525
529
|
|
|
530
|
+
# Retrieve potential attack parameters that user can control, and
|
|
531
|
+
# check that the attack accepts those parameters
|
|
532
|
+
attack_info = scenario_api.fetch_attack_by_name(attack_name)
|
|
533
|
+
|
|
534
|
+
for key in params.keys():
|
|
535
|
+
if key not in attack_info.options:
|
|
536
|
+
print(colored(f"Parameter '{key}' is not in the supported parameter list. Supported parameters are: {', '.join(attack_info.options)}", "red"))
|
|
537
|
+
sys.exit(1)
|
|
538
|
+
|
|
526
539
|
# Retrieve matching bas lab
|
|
527
540
|
lab_id = find_bas_lab_from_session_id(session_id)
|
|
528
541
|
|
|
@@ -687,7 +700,7 @@ def add_bas_parser(root_parser: argparse.ArgumentParser, subparsers: Any) -> Non
|
|
|
687
700
|
)
|
|
688
701
|
parser_bas_create.set_defaults(func=bas_create_handler)
|
|
689
702
|
parser_bas_create.add_argument(
|
|
690
|
-
"--
|
|
703
|
+
"--workspace",
|
|
691
704
|
dest="workspace_id",
|
|
692
705
|
help="The workspace ID on which you want to create the BAS lab infrastructure",
|
|
693
706
|
)
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/basebox_parser.py
RENAMED
|
@@ -90,7 +90,7 @@ def _basebox_create_or_run_lab(args: Any, do_run: bool = True):
|
|
|
90
90
|
|
|
91
91
|
# Retrieve associated group id
|
|
92
92
|
if workspace_id is None:
|
|
93
|
-
print(colored("
|
|
93
|
+
print(colored("You have to specify a workspace with --workspace", "yellow"))
|
|
94
94
|
sys.exit(1)
|
|
95
95
|
|
|
96
96
|
# Manage lab configuration
|
|
@@ -203,7 +203,7 @@ def add_basebox_parser(
|
|
|
203
203
|
help="Do not keep the lab up after basebox execution (False by default)",
|
|
204
204
|
)
|
|
205
205
|
parser_basebox_create_lab.add_argument(
|
|
206
|
-
"--
|
|
206
|
+
"--workspace",
|
|
207
207
|
dest="workspace_id",
|
|
208
208
|
help="The group ID that have ownership on lab",
|
|
209
209
|
)
|
|
@@ -230,7 +230,7 @@ def add_basebox_parser(
|
|
|
230
230
|
help="Do not keep the lab up after basebox execution (False by default)",
|
|
231
231
|
)
|
|
232
232
|
parser_basebox_run_lab.add_argument(
|
|
233
|
-
"--
|
|
233
|
+
"--workspace",
|
|
234
234
|
dest="workspace_id",
|
|
235
235
|
help="The group ID that have ownership on lab",
|
|
236
236
|
)
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/scenario_parser.py
RENAMED
|
@@ -95,7 +95,7 @@ def _scenario_create_or_run_lab(args: Any, do_run: bool = True):
|
|
|
95
95
|
|
|
96
96
|
# Retrieve associated group id
|
|
97
97
|
if workspace_id is None:
|
|
98
|
-
print(colored("
|
|
98
|
+
print(colored("You have to specify a workspace with --workspace", "yellow"))
|
|
99
99
|
sys.exit(1)
|
|
100
100
|
|
|
101
101
|
# Manage lab configuration
|
|
@@ -226,7 +226,7 @@ def add_scenario_parser(
|
|
|
226
226
|
"scenario_name", type=str, help="The scenario name"
|
|
227
227
|
)
|
|
228
228
|
parser_scenario_create_lab.add_argument(
|
|
229
|
-
"--
|
|
229
|
+
"--workspace",
|
|
230
230
|
dest="workspace_id",
|
|
231
231
|
help="The group ID that have ownership on lab",
|
|
232
232
|
)
|
|
@@ -263,7 +263,7 @@ def add_scenario_parser(
|
|
|
263
263
|
"scenario_name", type=str, help="The scenario name"
|
|
264
264
|
)
|
|
265
265
|
parser_scenario_run_lab.add_argument(
|
|
266
|
-
"--
|
|
266
|
+
"--workspace",
|
|
267
267
|
dest="workspace_id",
|
|
268
268
|
help="The group ID that have ownership on lab",
|
|
269
269
|
)
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/topology_parser.py
RENAMED
|
@@ -82,7 +82,7 @@ def _topology_create_or_run_lab(args: Any, do_run: bool = True):
|
|
|
82
82
|
|
|
83
83
|
# Retrieve associated group id
|
|
84
84
|
if workspace_id is None:
|
|
85
|
-
print(colored("
|
|
85
|
+
print(colored("You have to specify a workspace with --workspace", "yellow"))
|
|
86
86
|
sys.exit(1)
|
|
87
87
|
|
|
88
88
|
# Manage lab configuration
|
|
@@ -198,7 +198,7 @@ def add_topology_parser(
|
|
|
198
198
|
help="Do not keep the lab up after topology execution (False by default)",
|
|
199
199
|
)
|
|
200
200
|
parser_topology_create_lab.add_argument(
|
|
201
|
-
"--
|
|
201
|
+
"--workspace",
|
|
202
202
|
dest="workspace_id",
|
|
203
203
|
help="The group ID that have ownership on lab",
|
|
204
204
|
)
|
|
@@ -227,7 +227,7 @@ def add_topology_parser(
|
|
|
227
227
|
help="Do not keep the lab up after topology execution (False by default)",
|
|
228
228
|
)
|
|
229
229
|
parser_topology_run_lab.add_argument(
|
|
230
|
-
"--
|
|
230
|
+
"--workspace",
|
|
231
231
|
dest="workspace_id",
|
|
232
232
|
help="The group ID that have ownership on lab",
|
|
233
233
|
)
|
|
@@ -75,14 +75,14 @@ def _handle_error(
|
|
|
75
75
|
|
|
76
76
|
def get_version() -> str:
|
|
77
77
|
"""
|
|
78
|
-
Return
|
|
78
|
+
Return User API version.
|
|
79
79
|
|
|
80
80
|
:return: The version number is a string
|
|
81
81
|
"""
|
|
82
82
|
result = authorize(_get)("/version")
|
|
83
83
|
|
|
84
84
|
if result.status_code != 200:
|
|
85
|
-
_handle_error(result, "Cannot retrieve
|
|
85
|
+
_handle_error(result, "Cannot retrieve User API version")
|
|
86
86
|
|
|
87
87
|
return result.json()
|
|
88
88
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/dataset_parser.py
RENAMED
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/lab_parser.py
RENAMED
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/labs_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/redteam_parser.py
RENAMED
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/signature_parser.py
RENAMED
|
File without changes
|
{mantis_api_client-5.3.0 → mantis_api_client-5.4.0}/mantis_api_client/cli_parser/user_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|