-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcloudrange.py
More file actions
executable file
·88 lines (70 loc) · 2.32 KB
/
Copy pathcloudrange.py
File metadata and controls
executable file
·88 lines (70 loc) · 2.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/env python3
"""Interactive entrypoint for operating a Cloud Attack Range."""
from __future__ import annotations
from pathlib import Path
import sys
REPOSITORY_ROOT = Path(__file__).resolve().parent
TOOLS_ROOT = REPOSITORY_ROOT / "tools"
ACTION_FLAGS = {
"--setup": "setup",
"--preflight": "preflight",
"--install-deps": "install-deps",
"--deployments": "deployments",
"--list": "list",
"--show": "show",
"--doctor": "doctor",
"--plan": "plan",
"--deploy": "deploy",
"--status": "status",
"--extend": "extend",
"--teardown": "teardown",
"--verify-clean": "verify-clean",
}
HELP_TEXT = """\
Cloud Attack Range
Run the interactive setup:
python3 cloudrange.py --setup
Inspect this workstation:
python3 cloudrange.py --preflight --provider aws
python3 cloudrange.py --install-deps --provider aws
Operate a range:
python3 cloudrange.py --deployments
python3 cloudrange.py --doctor RANGE_ID
python3 cloudrange.py --plan RANGE_ID
python3 cloudrange.py --deploy RANGE_ID
python3 cloudrange.py --status RANGE_ID
python3 cloudrange.py --extend RANGE_ID --days 7
python3 cloudrange.py --teardown RANGE_ID
python3 cloudrange.py --verify-clean RANGE_ID
Inspect attack routes:
python3 cloudrange.py --list
python3 cloudrange.py --show BAR-026
Use an action with --help for its options, for example:
python3 cloudrange.py --plan --help
On native Windows, replace "python3" with "py -3".
"""
def translated_arguments(arguments: list[str]) -> list[str]:
if not arguments or arguments == ["--help"] or arguments == ["-h"]:
return []
action = ACTION_FLAGS.get(arguments[0])
if action is None:
choices = ", ".join(ACTION_FLAGS)
raise RuntimeError(
f"Unknown action {arguments[0]!r}. Choose one of: {choices}"
)
return [action, *arguments[1:]]
def main() -> int:
arguments = translated_arguments(sys.argv[1:])
if not arguments:
sys.stdout.write(HELP_TEXT)
return 0
sys.path.insert(0, str(TOOLS_ROOT))
import rangectl
sys.argv = [sys.argv[0], *arguments]
return rangectl.main()
if __name__ == "__main__":
try:
raise SystemExit(main())
except (EOFError, OSError, RuntimeError) as error:
sys.stderr.write(f"Error: {error}\n")
raise SystemExit(1) from error