cr_api_client 4.13.1__4-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.
- cr_api_client/__init__.py +18 -0
- cr_api_client/cli_parser/provisioning_parser.py +515 -0
- cr_api_client/config.py +48 -0
- cr_api_client/core_api.py +3820 -0
- cr_api_client/cyber_range.py +3206 -0
- cr_api_client/logger.py +4 -0
- cr_api_client/provisioning_api.py +725 -0
- cr_api_client/redteam_api.py +917 -0
- cr_api_client/topology/TopologyElements.py +235 -0
- cr_api_client/topology/TopologyGenerator.py +423 -0
- cr_api_client/topology/TopologyLinksGenerator.py +98 -0
- cr_api_client/topology/TopologyNodeGenerator.py +96 -0
- cr_api_client/topology/TopologyNodesGenerator.py +116 -0
- cr_api_client/topology/validator/__init__.py +13 -0
- cr_api_client/topology/validator/common.py +74 -0
- cr_api_client/topology/validator/link.py +58 -0
- cr_api_client/topology/validator/node.py +152 -0
- cr_api_client/topology/validator/topology.py +48 -0
- cr_api_client/user_activity_api.py +859 -0
- cr_api_client/yaml_helper.py +114 -0
- cr_api_client-4.13.1.dist-info/AUTHORS +1 -0
- cr_api_client-4.13.1.dist-info/LICENSE +19 -0
- cr_api_client-4.13.1.dist-info/METADATA +417 -0
- cr_api_client-4.13.1.dist-info/RECORD +26 -0
- cr_api_client-4.13.1.dist-info/WHEEL +4 -0
- cr_api_client-4.13.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
import os
|
|
4
|
+
import threading
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
# Component version
|
|
8
|
+
__version__ = "4.13.1"
|
|
9
|
+
|
|
10
|
+
# Get component full version from file generated at build time
|
|
11
|
+
current_file_dir = Path(__file__).resolve().parent
|
|
12
|
+
fullversion_file = Path(current_file_dir, "fullversion.txt")
|
|
13
|
+
if os.path.isfile(fullversion_file):
|
|
14
|
+
__fullversion__ = open(fullversion_file, "r").read().strip()
|
|
15
|
+
else:
|
|
16
|
+
__fullversion__ = __version__
|
|
17
|
+
|
|
18
|
+
shutil_make_archive_lock = threading.Lock()
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2016-2024 AMOSSYS
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
# furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
# copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
# SOFTWARE.
|
|
23
|
+
#
|
|
24
|
+
# PYTHON_ARGCOMPLETE_OK
|
|
25
|
+
import argparse
|
|
26
|
+
import sys
|
|
27
|
+
from typing import Any
|
|
28
|
+
|
|
29
|
+
import cr_api_client.provisioning_api as provisioning_api
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# 'provisioning_execute' related functions
|
|
34
|
+
#
|
|
35
|
+
def provisioning_execute_handler(args: Any) -> None:
|
|
36
|
+
"""Process YAML topology file and execute a new provisioning
|
|
37
|
+
chronology (generate + play)).
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# Parameters
|
|
42
|
+
id_simulation = args.id_simulation
|
|
43
|
+
machines_file = args.machines_file
|
|
44
|
+
provisioning_file = args.provisioning_file
|
|
45
|
+
debug = args.debug_mode
|
|
46
|
+
wait = not args.provisioning_nowait
|
|
47
|
+
timeout = args.timeout
|
|
48
|
+
ansible_verbosity = args.provisioning_ansible_verbosity
|
|
49
|
+
stream_ansible = args.provisioning_stream_ansible
|
|
50
|
+
reload_provisioning_agent = args.provisioning_reload_agent
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
provisioning_api.provisioning_execute(
|
|
54
|
+
id_simulation=id_simulation,
|
|
55
|
+
machines_file=machines_file,
|
|
56
|
+
provisioning_file=provisioning_file,
|
|
57
|
+
debug=debug,
|
|
58
|
+
wait=wait,
|
|
59
|
+
timeout=timeout,
|
|
60
|
+
ansible_verbosity=ansible_verbosity,
|
|
61
|
+
stream_ansible=stream_ansible,
|
|
62
|
+
reload_provisioning_agent=reload_provisioning_agent,
|
|
63
|
+
)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
print(f"Error during provisioning: '{e}'")
|
|
66
|
+
sys.exit(1)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
#
|
|
70
|
+
# 'provisioning_ansible' related functions
|
|
71
|
+
#
|
|
72
|
+
def provisioning_ansible_handler(args: Any) -> None:
|
|
73
|
+
"""Apply ansible playbook on targets."""
|
|
74
|
+
|
|
75
|
+
# Parameters
|
|
76
|
+
id_simulation = args.id_simulation
|
|
77
|
+
machines_file = args.machines_file
|
|
78
|
+
playbook_path = args.provisioning_playbook_path
|
|
79
|
+
provisioning_extra_vars = args.provisioning_extra_vars
|
|
80
|
+
provisioning_target_roles = args.provisioning_target_roles
|
|
81
|
+
provisioning_target_system_types = args.provisioning_target_system_types
|
|
82
|
+
provisioning_target_operating_systems = args.provisioning_target_operating_systems
|
|
83
|
+
provisioning_target_names = args.provisioning_target_names
|
|
84
|
+
provisioning_host_vars = args.provisioning_host_vars
|
|
85
|
+
provisioning_gather_facts_override = args.provisioning_gather_facts_override
|
|
86
|
+
provisioning_ansible_verbosity = args.provisioning_ansible_verbosity
|
|
87
|
+
debug = args.debug_mode
|
|
88
|
+
wait = not args.provisioning_nowait
|
|
89
|
+
timeout = args.timeout
|
|
90
|
+
provisioning_stream_ansible = args.provisioning_stream_ansible
|
|
91
|
+
provisioning_reload_agent = args.provisioning_reload_agent
|
|
92
|
+
|
|
93
|
+
# TODO: check that only one target type is defined
|
|
94
|
+
|
|
95
|
+
if provisioning_target_operating_systems is None:
|
|
96
|
+
provisioning_target_operating_systems = []
|
|
97
|
+
if provisioning_target_system_types is None:
|
|
98
|
+
provisioning_target_system_types = []
|
|
99
|
+
if provisioning_target_roles is None:
|
|
100
|
+
provisioning_target_roles = []
|
|
101
|
+
if provisioning_target_names is None:
|
|
102
|
+
provisioning_target_names = []
|
|
103
|
+
if provisioning_host_vars is None:
|
|
104
|
+
provisioning_host_vars = []
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
len(provisioning_target_operating_systems)
|
|
108
|
+
+ len(provisioning_target_system_types)
|
|
109
|
+
+ len(provisioning_target_roles)
|
|
110
|
+
+ len(provisioning_target_names)
|
|
111
|
+
== 0
|
|
112
|
+
):
|
|
113
|
+
raise SyntaxError(
|
|
114
|
+
"At least one of the following options should be defined: -n, -r, -s, -o."
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
provisioning_api.provisioning_ansible(
|
|
119
|
+
id_simulation=id_simulation,
|
|
120
|
+
machines_file=machines_file,
|
|
121
|
+
playbook_path=playbook_path,
|
|
122
|
+
extra_vars=provisioning_extra_vars,
|
|
123
|
+
target_roles=provisioning_target_roles,
|
|
124
|
+
target_system_types=provisioning_target_system_types,
|
|
125
|
+
target_operating_systems=provisioning_target_operating_systems,
|
|
126
|
+
target_names=provisioning_target_names,
|
|
127
|
+
host_vars=provisioning_host_vars,
|
|
128
|
+
gather_facts_override=provisioning_gather_facts_override,
|
|
129
|
+
debug=debug,
|
|
130
|
+
ansible_verbosity=provisioning_ansible_verbosity,
|
|
131
|
+
wait=wait,
|
|
132
|
+
timeout=timeout,
|
|
133
|
+
stream_ansible=provisioning_stream_ansible,
|
|
134
|
+
reload_provisioning_agent=provisioning_reload_agent,
|
|
135
|
+
)
|
|
136
|
+
except Exception as e:
|
|
137
|
+
error_msg = str(e)
|
|
138
|
+
error_msg = error_msg.replace("\\n", "\n")
|
|
139
|
+
print(f"Error during provisioning: {error_msg}")
|
|
140
|
+
sys.exit(1)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# 'provisioning_inventory' related functions
|
|
145
|
+
#
|
|
146
|
+
def provisioning_inventory_handler(args: Any) -> None:
|
|
147
|
+
"""Generate ansible inventory files."""
|
|
148
|
+
|
|
149
|
+
# Parameters
|
|
150
|
+
id_simulation = args.id_simulation
|
|
151
|
+
machines_file = args.machines_file
|
|
152
|
+
output_dir = args.output_inventory_dir
|
|
153
|
+
debug = args.debug_mode
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
provisioning_api.provisioning_inventory(
|
|
157
|
+
id_simulation=id_simulation,
|
|
158
|
+
machines_file=machines_file,
|
|
159
|
+
output_dir=output_dir,
|
|
160
|
+
debug=debug,
|
|
161
|
+
)
|
|
162
|
+
except Exception as e:
|
|
163
|
+
error_msg = str(e)
|
|
164
|
+
error_msg = error_msg.replace("\\n", "\n")
|
|
165
|
+
print(f"Error during provisioning: {error_msg}")
|
|
166
|
+
sys.exit(1)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
#
|
|
170
|
+
# 'provisioning_stop' related functions
|
|
171
|
+
#
|
|
172
|
+
def provisioning_stop_handler(args: Any) -> None:
|
|
173
|
+
"""Stop provisioning currently running"""
|
|
174
|
+
|
|
175
|
+
# Parameters
|
|
176
|
+
task_id = args.task_id
|
|
177
|
+
|
|
178
|
+
print("[+] Stopping provisioning task with id '{}'".format(task_id))
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
provisioning_api.provisioning_stop(task_id)
|
|
182
|
+
print("[+] Stopping done.")
|
|
183
|
+
|
|
184
|
+
except Exception as e:
|
|
185
|
+
error_msg = str(e)
|
|
186
|
+
error_msg = error_msg.replace("\\n", "\n")
|
|
187
|
+
print(f"[-] Error while stopping provisioning: {error_msg}")
|
|
188
|
+
sys.exit(1)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
#
|
|
192
|
+
# 'provisioning_status' related functions
|
|
193
|
+
#
|
|
194
|
+
def provisioning_status_handler(args: Any) -> None:
|
|
195
|
+
"""Status provisioning currently running"""
|
|
196
|
+
|
|
197
|
+
# Parameters
|
|
198
|
+
task_id = args.task_id
|
|
199
|
+
|
|
200
|
+
print("[+] Provisioning task status with id '{}'".format(task_id))
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
result = provisioning_api.provisioning_status(task_id)
|
|
204
|
+
status = result["status"]
|
|
205
|
+
if status is None:
|
|
206
|
+
print(
|
|
207
|
+
f"[+] Status unknown, this task id doesn't exist or is finished: {task_id}"
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
print(f"[+] Status: {status}")
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
error_msg = str(e)
|
|
214
|
+
error_msg = error_msg.replace("\\n", "\n")
|
|
215
|
+
print(f"[-] Error while provisioning status: {error_msg}")
|
|
216
|
+
sys.exit(1)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
#
|
|
220
|
+
# 'provisioning_report' related functions
|
|
221
|
+
#
|
|
222
|
+
def provisioning_report_handler(args: Any) -> None:
|
|
223
|
+
"""Report of all currently running provisioning agents"""
|
|
224
|
+
|
|
225
|
+
print("[+] Provisioning report: ")
|
|
226
|
+
task_id = args.task_id
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
result = provisioning_api.provisioning_report(task_id)
|
|
230
|
+
print(" [+] --------------------------------------")
|
|
231
|
+
print(f" [+] {task_id}:")
|
|
232
|
+
print(" [+] --------------------------------------")
|
|
233
|
+
print(result["logs"])
|
|
234
|
+
|
|
235
|
+
except Exception as e:
|
|
236
|
+
error_msg = str(e)
|
|
237
|
+
error_msg = error_msg.replace("\\n", "\n")
|
|
238
|
+
print(
|
|
239
|
+
f"[-] Error while retrieving provisioning report for {task_id} : {error_msg}"
|
|
240
|
+
)
|
|
241
|
+
sys.exit(1)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def add_provisioning_parser(
|
|
245
|
+
root_parser: argparse.ArgumentParser, subparsers: Any
|
|
246
|
+
) -> None:
|
|
247
|
+
# Subparser provisioning
|
|
248
|
+
parser_provisioning = subparsers.add_parser(
|
|
249
|
+
"provisioning",
|
|
250
|
+
help="Provisioning actions in running labs",
|
|
251
|
+
formatter_class=root_parser.formatter_class,
|
|
252
|
+
)
|
|
253
|
+
subparsers_provisioning = parser_provisioning.add_subparsers()
|
|
254
|
+
parser_provisioning.set_defaults(func=lambda _: parser_provisioning.print_help())
|
|
255
|
+
|
|
256
|
+
# 'execute' command
|
|
257
|
+
parser_provisioning_execute = subparsers_provisioning.add_parser(
|
|
258
|
+
"execute",
|
|
259
|
+
help="Execute provisioning chronology for a simulation",
|
|
260
|
+
formatter_class=root_parser.formatter_class,
|
|
261
|
+
)
|
|
262
|
+
parser_provisioning_execute.set_defaults(func=provisioning_execute_handler)
|
|
263
|
+
parser_provisioning_execute.add_argument(
|
|
264
|
+
"--id",
|
|
265
|
+
type=int,
|
|
266
|
+
action="store",
|
|
267
|
+
required=False,
|
|
268
|
+
dest="id_simulation",
|
|
269
|
+
help="The simulation id",
|
|
270
|
+
)
|
|
271
|
+
parser_provisioning_execute.add_argument(
|
|
272
|
+
"--machines",
|
|
273
|
+
action="store",
|
|
274
|
+
required=False,
|
|
275
|
+
dest="machines_file",
|
|
276
|
+
help="Input path of machines configuration (YAML format)",
|
|
277
|
+
)
|
|
278
|
+
parser_provisioning_execute.add_argument(
|
|
279
|
+
"-c",
|
|
280
|
+
action="store",
|
|
281
|
+
required=True,
|
|
282
|
+
dest="provisioning_file",
|
|
283
|
+
help="Input path of provisioning configuration",
|
|
284
|
+
)
|
|
285
|
+
parser_provisioning_execute.add_argument(
|
|
286
|
+
"--no-wait",
|
|
287
|
+
action="store_true",
|
|
288
|
+
default=False,
|
|
289
|
+
dest="provisioning_nowait",
|
|
290
|
+
help="Don't wait for the task to be done",
|
|
291
|
+
)
|
|
292
|
+
parser_provisioning_execute.add_argument(
|
|
293
|
+
"--timeout",
|
|
294
|
+
action="store",
|
|
295
|
+
type=int,
|
|
296
|
+
required=False,
|
|
297
|
+
default=10800,
|
|
298
|
+
dest="timeout",
|
|
299
|
+
help="Timeout of the provisioning task (default to 10800 seconds - 3 hours)",
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
parser_provisioning_execute.add_argument(
|
|
303
|
+
"--ansible-verbosity",
|
|
304
|
+
"-v",
|
|
305
|
+
action="store",
|
|
306
|
+
type=int,
|
|
307
|
+
required=False,
|
|
308
|
+
default=0,
|
|
309
|
+
dest="provisioning_ansible_verbosity",
|
|
310
|
+
help="Determines the verbosity of the ansible output (and the number of '-v' passed to ansible)",
|
|
311
|
+
)
|
|
312
|
+
parser_provisioning_execute.add_argument(
|
|
313
|
+
"--stream-ansible",
|
|
314
|
+
action="store_true",
|
|
315
|
+
required=False,
|
|
316
|
+
default=False,
|
|
317
|
+
dest="provisioning_stream_ansible",
|
|
318
|
+
help="If set, will stream the ansible output during the provisioning task",
|
|
319
|
+
)
|
|
320
|
+
parser_provisioning_execute.add_argument(
|
|
321
|
+
"--reload-provisioning-agent",
|
|
322
|
+
action="store_true",
|
|
323
|
+
required=False,
|
|
324
|
+
default=False,
|
|
325
|
+
dest="provisioning_reload_agent",
|
|
326
|
+
help="If set, will force the reloading of the provisioning agent docker container",
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# 'ansible' command
|
|
330
|
+
parser_provisioning_ansible = subparsers_provisioning.add_parser(
|
|
331
|
+
"ansible",
|
|
332
|
+
help="""Apply ansible playbook(s) on specific target(s).""",
|
|
333
|
+
formatter_class=root_parser.formatter_class,
|
|
334
|
+
)
|
|
335
|
+
parser_provisioning_ansible.set_defaults(func=provisioning_ansible_handler)
|
|
336
|
+
parser_provisioning_ansible.add_argument(
|
|
337
|
+
"--id",
|
|
338
|
+
type=int,
|
|
339
|
+
action="store",
|
|
340
|
+
required=False,
|
|
341
|
+
dest="id_simulation",
|
|
342
|
+
help="The simulation id",
|
|
343
|
+
)
|
|
344
|
+
parser_provisioning_ansible.add_argument(
|
|
345
|
+
"--machines",
|
|
346
|
+
action="store",
|
|
347
|
+
required=False,
|
|
348
|
+
dest="machines_file",
|
|
349
|
+
help="Input path of machines configuration (YAML format)",
|
|
350
|
+
)
|
|
351
|
+
parser_provisioning_ansible.add_argument(
|
|
352
|
+
"-c",
|
|
353
|
+
action="store",
|
|
354
|
+
required=True,
|
|
355
|
+
dest="provisioning_playbook_path",
|
|
356
|
+
help="Input directory containing ansible playbook(s)",
|
|
357
|
+
)
|
|
358
|
+
parser_provisioning_ansible.add_argument(
|
|
359
|
+
"-r",
|
|
360
|
+
action="append",
|
|
361
|
+
dest="provisioning_target_roles",
|
|
362
|
+
help="Role used to filter targets ('client', 'activate_directory', 'file_server', 'admin', ...)",
|
|
363
|
+
)
|
|
364
|
+
parser_provisioning_ansible.add_argument(
|
|
365
|
+
"-s",
|
|
366
|
+
action="append",
|
|
367
|
+
dest="provisioning_target_system_types",
|
|
368
|
+
help="System type used to filter targets ('linux', 'windows')",
|
|
369
|
+
)
|
|
370
|
+
parser_provisioning_ansible.add_argument(
|
|
371
|
+
"-o",
|
|
372
|
+
action="append",
|
|
373
|
+
dest="provisioning_target_operating_systems",
|
|
374
|
+
help="Operating system used to filter targets ('Windows 7', 'Windows 10', 'Debian', 'Ubuntu', ...)",
|
|
375
|
+
)
|
|
376
|
+
parser_provisioning_ansible.add_argument(
|
|
377
|
+
"-n",
|
|
378
|
+
action="append",
|
|
379
|
+
dest="provisioning_target_names",
|
|
380
|
+
help="Machine name used to filter targets",
|
|
381
|
+
)
|
|
382
|
+
parser_provisioning_ansible.add_argument(
|
|
383
|
+
"--host-vars",
|
|
384
|
+
action="append",
|
|
385
|
+
required=False,
|
|
386
|
+
dest="provisioning_host_vars",
|
|
387
|
+
help="Host vars given as a dictionary",
|
|
388
|
+
)
|
|
389
|
+
parser_provisioning_ansible.add_argument(
|
|
390
|
+
"-e",
|
|
391
|
+
"--extra-vars",
|
|
392
|
+
action="store",
|
|
393
|
+
dest="provisioning_extra_vars",
|
|
394
|
+
help="Variables for the ansible playbook(s)",
|
|
395
|
+
)
|
|
396
|
+
parser_provisioning_ansible.add_argument(
|
|
397
|
+
"--no-wait",
|
|
398
|
+
action="store_true",
|
|
399
|
+
default=False,
|
|
400
|
+
dest="provisioning_nowait",
|
|
401
|
+
help="Don't wait for the task to be done",
|
|
402
|
+
)
|
|
403
|
+
parser_provisioning_ansible.add_argument(
|
|
404
|
+
"--force-gather-facts",
|
|
405
|
+
action="store_true",
|
|
406
|
+
default=None,
|
|
407
|
+
dest="provisioning_gather_facts_override",
|
|
408
|
+
help="Force 'gather_facts' to 'yes' in the ansible playbook, regardless of its default value and its value in the playbook.",
|
|
409
|
+
)
|
|
410
|
+
parser_provisioning_ansible.add_argument(
|
|
411
|
+
"--force-no-gather-facts",
|
|
412
|
+
action="store_false",
|
|
413
|
+
default=None,
|
|
414
|
+
dest="provisioning_gather_facts_override",
|
|
415
|
+
help="Force 'gather_facts' to 'no' in the ansible playbook, regardless of its default value and its value in the playbook.",
|
|
416
|
+
)
|
|
417
|
+
parser_provisioning_ansible.add_argument(
|
|
418
|
+
"--timeout",
|
|
419
|
+
action="store",
|
|
420
|
+
type=int,
|
|
421
|
+
required=False,
|
|
422
|
+
default=3600,
|
|
423
|
+
dest="timeout",
|
|
424
|
+
help="Timeout of the provisioning task (default to 3600 seconds - 1 hour)",
|
|
425
|
+
)
|
|
426
|
+
parser_provisioning_ansible.add_argument(
|
|
427
|
+
"--ansible-verbosity",
|
|
428
|
+
"-v",
|
|
429
|
+
action="store",
|
|
430
|
+
type=int,
|
|
431
|
+
required=False,
|
|
432
|
+
default=0,
|
|
433
|
+
dest="provisioning_ansible_verbosity",
|
|
434
|
+
help="Determines the verbosity of the ansible output (and the number of '-v' passed to ansible)",
|
|
435
|
+
)
|
|
436
|
+
parser_provisioning_ansible.add_argument(
|
|
437
|
+
"--stream-ansible",
|
|
438
|
+
action="store_true",
|
|
439
|
+
required=False,
|
|
440
|
+
default=False,
|
|
441
|
+
dest="provisioning_stream_ansible",
|
|
442
|
+
help="If set, will stream the ansible output during the provisioning task",
|
|
443
|
+
)
|
|
444
|
+
parser_provisioning_ansible.add_argument(
|
|
445
|
+
"--reload-provisioning-agent",
|
|
446
|
+
action="store_true",
|
|
447
|
+
required=False,
|
|
448
|
+
default=False,
|
|
449
|
+
dest="provisioning_reload_agent",
|
|
450
|
+
help="If set, will force the reloading of the provisioning agent docker container",
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
# 'stop' command
|
|
454
|
+
parser_provisioning_stop = subparsers_provisioning.add_parser(
|
|
455
|
+
"stop",
|
|
456
|
+
help="Stop a provisioning task",
|
|
457
|
+
formatter_class=root_parser.formatter_class,
|
|
458
|
+
)
|
|
459
|
+
parser_provisioning_stop.set_defaults(func=provisioning_stop_handler)
|
|
460
|
+
parser_provisioning_stop.add_argument(
|
|
461
|
+
"task_id", type=str, help="The provisioning task id"
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
# 'status' command
|
|
465
|
+
parser_provisioning_status = subparsers_provisioning.add_parser(
|
|
466
|
+
"status",
|
|
467
|
+
help="Get status of a provisioning task",
|
|
468
|
+
formatter_class=root_parser.formatter_class,
|
|
469
|
+
)
|
|
470
|
+
parser_provisioning_status.set_defaults(func=provisioning_status_handler)
|
|
471
|
+
parser_provisioning_status.add_argument(
|
|
472
|
+
"task_id", type=str, help="The provisioning task id"
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
# 'report' command
|
|
476
|
+
parser_provisioning_report = subparsers_provisioning.add_parser(
|
|
477
|
+
"report",
|
|
478
|
+
help="Print report of all active provisioning tasks",
|
|
479
|
+
formatter_class=root_parser.formatter_class,
|
|
480
|
+
)
|
|
481
|
+
parser_provisioning_report.set_defaults(func=provisioning_report_handler)
|
|
482
|
+
parser_provisioning_report.add_argument(
|
|
483
|
+
"task_id", type=str, help="The provisioning task id"
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
# 'inventory' command
|
|
487
|
+
parser_provisioning_inventory = subparsers_provisioning.add_parser(
|
|
488
|
+
"inventory",
|
|
489
|
+
help="Generate ansible inventory files from targets information",
|
|
490
|
+
formatter_class=root_parser.formatter_class,
|
|
491
|
+
)
|
|
492
|
+
parser_provisioning_inventory.set_defaults(func=provisioning_inventory_handler)
|
|
493
|
+
parser_provisioning_inventory.add_argument(
|
|
494
|
+
"--id",
|
|
495
|
+
type=int,
|
|
496
|
+
action="store",
|
|
497
|
+
required=False,
|
|
498
|
+
dest="id_simulation",
|
|
499
|
+
help="The simulation id",
|
|
500
|
+
)
|
|
501
|
+
parser_provisioning_inventory.add_argument(
|
|
502
|
+
"--machines",
|
|
503
|
+
action="store",
|
|
504
|
+
required=False,
|
|
505
|
+
dest="machines_file",
|
|
506
|
+
help="Input path of machines configuration (YAML format)",
|
|
507
|
+
)
|
|
508
|
+
parser_provisioning_inventory.add_argument(
|
|
509
|
+
"-o",
|
|
510
|
+
"--output",
|
|
511
|
+
type=str,
|
|
512
|
+
required=True,
|
|
513
|
+
dest="output_inventory_dir",
|
|
514
|
+
help="Path to the output inventory directory that will be created",
|
|
515
|
+
)
|
cr_api_client/config.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2016-2021 AMOSSYS
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
# furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
# copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
# SOFTWARE.
|
|
23
|
+
#
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
from omegaconf import OmegaConf
|
|
29
|
+
from omegaconf import SI
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class CrApiClientConfig:
|
|
34
|
+
_api_host: str = "${oc.env:API_HOST,localhost}"
|
|
35
|
+
core_api_url: str = "${oc.env:CORE_API_URL,http://${._api_host}:5000}"
|
|
36
|
+
user_activity_api_url: str = (
|
|
37
|
+
"${oc.env:USER_ACTIVITY_API_URL,http://${._api_host}:5002}"
|
|
38
|
+
)
|
|
39
|
+
provisioning_api_url: str = (
|
|
40
|
+
"${oc.env:PROVISIONING_API_URL,http://${._api_host}:5003}"
|
|
41
|
+
)
|
|
42
|
+
redteam_api_url: str = "${oc.env:REDTEAM_API_URL,http://${._api_host}:5004}"
|
|
43
|
+
cacert: Optional[Path] = SI("${oc.env:CR_CA_CERT,null}")
|
|
44
|
+
cert: Optional[Path] = SI("${oc.env:CR_CLIENT_CERT,null}")
|
|
45
|
+
key: Optional[Path] = SI("${oc.env:CR_CLIENT_KEY,null}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
cr_api_client_config = OmegaConf.structured(CrApiClientConfig)
|