mantis_api_client 5.5.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.
- mantis_api_client/__init__.py +21 -0
- mantis_api_client/cli_parser/account_parser.py +451 -0
- mantis_api_client/cli_parser/attack_parser.py +317 -0
- mantis_api_client/cli_parser/bas_parser.py +1204 -0
- mantis_api_client/cli_parser/basebox_parser.py +258 -0
- mantis_api_client/cli_parser/dataset_parser.py +200 -0
- mantis_api_client/cli_parser/lab_parser.py +805 -0
- mantis_api_client/cli_parser/labs_parser.py +87 -0
- mantis_api_client/cli_parser/log_collector_parser.py +71 -0
- mantis_api_client/cli_parser/redteam_parser.py +375 -0
- mantis_api_client/cli_parser/scenario_parser.py +311 -0
- mantis_api_client/cli_parser/signature_parser.py +147 -0
- mantis_api_client/cli_parser/topology_parser.py +255 -0
- mantis_api_client/cli_parser/user_parser.py +225 -0
- mantis_api_client/config.py +73 -0
- mantis_api_client/dataset_api.py +267 -0
- mantis_api_client/exceptions.py +27 -0
- mantis_api_client/mantis.py +186 -0
- mantis_api_client/oidc.py +302 -0
- mantis_api_client/scenario_api.py +1196 -0
- mantis_api_client/user_api.py +282 -0
- mantis_api_client/utils.py +130 -0
- mantis_api_client-5.5.0.dist-info/AUTHORS +1 -0
- mantis_api_client-5.5.0.dist-info/LICENSE +19 -0
- mantis_api_client-5.5.0.dist-info/METADATA +33 -0
- mantis_api_client-5.5.0.dist-info/RECORD +28 -0
- mantis_api_client-5.5.0.dist-info/WHEEL +4 -0
- mantis_api_client-5.5.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from mantis_api_client.config import mantis_api_client_config
|
|
8
|
+
from mantis_api_client.oidc import authorize
|
|
9
|
+
|
|
10
|
+
# -------------------------------------------------------------------------- #
|
|
11
|
+
# Internal helpers
|
|
12
|
+
# -------------------------------------------------------------------------- #
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get(route: str, **kwargs: Any) -> requests.Response:
|
|
16
|
+
return requests.get(
|
|
17
|
+
f"{mantis_api_client_config.user_api_url}{route}",
|
|
18
|
+
verify=mantis_api_client_config.cacert,
|
|
19
|
+
cert=(mantis_api_client_config.cert, mantis_api_client_config.key),
|
|
20
|
+
**kwargs,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _post(route: str, **kwargs: Any) -> requests.Response:
|
|
25
|
+
return requests.post(
|
|
26
|
+
f"{mantis_api_client_config.user_api_url}{route}",
|
|
27
|
+
verify=mantis_api_client_config.cacert,
|
|
28
|
+
cert=(mantis_api_client_config.cert, mantis_api_client_config.key),
|
|
29
|
+
**kwargs,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _put(route: str, **kwargs: Any) -> requests.Response:
|
|
34
|
+
return requests.put(
|
|
35
|
+
f"{mantis_api_client_config.user_api_url}{route}",
|
|
36
|
+
verify=mantis_api_client_config.cacert,
|
|
37
|
+
cert=(mantis_api_client_config.cert, mantis_api_client_config.key),
|
|
38
|
+
**kwargs,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _delete(route: str, **kwargs: Any) -> requests.Response:
|
|
43
|
+
return requests.delete(
|
|
44
|
+
f"{mantis_api_client_config.user_api_url}{route}",
|
|
45
|
+
verify=mantis_api_client_config.cacert,
|
|
46
|
+
cert=(mantis_api_client_config.cert, mantis_api_client_config.key),
|
|
47
|
+
**kwargs,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _handle_error(
|
|
52
|
+
result: requests.Response, context_error_msg: str
|
|
53
|
+
) -> requests.Response:
|
|
54
|
+
error_msg = ""
|
|
55
|
+
if result.headers.get("content-type") == "application/json":
|
|
56
|
+
error_data = result.json()
|
|
57
|
+
for k in ("message", "detail"):
|
|
58
|
+
if k in error_data:
|
|
59
|
+
error_msg = error_data[k]
|
|
60
|
+
break
|
|
61
|
+
if not error_msg:
|
|
62
|
+
error_msg = result.text
|
|
63
|
+
|
|
64
|
+
raise Exception(
|
|
65
|
+
f"{context_error_msg}. "
|
|
66
|
+
f"Status code: '{result.status_code}'.\n"
|
|
67
|
+
f"Error message: '{error_msg}'."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# -------------------------------------------------------------------------- #
|
|
72
|
+
# Internal helpers
|
|
73
|
+
# -------------------------------------------------------------------------- #
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_version() -> str:
|
|
77
|
+
"""
|
|
78
|
+
Return User API version.
|
|
79
|
+
|
|
80
|
+
:return: The version number is a string
|
|
81
|
+
"""
|
|
82
|
+
result = authorize(_get)("/version")
|
|
83
|
+
|
|
84
|
+
if result.status_code != 200:
|
|
85
|
+
_handle_error(result, "Cannot retrieve User API version")
|
|
86
|
+
|
|
87
|
+
return result.json()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# -------------------------------------------------------------------------- #
|
|
91
|
+
# User API (users)
|
|
92
|
+
# -------------------------------------------------------------------------- #
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# def fetch_users() -> Any:
|
|
96
|
+
# """Fetch users of the current organization."""
|
|
97
|
+
# result = authorize(_get)("/users")
|
|
98
|
+
|
|
99
|
+
# if result.status_code != 200:
|
|
100
|
+
# _handle_error(result, "Cannot retrieve user list from User API")
|
|
101
|
+
# else:
|
|
102
|
+
# data = result.json()
|
|
103
|
+
|
|
104
|
+
# return data
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def fetch_current_user() -> Any:
|
|
108
|
+
"""Fetch current user information."""
|
|
109
|
+
result = authorize(_get)("/my/self")
|
|
110
|
+
|
|
111
|
+
if result.status_code != 200:
|
|
112
|
+
_handle_error(result, "Cannot retrieve current user from User API")
|
|
113
|
+
else:
|
|
114
|
+
data = result.json()
|
|
115
|
+
|
|
116
|
+
return data
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def fetch_user(user_id: str) -> Any:
|
|
120
|
+
"""Fetch information for a specific user."""
|
|
121
|
+
result = authorize(_get)(f"/users/{user_id}")
|
|
122
|
+
|
|
123
|
+
if result.status_code != 200:
|
|
124
|
+
_handle_error(
|
|
125
|
+
result,
|
|
126
|
+
f"Cannot retrieve user info for user_id '{user_id}' from User API",
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
data = result.json()
|
|
130
|
+
|
|
131
|
+
return data
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# -------------------------------------------------------------------------- #
|
|
135
|
+
# User API (seats)
|
|
136
|
+
# -------------------------------------------------------------------------- #
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def fetch_current_seats() -> Any:
|
|
140
|
+
"""Fetch seats of the current user."""
|
|
141
|
+
result = authorize(_get)("/my/organizations")
|
|
142
|
+
|
|
143
|
+
if result.status_code != 200:
|
|
144
|
+
_handle_error(result, "Cannot retrieve current seat from User API")
|
|
145
|
+
else:
|
|
146
|
+
data = result.json()
|
|
147
|
+
|
|
148
|
+
return data
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def fetch_current_workspaces() -> list:
|
|
152
|
+
"""Fetch workspaces of the current user."""
|
|
153
|
+
result = authorize(_get)("/my/workspaces")
|
|
154
|
+
|
|
155
|
+
if result.status_code != 200:
|
|
156
|
+
_handle_error(result, "Cannot retrieve current workspaces from User API")
|
|
157
|
+
else:
|
|
158
|
+
data = result.json()
|
|
159
|
+
|
|
160
|
+
return data
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# -------------------------------------------------------------------------- #
|
|
164
|
+
# User API (organizations)
|
|
165
|
+
# -------------------------------------------------------------------------- #
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def fetch_organization(organization_id: str) -> Any:
|
|
169
|
+
"""Fetch information for a specific organization."""
|
|
170
|
+
result = authorize(_get)(f"/organizations/{organization_id}")
|
|
171
|
+
|
|
172
|
+
if result.status_code != 200:
|
|
173
|
+
_handle_error(
|
|
174
|
+
result,
|
|
175
|
+
f"Cannot retrieve organization for organization_id {organization_id} from User API",
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
data = result.json()
|
|
179
|
+
|
|
180
|
+
return data
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def get_organization_workspaces(organization_id: str) -> list[dict]:
|
|
184
|
+
"""Retrieve workspaces from an organization ID."""
|
|
185
|
+
|
|
186
|
+
result = authorize(_get)(f"/organization/{organization_id}/workspaces")
|
|
187
|
+
|
|
188
|
+
if result.status_code != 200:
|
|
189
|
+
_handle_error(
|
|
190
|
+
result,
|
|
191
|
+
f"Cannot retrieve workspaces from organization ID '{organization_id}' from User API",
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
data = result.json()
|
|
195
|
+
|
|
196
|
+
return data
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def get_plan(plan_id: str) -> dict:
|
|
200
|
+
"""Retrieve plan information for a specific plan ID."""
|
|
201
|
+
|
|
202
|
+
result = authorize(_get)(f"/plans/{plan_id}")
|
|
203
|
+
|
|
204
|
+
if result.status_code != 200:
|
|
205
|
+
_handle_error(
|
|
206
|
+
result,
|
|
207
|
+
f"Cannot retrieve plan info for plan ID '{plan_id}' from User API",
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
data = result.json()
|
|
211
|
+
|
|
212
|
+
return data
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_plan_limits(plan_id: str) -> dict:
|
|
216
|
+
"""Retrieve plan limits for a specific plan ID."""
|
|
217
|
+
|
|
218
|
+
result = authorize(_get)(f"/plans/{plan_id}/limits")
|
|
219
|
+
|
|
220
|
+
if result.status_code != 200:
|
|
221
|
+
_handle_error(
|
|
222
|
+
result,
|
|
223
|
+
f"Cannot retrieve plan limits for plan ID '{plan_id}' from User API",
|
|
224
|
+
)
|
|
225
|
+
else:
|
|
226
|
+
data = result.json()
|
|
227
|
+
|
|
228
|
+
return data
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def get_credits_list(organization_id: str) -> dict:
|
|
232
|
+
"""Retrieve credits list for a specific organization ID."""
|
|
233
|
+
|
|
234
|
+
result = authorize(_get)(
|
|
235
|
+
"/credits",
|
|
236
|
+
params={"organization_id": organization_id},
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
if result.status_code != 200:
|
|
240
|
+
_handle_error(
|
|
241
|
+
result,
|
|
242
|
+
f"Cannot retrieve credits list for organization ID '{organization_id}' from User API",
|
|
243
|
+
)
|
|
244
|
+
else:
|
|
245
|
+
data = result.json()
|
|
246
|
+
|
|
247
|
+
return data
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def get_consumption_history(organization_id: str) -> dict:
|
|
251
|
+
"""Retrieve consumption history for a specific organization ID."""
|
|
252
|
+
|
|
253
|
+
result = authorize(_get)(
|
|
254
|
+
"/history",
|
|
255
|
+
params={"organization_id": organization_id},
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if result.status_code != 200:
|
|
259
|
+
_handle_error(
|
|
260
|
+
result,
|
|
261
|
+
f"Cannot retrieve consumption history for organization ID '{organization_id}' from User API",
|
|
262
|
+
)
|
|
263
|
+
else:
|
|
264
|
+
data = result.json()
|
|
265
|
+
|
|
266
|
+
return data
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def get_subject_roles() -> dict[str, list[dict]]:
|
|
270
|
+
"""Retrieve subject roles."""
|
|
271
|
+
|
|
272
|
+
result = authorize(_get)("/my/roles")
|
|
273
|
+
|
|
274
|
+
if result.status_code != "200":
|
|
275
|
+
_handle_error(
|
|
276
|
+
result,
|
|
277
|
+
"Cannot retrieve subject roles from User API",
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
data = result.json()
|
|
281
|
+
|
|
282
|
+
return data
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import json
|
|
3
|
+
import time
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Dict
|
|
6
|
+
from typing import List
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from alive_progress import alive_bar
|
|
10
|
+
from mantis_scenario_model.lab_model import ScenarioExecutionStatus
|
|
11
|
+
from urllib3.exceptions import NewConnectionError
|
|
12
|
+
|
|
13
|
+
from mantis_api_client import scenario_api
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
from colorama import init
|
|
17
|
+
from termcolor import colored
|
|
18
|
+
|
|
19
|
+
HAS_COLOUR = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
HAS_COLOUR = False
|
|
22
|
+
|
|
23
|
+
# Initialize colorama
|
|
24
|
+
if HAS_COLOUR:
|
|
25
|
+
init(autoreset=True)
|
|
26
|
+
else:
|
|
27
|
+
# Override colored function to return first argument
|
|
28
|
+
def colored(text: object, *args: Any, **kwargs: Any) -> str: # type: ignore # noqa
|
|
29
|
+
return str(text)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def wait_lab(
|
|
33
|
+
lab_id: str,
|
|
34
|
+
quiet: bool = False,
|
|
35
|
+
exit_on_status: Optional[List[ScenarioExecutionStatus]] = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""
|
|
38
|
+
- exit_on_status: allow to break the wait loop if current status matches one of the
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
if exit_on_status is None:
|
|
42
|
+
exit_on_status = []
|
|
43
|
+
|
|
44
|
+
notifications_output: List[Dict[str, str]] = []
|
|
45
|
+
|
|
46
|
+
if not quiet:
|
|
47
|
+
print("[+] Notifications:")
|
|
48
|
+
|
|
49
|
+
with alive_bar(
|
|
50
|
+
refresh_secs=0.08,
|
|
51
|
+
spinner=None,
|
|
52
|
+
enrich_print=False,
|
|
53
|
+
stats=False,
|
|
54
|
+
monitor=False,
|
|
55
|
+
theme="classic",
|
|
56
|
+
) as bar:
|
|
57
|
+
nb_requests_failed = 0
|
|
58
|
+
while True:
|
|
59
|
+
in_error = False
|
|
60
|
+
|
|
61
|
+
time.sleep(1)
|
|
62
|
+
|
|
63
|
+
# Retrieve current lab status and associated
|
|
64
|
+
# notifications. Only display error message if it occurs
|
|
65
|
+
# multiple times.
|
|
66
|
+
try:
|
|
67
|
+
lab = scenario_api.fetch_lab(lab_id)
|
|
68
|
+
except NewConnectionError as e:
|
|
69
|
+
in_error = True
|
|
70
|
+
nb_requests_failed += 1
|
|
71
|
+
if nb_requests_failed > 10:
|
|
72
|
+
print(e)
|
|
73
|
+
except Exception as e:
|
|
74
|
+
in_error = True
|
|
75
|
+
nb_requests_failed += 1
|
|
76
|
+
if nb_requests_failed > 10:
|
|
77
|
+
print(e)
|
|
78
|
+
|
|
79
|
+
# Exit in case of multiple failures when fetching lab status
|
|
80
|
+
if nb_requests_failed > 10:
|
|
81
|
+
break
|
|
82
|
+
|
|
83
|
+
if in_error:
|
|
84
|
+
continue
|
|
85
|
+
|
|
86
|
+
if not quiet:
|
|
87
|
+
# Retrieve lab notifications
|
|
88
|
+
notifications = scenario_api.fetch_lab_notifications(lab_id)
|
|
89
|
+
|
|
90
|
+
# Only display new notifications
|
|
91
|
+
new_output = notifications[len(notifications_output) :]
|
|
92
|
+
for event in new_output:
|
|
93
|
+
event = json.loads(event)
|
|
94
|
+
data = event["event_data"]
|
|
95
|
+
iso_str = event["event_datetime"]
|
|
96
|
+
dtime = datetime.fromisoformat(iso_str).strftime(
|
|
97
|
+
"%Y-%m-%d %H:%M:%S"
|
|
98
|
+
)
|
|
99
|
+
print(f"⚡ {dtime} UTC - {data}")
|
|
100
|
+
notifications_output = notifications
|
|
101
|
+
|
|
102
|
+
# Display current macro step (deploy, provisioning, attack, etc.)
|
|
103
|
+
if "status" in lab:
|
|
104
|
+
bar.text(lab["status"])
|
|
105
|
+
if lab["status"].rstrip() == "PAUSE":
|
|
106
|
+
with bar.pause():
|
|
107
|
+
print("Press Enter to continue the scenario...")
|
|
108
|
+
input()
|
|
109
|
+
scenario_api.resume_lab(lab_id)
|
|
110
|
+
lab = scenario_api.fetch_lab(lab_id)
|
|
111
|
+
else:
|
|
112
|
+
bar()
|
|
113
|
+
|
|
114
|
+
# Condition to break loop: the scenario execution
|
|
115
|
+
# has finished, either because it has been cancelled or
|
|
116
|
+
# because it has successfully finished
|
|
117
|
+
if "status" in lab and lab["status"] in [
|
|
118
|
+
ScenarioExecutionStatus.scenario_finished.value,
|
|
119
|
+
ScenarioExecutionStatus.completed.value,
|
|
120
|
+
ScenarioExecutionStatus.cancelled.value,
|
|
121
|
+
ScenarioExecutionStatus.error.value,
|
|
122
|
+
]:
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
# Exit on specific statuses decided by the current function caller
|
|
126
|
+
if "status" in lab and lab["status"] in [s.value for s in exit_on_status]:
|
|
127
|
+
break
|
|
128
|
+
|
|
129
|
+
if not quiet:
|
|
130
|
+
print("[+] Lab content has been completed")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Created by Amossys <contact@amossys.fr>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2016-2021 AMOSSYS
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mantis_api_client
|
|
3
|
+
Version: 5.5.0
|
|
4
|
+
Summary: M&NTIS Platform client API
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: AMOSSYS
|
|
7
|
+
Requires-Python: >=3.10,<4.0
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Dist: alive-progress (>=3.1.5,<4.0.0)
|
|
15
|
+
Requires-Dist: argcomplete (>=1.12.1,<1.13.0)
|
|
16
|
+
Requires-Dist: colorama (>=0.4.4,<0.5.0)
|
|
17
|
+
Requires-Dist: cr-api-client (>=5.0.26,<6.0.0)
|
|
18
|
+
Requires-Dist: mantis-authz (>=0.2.3,<1.0.0)
|
|
19
|
+
Requires-Dist: mantis-catalog (>=0.1.2,<0.2.0)
|
|
20
|
+
Requires-Dist: mantis-logger (>=0.2.0,<0.3.0)
|
|
21
|
+
Requires-Dist: mantis-models (>=3.4.11,<4.0.0)
|
|
22
|
+
Requires-Dist: omegaconf (>=2.2.2,<3.0.0)
|
|
23
|
+
Requires-Dist: pydantic (>=2.10.3,<3.0.0)
|
|
24
|
+
Requires-Dist: requests (>=2.24.0,<3.0.0)
|
|
25
|
+
Requires-Dist: rich (>=13.7.1,<14.0.0)
|
|
26
|
+
Requires-Dist: rich_argparse (>=1.5.2,<2.0.0)
|
|
27
|
+
Requires-Dist: ruamel-yaml (>=0.16.10,<0.17.0)
|
|
28
|
+
Requires-Dist: ruamel.yaml (>=0.16.10,<0.17.0)
|
|
29
|
+
Requires-Dist: termcolor (>=1.1.0,<1.2.0)
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# M&NTIS Platform client API
|
|
33
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
mantis_api_client/__init__.py,sha256=a0qcQBVKkpnLmwNU6jpqAPYR0_9rDCg-8seK-9uu1AY,581
|
|
2
|
+
mantis_api_client/cli_parser/account_parser.py,sha256=wUosGQ8Jadnjd_526kLRgxVIJZx4MULO4fbLBpnOTJk,15369
|
|
3
|
+
mantis_api_client/cli_parser/attack_parser.py,sha256=ol0biecEO0yOx6RvYWoHTBCf3LMa9wrBVYQjlSkhmQo,10143
|
|
4
|
+
mantis_api_client/cli_parser/bas_parser.py,sha256=T7ARupf5-KaE7R-CsBtgf2Y15rkv2aR1g47wpm1wfHQ,39484
|
|
5
|
+
mantis_api_client/cli_parser/basebox_parser.py,sha256=56ZvZe96TZm44wHd9lCmkOq_Dvi7-PmsTUYl1e8HtnY,8267
|
|
6
|
+
mantis_api_client/cli_parser/dataset_parser.py,sha256=T4e7lN6Qh6FryKtb-DzNj0dO-jiC5sgMBxVT3b1I8G0,6469
|
|
7
|
+
mantis_api_client/cli_parser/lab_parser.py,sha256=5lV5ESqtj0yz4PUb85O0ANx2z7JbzAYAhMKMYxvUJTU,24542
|
|
8
|
+
mantis_api_client/cli_parser/labs_parser.py,sha256=HcC_gCCd7okHU6pjZaHZOhU7vpfBjXQub6WQeL4AOeE,3057
|
|
9
|
+
mantis_api_client/cli_parser/log_collector_parser.py,sha256=MtWJLiI_64B306qgLIs9oPwywYcF_ndulykyMtdvTy0,2316
|
|
10
|
+
mantis_api_client/cli_parser/redteam_parser.py,sha256=go0dBgWVrRnqOyJ0sfaX5FfqSlQfq-qvNl-nAOifUJE,11187
|
|
11
|
+
mantis_api_client/cli_parser/scenario_parser.py,sha256=axlTdcwWp3x9N_ZvhWfPOD9W42gmnhct1l9_2lQzfA4,9918
|
|
12
|
+
mantis_api_client/cli_parser/signature_parser.py,sha256=XIRu4MSfVbrmS2-gMP0Vi63Fp0HTX5z4yHcgs0gmhqg,4774
|
|
13
|
+
mantis_api_client/cli_parser/topology_parser.py,sha256=Opvk02bG_8slkCWNSf9hLofklXcDH9w4G5D8Wz9Uke8,7919
|
|
14
|
+
mantis_api_client/cli_parser/user_parser.py,sha256=oa414THhg8HWetDYCMs3_XHTKBPpe3UnH5bTBWZ066Y,7256
|
|
15
|
+
mantis_api_client/config.py,sha256=eCXId_C0Xe-KAey8irnN4Dk8FCGmppL1XqguuvLdn04,2588
|
|
16
|
+
mantis_api_client/dataset_api.py,sha256=n30NjHOc7OnbX_p1sFAFgvKCbTYHoFR0sxIkmeVYaNc,9008
|
|
17
|
+
mantis_api_client/exceptions.py,sha256=EbfPig5Mu0aa8iqqILmOIjbfcFm3nfUhebeNYbHGe68,1187
|
|
18
|
+
mantis_api_client/mantis.py,sha256=f0LTOM8XdzXWePUPhZmn9sseLgly50GrrLOfTb5485w,5949
|
|
19
|
+
mantis_api_client/oidc.py,sha256=-H3-hlWbS7N44ZbgQvf6fkLFyzovaMTCaKQS5OCetYE,10756
|
|
20
|
+
mantis_api_client/scenario_api.py,sha256=es7btbpVkfIMnVmtNqSSLhuSwNEfxov6nfwoSYkrgTc,31306
|
|
21
|
+
mantis_api_client/user_api.py,sha256=IXJ3sOlWPgWJUhfV08qsWO7dIfUDdIbDTAGOjRx-gxY,7588
|
|
22
|
+
mantis_api_client/utils.py,sha256=d5TxLzofDcK4WbgTrm8mz5_M9Wvuq-ANgsjZIhbzQIU,4182
|
|
23
|
+
mantis_api_client-5.5.0.dist-info/AUTHORS,sha256=cZG0yas_cZYZStWPnFCG3wL9kNtihpB7rONDqqOhCk8,40
|
|
24
|
+
mantis_api_client-5.5.0.dist-info/LICENSE,sha256=8sBbPetGUTlhPzK-BXmdnV_hadvwFxL77L4WsghguvI,1056
|
|
25
|
+
mantis_api_client-5.5.0.dist-info/METADATA,sha256=pLixUQ828NKxK54fFXVo-Yehan_3HKexi4OLxSILgQQ,1242
|
|
26
|
+
mantis_api_client-5.5.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
27
|
+
mantis_api_client-5.5.0.dist-info/entry_points.txt,sha256=h3Qq03yHa0O9niMtTDGIj7hE2SqXbZBR3Bt7kkQSIJs,56
|
|
28
|
+
mantis_api_client-5.5.0.dist-info/RECORD,,
|