pyntcli 0.1.108__py3-none-any.whl → 0.1.109__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 +61 -14
- pyntcli/commands/command.py +2 -2
- pyntcli/commands/listen.py +2 -2
- pyntcli/commands/newman.py +2 -3
- pyntcli/commands/pynt_cmd.py +5 -6
- pyntcli/commands/template.py +182 -0
- pyntcli/pynt_docker/pynt_container.py +2 -1
- {pyntcli-0.1.108.dist-info → pyntcli-0.1.109.dist-info}/METADATA +1 -1
- {pyntcli-0.1.108.dist-info → pyntcli-0.1.109.dist-info}/RECORD +13 -12
- {pyntcli-0.1.108.dist-info → pyntcli-0.1.109.dist-info}/WHEEL +0 -0
- {pyntcli-0.1.108.dist-info → pyntcli-0.1.109.dist-info}/entry_points.txt +0 -0
- {pyntcli-0.1.108.dist-info → pyntcli-0.1.109.dist-info}/top_level.txt +0 -0
pyntcli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.109"
|
pyntcli/commands/burp.py
CHANGED
|
@@ -10,6 +10,9 @@ from subprocess import Popen, PIPE
|
|
|
10
10
|
from functools import partial
|
|
11
11
|
import xmltodict
|
|
12
12
|
import base64
|
|
13
|
+
|
|
14
|
+
from pyntcli.store import store
|
|
15
|
+
|
|
13
16
|
import pyntcli.log.log as log
|
|
14
17
|
from xml.parsers.expat import ExpatError
|
|
15
18
|
|
|
@@ -19,7 +22,6 @@ from pyntcli.commands import util, sub_command
|
|
|
19
22
|
from pyntcli.ui import report as cli_reporter
|
|
20
23
|
from pyntcli.transport import pynt_requests
|
|
21
24
|
|
|
22
|
-
|
|
23
25
|
methods = [
|
|
24
26
|
"get",
|
|
25
27
|
"post",
|
|
@@ -138,9 +140,8 @@ def burp_usage():
|
|
|
138
140
|
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
139
141
|
.with_line("\t--xml - Path to the xml to run tests on")
|
|
140
142
|
.with_line('\t--captured-domains - Pynt will scan only these domains and subdomains. For all domains write "*"')
|
|
141
|
-
.with_line("\t--port - Set the port pynt will listen to (DEFAULT:
|
|
143
|
+
.with_line("\t--port - Set the port pynt will listen to (DEFAULT: random)")
|
|
142
144
|
.with_line("\t--ca-path - The path to the CA file in PEM format")
|
|
143
|
-
.with_line("\t--proxy-port - Set the port proxied traffic should be routed to (DEFAULT: 6666)")
|
|
144
145
|
.with_line("\t--report - If present will save the generated report in this path.")
|
|
145
146
|
.with_line("\t--insecure - Use when target uses self signed certificates")
|
|
146
147
|
.with_line("\t--application-id - Attach the scan to an application, you can find the ID in your applications area at app.pynt.io")
|
|
@@ -163,23 +164,23 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
163
164
|
|
|
164
165
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
165
166
|
burp_cmd = parent.add_parser(self.name)
|
|
166
|
-
burp_cmd.add_argument("--port", "-p", help="", type=int, default=
|
|
167
|
-
burp_cmd.add_argument("--proxy-port", help="", type=int, default=6666)
|
|
167
|
+
burp_cmd.add_argument("--port", "-p", help="", type=int, default=util.find_open_port())
|
|
168
168
|
burp_cmd.add_argument("--xml", help="", default="", required=True)
|
|
169
169
|
burp_cmd.add_argument("--ca-path", type=str, default="")
|
|
170
170
|
burp_cmd.add_argument("--report", type=str, default="")
|
|
171
|
+
burp_cmd.add_argument("--save-collection", action="store_true", help="Get postman collection")
|
|
171
172
|
burp_cmd.add_argument("--captured-domains", nargs="+", help="", default="")
|
|
172
173
|
burp_cmd.add_argument("--severity-level", choices=["all", "medium", "high", "critical", "none"], default="none")
|
|
173
174
|
burp_cmd.print_usage = self.print_usage
|
|
174
175
|
burp_cmd.print_help = self.print_usage
|
|
175
176
|
return burp_cmd
|
|
176
177
|
|
|
177
|
-
def _updated_environment(self,
|
|
178
|
+
def _updated_environment(self, proxy_port: int):
|
|
178
179
|
env_copy = deepcopy(os.environ)
|
|
179
180
|
return env_copy.update(
|
|
180
181
|
{
|
|
181
|
-
"HTTP_PROXY": "http://localhost:{}".format(
|
|
182
|
-
"HTTPS_PROXY": "http://localhost:{}".format(
|
|
182
|
+
"HTTP_PROXY": "http://localhost:{}".format(proxy_port),
|
|
183
|
+
"HTTPS_PROXY": "http://localhost:{}".format(proxy_port),
|
|
183
184
|
}
|
|
184
185
|
)
|
|
185
186
|
|
|
@@ -224,12 +225,43 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
224
225
|
ui_thread.print("Error in polling for scan report: {}".format(res.text))
|
|
225
226
|
return
|
|
226
227
|
|
|
228
|
+
def _get_postman_collection(self, args):
|
|
229
|
+
while True:
|
|
230
|
+
res = pynt_requests.get(
|
|
231
|
+
self.proxy_server_base_url.format(args.port)
|
|
232
|
+
+ "/collection",
|
|
233
|
+
params={"scanId": self.scan_id},
|
|
234
|
+
)
|
|
235
|
+
if res.status_code == HTTPStatus.OK:
|
|
236
|
+
return res.text
|
|
237
|
+
if res.status_code == HTTPStatus.ACCEPTED:
|
|
238
|
+
time.sleep(self.proxy_sleep_interval)
|
|
239
|
+
continue
|
|
240
|
+
if res.status_code == 517: # pynt did not recieve any requests
|
|
241
|
+
ui_thread.print(
|
|
242
|
+
ui_thread.PrinterText(
|
|
243
|
+
res.json()["message"], ui_thread.PrinterText.WARNING
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
return
|
|
247
|
+
if res.status_code == 404:
|
|
248
|
+
ui_thread.print(
|
|
249
|
+
ui_thread.PrinterText(
|
|
250
|
+
"No collection found", ui_thread.PrinterText.WARNING
|
|
251
|
+
)
|
|
252
|
+
)
|
|
253
|
+
return
|
|
254
|
+
ui_thread.print("Error in polling for scan report: {}".format(res.text))
|
|
255
|
+
return
|
|
256
|
+
|
|
227
257
|
def run_cmd(self, args: argparse.Namespace):
|
|
258
|
+
proxy_port = util.find_open_port()
|
|
259
|
+
|
|
228
260
|
container_config = pynt_container.DockerContainerConfig(
|
|
229
261
|
args,
|
|
230
262
|
"proxy",
|
|
231
263
|
pynt_container.api_port(args.port),
|
|
232
|
-
pynt_container.proxy_port(
|
|
264
|
+
pynt_container.proxy_port(proxy_port),
|
|
233
265
|
)
|
|
234
266
|
|
|
235
267
|
for host in args.captured_domains:
|
|
@@ -301,7 +333,7 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
301
333
|
|
|
302
334
|
self._start_proxy(args)
|
|
303
335
|
|
|
304
|
-
run_burp_xml(doc,
|
|
336
|
+
run_burp_xml(doc, proxy_port)
|
|
305
337
|
|
|
306
338
|
self._stop_proxy(args)
|
|
307
339
|
|
|
@@ -313,10 +345,10 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
313
345
|
)
|
|
314
346
|
|
|
315
347
|
with ui_thread.progress(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
348
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
349
|
+
partial(lambda *args: None),
|
|
350
|
+
"scan in progress...",
|
|
351
|
+
100,
|
|
320
352
|
):
|
|
321
353
|
html_report = self._get_report(args, "html")
|
|
322
354
|
html_report_path = os.path.join(
|
|
@@ -328,6 +360,11 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
328
360
|
tempfile.gettempdir(), "pynt_report_{}.json".format(int(time.time()))
|
|
329
361
|
)
|
|
330
362
|
|
|
363
|
+
collection = self._get_postman_collection(args) if args.save_collection else None
|
|
364
|
+
collection_path = os.path.join(
|
|
365
|
+
store.get_default_store_dir(), "postman_collection_{}.json".format(int(time.time()))
|
|
366
|
+
)
|
|
367
|
+
|
|
331
368
|
if "report" in args and args.report:
|
|
332
369
|
full_path = os.path.abspath(args.report)
|
|
333
370
|
html_report_path = util.get_user_report_path(full_path, "html")
|
|
@@ -344,6 +381,16 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
344
381
|
reporter = cli_reporter.PyntReporter(json_report_path)
|
|
345
382
|
reporter.print_summary()
|
|
346
383
|
|
|
384
|
+
if collection:
|
|
385
|
+
with open(collection_path, "w", encoding="utf-8") as collection_file:
|
|
386
|
+
collection_file.write(collection)
|
|
387
|
+
ui_thread.print(
|
|
388
|
+
ui_thread.PrinterText(
|
|
389
|
+
"Postman collection saved at: {}".format(collection_path),
|
|
390
|
+
ui_thread.PrinterText.INFO,
|
|
391
|
+
)
|
|
392
|
+
)
|
|
393
|
+
|
|
347
394
|
if json_report:
|
|
348
395
|
json_obj = json.loads(json_report)
|
|
349
396
|
if json_obj:
|
pyntcli/commands/command.py
CHANGED
|
@@ -29,7 +29,7 @@ def command_usage():
|
|
|
29
29
|
.with_line("\t--cmd - The command that runs the functional tests")
|
|
30
30
|
.with_line('\t--captured-domains - Pynt will scan only these domains and subdomains. For all domains write "*"')
|
|
31
31
|
.with_line('\t--test-name - A name for your Pynt scan')
|
|
32
|
-
.with_line("\t--port - Set the port pynt will listen to (DEFAULT:
|
|
32
|
+
.with_line("\t--port - Set the port pynt will listen to (DEFAULT: random)")
|
|
33
33
|
.with_line("\t--allow-errors - If present will allow command to fail and continue execution")
|
|
34
34
|
.with_line("\t--ca-path - The path to the CA file in PEM format")
|
|
35
35
|
.with_line("\t--proxy-port - Set the port proxied traffic should be routed to (DEFAULT: 6666)")
|
|
@@ -57,7 +57,7 @@ class CommandSubCommand(sub_command.PyntSubCommand):
|
|
|
57
57
|
|
|
58
58
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
59
59
|
proxy_cmd = parent.add_parser(self.name)
|
|
60
|
-
proxy_cmd.add_argument("--port", "-p", help="", type=int, default=
|
|
60
|
+
proxy_cmd.add_argument("--port", "-p", help="", type=int, default=util.find_open_port())
|
|
61
61
|
proxy_cmd.add_argument("--proxy-port", help="", type=int, default=6666)
|
|
62
62
|
proxy_cmd.add_argument("--cmd", help="", default="", required=True)
|
|
63
63
|
proxy_cmd.add_argument("--captured-domains", nargs="+", help="", default="", required=False)
|
pyntcli/commands/listen.py
CHANGED
|
@@ -26,7 +26,7 @@ def listen_usage():
|
|
|
26
26
|
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
27
27
|
.with_line('\t--captured-domains - Pynt will scan only these domains and subdomains. For all domains write "*"')
|
|
28
28
|
.with_line('\t--test-name - A name for your Pynt scan')
|
|
29
|
-
.with_line("\t--port - Set the port pynt will listen to (DEFAULT:
|
|
29
|
+
.with_line("\t--port - Set the port pynt will listen to (DEFAULT: random)")
|
|
30
30
|
.with_line("\t--ca-path - The path to the CA file in PEM format")
|
|
31
31
|
.with_line("\t--proxy-port - Set the port proxied traffic should be routed to (DEFAULT: 6666)")
|
|
32
32
|
.with_line("\t--report - If present will save the generated report in this path.")
|
|
@@ -51,7 +51,7 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
51
51
|
|
|
52
52
|
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
53
53
|
listen_cmd = parent.add_parser(self.name)
|
|
54
|
-
listen_cmd.add_argument("--port", "-p", help="", type=int, default=
|
|
54
|
+
listen_cmd.add_argument("--port", "-p", help="", type=int, default=util.find_open_port())
|
|
55
55
|
listen_cmd.add_argument("--proxy-port", help="", type=int, default=6666)
|
|
56
56
|
listen_cmd.add_argument("--captured-domains", nargs="+", help="", default="", required=True)
|
|
57
57
|
listen_cmd.add_argument("--test-name", help="", default="", required=False)
|
pyntcli/commands/newman.py
CHANGED
|
@@ -53,7 +53,6 @@ class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
|
53
53
|
return newman_cmd
|
|
54
54
|
|
|
55
55
|
def run_cmd(self, args: argparse.Namespace):
|
|
56
|
-
|
|
57
56
|
port = util.find_open_port()
|
|
58
57
|
container_config = pynt_container.DockerContainerConfig(
|
|
59
58
|
args,
|
|
@@ -115,8 +114,8 @@ class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
|
115
114
|
ui_thread.print(ui_thread.PrinterText(
|
|
116
115
|
"Pynt docker is ready",
|
|
117
116
|
ui_thread.PrinterText.INFO,
|
|
118
|
-
))
|
|
119
|
-
|
|
117
|
+
))
|
|
118
|
+
|
|
120
119
|
ui_thread.print_generator(newman_docker.stdout)
|
|
121
120
|
|
|
122
121
|
with ui_thread.progress(
|
pyntcli/commands/pynt_cmd.py
CHANGED
|
@@ -12,8 +12,7 @@ import pyntcli.log.log as log
|
|
|
12
12
|
|
|
13
13
|
from requests.exceptions import SSLError, HTTPError
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
from . import command, listen, postman, root, sub_command, id_command, newman, har, burp
|
|
15
|
+
from . import command, listen, postman, root, sub_command, id_command, newman, har, burp, template
|
|
17
16
|
|
|
18
17
|
logger = log.get_logger()
|
|
19
18
|
|
|
@@ -25,6 +24,7 @@ avail_sub_commands = [
|
|
|
25
24
|
command.CommandSubCommand("command"),
|
|
26
25
|
listen.ListenSubCommand("listen"),
|
|
27
26
|
burp.BurpCommand("burp"),
|
|
27
|
+
template.TemplateSubCommand("template")
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
commands_without_app_id = ["postman", "pynt-id"]
|
|
@@ -50,7 +50,6 @@ VERSION_CHECK_URL = "https://d1efigcr4c19qn.cloudfront.net/cli/version"
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def check_is_latest_version(current_version):
|
|
53
|
-
|
|
54
53
|
try:
|
|
55
54
|
res = pynt_requests.get(VERSION_CHECK_URL)
|
|
56
55
|
res.raise_for_status()
|
|
@@ -175,9 +174,9 @@ class PyntCommand:
|
|
|
175
174
|
return True
|
|
176
175
|
|
|
177
176
|
if prompt.confirmation_prompt_with_timeout("Application ID is missing. Use the '--application-id' flag to provide it.\n" +
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
"Without an Application ID, the scan will not be associated with your application.\n" +
|
|
178
|
+
"The Application ID can be fetched from https://app.pynt.io/dashboard/applications.\n" +
|
|
179
|
+
"Do you want to continue without associating the scan?", default="yes", timeout=15):
|
|
181
180
|
prompts_history["missing_app_id"] = {"last_confirmation": current_time.strftime("%Y-%m-%d %H:%M:%S")}
|
|
182
181
|
state_store.put_prompts_history(
|
|
183
182
|
prompts_history)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import tempfile
|
|
5
|
+
import time
|
|
6
|
+
from functools import partial
|
|
7
|
+
|
|
8
|
+
from pyntcli.pynt_docker import pynt_container
|
|
9
|
+
from pyntcli.ui import ui_thread
|
|
10
|
+
from pyntcli.commands import sub_command, util
|
|
11
|
+
|
|
12
|
+
PYNT_CONTAINER_INTERNAL_PORT = "5001"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def template_usage():
|
|
16
|
+
return (
|
|
17
|
+
ui_thread.PrinterText("Integration with template testing")
|
|
18
|
+
.with_line("")
|
|
19
|
+
.with_line("Usage:", style=ui_thread.PrinterText.HEADER)
|
|
20
|
+
.with_line("\tpynt template [OPTIONS]")
|
|
21
|
+
.with_line("")
|
|
22
|
+
.with_line("Options:", style=ui_thread.PrinterText.HEADER)
|
|
23
|
+
.with_line("\t--template-file / -tf - Path to the template file")
|
|
24
|
+
.with_line("\t--template-paths-file / -tpf - Path to the file containing the template paths (with new line separator) for the attacks")
|
|
25
|
+
.with_line("\t--url - Base URL for the attacks")
|
|
26
|
+
.with_line("\t--urls - Path to the file containing the base URLs (with new line separator) for the attacks")
|
|
27
|
+
.with_line("\t--reporters - Output results to json")
|
|
28
|
+
.with_line("\t--severity-level - 'all', 'medium', 'high', 'critical', 'none' (default)")
|
|
29
|
+
.with_line("\t--verbose - Use to get more detailed information about the run")
|
|
30
|
+
.with_line("")
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TemplateSubCommand(sub_command.PyntSubCommand):
|
|
35
|
+
def __init__(self, name) -> None:
|
|
36
|
+
super().__init__(name)
|
|
37
|
+
|
|
38
|
+
def usage(self, *args):
|
|
39
|
+
ui_thread.print(template_usage())
|
|
40
|
+
|
|
41
|
+
def add_cmd(self, parent: argparse._SubParsersAction) -> argparse.ArgumentParser:
|
|
42
|
+
template_cmd = parent.add_parser(self.name)
|
|
43
|
+
template_cmd.add_argument("--template-file", "-tf", type=str, help="Path to the template file")
|
|
44
|
+
template_cmd.add_argument("--template-paths-file", "-tpf", type=str, help="Path to the file containing the template paths (with new line separator) for the attacks")
|
|
45
|
+
template_cmd.add_argument("--url", "-u", type=str, help="Base URL for the attacks")
|
|
46
|
+
template_cmd.add_argument("--urls", type=str, help="Path to the file containing the base URLs (with new line separator) for the attacks")
|
|
47
|
+
template_cmd.add_argument("--reporters", action="store_true")
|
|
48
|
+
template_cmd.add_argument("--severity-level", choices=["all", "medium", "high", "critical", "none"], default="none")
|
|
49
|
+
template_cmd.print_usage = self.usage
|
|
50
|
+
template_cmd.print_help = self.usage
|
|
51
|
+
return template_cmd
|
|
52
|
+
|
|
53
|
+
def run_cmd(self, args: argparse.Namespace):
|
|
54
|
+
pynt_folder_path = "/etc/pynt"
|
|
55
|
+
templates_folder_path = f"{pynt_folder_path}/templates"
|
|
56
|
+
ui_thread.print_verbose("Building container")
|
|
57
|
+
port = util.find_open_port()
|
|
58
|
+
container_config = pynt_container.DockerContainerConfig(
|
|
59
|
+
args,
|
|
60
|
+
"template",
|
|
61
|
+
pynt_container._PyntDockerPort(port=port, name="--port")
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
validate_args(args)
|
|
66
|
+
except ValueError as e:
|
|
67
|
+
ui_thread.print(
|
|
68
|
+
ui_thread.PrinterText(
|
|
69
|
+
str(e),
|
|
70
|
+
ui_thread.PrinterText.WARNING,
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
if args.template_file:
|
|
76
|
+
if not os.path.isfile(args.template_file):
|
|
77
|
+
ui_thread.print(
|
|
78
|
+
ui_thread.PrinterText(
|
|
79
|
+
"Could not find the provided path, please provide a valid path",
|
|
80
|
+
ui_thread.PrinterText.WARNING,
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
return
|
|
84
|
+
template_name = os.path.basename(args.template_file)
|
|
85
|
+
full_template_path = f"{templates_folder_path}/{template_name}"
|
|
86
|
+
container_config.mounts.append(
|
|
87
|
+
pynt_container.create_mount(
|
|
88
|
+
os.path.abspath(args.template_file), full_template_path
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
container_config.docker_arguments += ["--template-file", full_template_path]
|
|
92
|
+
|
|
93
|
+
if args.template_paths_file:
|
|
94
|
+
if not os.path.isfile(args.template_paths_file):
|
|
95
|
+
ui_thread.print(
|
|
96
|
+
ui_thread.PrinterText(
|
|
97
|
+
"Could not find the provided paths file, please provide a valid paths file",
|
|
98
|
+
ui_thread.PrinterText.WARNING,
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
# read the file, mount each uncommented file to /etc/pynt/templates, create a temp file with the paths as they are in the container (in /etc/pynt) and mount it to /etc/pynt/paths.txt
|
|
104
|
+
with open(args.template_paths_file, "r") as f:
|
|
105
|
+
paths = [line.strip() for line in f if not (line.strip().startswith("#") or line.startswith("//"))]
|
|
106
|
+
for path in paths:
|
|
107
|
+
container_config.mounts.append(
|
|
108
|
+
pynt_container.create_mount(
|
|
109
|
+
os.path.abspath(path), f"{templates_folder_path}/{os.path.basename(path)}"
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
container_config.docker_arguments += ["--templates-folder", templates_folder_path]
|
|
114
|
+
|
|
115
|
+
if args.url:
|
|
116
|
+
container_config.docker_arguments += ["--url", args.url]
|
|
117
|
+
|
|
118
|
+
if args.urls and not os.path.isfile(args.urls):
|
|
119
|
+
ui_thread.print(
|
|
120
|
+
ui_thread.PrinterText(
|
|
121
|
+
"Could not find the provided urls file, please provide a valid urls file",
|
|
122
|
+
ui_thread.PrinterText.WARNING,
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
if args.urls:
|
|
128
|
+
base_urls_path = f"{pynt_folder_path}/base_urls.txt"
|
|
129
|
+
container_config.docker_arguments += ["--urls", base_urls_path]
|
|
130
|
+
container_config.mounts.append(
|
|
131
|
+
pynt_container.create_mount(
|
|
132
|
+
os.path.abspath(args.urls), base_urls_path
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
with util.create_default_file_mounts(args) as m:
|
|
137
|
+
container_config.mounts += m
|
|
138
|
+
|
|
139
|
+
template_docker = pynt_container.PyntContainerNative(container_config)
|
|
140
|
+
|
|
141
|
+
template_docker.prepare_client()
|
|
142
|
+
template_docker.pre_run_validation(port)
|
|
143
|
+
template_docker.run()
|
|
144
|
+
|
|
145
|
+
healthcheck = partial(
|
|
146
|
+
util.wait_for_healthcheck, "http://localhost:{}".format(port)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
healthcheck()
|
|
150
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
151
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
152
|
+
"Pynt docker is ready",
|
|
153
|
+
ui_thread.PrinterText.INFO,
|
|
154
|
+
))
|
|
155
|
+
|
|
156
|
+
ui_thread.print_generator(template_docker.stdout)
|
|
157
|
+
|
|
158
|
+
with ui_thread.progress(
|
|
159
|
+
"ws://localhost:{}/progress".format(port),
|
|
160
|
+
healthcheck,
|
|
161
|
+
"scan in progress...",
|
|
162
|
+
100,
|
|
163
|
+
):
|
|
164
|
+
while template_docker.is_alive():
|
|
165
|
+
time.sleep(1)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def validate_args(args: argparse.Namespace):
|
|
169
|
+
if not args.template_file and not args.template_paths_file:
|
|
170
|
+
raise ValueError("Please provide either a template file or a template paths file")
|
|
171
|
+
if args.template_file and args.template_paths_file:
|
|
172
|
+
raise ValueError("Please provide either a template file or a template paths file, not both")
|
|
173
|
+
if not args.url and not args.urls:
|
|
174
|
+
raise ValueError("Please provide either a url or a urls file")
|
|
175
|
+
if args.url and args.urls:
|
|
176
|
+
raise ValueError("Please provide either a url or a urls file, not both")
|
|
177
|
+
if args.urls and not os.path.isfile(args.urls):
|
|
178
|
+
raise ValueError("Could not find the provided urls file, please provide a valid urls file")
|
|
179
|
+
if args.template_file and not os.path.isfile(args.template_file):
|
|
180
|
+
raise ValueError("Could not find the provided path, please provide a valid path")
|
|
181
|
+
if args.template_paths_file and not os.path.isfile(args.template_paths_file):
|
|
182
|
+
raise ValueError("Could not find the provided paths file, please provide a valid paths file")
|
|
@@ -240,6 +240,7 @@ class PyntContainerNative:
|
|
|
240
240
|
docker_command += args
|
|
241
241
|
|
|
242
242
|
command = self.adapt_run_command(docker_command)
|
|
243
|
+
|
|
243
244
|
PyntContainerRegistry.instance().register_container(self)
|
|
244
245
|
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
245
246
|
stdout, stderr = process.communicate()
|
|
@@ -288,7 +289,7 @@ class PyntContainerNative:
|
|
|
288
289
|
for container_id in container_ids:
|
|
289
290
|
kill_command = ["docker", "kill", container_id]
|
|
290
291
|
remove_command = ["docker", "remove", container_id]
|
|
291
|
-
subprocess.run(kill_command,stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
292
|
+
subprocess.run(kill_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
292
293
|
subprocess.run(remove_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
293
294
|
if report_to_user:
|
|
294
295
|
ui_thread.print(
|
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
ignoreTests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
|
|
2
2
|
ignoreTests/auth/login.py,sha256=KFlzWhXBAuwdi7GXf16gCB3ya94LQG2wjcSChE149rQ,3798
|
|
3
3
|
ignoreTests/store/cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
|
|
4
|
-
pyntcli/__init__.py,sha256=
|
|
4
|
+
pyntcli/__init__.py,sha256=Cd4SdQA_B1lvL3flAA4RSH333OefFegLyvOlQ3QX7IA,24
|
|
5
5
|
pyntcli/main.py,sha256=RD0W2_0ogYBCXubo-YewxHYkiIXxNv6NkZOh3n1VujE,5964
|
|
6
6
|
pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
pyntcli/analytics/send.py,sha256=0hJ0WJNFHLqyohtRr_xOg5WEXzxHrUOlcePPg-k65Hk,3846
|
|
8
8
|
pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
pyntcli/auth/login.py,sha256=TljsRXbEkNI1YUrKm5mlTw4YiecYScYUsit8Z8vstss,5228
|
|
10
10
|
pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
pyntcli/commands/burp.py,sha256=
|
|
12
|
-
pyntcli/commands/command.py,sha256=
|
|
11
|
+
pyntcli/commands/burp.py,sha256=sR5D2vlOXj9Qae3c1-VWfIXMouXoEv2Ik3O-C-Wqqkc,13891
|
|
12
|
+
pyntcli/commands/command.py,sha256=mMf1_bU7IFbE54FN3S3FuPODjHSSSu8aHzHJX-MgEFA,10832
|
|
13
13
|
pyntcli/commands/har.py,sha256=v6yWTuxPpXLlEi3yJ7gUDhFFGJZSpNQ3ehl2oaZJ-wc,4202
|
|
14
14
|
pyntcli/commands/id_command.py,sha256=UBEgMIpm4vauTCsKyixltiGUolNg_OfHEJvJ_i5BpJY,943
|
|
15
|
-
pyntcli/commands/listen.py,sha256=
|
|
16
|
-
pyntcli/commands/newman.py,sha256=
|
|
15
|
+
pyntcli/commands/listen.py,sha256=bsO7c3cHmZyxUTXspCcq_O9BR8tI2qYqOpHtJDb8hZY,8827
|
|
16
|
+
pyntcli/commands/newman.py,sha256=68P1bCjSSjTWrzOwKN_-fGQC4j484KlVpMbezMJOCMo,5045
|
|
17
17
|
pyntcli/commands/postman.py,sha256=ExfvG0iLRmK_rHcqIj8itcd3mh2-BdPuQEDm8viLP6Q,4891
|
|
18
|
-
pyntcli/commands/pynt_cmd.py,sha256=
|
|
18
|
+
pyntcli/commands/pynt_cmd.py,sha256=AeXxKy8dtZTdwWhTirHVvkPkeFUSoZNb3FRyuwkL6kg,7103
|
|
19
19
|
pyntcli/commands/root.py,sha256=UtGky7LfbfQ6mELHoNJcdHznFrUVBlhXI47_8QdApfc,4068
|
|
20
20
|
pyntcli/commands/static_file_extensions.py,sha256=PZJb02BI-64tbU-j3rdCNsXzTh7gkIDGxGKbKNw3h5k,1995
|
|
21
21
|
pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
|
|
22
|
+
pyntcli/commands/template.py,sha256=KocIH1T7occrrjaWJQaKKGgGWrU1bieTKEJbhFw3KLI,7976
|
|
22
23
|
pyntcli/commands/util.py,sha256=FGtuXLxMAL0b9sbsrJaQR_-5sEu-PwZOJonMwuCjO2U,4450
|
|
23
24
|
pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
|
|
24
25
|
pyntcli/log/log.py,sha256=YXCvcCzuhQ5QUT2L02uQEdN_lTCzLEuet4OnLuEnjlM,112
|
|
25
26
|
pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
|
|
26
27
|
pyntcli/pynt_docker/container_utils.py,sha256=_Onn7loInzyJAG2-Uk6CGpsuRyelmUFHOvtJj4Uzi9A,175
|
|
27
|
-
pyntcli/pynt_docker/pynt_container.py,sha256=
|
|
28
|
+
pyntcli/pynt_docker/pynt_container.py,sha256=42Qgwcd5EgtF0RKa2e9O2AjGSngAz9rZveCMOHGZaS8,13233
|
|
28
29
|
pyntcli/store/__init__.py,sha256=1fP8cEAQCF_myja3gnhHH9FEqtBiOJ-2aBmUXSKBdFA,41
|
|
29
30
|
pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
|
|
30
31
|
pyntcli/store/store.py,sha256=Kl_HT9FJFdKlAH7SwAt3g4-bW-r-1ve_u13OPggQai0,2529
|
|
@@ -39,8 +40,8 @@ pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
|
|
|
39
40
|
pyntcli/ui/ui_thread.py,sha256=XUBgLpYQjVhrilU-ofw7VSXgTiwneSdTxm61EvC3x4Q,5091
|
|
40
41
|
tests/test_utils.py,sha256=t5fTQUk1U_Js6iMxcGYGqt4C-crzOJ0CqCKtLkRtUi0,2050
|
|
41
42
|
tests/commands/test_pynt_cmd.py,sha256=BjGFCFACcSziLrNA6_27t6TjSmvdu54wx9njwLpRSJY,8379
|
|
42
|
-
pyntcli-0.1.
|
|
43
|
-
pyntcli-0.1.
|
|
44
|
-
pyntcli-0.1.
|
|
45
|
-
pyntcli-0.1.
|
|
46
|
-
pyntcli-0.1.
|
|
43
|
+
pyntcli-0.1.109.dist-info/METADATA,sha256=fHnwDHSJvgjpR3B2PBXIdU9t3WVMl6bLFbD2p1mz9PU,428
|
|
44
|
+
pyntcli-0.1.109.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
45
|
+
pyntcli-0.1.109.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
|
|
46
|
+
pyntcli-0.1.109.dist-info/top_level.txt,sha256=64XSgBzSpgwjYjEKHZE7q3JH2a816zEeyZBXfJi3AKI,42
|
|
47
|
+
pyntcli-0.1.109.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|