pyntcli 0.1.71__py3-none-any.whl → 0.1.73__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.
- pyntcli/__init__.py +1 -1
- pyntcli/commands/burp.py +311 -0
- pyntcli/commands/command.py +154 -63
- pyntcli/commands/har.py +62 -25
- pyntcli/commands/listen.py +140 -71
- pyntcli/commands/newman.py +81 -33
- pyntcli/commands/postman.py +1 -1
- pyntcli/commands/pynt_cmd.py +2 -1
- pyntcli/commands/root.py +44 -23
- pyntcli/main.py +28 -20
- pyntcli/transport/pynt_requests.py +21 -9
- pyntcli/ui/ui_thread.py +4 -0
- {pyntcli-0.1.71.dist-info → pyntcli-0.1.73.dist-info}/METADATA +2 -1
- {pyntcli-0.1.71.dist-info → pyntcli-0.1.73.dist-info}/RECORD +17 -16
- {pyntcli-0.1.71.dist-info → pyntcli-0.1.73.dist-info}/WHEEL +1 -1
- {pyntcli-0.1.71.dist-info → pyntcli-0.1.73.dist-info}/entry_points.txt +0 -0
- {pyntcli-0.1.71.dist-info → pyntcli-0.1.73.dist-info}/top_level.txt +0 -0
pyntcli/commands/har.py
CHANGED
|
@@ -9,17 +9,28 @@ from pyntcli.ui.progress import PyntProgress
|
|
|
9
9
|
from pyntcli.commands import sub_command, util
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
def har_usage():
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
return (
|
|
14
|
+
ui_thread.PrinterText("Integration with static har file testing")
|
|
15
|
+
.with_line("")
|
|
16
|
+
.with_line("Usage:", style=ui_thread.PrinterText.HEADER)
|
|
17
|
+
.with_line("\tpynt har [OPTIONS]")
|
|
18
|
+
.with_line("")
|
|
19
|
+
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
20
|
+
.with_line("\t--har - Path to har file")
|
|
21
|
+
.with_line(
|
|
22
|
+
'\t--captured-domains - Pynt will scan only these domains and subdomains. For all domains write "*"'
|
|
23
|
+
)
|
|
24
|
+
.with_line("\t--reporters - Output results to json")
|
|
25
|
+
.with_line(
|
|
26
|
+
"\t--application-id - Attach the scan to an application, you can find the ID in your applications area at app.pynt.io"
|
|
27
|
+
)
|
|
28
|
+
.with_line(
|
|
29
|
+
"\t--host-ca - Path to the CA file in PEM format to enable SSL certificate verification for pynt when running through a VPN."
|
|
30
|
+
)
|
|
31
|
+
.with_line("")
|
|
32
|
+
)
|
|
33
|
+
|
|
23
34
|
|
|
24
35
|
class HarSubCommand(sub_command.PyntSubCommand):
|
|
25
36
|
def __init__(self, name) -> None:
|
|
@@ -31,37 +42,63 @@ class HarSubCommand(sub_command.PyntSubCommand):
|
|
|
31
42
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
32
43
|
har_cmd = parent.add_parser(self.name)
|
|
33
44
|
har_cmd.add_argument("--har", type=str, required=True)
|
|
34
|
-
har_cmd.add_argument(
|
|
45
|
+
har_cmd.add_argument(
|
|
46
|
+
"--captured-domains", nargs="+", help="", default="", required=True
|
|
47
|
+
)
|
|
48
|
+
har_cmd.add_argument("--reporters", action="store_true")
|
|
35
49
|
har_cmd.print_usage = self.usage
|
|
36
50
|
har_cmd.print_help = self.usage
|
|
37
51
|
return har_cmd
|
|
38
|
-
|
|
52
|
+
|
|
39
53
|
def run_cmd(self, args: argparse.Namespace):
|
|
40
54
|
port = str(util.find_open_port())
|
|
41
|
-
container = pynt_container.get_container_with_arguments(
|
|
55
|
+
container = pynt_container.get_container_with_arguments(
|
|
56
|
+
args, pynt_container.PyntDockerPort(src=port, dest=port, name="--port")
|
|
57
|
+
)
|
|
42
58
|
|
|
43
|
-
if not os.path.isfile(args.har):
|
|
44
|
-
ui_thread.print(
|
|
59
|
+
if not os.path.isfile(args.har):
|
|
60
|
+
ui_thread.print(
|
|
61
|
+
ui_thread.PrinterText(
|
|
62
|
+
"Could not find the provided har path, please provide with a valid har path",
|
|
63
|
+
ui_thread.PrinterText.WARNING,
|
|
64
|
+
)
|
|
65
|
+
)
|
|
45
66
|
return
|
|
46
67
|
|
|
47
68
|
har_name = os.path.basename(args.har)
|
|
48
69
|
container.docker_arguments += ["--har", har_name]
|
|
49
|
-
container.mounts.append(
|
|
70
|
+
container.mounts.append(
|
|
71
|
+
pynt_container.create_mount(
|
|
72
|
+
os.path.abspath(args.har), "/etc/pynt/{}".format(har_name)
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
for host in args.captured_domains:
|
|
77
|
+
container.docker_arguments += ["--host-targets", host]
|
|
50
78
|
|
|
51
79
|
with util.create_default_file_mounts(args) as m:
|
|
52
80
|
|
|
53
81
|
container.mounts += m
|
|
54
|
-
|
|
55
|
-
har_docker = pynt_container.PyntContainer(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
82
|
+
|
|
83
|
+
har_docker = pynt_container.PyntContainer(
|
|
84
|
+
image_name=pynt_container.PYNT_DOCKER_IMAGE,
|
|
85
|
+
tag="har-latest",
|
|
86
|
+
detach=True,
|
|
87
|
+
base_container=container,
|
|
88
|
+
)
|
|
59
89
|
|
|
60
90
|
har_docker.run()
|
|
61
91
|
|
|
62
|
-
healthcheck = partial(
|
|
92
|
+
healthcheck = partial(
|
|
93
|
+
util.wait_for_healthcheck, "http://localhost:{}".format(port)
|
|
94
|
+
)
|
|
63
95
|
ui_thread.print_generator(ui_thread.AnsiText.wrap_gen(har_docker.stdout))
|
|
64
|
-
|
|
65
|
-
with ui_thread.progress(
|
|
96
|
+
|
|
97
|
+
with ui_thread.progress(
|
|
98
|
+
"ws://localhost:{}/progress".format(port),
|
|
99
|
+
healthcheck,
|
|
100
|
+
"scan in progress...",
|
|
101
|
+
100,
|
|
102
|
+
):
|
|
66
103
|
while har_docker.is_alive():
|
|
67
|
-
time.sleep(1)
|
|
104
|
+
time.sleep(1)
|
pyntcli/commands/listen.py
CHANGED
|
@@ -16,128 +16,198 @@ from pyntcli.ui import report as cli_reporter
|
|
|
16
16
|
from pyntcli.transport import pynt_requests
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
def listen_usage():
|
|
21
|
-
return
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.with_line("")
|
|
26
|
-
.with_line("
|
|
27
|
-
.with_line("\
|
|
28
|
-
.with_line("
|
|
29
|
-
.with_line("
|
|
30
|
-
.with_line(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.with_line("\t--
|
|
34
|
-
.with_line("\t--
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
20
|
+
return (
|
|
21
|
+
ui_thread.PrinterText(
|
|
22
|
+
"Listen integration to Pynt. Run a security scan with routed traffic."
|
|
23
|
+
)
|
|
24
|
+
.with_line("")
|
|
25
|
+
.with_line("Usage:", style=ui_thread.PrinterText.HEADER)
|
|
26
|
+
.with_line("\tpynt listen [OPTIONS]")
|
|
27
|
+
.with_line("")
|
|
28
|
+
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
29
|
+
.with_line(
|
|
30
|
+
'\t--captured-domains - Pynt will scan only these domains and subdomains. For all domains write "*"'
|
|
31
|
+
)
|
|
32
|
+
.with_line("\t--port - Set the port pynt will listen to (DEFAULT: 5001)")
|
|
33
|
+
.with_line("\t--ca-path - The path to the CA file in PEM format")
|
|
34
|
+
.with_line(
|
|
35
|
+
"\t--proxy-port - Set the port proxied traffic should be routed to (DEFAULT: 6666)"
|
|
36
|
+
)
|
|
37
|
+
.with_line(
|
|
38
|
+
"\t--report - If present will save the generated report in this path."
|
|
39
|
+
)
|
|
40
|
+
.with_line(
|
|
41
|
+
"\t--application-id - Attach the scan to an application, you can find the ID in your applications area at app.pynt.io"
|
|
42
|
+
)
|
|
43
|
+
.with_line("\t--insecure - use when target uses self signed certificates")
|
|
44
|
+
.with_line(
|
|
45
|
+
"\t--host-ca - path to the CA file in PEM format to enable SSL certificate verification for pynt when running through a VPN."
|
|
46
|
+
)
|
|
47
|
+
.with_line(
|
|
48
|
+
"\t--return-error - 'all-findings' (warnings, or errors), 'errors-only', 'never' (default), "
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ListenSubCommand(sub_command.PyntSubCommand):
|
|
38
54
|
def __init__(self, name) -> None:
|
|
39
55
|
super().__init__(name)
|
|
40
56
|
self.scan_id = ""
|
|
41
57
|
self.proxy_sleep_interval = 2
|
|
42
58
|
self.proxy_healthcheck_buffer = 10
|
|
43
59
|
self.proxy_server_base_url = "http://localhost:{}/api"
|
|
44
|
-
|
|
60
|
+
|
|
45
61
|
def print_usage(self, *args):
|
|
46
62
|
ui_thread.print(listen_usage())
|
|
47
63
|
|
|
48
64
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
49
65
|
listen_cmd = parent.add_parser(self.name)
|
|
50
66
|
listen_cmd.add_argument("--port", "-p", help="", type=int, default=5001)
|
|
51
|
-
listen_cmd.add_argument("--proxy-port", help="", type=int, default=6666)
|
|
52
|
-
listen_cmd.add_argument(
|
|
67
|
+
listen_cmd.add_argument("--proxy-port", help="", type=int, default=6666)
|
|
68
|
+
listen_cmd.add_argument(
|
|
69
|
+
"--captured-domains", nargs="+", help="", default="", required=True
|
|
70
|
+
)
|
|
53
71
|
listen_cmd.add_argument("--allow-errors", action="store_true")
|
|
54
72
|
listen_cmd.add_argument("--ca-path", type=str, default="")
|
|
55
73
|
listen_cmd.add_argument("--report", type=str, default="")
|
|
56
|
-
listen_cmd.add_argument(
|
|
74
|
+
listen_cmd.add_argument(
|
|
75
|
+
"--return-error",
|
|
76
|
+
choices=["all-findings", "errors-only", "never"],
|
|
77
|
+
default="never",
|
|
78
|
+
)
|
|
57
79
|
listen_cmd.print_usage = self.print_usage
|
|
58
80
|
listen_cmd.print_help = self.print_usage
|
|
59
81
|
return listen_cmd
|
|
60
|
-
|
|
82
|
+
|
|
61
83
|
def _start_proxy(self, args):
|
|
62
|
-
res = pynt_requests.put(
|
|
84
|
+
res = pynt_requests.put(
|
|
85
|
+
self.proxy_server_base_url.format(args.port) + "/proxy/start"
|
|
86
|
+
)
|
|
63
87
|
res.raise_for_status()
|
|
64
88
|
self.scan_id = res.json()["scanId"]
|
|
65
|
-
|
|
89
|
+
|
|
66
90
|
def _stop_proxy(self, args):
|
|
67
91
|
start = time.time()
|
|
68
|
-
while start + self.proxy_healthcheck_buffer > time.time():
|
|
69
|
-
res = pynt_requests.put(
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
while start + self.proxy_healthcheck_buffer > time.time():
|
|
93
|
+
res = pynt_requests.put(
|
|
94
|
+
self.proxy_server_base_url.format(args.port) + "/proxy/stop",
|
|
95
|
+
json={"scanId": self.scan_id},
|
|
96
|
+
)
|
|
97
|
+
if res.status_code == HTTPStatus.OK:
|
|
98
|
+
return
|
|
72
99
|
time.sleep(self.proxy_sleep_interval)
|
|
73
100
|
raise TimeoutError()
|
|
74
|
-
|
|
75
|
-
def _get_report(self, args,report_format):
|
|
76
|
-
while True:
|
|
77
|
-
res = pynt_requests.get(
|
|
101
|
+
|
|
102
|
+
def _get_report(self, args, report_format):
|
|
103
|
+
while True:
|
|
104
|
+
res = pynt_requests.get(
|
|
105
|
+
self.proxy_server_base_url.format(args.port)
|
|
106
|
+
+ "/report?format={}".format(report_format),
|
|
107
|
+
params={"scanId": self.scan_id},
|
|
108
|
+
)
|
|
78
109
|
if res.status_code == HTTPStatus.OK:
|
|
79
110
|
return res.text
|
|
80
111
|
if res.status_code == HTTPStatus.ACCEPTED:
|
|
81
112
|
time.sleep(self.proxy_sleep_interval)
|
|
82
113
|
continue
|
|
83
|
-
if res.status_code == 517:
|
|
84
|
-
ui_thread.print(
|
|
85
|
-
|
|
114
|
+
if res.status_code == 517: # pynt did not recieve any requests
|
|
115
|
+
ui_thread.print(
|
|
116
|
+
ui_thread.PrinterText(
|
|
117
|
+
res.json()["message"], ui_thread.PrinterText.WARNING
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
return
|
|
86
121
|
ui_thread.print("Error in polling for scan report: {}".format(res.text))
|
|
87
|
-
return
|
|
122
|
+
return
|
|
88
123
|
|
|
89
|
-
|
|
90
124
|
def run_cmd(self, args: argparse.Namespace):
|
|
91
|
-
container = pynt_container.get_container_with_arguments(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
125
|
+
container = pynt_container.get_container_with_arguments(
|
|
126
|
+
args,
|
|
127
|
+
pynt_container.PyntDockerPort(args.port, args.port, "--port"),
|
|
128
|
+
pynt_container.PyntDockerPort(
|
|
129
|
+
args.proxy_port, args.proxy_port, "--proxy-port"
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
for host in args.captured_domains:
|
|
134
|
+
container.docker_arguments += ["--host-targets", host]
|
|
99
135
|
|
|
100
136
|
if "ca_path" in args and args.ca_path:
|
|
101
137
|
if not os.path.isfile(args.ca_path):
|
|
102
|
-
ui_thread.print(
|
|
138
|
+
ui_thread.print(
|
|
139
|
+
ui_thread.PrinterText(
|
|
140
|
+
"Could not find the provided ca path, please provide with a valid path",
|
|
141
|
+
ui_thread.PrinterText.WARNING,
|
|
142
|
+
)
|
|
143
|
+
)
|
|
103
144
|
return
|
|
104
145
|
|
|
105
146
|
ca_name = os.path.basename(args.ca_path)
|
|
106
147
|
container.docker_arguments += ["--ca-path", ca_name]
|
|
107
|
-
container.mounts.append(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
148
|
+
container.mounts.append(
|
|
149
|
+
pynt_container.create_mount(
|
|
150
|
+
os.path.abspath(args.ca_path), "/etc/pynt/{}".format(ca_name)
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
proxy_docker = pynt_container.PyntContainer(
|
|
155
|
+
image_name=pynt_container.PYNT_DOCKER_IMAGE,
|
|
156
|
+
tag="proxy-latest",
|
|
157
|
+
detach=True,
|
|
158
|
+
base_container=container,
|
|
159
|
+
)
|
|
113
160
|
proxy_docker.run()
|
|
114
161
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
115
|
-
|
|
162
|
+
|
|
116
163
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
117
|
-
|
|
164
|
+
|
|
118
165
|
self._start_proxy(args)
|
|
119
166
|
|
|
120
|
-
ui_thread.print(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
167
|
+
ui_thread.print(
|
|
168
|
+
ui_thread.PrinterText(
|
|
169
|
+
"\nListening to traffic on port: {}".format(args.proxy_port),
|
|
170
|
+
ui_thread.PrinterText.DEFAULT,
|
|
171
|
+
)
|
|
172
|
+
.with_line(
|
|
173
|
+
"Will scan APIs that belong to '{}' domains only".format(
|
|
174
|
+
args.captured_domains
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
.with_line("")
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
ui_thread.print(
|
|
181
|
+
ui_thread.PrinterText(
|
|
182
|
+
"Press Enter to stop recording traffic and run security scan...",
|
|
183
|
+
ui_thread.PrinterText.HEADER,
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
|
|
126
187
|
input()
|
|
127
|
-
|
|
188
|
+
|
|
128
189
|
self._stop_proxy(args)
|
|
129
|
-
|
|
130
|
-
with ui_thread.progress("ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),partial(lambda *args: None), "scan in progress...", 100):
|
|
131
|
-
html_report = self._get_report(args,"html")
|
|
132
|
-
html_report_path = os.path.join(tempfile.gettempdir(), "pynt_report_{}.html".format(int(time.time())))
|
|
133
190
|
|
|
134
|
-
|
|
135
|
-
|
|
191
|
+
with ui_thread.progress(
|
|
192
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
193
|
+
partial(lambda *args: None),
|
|
194
|
+
"scan in progress...",
|
|
195
|
+
100,
|
|
196
|
+
):
|
|
197
|
+
html_report = self._get_report(args, "html")
|
|
198
|
+
html_report_path = os.path.join(
|
|
199
|
+
tempfile.gettempdir(), "pynt_report_{}.html".format(int(time.time()))
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
json_report = self._get_report(args, "json")
|
|
203
|
+
json_report_path = os.path.join(
|
|
204
|
+
tempfile.gettempdir(), "pynt_report_{}.json".format(int(time.time()))
|
|
205
|
+
)
|
|
136
206
|
|
|
137
207
|
if "report" in args and args.report:
|
|
138
208
|
full_path = os.path.abspath(args.report)
|
|
139
|
-
html_report_path = util.get_user_report_path(full_path,"html")
|
|
140
|
-
json_report_path = util.get_user_report_path(full_path,"json")
|
|
209
|
+
html_report_path = util.get_user_report_path(full_path, "html")
|
|
210
|
+
json_report_path = util.get_user_report_path(full_path, "json")
|
|
141
211
|
|
|
142
212
|
if html_report:
|
|
143
213
|
with open(html_report_path, "w") as html_file:
|
|
@@ -154,4 +224,3 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
154
224
|
json_obj = json.loads(json_report)
|
|
155
225
|
if json_obj:
|
|
156
226
|
util.check_for_findings_or_warnings(args, json_obj)
|
|
157
|
-
|
pyntcli/commands/newman.py
CHANGED
|
@@ -8,32 +8,51 @@ from pyntcli.commands import sub_command, util
|
|
|
8
8
|
from pyntcli.ui import ui_thread
|
|
9
9
|
from pyntcli.ui.progress import PyntProgress
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
def newman_usage():
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
return (
|
|
14
|
+
ui_thread.PrinterText(
|
|
15
|
+
"Integration with newman, run scan using postman collection from the CLI"
|
|
16
|
+
)
|
|
17
|
+
.with_line("")
|
|
18
|
+
.with_line("Usage:", style=ui_thread.PrinterText.HEADER)
|
|
19
|
+
.with_line("\tpynt newman [OPTIONS]")
|
|
20
|
+
.with_line("")
|
|
21
|
+
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
22
|
+
.with_line("\t--collection - Postman collection file name")
|
|
23
|
+
.with_line("\t--environment - Postman environment file name")
|
|
24
|
+
.with_line("\t--reporters Output results to json")
|
|
25
|
+
.with_line(
|
|
26
|
+
"\t--host-ca - Path to the CA file in PEM format to enable SSL certificate verification for pynt when running through a VPN."
|
|
27
|
+
)
|
|
28
|
+
.with_line(
|
|
29
|
+
"\t--application-id - Attach the scan to an application, you can find the ID in your applications area at app.pynt.io"
|
|
30
|
+
)
|
|
31
|
+
.with_line(
|
|
32
|
+
"\t--return-error - 'all-findings' (warnings, or errors), 'errors-only', 'never' (default), "
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
23
36
|
|
|
24
37
|
class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
25
38
|
def __init__(self, name) -> None:
|
|
26
39
|
super().__init__(name)
|
|
27
40
|
|
|
28
|
-
def usage(self, *args):
|
|
41
|
+
def usage(self, *args):
|
|
29
42
|
ui_thread.print(newman_usage())
|
|
30
43
|
|
|
31
44
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
32
45
|
newman_cmd = parent.add_parser(self.name)
|
|
33
|
-
newman_cmd.add_argument("--collection", type=str, required=True)
|
|
34
|
-
newman_cmd.add_argument("--environment", nargs=
|
|
35
|
-
newman_cmd.add_argument(
|
|
36
|
-
|
|
46
|
+
newman_cmd.add_argument("--collection", type=str, required=True)
|
|
47
|
+
newman_cmd.add_argument("--environment", nargs="+", required=False)
|
|
48
|
+
newman_cmd.add_argument(
|
|
49
|
+
"--reporters", action="store_true", default=False, required=False
|
|
50
|
+
)
|
|
51
|
+
newman_cmd.add_argument(
|
|
52
|
+
"--return-error",
|
|
53
|
+
choices=["all-findings", "errors-only", "never"],
|
|
54
|
+
default="never",
|
|
55
|
+
)
|
|
37
56
|
|
|
38
57
|
newman_cmd.print_usage = self.usage
|
|
39
58
|
newman_cmd.print_help = self.usage
|
|
@@ -41,38 +60,67 @@ class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
|
41
60
|
|
|
42
61
|
def run_cmd(self, args: argparse.Namespace):
|
|
43
62
|
port = str(util.find_open_port())
|
|
44
|
-
container = pynt_container.get_container_with_arguments(
|
|
63
|
+
container = pynt_container.get_container_with_arguments(
|
|
64
|
+
args, pynt_container.PyntDockerPort(src=port, dest=port, name="--port")
|
|
65
|
+
)
|
|
45
66
|
|
|
46
|
-
if not os.path.isfile(args.collection):
|
|
47
|
-
ui_thread.print(
|
|
67
|
+
if not os.path.isfile(args.collection):
|
|
68
|
+
ui_thread.print(
|
|
69
|
+
ui_thread.PrinterText(
|
|
70
|
+
"Could not find the provided collection path, please provide with a valid collection path",
|
|
71
|
+
ui_thread.PrinterText.WARNING,
|
|
72
|
+
)
|
|
73
|
+
)
|
|
48
74
|
return
|
|
49
|
-
|
|
75
|
+
|
|
50
76
|
collection_name = os.path.basename(args.collection)
|
|
51
77
|
container.docker_arguments += ["-c", collection_name]
|
|
52
|
-
container.mounts.append(
|
|
53
|
-
|
|
78
|
+
container.mounts.append(
|
|
79
|
+
pynt_container.create_mount(
|
|
80
|
+
os.path.abspath(args.collection), "/etc/pynt/{}".format(collection_name)
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
54
84
|
if "environment" in args and args.environment:
|
|
55
85
|
env_names = []
|
|
56
86
|
for environ in args.environment:
|
|
57
87
|
if not os.path.isfile(environ):
|
|
58
|
-
ui_thread.print(
|
|
88
|
+
ui_thread.print(
|
|
89
|
+
ui_thread.PrinterText(
|
|
90
|
+
f"Could not find the provided environment path: {environ}, please provide with a valid environment path",
|
|
91
|
+
ui_thread.PrinterText.WARNING,
|
|
92
|
+
)
|
|
93
|
+
)
|
|
59
94
|
return
|
|
60
95
|
env_name = os.path.basename(environ)
|
|
61
96
|
env_names.append(env_name)
|
|
62
|
-
container.mounts.append(
|
|
97
|
+
container.mounts.append(
|
|
98
|
+
pynt_container.create_mount(
|
|
99
|
+
os.path.abspath(environ), "/etc/pynt/{}".format(env_name)
|
|
100
|
+
)
|
|
101
|
+
)
|
|
63
102
|
container.docker_arguments += ["-e", ",".join(env_names)]
|
|
64
|
-
|
|
103
|
+
|
|
65
104
|
with util.create_default_file_mounts(args) as m:
|
|
66
105
|
container.mounts += m
|
|
67
|
-
newman_docker = pynt_container.PyntContainer(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
106
|
+
newman_docker = pynt_container.PyntContainer(
|
|
107
|
+
image_name=pynt_container.PYNT_DOCKER_IMAGE,
|
|
108
|
+
tag="latest",
|
|
109
|
+
detach=True,
|
|
110
|
+
base_container=container,
|
|
111
|
+
)
|
|
71
112
|
newman_docker.run()
|
|
72
|
-
|
|
73
|
-
healthcheck = partial(
|
|
113
|
+
|
|
114
|
+
healthcheck = partial(
|
|
115
|
+
util.wait_for_healthcheck, "http://localhost:{}".format(port)
|
|
116
|
+
)
|
|
74
117
|
ui_thread.print_generator(ui_thread.AnsiText.wrap_gen(newman_docker.stdout))
|
|
75
|
-
|
|
76
|
-
with ui_thread.progress(
|
|
118
|
+
|
|
119
|
+
with ui_thread.progress(
|
|
120
|
+
"ws://localhost:{}/progress".format(port),
|
|
121
|
+
healthcheck,
|
|
122
|
+
"scan in progress...",
|
|
123
|
+
100,
|
|
124
|
+
):
|
|
77
125
|
while newman_docker.is_alive():
|
|
78
126
|
time.sleep(1)
|
pyntcli/commands/postman.py
CHANGED
|
@@ -112,7 +112,7 @@ class PostmanSubCommand(sub_command.PyntSubCommand):
|
|
|
112
112
|
html_report_path = os.path.join(tempfile.gettempdir(), "pynt_report_{}.html".format(int(time.time())))
|
|
113
113
|
|
|
114
114
|
if html_report:
|
|
115
|
-
with open(html_report_path, "w") as html_file:
|
|
115
|
+
with open(html_report_path, "w", encoding="utf-8") as html_file:
|
|
116
116
|
html_file.write(html_report)
|
|
117
117
|
webbrowser.open("file://{}".format(html_report_path))
|
|
118
118
|
|
pyntcli/commands/pynt_cmd.py
CHANGED
|
@@ -5,7 +5,7 @@ from pyntcli.analytics import send as analytics
|
|
|
5
5
|
from pyntcli.transport import pynt_requests
|
|
6
6
|
from pyntcli.ui import ui_thread
|
|
7
7
|
|
|
8
|
-
from . import command, listen, postman, root, sub_command, id_command, newman, har
|
|
8
|
+
from . import command, listen, postman, root, sub_command, id_command, newman, har, burp
|
|
9
9
|
|
|
10
10
|
avail_sub_commands = [
|
|
11
11
|
postman.PostmanSubCommand("postman"),
|
|
@@ -14,6 +14,7 @@ avail_sub_commands = [
|
|
|
14
14
|
har.HarSubCommand("har"),
|
|
15
15
|
command.CommandSubCommand("command"),
|
|
16
16
|
listen.ListenSubCommand("listen"),
|
|
17
|
+
burp.BurpCommand("burp"),
|
|
17
18
|
]
|
|
18
19
|
|
|
19
20
|
class PyntCommandException(Exception):
|