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.
@@ -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
+ )
@@ -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)